From f6181b3428ffb414767ee4eb2bea202280261e6e Mon Sep 17 00:00:00 2001 From: Jefferson Montgomery Date: Mon, 22 Feb 2016 15:22:48 -0800 Subject: [PATCH 001/823] Examples: DirectX12: Add directx12_example --- examples/README.txt | 4 + examples/directx12_example/build_win32.bat | 4 + .../directx12_example.vcxproj | 164 +++++ .../directx12_example.vcxproj.filters | 45 ++ .../directx12_example/imgui_impl_dx12.cpp | 667 ++++++++++++++++++ examples/directx12_example/imgui_impl_dx12.h | 34 + examples/directx12_example/main.cpp | 418 +++++++++++ examples/imgui_examples_msvc2010.sln | 10 + 8 files changed, 1346 insertions(+) create mode 100644 examples/directx12_example/build_win32.bat create mode 100644 examples/directx12_example/directx12_example.vcxproj create mode 100644 examples/directx12_example/directx12_example.vcxproj.filters create mode 100644 examples/directx12_example/imgui_impl_dx12.cpp create mode 100644 examples/directx12_example/imgui_impl_dx12.h create mode 100644 examples/directx12_example/main.cpp diff --git a/examples/README.txt b/examples/README.txt index b80866c117a6..11d785d4ac1e 100644 --- a/examples/README.txt +++ b/examples/README.txt @@ -58,6 +58,10 @@ directx11_example/ DirectX11 example, Windows only. This is quite long and tedious, because: DirectX11. +directx12_example/ + DirectX12 example, Windows only. + This is quite long and tedious, because: DirectX12. + ios_example/ iOS example. Using Synergy to access keyboard/mouse data from server computer. diff --git a/examples/directx12_example/build_win32.bat b/examples/directx12_example/build_win32.bat new file mode 100644 index 000000000000..dd919b236139 --- /dev/null +++ b/examples/directx12_example/build_win32.bat @@ -0,0 +1,4 @@ +@REM Build for Visual Studio compiler. Run your copy of vcvars32.bat or vcvarsall.bat to setup command-line compiler. +mkdir Debug +cl /nologo /Zi /MD /I ..\.. /I "%WindowsSdkDir%Include\um" /I "%WindowsSdkDir%Include\shared" /I "%DXSDK_DIR%Include" /D UNICODE /D _UNICODE *.cpp ..\..\*.cpp /FeDebug/directx12_example.exe /FoDebug/ /link /LIBPATH:"%DXSDK_DIR%/Lib/x86" d3d12.lib d3dcompiler.lib + diff --git a/examples/directx12_example/directx12_example.vcxproj b/examples/directx12_example/directx12_example.vcxproj new file mode 100644 index 000000000000..94d7fa0857ef --- /dev/null +++ b/examples/directx12_example/directx12_example.vcxproj @@ -0,0 +1,164 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + {b4cf9797-519d-4afe-a8f4-5141a6b521d3} + directx12_example + 10.0.10240.0 + + + + Application + true + Unicode + v140 + + + Application + true + Unicode + v140 + + + Application + false + true + Unicode + v140 + + + Application + false + true + Unicode + v140 + + + + + + + + + + + + + + + + + + + $(ProjectDir)$(Configuration)\ + $(ProjectDir)$(Configuration)\ + + + $(ProjectDir)$(Configuration)\ + $(ProjectDir)$(Configuration)\ + + + $(ProjectDir)$(Configuration)\ + $(ProjectDir)$(Configuration)\ + + + $(ProjectDir)$(Configuration)\ + $(ProjectDir)$(Configuration)\ + + + + Level4 + Disabled + ..\..;%(AdditionalIncludeDirectories) + + + true + d3d12.lib;d3dcompiler.lib;dxgi.lib;%(AdditionalDependencies) + %(AdditionalLibraryDirectories) + Console + + + + + Level4 + Disabled + ..\..;%(AdditionalIncludeDirectories) + + + true + d3d12.lib;d3dcompiler.lib;dxgi.lib;%(AdditionalDependencies) + %(AdditionalLibraryDirectories) + Console + + + + + Level4 + MaxSpeed + true + true + ..\..;%(AdditionalIncludeDirectories) + + + true + true + true + d3d12.lib;d3dcompiler.lib;dxgi.lib;imm32.lib;%(AdditionalDependencies) + %(AdditionalLibraryDirectories) + Console + + + + + Level4 + MaxSpeed + true + true + ..\..;%(AdditionalIncludeDirectories) + + + true + true + true + d3d12.lib;d3dcompiler.lib;dxgi.lib;imm32.lib;%(AdditionalDependencies) + %(AdditionalLibraryDirectories) + Console + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/directx12_example/directx12_example.vcxproj.filters b/examples/directx12_example/directx12_example.vcxproj.filters new file mode 100644 index 000000000000..d445f985b5ae --- /dev/null +++ b/examples/directx12_example/directx12_example.vcxproj.filters @@ -0,0 +1,45 @@ + + + + + {fb3d294f-51ec-478e-a627-25831c80fefd} + + + {4f33ddea-9910-456d-b868-4267eb3c2b19} + + + + + imgui + + + imgui + + + sources + + + imgui + + + + + imgui + + + sources + + + sources + + + imgui + + + imgui + + + + + + diff --git a/examples/directx12_example/imgui_impl_dx12.cpp b/examples/directx12_example/imgui_impl_dx12.cpp new file mode 100644 index 000000000000..f19839270040 --- /dev/null +++ b/examples/directx12_example/imgui_impl_dx12.cpp @@ -0,0 +1,667 @@ +// ImGui Win32 + DirectX12 binding +// You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this. +// If you use this binding you'll need to call 4 functions: ImGui_ImplXXXX_Init(), ImGui_ImplXXXX_NewFrame(), ImGui::Render() and ImGui_ImplXXXX_Shutdown(). +// If you are new to ImGui, see examples/README.txt and documentation at the top of imgui.cpp. +// https://github.com/ocornut/imgui + +#include +#include "imgui_impl_dx12.h" + +// DirectX +#include +#include + +struct FrameResources +{ + ID3D12Resource* IB; + ID3D12Resource* VB; + int VertexBufferSize; + int IndexBufferSize; +}; + +// Data +static INT64 g_Time = 0; +static INT64 g_TicksPerSecond = 0; + +static HWND g_hWnd = 0; +static ID3D12Device* g_pd3dDevice = NULL; +static ID3D12GraphicsCommandList* g_pd3dCommandList = NULL; +static ID3D10Blob* g_pVertexShaderBlob = NULL; +static ID3D10Blob* g_pPixelShaderBlob = NULL; +static ID3D12RootSignature* g_pRootSignature = NULL; +static ID3D12PipelineState* g_pPipelineState = NULL; +static ID3D12Resource* g_pFontTextureResource = NULL; +static D3D12_CPU_DESCRIPTOR_HANDLE g_hFontSrvCpuDescHandle = {}; +static D3D12_GPU_DESCRIPTOR_HANDLE g_hFontSrvGpuDescHandle = {}; + +static FrameResources* g_pFrameResources = NULL; +static UINT g_numFramesInFlight = 0; +static UINT g_frameIndex = UINT_MAX; + +struct VERTEX_CONSTANT_BUFFER +{ + float mvp[4][4]; +}; + +// 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) +void ImGui_ImplDX12_RenderDrawLists(ImDrawData* draw_data) +{ + // Create and grow vertex/index buffers if needed + // + // NOTE: I'm assuming that this only get's called once per frame! If not, + // we can't just re-allocate the IB or VB, we'll have to do a proper + // allocator. + g_frameIndex = g_frameIndex + 1; + FrameResources* frameResources = &g_pFrameResources[g_frameIndex % g_numFramesInFlight]; + + D3D12_HEAP_PROPERTIES props = {}; + props.Type = D3D12_HEAP_TYPE_UPLOAD; + props.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN; + props.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN; + + D3D12_RESOURCE_DESC desc = {}; + desc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER; + desc.Height = 1; + desc.DepthOrArraySize = 1; + desc.MipLevels = 1; + desc.Format = DXGI_FORMAT_UNKNOWN; + desc.SampleDesc.Count = 1; + desc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR; + desc.Flags = D3D12_RESOURCE_FLAG_NONE; + + if (!frameResources->VB || frameResources->VertexBufferSize < draw_data->TotalVtxCount) + { + if (frameResources->VB) { frameResources->VB->Release(); frameResources->VB = NULL; } + frameResources->VertexBufferSize = draw_data->TotalVtxCount + 5000; + desc.Width = frameResources->VertexBufferSize * sizeof(ImDrawVert); + HRESULT hr = g_pd3dDevice->CreateCommittedResource(&props, D3D12_HEAP_FLAG_NONE, &desc, D3D12_RESOURCE_STATE_GENERIC_READ, NULL, IID_PPV_ARGS(&frameResources->VB)); + assert(SUCCEEDED(hr)); + } + if (!frameResources->IB || frameResources->IndexBufferSize < draw_data->TotalIdxCount) + { + if (frameResources->IB) { frameResources->IB->Release(); frameResources->IB = NULL; } + frameResources->IndexBufferSize = draw_data->TotalIdxCount + 10000; + desc.Width = frameResources->IndexBufferSize * sizeof(ImDrawIdx); + HRESULT hr = g_pd3dDevice->CreateCommittedResource(&props, D3D12_HEAP_FLAG_NONE, &desc, D3D12_RESOURCE_STATE_GENERIC_READ, NULL, IID_PPV_ARGS(&frameResources->IB)); + assert(SUCCEEDED(hr)); + } + + // Copy and convert all vertices into a single contiguous buffer + D3D12_RANGE range = {}; + void* vtx_resource = NULL; + HRESULT hr = frameResources->VB->Map(0, &range, &vtx_resource); + assert(SUCCEEDED(hr)); + + void* idx_resource = NULL; + hr = frameResources->IB->Map(0, &range, &idx_resource); + assert(SUCCEEDED(hr)); + + ImDrawVert* vtx_dst = (ImDrawVert*)vtx_resource; + ImDrawIdx* idx_dst = (ImDrawIdx*)idx_resource; + for (int n = 0; n < draw_data->CmdListsCount; n++) + { + const ImDrawList* cmd_list = draw_data->CmdLists[n]; + memcpy(vtx_dst, &cmd_list->VtxBuffer[0], cmd_list->VtxBuffer.size() * sizeof(ImDrawVert)); + memcpy(idx_dst, &cmd_list->IdxBuffer[0], cmd_list->IdxBuffer.size() * sizeof(ImDrawIdx)); + vtx_dst += cmd_list->VtxBuffer.size(); + idx_dst += cmd_list->IdxBuffer.size(); + } + frameResources->VB->Unmap(0, &range); + frameResources->IB->Unmap(0, &range); + + // Setup orthographic projection matrix into our constant buffer + VERTEX_CONSTANT_BUFFER vertexConstantBuffer = {}; + { + const float L = 0.0f; + const float R = ImGui::GetIO().DisplaySize.x; + const float B = ImGui::GetIO().DisplaySize.y; + const float T = 0.0f; + const float mvp[4][4] = + { + { 2.0f/(R-L), 0.0f, 0.0f, 0.0f }, + { 0.0f, 2.0f/(T-B), 0.0f, 0.0f }, + { 0.0f, 0.0f, 0.5f, 0.0f }, + { (R+L)/(L-R), (T+B)/(B-T), 0.5f, 1.0f }, + }; + memcpy(&vertexConstantBuffer.mvp, mvp, sizeof(mvp)); + } + + // Setup viewport + D3D12_VIEWPORT viewport = {}; + viewport.Width = ImGui::GetIO().DisplaySize.x; + viewport.Height = ImGui::GetIO().DisplaySize.y; + viewport.MinDepth = 0.0f; + viewport.MaxDepth = 1.0f; + viewport.TopLeftX = 0; + viewport.TopLeftY = 0; + + // Bind shader and vertex buffers + D3D12_VERTEX_BUFFER_VIEW vbv = {}; + vbv.BufferLocation = frameResources->VB->GetGPUVirtualAddress(); + vbv.SizeInBytes = frameResources->VertexBufferSize * sizeof(ImDrawVert); + vbv.StrideInBytes = sizeof(ImDrawVert); + + D3D12_INDEX_BUFFER_VIEW ibv = {}; + ibv.BufferLocation = frameResources->IB->GetGPUVirtualAddress(); + ibv.SizeInBytes = frameResources->IndexBufferSize * sizeof(ImDrawIdx); + ibv.Format = sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT; + + FLOAT blendFactor[4] = { 0.f, 0.f, 0.f, 0.f }; + + g_pd3dCommandList->SetPipelineState(g_pPipelineState); + g_pd3dCommandList->SetGraphicsRootSignature(g_pRootSignature); + g_pd3dCommandList->SetGraphicsRoot32BitConstants(0, 16, &vertexConstantBuffer, 0); + g_pd3dCommandList->IASetIndexBuffer(&ibv); + g_pd3dCommandList->IASetVertexBuffers(0, 1, &vbv); + g_pd3dCommandList->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + g_pd3dCommandList->RSSetViewports(1, &viewport); + g_pd3dCommandList->OMSetBlendFactor(blendFactor); + + // Render command lists + int vtx_offset = 0; + int idx_offset = 0; + for (int n = 0; n < draw_data->CmdListsCount; n++) + { + const ImDrawList* cmd_list = draw_data->CmdLists[n]; + for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.size(); cmd_i++) + { + const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i]; + if (pcmd->UserCallback) + { + pcmd->UserCallback(cmd_list, pcmd); + } + else + { + D3D12_RECT scissorRect = { (LONG)pcmd->ClipRect.x, (LONG)pcmd->ClipRect.y, (LONG)pcmd->ClipRect.z, (LONG)pcmd->ClipRect.w }; + + D3D12_GPU_DESCRIPTOR_HANDLE srvHandle = {}; + srvHandle.ptr = (UINT64) pcmd->TextureId; + + g_pd3dCommandList->SetGraphicsRootDescriptorTable(1, srvHandle); + g_pd3dCommandList->RSSetScissorRects(1, &scissorRect); + g_pd3dCommandList->DrawIndexedInstanced(pcmd->ElemCount, 1, idx_offset, vtx_offset, 0); + } + idx_offset += pcmd->ElemCount; + } + vtx_offset += cmd_list->VtxBuffer.size(); + } +} + +IMGUI_API LRESULT ImGui_ImplDX12_WndProcHandler(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_MBUTTONDOWN: + io.MouseDown[2] = true; + return true; + case WM_MBUTTONUP: + io.MouseDown[2] = 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 < 256) + io.KeysDown[wParam] = 1; + return true; + case WM_KEYUP: + if (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; +} + +static void ImGui_ImplDX12_CreateFontsTexture() +{ + // Build texture atlas + ImGuiIO& io = ImGui::GetIO(); + unsigned char* pixels; + int width, height; + io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); + + // Upload texture to graphics system + { + D3D12_RESOURCE_DESC resourceDesc = {}; + resourceDesc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D; + resourceDesc.Alignment = 0; + resourceDesc.Width = width; + resourceDesc.Height = height; + resourceDesc.DepthOrArraySize = 1; + resourceDesc.MipLevels = 1; + resourceDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + resourceDesc.SampleDesc.Count = 1; + resourceDesc.SampleDesc.Quality = 0; + resourceDesc.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN; + resourceDesc.Flags = D3D12_RESOURCE_FLAG_NONE; + + D3D12_HEAP_PROPERTIES props = {}; + props.Type = D3D12_HEAP_TYPE_DEFAULT; + props.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN; + props.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN; + + HRESULT hr = g_pd3dDevice->CreateCommittedResource(&props, D3D12_HEAP_FLAG_NONE, &resourceDesc, + D3D12_RESOURCE_STATE_COPY_DEST, NULL, IID_PPV_ARGS(&g_pFontTextureResource)); + assert(SUCCEEDED(hr)); + + UINT uploadPitch = (width * 4 + D3D12_TEXTURE_DATA_PITCH_ALIGNMENT - 1u) & ~(D3D12_TEXTURE_DATA_PITCH_ALIGNMENT - 1u); + UINT uploadSize = height * uploadPitch; + resourceDesc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER; + resourceDesc.Alignment = 0; + resourceDesc.Width = uploadSize; + resourceDesc.Height = 1; + resourceDesc.DepthOrArraySize = 1; + resourceDesc.MipLevels = 1; + resourceDesc.Format = DXGI_FORMAT_UNKNOWN; + resourceDesc.SampleDesc.Count = 1; + resourceDesc.SampleDesc.Quality = 0; + resourceDesc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR; + resourceDesc.Flags = D3D12_RESOURCE_FLAG_NONE; + + props.Type = D3D12_HEAP_TYPE_UPLOAD; + props.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN; + props.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN; + + ID3D12Resource* uploadBuffer = NULL; + hr = g_pd3dDevice->CreateCommittedResource(&props, D3D12_HEAP_FLAG_NONE, &resourceDesc, + D3D12_RESOURCE_STATE_GENERIC_READ, NULL, IID_PPV_ARGS(&uploadBuffer)); + assert(SUCCEEDED(hr)); + + void* mapped = NULL; + D3D12_RANGE range = { 0, uploadSize }; + hr = uploadBuffer->Map(0, &range, &mapped); + assert(SUCCEEDED(hr)); + for (int y = 0; y < height; ++y) + { + memcpy((void*) ((uintptr_t) mapped + y * uploadPitch), pixels + y * width * 4, width * 4); + } + uploadBuffer->Unmap(0, &range); + + D3D12_TEXTURE_COPY_LOCATION srcLocation = {}; + srcLocation.pResource = uploadBuffer; + srcLocation.Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT; + srcLocation.PlacedFootprint.Footprint.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + srcLocation.PlacedFootprint.Footprint.Width = width; + srcLocation.PlacedFootprint.Footprint.Height = height; + srcLocation.PlacedFootprint.Footprint.Depth = 1; + srcLocation.PlacedFootprint.Footprint.RowPitch = uploadPitch; + + D3D12_TEXTURE_COPY_LOCATION dstLocation = {}; + dstLocation.pResource = g_pFontTextureResource; + dstLocation.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX; + dstLocation.SubresourceIndex = 0; + + D3D12_RESOURCE_BARRIER barrier = {}; + barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION; + barrier.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE; + barrier.Transition.pResource = g_pFontTextureResource; + barrier.Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES; + barrier.Transition.StateBefore = D3D12_RESOURCE_STATE_COPY_DEST; + barrier.Transition.StateAfter = D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE; + + ID3D12Fence* fence = NULL; + hr = g_pd3dDevice->CreateFence(0, D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS(&fence)); + assert(SUCCEEDED(hr)); + + HANDLE event = CreateEvent(0, 0, 0, 0); + assert(event != NULL); + + D3D12_COMMAND_QUEUE_DESC queueDesc = {}; + queueDesc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT; + queueDesc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE; + queueDesc.NodeMask = 1; + + ID3D12CommandQueue* cmdQueue = NULL; + hr = g_pd3dDevice->CreateCommandQueue(&queueDesc, IID_PPV_ARGS(&cmdQueue)); + assert(SUCCEEDED(hr)); + + ID3D12CommandAllocator* cmdAlloc = NULL; + hr = g_pd3dDevice->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, IID_PPV_ARGS(&cmdAlloc)); + assert(SUCCEEDED(hr)); + + ID3D12GraphicsCommandList* cmdList = NULL; + hr = g_pd3dDevice->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT, cmdAlloc, NULL, IID_PPV_ARGS(&cmdList)); + assert(SUCCEEDED(hr)); + + cmdList->CopyTextureRegion(&dstLocation, 0, 0, 0, &srcLocation, NULL); + cmdList->ResourceBarrier(1, &barrier); + + hr = cmdList->Close(); + assert(SUCCEEDED(hr)); + + cmdQueue->ExecuteCommandLists(1, (ID3D12CommandList* const*) &cmdList); + hr = cmdQueue->Signal(fence, 1); + assert(SUCCEEDED(hr)); + + fence->SetEventOnCompletion(1, event); + WaitForSingleObject(event, INFINITE); + + cmdList->Release(); + cmdAlloc->Release(); + cmdQueue->Release(); + CloseHandle(event); + fence->Release(); + uploadBuffer->Release(); + } + + // Create texture view + g_pd3dDevice->CreateShaderResourceView(g_pFontTextureResource, NULL, g_hFontSrvCpuDescHandle); + + // Store our identifier + static_assert(sizeof(void*) >= sizeof(g_hFontSrvGpuDescHandle.ptr), "Can't pack descriptor handle into TexID"); + ImGui::GetIO().Fonts->TexID = (void*) g_hFontSrvGpuDescHandle.ptr; +} + +bool ImGui_ImplDX12_CreateDeviceObjects() +{ + if (!g_pd3dDevice) + return false; + if (g_pPipelineState) + ImGui_ImplDX12_InvalidateDeviceObjects(); + + // Create the root signature + { + D3D12_DESCRIPTOR_RANGE descRange = {}; + descRange.RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_SRV; + descRange.NumDescriptors = 1; + descRange.BaseShaderRegister = 0; + descRange.RegisterSpace = 0; + descRange.OffsetInDescriptorsFromTableStart = 0; + + D3D12_ROOT_PARAMETER param[2] = {}; + + param[0].ParameterType = D3D12_ROOT_PARAMETER_TYPE_32BIT_CONSTANTS; + param[0].Constants.ShaderRegister = 0; + param[0].Constants.RegisterSpace = 0; + param[0].Constants.Num32BitValues = 16; + param[0].ShaderVisibility = D3D12_SHADER_VISIBILITY_VERTEX; + + param[1].ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE; + param[1].DescriptorTable.NumDescriptorRanges = 1; + param[1].DescriptorTable.pDescriptorRanges = &descRange; + param[1].ShaderVisibility = D3D12_SHADER_VISIBILITY_PIXEL; + + D3D12_STATIC_SAMPLER_DESC staticSampler = {}; + staticSampler.Filter = D3D12_FILTER_MIN_MAG_MIP_LINEAR; + staticSampler.AddressU = D3D12_TEXTURE_ADDRESS_MODE_WRAP; + staticSampler.AddressV = D3D12_TEXTURE_ADDRESS_MODE_WRAP; + staticSampler.AddressW = D3D12_TEXTURE_ADDRESS_MODE_WRAP; + staticSampler.MipLODBias = 0.f; + staticSampler.MaxAnisotropy = 0; + staticSampler.ComparisonFunc = D3D12_COMPARISON_FUNC_ALWAYS; + staticSampler.BorderColor = D3D12_STATIC_BORDER_COLOR_TRANSPARENT_BLACK; + staticSampler.MinLOD = 0.f; + staticSampler.MaxLOD = 0.f; + staticSampler.ShaderRegister = 0; + staticSampler.RegisterSpace = 0; + staticSampler.ShaderVisibility = D3D12_SHADER_VISIBILITY_PIXEL; + + D3D12_ROOT_SIGNATURE_DESC desc = {}; + desc.NumParameters = _countof(param); + desc.pParameters = param; + desc.NumStaticSamplers = 1; + desc.pStaticSamplers = &staticSampler; + desc.Flags = + D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT | + D3D12_ROOT_SIGNATURE_FLAG_DENY_HULL_SHADER_ROOT_ACCESS | + D3D12_ROOT_SIGNATURE_FLAG_DENY_DOMAIN_SHADER_ROOT_ACCESS | + D3D12_ROOT_SIGNATURE_FLAG_DENY_GEOMETRY_SHADER_ROOT_ACCESS; + + ID3DBlob* blob = NULL; + if (D3D12SerializeRootSignature(&desc, D3D_ROOT_SIGNATURE_VERSION_1, &blob, NULL) != S_OK) + return false; + + g_pd3dDevice->CreateRootSignature(0, blob->GetBufferPointer(), blob->GetBufferSize(), IID_PPV_ARGS(&g_pRootSignature)); + blob->Release(); + } + // Create the pipeline state object + { + static const char* vertexShader = + "cbuffer vertexBuffer : register(b0) \ + {\ + float4x4 ProjectionMatrix; \ + };\ + struct VS_INPUT\ + {\ + float2 pos : POSITION;\ + float4 col : COLOR0;\ + float2 uv : TEXCOORD0;\ + };\ + \ + struct PS_INPUT\ + {\ + float4 pos : SV_POSITION;\ + float4 col : COLOR0;\ + float2 uv : TEXCOORD0;\ + };\ + \ + PS_INPUT main(VS_INPUT input)\ + {\ + PS_INPUT output;\ + output.pos = mul( ProjectionMatrix, float4(input.pos.xy, 0.f, 1.f));\ + output.col = input.col;\ + output.uv = input.uv;\ + return output;\ + }"; + + static const char* pixelShader = + "struct PS_INPUT\ + {\ + float4 pos : SV_POSITION;\ + float4 col : COLOR0;\ + float2 uv : TEXCOORD0;\ + };\ + SamplerState sampler0 : register(s0);\ + Texture2D texture0 : register(t0);\ + \ + float4 main(PS_INPUT input) : SV_Target\ + {\ + float4 out_col = input.col * texture0.Sample(sampler0, input.uv); \ + return out_col; \ + }"; + + D3DCompile(vertexShader, strlen(vertexShader), NULL, NULL, NULL, "main", "vs_5_0", 0, 0, &g_pVertexShaderBlob, NULL); + if (g_pVertexShaderBlob == NULL) // NB: Pass ID3D10Blob* pErrorBlob to D3DCompile() to get error showing in (const char*)pErrorBlob->GetBufferPointer(). Make sure to Release() the blob! + return false; + + D3DCompile(pixelShader, strlen(pixelShader), NULL, NULL, NULL, "main", "ps_5_0", 0, 0, &g_pPixelShaderBlob, NULL); + if (g_pPixelShaderBlob == NULL) // NB: Pass ID3D10Blob* pErrorBlob to D3DCompile() to get error showing in (const char*)pErrorBlob->GetBufferPointer(). Make sure to Release() the blob! + return false; + + D3D12_INPUT_ELEMENT_DESC localLayout[] = { + { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->pos), D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 }, + { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (size_t)(&((ImDrawVert*)0)->uv), D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 }, + { "COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, (size_t)(&((ImDrawVert*)0)->col), D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 }, + }; + + D3D12_GRAPHICS_PIPELINE_STATE_DESC desc = {}; + desc.NodeMask = 1; + desc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE; + desc.InputLayout = { localLayout, _countof(localLayout) }; + desc.pRootSignature = g_pRootSignature; + desc.VS = { g_pVertexShaderBlob->GetBufferPointer(), g_pVertexShaderBlob->GetBufferSize() }; + desc.PS = { g_pPixelShaderBlob->GetBufferPointer(), g_pPixelShaderBlob->GetBufferSize() }; + desc.SampleMask = UINT_MAX; + desc.NumRenderTargets = 1; + desc.RTVFormats[0] = DXGI_FORMAT_B8G8R8A8_UNORM; + desc.SampleDesc.Count = 1; + desc.Flags = D3D12_PIPELINE_STATE_FLAG_NONE; + + desc.RasterizerState.FillMode = D3D12_FILL_MODE_SOLID; + desc.RasterizerState.CullMode = D3D12_CULL_MODE_NONE; + desc.RasterizerState.FrontCounterClockwise = FALSE; + desc.RasterizerState.DepthBias = D3D12_DEFAULT_DEPTH_BIAS; + desc.RasterizerState.DepthBiasClamp = D3D12_DEFAULT_DEPTH_BIAS_CLAMP; + desc.RasterizerState.SlopeScaledDepthBias = D3D12_DEFAULT_SLOPE_SCALED_DEPTH_BIAS; + desc.RasterizerState.DepthClipEnable = TRUE; + desc.RasterizerState.MultisampleEnable = FALSE; + desc.RasterizerState.AntialiasedLineEnable = FALSE; + desc.RasterizerState.ForcedSampleCount = 0; + desc.RasterizerState.ConservativeRaster = D3D12_CONSERVATIVE_RASTERIZATION_MODE_OFF; + + desc.BlendState.AlphaToCoverageEnable = FALSE; + desc.BlendState.RenderTarget[0].BlendEnable = TRUE; + desc.BlendState.RenderTarget[0].SrcBlend = D3D12_BLEND_SRC_ALPHA; + desc.BlendState.RenderTarget[0].DestBlend = D3D12_BLEND_INV_SRC_ALPHA; + desc.BlendState.RenderTarget[0].BlendOp = D3D12_BLEND_OP_ADD; + desc.BlendState.RenderTarget[0].SrcBlendAlpha = D3D12_BLEND_INV_SRC_ALPHA; + desc.BlendState.RenderTarget[0].DestBlendAlpha = D3D12_BLEND_ZERO; + desc.BlendState.RenderTarget[0].BlendOpAlpha = D3D12_BLEND_OP_ADD; + desc.BlendState.RenderTarget[0].RenderTargetWriteMask = D3D12_COLOR_WRITE_ENABLE_ALL; + + desc.DepthStencilState.DepthEnable = FALSE; + desc.DepthStencilState.StencilEnable = FALSE; + + HRESULT hr = g_pd3dDevice->CreateGraphicsPipelineState(&desc, IID_PPV_ARGS(&g_pPipelineState)); + assert(SUCCEEDED(hr)); + } + + ImGui_ImplDX12_CreateFontsTexture(); + + return true; +} + +void ImGui_ImplDX12_InvalidateDeviceObjects() +{ + if (!g_pd3dDevice) + return; + + if (g_pVertexShaderBlob) { g_pVertexShaderBlob->Release(); g_pVertexShaderBlob = NULL; } + if (g_pPixelShaderBlob) { g_pPixelShaderBlob->Release(); g_pPixelShaderBlob = NULL; } + if (g_pRootSignature) { g_pRootSignature->Release(); g_pRootSignature = NULL; } + if (g_pPipelineState) { g_pPipelineState->Release(); g_pPipelineState = NULL; } + if (g_pFontTextureResource) { g_pFontTextureResource->Release(); g_pFontTextureResource = NULL; } + for (UINT i = 0; i < g_numFramesInFlight; ++i) + { + if (g_pFrameResources[i].IB) { g_pFrameResources[i].IB->Release(); g_pFrameResources[i].IB = NULL; } + if (g_pFrameResources[i].VB) { g_pFrameResources[i].VB->Release(); g_pFrameResources[i].VB = NULL; } + } + ImGui::GetIO().Fonts->TexID = 0; +} + +bool ImGui_ImplDX12_Init(void* hwnd, int numFramesInFlight, + ID3D12Device* device, ID3D12GraphicsCommandList* cmdList, + D3D12_CPU_DESCRIPTOR_HANDLE fontSrvCpuDescHandle, + D3D12_GPU_DESCRIPTOR_HANDLE fontSrvGpuDescHandle) +{ + g_hWnd = (HWND)hwnd; + g_pd3dDevice = device; + g_pd3dCommandList = cmdList; + g_hFontSrvCpuDescHandle = fontSrvCpuDescHandle; + g_hFontSrvGpuDescHandle = fontSrvGpuDescHandle; + g_pFrameResources = new FrameResources [numFramesInFlight]; + g_numFramesInFlight = numFramesInFlight; + g_frameIndex = UINT_MAX; + + for (int i = 0; i < numFramesInFlight; ++i) + { + g_pFrameResources[i].IB = NULL; + g_pFrameResources[i].VB = NULL; + g_pFrameResources[i].VertexBufferSize = 5000; + g_pFrameResources[i].IndexBufferSize = 10000; + } + + if (!QueryPerformanceFrequency((LARGE_INTEGER *)&g_TicksPerSecond)) + return false; + if (!QueryPerformanceCounter((LARGE_INTEGER *)&g_Time)) + return false; + + ImGuiIO& io = ImGui::GetIO(); + 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_DOWN; + io.KeyMap[ImGuiKey_PageUp] = VK_PRIOR; + io.KeyMap[ImGuiKey_PageDown] = VK_NEXT; + 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_ImplDX12_RenderDrawLists; // Alternatively you can set this to NULL and call ImGui::GetDrawData() after ImGui::Render() to get the same ImDrawData pointer. + io.ImeWindowHandle = g_hWnd; + + return true; +} + +void ImGui_ImplDX12_Shutdown() +{ + ImGui_ImplDX12_InvalidateDeviceObjects(); + ImGui::Shutdown(); + delete[] g_pFrameResources; + g_pd3dDevice = NULL; + g_hWnd = (HWND)0; + g_pd3dCommandList = NULL; + g_hFontSrvCpuDescHandle.ptr = 0; + g_hFontSrvGpuDescHandle.ptr = 0; + g_pFrameResources = NULL; + g_numFramesInFlight = 0; + g_frameIndex = UINT_MAX; +} + +void ImGui_ImplDX12_NewFrame() +{ + if (!g_pPipelineState) + ImGui_ImplDX12_CreateDeviceObjects(); + + ImGuiIO& io = ImGui::GetIO(); + + // Setup display size (every frame to accommodate for window resizing) + RECT rect; + GetClientRect(g_hWnd, &rect); + io.DisplaySize = ImVec2((float)(rect.right - rect.left), (float)(rect.bottom - rect.top)); + + // 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.KeyAlt = (GetKeyState(VK_MENU) & 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 + + // Hide OS mouse cursor if ImGui is drawing it + SetCursor(io.MouseDrawCursor ? NULL : LoadCursor(NULL, IDC_ARROW)); + + // Start the frame + ImGui::NewFrame(); +} diff --git a/examples/directx12_example/imgui_impl_dx12.h b/examples/directx12_example/imgui_impl_dx12.h new file mode 100644 index 000000000000..f5c58bb84223 --- /dev/null +++ b/examples/directx12_example/imgui_impl_dx12.h @@ -0,0 +1,34 @@ +// ImGui Win32 + DirectX12 binding +// You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this. +// If you use this binding you'll need to call 4 functions: ImGui_ImplXXXX_Init(), ImGui_ImplXXXX_NewFrame(), ImGui::Render() and ImGui_ImplXXXX_Shutdown(). +// If you are new to ImGui, see examples/README.txt and documentation at the top of imgui.cpp. +// https://github.com/ocornut/imgui + +#include + +// cmdList is the command list that the implementation will use to render the +// GUI. +// +// Before calling ImGui::Render(), caller must prepare cmdList by resetting it +// and setting the appropriate render target and descriptor heap that contains +// fontSrv*puDescHandle. +// +// fontSrvCpuDescHandle and fontSrvGpuDescHandle are handles to a single SRV +// descriptor to use for the internal font texture. +IMGUI_API bool ImGui_ImplDX12_Init(void* hwnd, int numFramesInFlight, + ID3D12Device* device, ID3D12GraphicsCommandList* cmdList, + D3D12_CPU_DESCRIPTOR_HANDLE fontSrvCpuDescHandle, + D3D12_GPU_DESCRIPTOR_HANDLE fontSrvGpuDescHandle); +IMGUI_API void ImGui_ImplDX12_Shutdown(); +IMGUI_API void ImGui_ImplDX12_NewFrame(); + +// Use if you want to reset your rendering device without losing ImGui state. +IMGUI_API void ImGui_ImplDX12_InvalidateDeviceObjects(); +IMGUI_API bool ImGui_ImplDX12_CreateDeviceObjects(); + +// 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. +/* +IMGUI_API LRESULT ImGui_ImplDX12_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); +*/ diff --git a/examples/directx12_example/main.cpp b/examples/directx12_example/main.cpp new file mode 100644 index 000000000000..dbd822acf601 --- /dev/null +++ b/examples/directx12_example/main.cpp @@ -0,0 +1,418 @@ +// ImGui - standalone example application for DirectX 11 +// If you are new to ImGui, see examples/README.txt and documentation at the top of imgui.cpp. + +#include +#include +#include "imgui_impl_dx12.h" +#include +#include +#include + +struct FrameContext +{ + ID3D12CommandAllocator* CommandAllocator; + UINT64 FenceValue; + bool FenceSignalled; +}; + +// Data +static int const NUM_FRAMES_IN_FLIGHT = 3; +static FrameContext g_frameContext[NUM_FRAMES_IN_FLIGHT] = {}; +static UINT g_frameIndex = 0; + +static int const NUM_BACK_BUFFERS = 3; +static IDXGIFactory4* g_pdxgiFactory = NULL; +static ID3D12Device* g_pd3dDevice = NULL; +static ID3D12DescriptorHeap* g_pd3dRtvDescHeap = NULL; +static ID3D12DescriptorHeap* g_pd3dSrvDescHeap = NULL; +static ID3D12CommandQueue* g_pd3dCommandQueue = NULL; +static ID3D12GraphicsCommandList* g_pd3dCommandList = NULL; +static ID3D12Fence* g_fence = NULL; +static HANDLE g_fenceEvent = NULL; +static UINT64 g_fenceLastSignalledValue = 0; +static IDXGISwapChain3* g_pSwapChain = NULL; +static HANDLE g_hSwapChainWaitableObject = NULL; +static ID3D12Resource* g_mainRenderTargetResource[NUM_BACK_BUFFERS] = {}; +static D3D12_CPU_DESCRIPTOR_HANDLE g_mainRenderTargetDescriptor[NUM_BACK_BUFFERS] = {}; + +static void WaitForLastSubmittedFrame() +{ + FrameContext* frameCtxt = &g_frameContext[g_frameIndex % NUM_FRAMES_IN_FLIGHT]; + + UINT64 fenceValue = frameCtxt->FenceValue; + if (fenceValue == 0) { // means no fence was signalled + return; + } + + frameCtxt->FenceValue = 0; + if (g_fence->GetCompletedValue() >= fenceValue) { + return; + } + + HRESULT hr = g_fence->SetEventOnCompletion(fenceValue, g_fenceEvent); + assert(SUCCEEDED(hr)); + + WaitForSingleObject(g_fenceEvent, INFINITE); +} + +static FrameContext* WaitForNextFrameResources() +{ + UINT nextFrameIndex = g_frameIndex + 1; + g_frameIndex = nextFrameIndex; + + HANDLE waitableObjects[] = { + g_hSwapChainWaitableObject, + NULL, + }; + DWORD numWaitableObjects = 1; + + FrameContext* frameCtxt = &g_frameContext[nextFrameIndex % NUM_FRAMES_IN_FLIGHT]; + UINT64 fenceValue = frameCtxt->FenceValue; + if (fenceValue != 0) { // means no fence was signalled + frameCtxt->FenceValue = 0; + + HRESULT hr = g_fence->SetEventOnCompletion(fenceValue, g_fenceEvent); + assert(SUCCEEDED(hr)); + + waitableObjects[1] = g_fenceEvent; + numWaitableObjects = 2; + } + + HRESULT hr = WaitForMultipleObjects(numWaitableObjects, waitableObjects, TRUE, INFINITE); + assert(SUCCEEDED(hr)); + + return frameCtxt; +} + +void CreateRenderTarget(HWND hWnd, int width, int height) +{ + DXGI_SWAP_CHAIN_DESC1 desc = {}; + desc.Width = width; + desc.Height = height; + desc.Format = DXGI_FORMAT_B8G8R8A8_UNORM; + desc.Stereo = FALSE; + desc.SampleDesc.Count = 1; + desc.SampleDesc.Quality = 0; + desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; + desc.BufferCount = NUM_BACK_BUFFERS; + desc.Scaling = DXGI_SCALING_STRETCH; + desc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD; + desc.AlphaMode = DXGI_ALPHA_MODE_UNSPECIFIED; + desc.Flags = DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT; + + IDXGISwapChain1* swapChain1 = NULL; + HRESULT hr = g_pdxgiFactory->CreateSwapChainForHwnd(g_pd3dCommandQueue, hWnd, &desc, NULL, NULL, &swapChain1); + assert(SUCCEEDED(hr)); + + hr = swapChain1->QueryInterface(IID_PPV_ARGS(&g_pSwapChain)); + assert(SUCCEEDED(hr)); + + swapChain1->Release(); + + hr = g_pSwapChain->SetMaximumFrameLatency(NUM_BACK_BUFFERS); + assert(SUCCEEDED(hr)); + + g_hSwapChainWaitableObject = g_pSwapChain->GetFrameLatencyWaitableObject(); + assert(g_hSwapChainWaitableObject != NULL); + + for (UINT i = 0; i < NUM_BACK_BUFFERS; ++i) + { + hr = g_pSwapChain->GetBuffer(i, IID_PPV_ARGS(&g_mainRenderTargetResource[i])); + assert(SUCCEEDED(hr)); + + g_pd3dDevice->CreateRenderTargetView(g_mainRenderTargetResource[i], NULL, g_mainRenderTargetDescriptor[i]); + } +} + +void CleanupRenderTarget() +{ + WaitForLastSubmittedFrame(); + + if (g_pSwapChain) { g_pSwapChain->Release(); g_pSwapChain = NULL; } + for (UINT i = 0; i < NUM_BACK_BUFFERS; ++i) + { + if (g_mainRenderTargetResource[i]) { g_mainRenderTargetResource[i]->Release(); g_mainRenderTargetResource[i] = NULL; } + } + if (g_hSwapChainWaitableObject != NULL) { CloseHandle(g_hSwapChainWaitableObject); } +} + +HRESULT CreateDeviceD3D(HWND hWnd) +{ + (void) hWnd; + +#ifdef _DEBUG + { + ID3D12Debug* debugController = NULL; + if (SUCCEEDED(D3D12GetDebugInterface(IID_PPV_ARGS(&debugController)))) + { + debugController->EnableDebugLayer(); + debugController->Release(); + } + } +#endif + + if (CreateDXGIFactory1(IID_PPV_ARGS(&g_pdxgiFactory)) != S_OK) + return E_FAIL; + + IDXGIAdapter1* adapter = NULL; + for (UINT adapterIndex = 0; DXGI_ERROR_NOT_FOUND != g_pdxgiFactory->EnumAdapters1(adapterIndex, &adapter); ++adapterIndex) + { + DXGI_ADAPTER_DESC1 desc = {}; + adapter->GetDesc1(&desc); + + if (desc.Flags & DXGI_ADAPTER_FLAG_SOFTWARE) + { + adapter->Release(); + continue; + } + + if (FAILED(D3D12CreateDevice(adapter, D3D_FEATURE_LEVEL_11_0, _uuidof(ID3D12Device), NULL))) + { + adapter->Release(); + continue; + } + + break; + } + + HRESULT hr = D3D12CreateDevice(adapter, D3D_FEATURE_LEVEL_11_0, IID_PPV_ARGS(&g_pd3dDevice)); + + if (adapter != NULL) + { + adapter->Release(); + } + + if (FAILED(hr)) + return hr; + + { + D3D12_DESCRIPTOR_HEAP_DESC desc = {}; + desc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_RTV; + desc.NumDescriptors = NUM_BACK_BUFFERS; + desc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE; + desc.NodeMask = 1; + if (g_pd3dDevice->CreateDescriptorHeap(&desc, IID_PPV_ARGS(&g_pd3dRtvDescHeap)) != S_OK) + return E_FAIL; + + SIZE_T rtvDescriptorSize = g_pd3dDevice->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_RTV); + D3D12_CPU_DESCRIPTOR_HANDLE rtvHandle = g_pd3dRtvDescHeap->GetCPUDescriptorHandleForHeapStart(); + for (UINT i = 0; i < NUM_BACK_BUFFERS; ++i) { + g_mainRenderTargetDescriptor[i] = rtvHandle; + rtvHandle.ptr += rtvDescriptorSize; + } + } + + { + D3D12_DESCRIPTOR_HEAP_DESC desc = {}; + desc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV; + desc.NumDescriptors = 1; + desc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE; + if (g_pd3dDevice->CreateDescriptorHeap(&desc, IID_PPV_ARGS(&g_pd3dSrvDescHeap)) != S_OK) + return E_FAIL; + } + + { + D3D12_COMMAND_QUEUE_DESC desc = {}; + desc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT; + desc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE; + desc.NodeMask = 1; + if (g_pd3dDevice->CreateCommandQueue(&desc, IID_PPV_ARGS(&g_pd3dCommandQueue)) != S_OK) + return E_FAIL; + } + + for (UINT i = 0; i < NUM_FRAMES_IN_FLIGHT; ++i) + { + if (g_pd3dDevice->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, IID_PPV_ARGS(&g_frameContext[i].CommandAllocator)) != S_OK) + return E_FAIL; + } + + if (g_pd3dDevice->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT, g_frameContext[0].CommandAllocator, NULL, IID_PPV_ARGS(&g_pd3dCommandList)) != S_OK || + g_pd3dCommandList->Close() != S_OK) + return E_FAIL; + + if (g_pd3dDevice->CreateFence(0, D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS(&g_fence)) != S_OK) + return E_FAIL; + + g_fenceEvent = CreateEvent(NULL, FALSE, FALSE, NULL); + if (g_fenceEvent == NULL) + return E_FAIL; + + return S_OK; +} + +void CleanupDeviceD3D() +{ + CleanupRenderTarget(); + for (UINT i = 0; i < NUM_FRAMES_IN_FLIGHT; ++i) + { + if (g_frameContext[i].CommandAllocator) { g_frameContext[i].CommandAllocator->Release(); g_frameContext[i].CommandAllocator = NULL; } + } + if (g_pd3dCommandQueue) { g_pd3dCommandQueue->Release(); g_pd3dCommandQueue = NULL; } + if (g_pd3dCommandList) { g_pd3dCommandList->Release(); g_pd3dCommandList = NULL; } + if (g_pd3dRtvDescHeap) { g_pd3dRtvDescHeap->Release(); g_pd3dRtvDescHeap = NULL; } + if (g_pd3dSrvDescHeap) { g_pd3dSrvDescHeap->Release(); g_pd3dSrvDescHeap = NULL; } + if (g_fence) { g_fence->Release(); g_fence = NULL; } + if (g_fenceEvent) { CloseHandle(g_fenceEvent); g_fenceEvent = NULL; } + if (g_pd3dDevice) { g_pd3dDevice->Release(); g_pd3dDevice = NULL; } + if (g_pdxgiFactory) { g_pdxgiFactory->Release(); g_pdxgiFactory = NULL; } +} + +extern LRESULT ImGui_ImplDX12_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); +LRESULT WINAPI WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + if (ImGui_ImplDX12_WndProcHandler(hWnd, msg, wParam, lParam)) + return true; + + switch (msg) + { + case WM_SIZE: + if (g_pd3dDevice != NULL && wParam != SIZE_MINIMIZED) + { + ImGui_ImplDX12_InvalidateDeviceObjects(); + CleanupRenderTarget(); + CreateRenderTarget(hWnd, (UINT)LOWORD(lParam), (UINT)HIWORD(lParam)); + ImGui_ImplDX12_CreateDeviceObjects(); + } + return 0; + case WM_SYSCOMMAND: + if ((wParam & 0xfff0) == SC_KEYMENU) // Disable ALT application menu + return 0; + break; + case WM_DESTROY: + PostQuitMessage(0); + return 0; + } + return DefWindowProc(hWnd, msg, wParam, lParam); +} + +int main(int, char**) +{ + // Create application window + WNDCLASSEX wc = { sizeof(WNDCLASSEX), CS_CLASSDC, WndProc, 0L, 0L, GetModuleHandle(NULL), NULL, LoadCursor(NULL, IDC_ARROW), NULL, NULL, _T("ImGui Example"), NULL }; + RegisterClassEx(&wc); + HWND hwnd = CreateWindow(_T("ImGui Example"), _T("ImGui DirectX12 Example"), WS_OVERLAPPEDWINDOW, 100, 100, 1280, 800, NULL, NULL, wc.hInstance, NULL); + + // Initialize Direct3D + if (CreateDeviceD3D(hwnd) < 0) + { + CleanupDeviceD3D(); + UnregisterClass(_T("ImGui Example"), wc.hInstance); + return 1; + } + + // Show the window + ShowWindow(hwnd, SW_SHOWDEFAULT); + UpdateWindow(hwnd); + + // Setup ImGui binding + ImGui_ImplDX12_Init(hwnd, NUM_FRAMES_IN_FLIGHT, g_pd3dDevice, g_pd3dCommandList, + g_pd3dSrvDescHeap->GetCPUDescriptorHandleForHeapStart(), + g_pd3dSrvDescHeap->GetGPUDescriptorHandleForHeapStart()); + + // Load Fonts + // (there is a default font, this is only if you want to change it. see extra_fonts/README.txt for more details) + //ImGuiIO& io = ImGui::GetIO(); + //io.Fonts->AddFontDefault(); + //io.Fonts->AddFontFromFileTTF("../../extra_fonts/Cousine-Regular.ttf", 15.0f); + //io.Fonts->AddFontFromFileTTF("../../extra_fonts/DroidSans.ttf", 16.0f); + //io.Fonts->AddFontFromFileTTF("../../extra_fonts/ProggyClean.ttf", 13.0f); + //io.Fonts->AddFontFromFileTTF("../../extra_fonts/ProggyTiny.ttf", 10.0f); + //io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf", 18.0f, NULL, io.Fonts->GetGlyphRangesJapanese()); + + bool show_test_window = true; + bool show_another_window = false; + ImVec4 clear_col = ImColor(114, 144, 154); + + // Main loop + MSG msg; + ZeroMemory(&msg, sizeof(msg)); + while (msg.message != WM_QUIT) + { + if (PeekMessage(&msg, NULL, 0U, 0U, PM_REMOVE)) + { + TranslateMessage(&msg); + DispatchMessage(&msg); + continue; + } + + // Wait for frame resources to be available + + ImGui_ImplDX12_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" + { + static float f = 0.0f; + ImGui::Text("Hello, world!"); + ImGui::SliderFloat("float", &f, 0.0f, 1.0f); + ImGui::ColorEdit3("clear color", (float*)&clear_col); + if (ImGui::Button("Test Window")) show_test_window ^= 1; + if (ImGui::Button("Another Window")) show_another_window ^= 1; + ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate); + } + + // 2. Show another simple window, this time using an explicit Begin/End pair + if (show_another_window) + { + ImGui::SetNextWindowSize(ImVec2(200,100), ImGuiSetCond_FirstUseEver); + ImGui::Begin("Another Window", &show_another_window); + ImGui::Text("Hello"); + ImGui::End(); + } + + // 3. Show the ImGui test window. Most of the sample code is in ImGui::ShowTestWindow() + if (show_test_window) + { + ImGui::SetNextWindowPos(ImVec2(650, 20), ImGuiSetCond_FirstUseEver); // 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); + } + + // Rendering + FrameContext* frameCtxt = WaitForNextFrameResources(); + UINT backBufferIdx = g_pSwapChain->GetCurrentBackBufferIndex(); + + HRESULT hr = frameCtxt->CommandAllocator->Reset(); + assert(SUCCEEDED(hr)); + + hr = g_pd3dCommandList->Reset(frameCtxt->CommandAllocator, NULL); + assert(SUCCEEDED(hr)); + + D3D12_RESOURCE_BARRIER barrier = {}; + barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION; + barrier.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE; + barrier.Transition.pResource = g_mainRenderTargetResource[backBufferIdx]; + barrier.Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES; + barrier.Transition.StateBefore = D3D12_RESOURCE_STATE_PRESENT; + barrier.Transition.StateAfter = D3D12_RESOURCE_STATE_RENDER_TARGET; + g_pd3dCommandList->ResourceBarrier(1, &barrier); + + g_pd3dCommandList->ClearRenderTargetView(g_mainRenderTargetDescriptor[backBufferIdx], (float*)&clear_col, 0, NULL); + g_pd3dCommandList->OMSetRenderTargets(1, &g_mainRenderTargetDescriptor[backBufferIdx], FALSE, NULL); + g_pd3dCommandList->SetDescriptorHeaps(1, &g_pd3dSrvDescHeap); + ImGui::Render(); + + barrier.Transition.StateBefore = D3D12_RESOURCE_STATE_RENDER_TARGET; + barrier.Transition.StateAfter = D3D12_RESOURCE_STATE_PRESENT; + g_pd3dCommandList->ResourceBarrier(1, &barrier); + + hr = g_pd3dCommandList->Close(); + assert(SUCCEEDED(hr)); + + g_pd3dCommandQueue->ExecuteCommandLists(1, (ID3D12CommandList* const*) &g_pd3dCommandList); + + hr = g_pSwapChain->Present(1, 0); + assert(SUCCEEDED(hr)); + + auto fenceValue = g_fenceLastSignalledValue + 1; + hr = g_pd3dCommandQueue->Signal(g_fence, fenceValue); + assert(SUCCEEDED(hr)); + g_fenceLastSignalledValue = fenceValue; + frameCtxt->FenceValue = fenceValue; + } + + ImGui_ImplDX12_Shutdown(); + CleanupDeviceD3D(); + UnregisterClass(_T("ImGui Example"), wc.hInstance); + + return 0; +} diff --git a/examples/imgui_examples_msvc2010.sln b/examples/imgui_examples_msvc2010.sln index b7e6a2522d4c..200a38f5f3c7 100644 --- a/examples/imgui_examples_msvc2010.sln +++ b/examples/imgui_examples_msvc2010.sln @@ -7,6 +7,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "directx9_example", "directx EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "directx11_example", "directx11_example\directx11_example.vcxproj", "{9F316E83-5AE5-4939-A723-305A94F48005}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "directx12_example", "directx12_example\directx12_example.vcxproj", "{B4CF9797-519D-4AFE-A8F4-5141A6B521D3}" +EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "opengl3_example", "opengl3_example\opengl3_example.vcxproj", "{4A1FB5EA-22F5-42A8-AB92-1D2DF5D47FB9}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "directx10_example", "directx10_example\directx10_example.vcxproj", "{345A953E-A004-4648-B442-DC5F9F11068C}" @@ -43,6 +45,14 @@ Global {9F316E83-5AE5-4939-A723-305A94F48005}.Release|Win32.Build.0 = Release|Win32 {9F316E83-5AE5-4939-A723-305A94F48005}.Release|x64.ActiveCfg = Release|x64 {9F316E83-5AE5-4939-A723-305A94F48005}.Release|x64.Build.0 = Release|x64 + {B4CF9797-519D-4AFE-A8F4-5141A6B521D3}.Debug|Win32.ActiveCfg = Debug|Win32 + {B4CF9797-519D-4AFE-A8F4-5141A6B521D3}.Debug|Win32.Build.0 = Debug|Win32 + {B4CF9797-519D-4AFE-A8F4-5141A6B521D3}.Debug|x64.ActiveCfg = Debug|x64 + {B4CF9797-519D-4AFE-A8F4-5141A6B521D3}.Debug|x64.Build.0 = Debug|x64 + {B4CF9797-519D-4AFE-A8F4-5141A6B521D3}.Release|Win32.ActiveCfg = Release|Win32 + {B4CF9797-519D-4AFE-A8F4-5141A6B521D3}.Release|Win32.Build.0 = Release|Win32 + {B4CF9797-519D-4AFE-A8F4-5141A6B521D3}.Release|x64.ActiveCfg = Release|x64 + {B4CF9797-519D-4AFE-A8F4-5141A6B521D3}.Release|x64.Build.0 = Release|x64 {4A1FB5EA-22F5-42A8-AB92-1D2DF5D47FB9}.Debug|Win32.ActiveCfg = Debug|Win32 {4A1FB5EA-22F5-42A8-AB92-1D2DF5D47FB9}.Debug|Win32.Build.0 = Debug|Win32 {4A1FB5EA-22F5-42A8-AB92-1D2DF5D47FB9}.Debug|x64.ActiveCfg = Debug|x64 From 9f92cc255bbc9a922211806e6ea50e4c5ab91cb7 Mon Sep 17 00:00:00 2001 From: ocornut Date: Sat, 16 Jul 2016 10:36:09 +0200 Subject: [PATCH 002/823] SetActiveId() sets ActiveIdIsJustActivated only when id changes. (#323) --- imgui.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/imgui.cpp b/imgui.cpp index 19b4453609fd..b8a6fe9c92bb 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1803,9 +1803,9 @@ ImGuiWindow* ImGui::GetParentWindow() void ImGui::SetActiveID(ImGuiID id, ImGuiWindow* window = NULL) { ImGuiContext& g = *GImGui; + g.ActiveIdIsJustActivated = (g.ActiveId != id); g.ActiveId = id; g.ActiveIdAllowOverlap = false; - g.ActiveIdIsJustActivated = true; g.ActiveIdWindow = window; } From bbd3b7560922fe3ff68cf418ed7ada7370a31c79 Mon Sep 17 00:00:00 2001 From: ocornut Date: Sat, 16 Jul 2016 10:46:22 +0200 Subject: [PATCH 003/823] Added IsKeyPressed() with explicit repeat delay and repeat rate (for usage by nav) (#323) --- imgui.cpp | 34 ++++++++++++++++++++++++---------- imgui.h | 1 + 2 files changed, 25 insertions(+), 10 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index b8a6fe9c92bb..a8f70f32e378 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -652,6 +652,7 @@ static void LogRenderedText(const ImVec2& ref_pos, const char* text, static void PushMultiItemsWidths(int components, float w_full = 0.0f); static float GetDraggedColumnOffset(int column_index); +static bool IsKeyDownMap(ImGuiKey key); static bool IsKeyPressedMap(ImGuiKey key, bool repeat = true); static void SetCurrentFont(ImFont* font); @@ -3065,10 +3066,16 @@ bool ImGui::IsPosHoveringAnyWindow(const ImVec2& pos) return FindHoveredWindow(pos, false) != NULL; } +static bool IsKeyDownMap(ImGuiKey key) +{ + const int key_index = GImGui->IO.KeyMap[key]; + return (key_index >= 0) ? ImGui::IsKeyDown(key_index) : false; +} + static bool IsKeyPressedMap(ImGuiKey key, bool repeat) { const int key_index = GImGui->IO.KeyMap[key]; - return ImGui::IsKeyPressed(key_index, repeat); + return (key_index >= 0) ? ImGui::IsKeyPressed(key_index, repeat) : false; } int ImGui::GetKeyIndex(ImGuiKey key) @@ -3084,7 +3091,7 @@ bool ImGui::IsKeyDown(int key_index) return GImGui->IO.KeysDown[key_index]; } -bool ImGui::IsKeyPressed(int key_index, bool repeat) +bool ImGui::IsKeyPressed(int key_index, float repeat_delay, float repeat_rate) { ImGuiContext& g = *GImGui; if (key_index < 0) return false; @@ -3092,16 +3099,23 @@ bool ImGui::IsKeyPressed(int key_index, bool repeat) const float t = g.IO.KeysDownDuration[key_index]; if (t == 0.0f) return true; - - if (repeat && t > g.IO.KeyRepeatDelay) - { - float delay = g.IO.KeyRepeatDelay, rate = g.IO.KeyRepeatRate; - if ((fmodf(t - delay, rate) > rate*0.5f) != (fmodf(t - delay - g.IO.DeltaTime, rate) > rate*0.5f)) + + if (t > repeat_delay && repeat_rate > 0.0f) + if ((fmodf(t - repeat_delay, repeat_rate) > repeat_rate*0.5f) != (fmodf(t - repeat_delay - g.IO.DeltaTime, repeat_rate) > repeat_rate*0.5f)) return true; - } + return false; } +bool ImGui::IsKeyPressed(int key_index, bool repeat) +{ + ImGuiContext& g = *GImGui; + if (repeat) + return IsKeyPressed(key_index, g.IO.KeyRepeatDelay, g.IO.KeyRepeatRate); + else + return IsKeyPressed(key_index, 0.0f, 0.0f); +} + bool ImGui::IsKeyReleased(int key_index) { ImGuiContext& g = *GImGui; @@ -9725,8 +9739,8 @@ void ImGui::ShowMetricsWindow(bool* p_open) ImGui::Text("FocusedWindow: '%s'", g.FocusedWindow ? g.FocusedWindow->Name : "NULL"); ImGui::Text("HoveredWindow: '%s'", g.HoveredWindow ? g.HoveredWindow->Name : "NULL"); ImGui::Text("HoveredRootWindow: '%s'", g.HoveredRootWindow ? g.HoveredRootWindow->Name : "NULL"); - ImGui::Text("HoveredID: 0x%08X/0x%08X", g.HoveredId, g.HoveredIdPreviousFrame); // Data is "in-flight" so depending on when the Metrics window is called we may see current frame information or not - ImGui::Text("ActiveID: 0x%08X/0x%08X", g.ActiveId, g.ActiveIdPreviousFrame); + ImGui::Text("HoveredId: 0x%08X/0x%08X", g.HoveredId, g.HoveredIdPreviousFrame); // Data is "in-flight" so depending on when the Metrics window is called we may see current frame information or not + ImGui::Text("ActiveId: 0x%08X/0x%08X", g.ActiveId, g.ActiveIdPreviousFrame); ImGui::TreePop(); } } diff --git a/imgui.h b/imgui.h index dffb50604931..c4b8c35fa39d 100644 --- a/imgui.h +++ b/imgui.h @@ -430,6 +430,7 @@ namespace ImGui IMGUI_API int GetKeyIndex(ImGuiKey key); // map ImGuiKey_* values into user's key index. == io.KeyMap[key] IMGUI_API bool IsKeyDown(int key_index); // key_index into the keys_down[] array, imgui doesn't know the semantic of each entry, uses your own indices! IMGUI_API bool IsKeyPressed(int key_index, bool repeat = true); // uses user's key indices as stored in the keys_down[] array. if repeat=true. uses io.KeyRepeatDelay / KeyRepeatRate + IMGUI_API bool IsKeyPressed(int key_index, float repeat_delay, float repeat_rate); // uses user's key indices as stored in the keys_down[] array. uses provided repeat rate/delay IMGUI_API bool IsKeyReleased(int key_index); // " IMGUI_API bool IsMouseDown(int button); // is mouse button held IMGUI_API bool IsMouseClicked(int button, bool repeat = false); // did mouse button clicked (went from !Down to Down) From 91e1c56da614ac635fcc61b5a9e37e270c814f21 Mon Sep 17 00:00:00 2001 From: ocornut Date: Sat, 16 Jul 2016 10:46:51 +0200 Subject: [PATCH 004/823] Minor bits. --- imgui.cpp | 4 +--- imgui_demo.cpp | 2 +- imgui_internal.h | 2 +- 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index a8f70f32e378..e2952a280c64 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -4488,10 +4488,8 @@ void ImGui::FocusWindow(ImGuiWindow* window) { ImGuiContext& g = *GImGui; - // Always mark the window we passed as focused. This is used for keyboard interactions such as tabbing. - g.FocusedWindow = window; - // Passing NULL allow to disable keyboard focus + g.FocusedWindow = window; if (!window) return; diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 67846e7ab1b9..20337f388f1d 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -784,7 +784,7 @@ void ImGui::ShowTestWindow(bool* p_open) struct Funcs { static float Sin(void*, int i) { return sinf(i * 0.1f); } - static float Saw(void*, int i) { return (i & 1) ? 1.0f : 0.0f; } + static float Saw(void*, int i) { return (i & 1) ? 1.0f : -1.0f; } }; static int func_type = 0, display_count = 70; ImGui::Separator(); diff --git a/imgui_internal.h b/imgui_internal.h index 4dfa64791921..21a345bf1a16 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -482,7 +482,7 @@ struct ImGuiContext DragCurrentValue = 0.0f; DragLastMouseDelta = ImVec2(0.0f, 0.0f); DragSpeedDefaultRatio = 1.0f / 100.0f; - DragSpeedScaleSlow = 0.01f; + DragSpeedScaleSlow = 1.0f / 100.0f; DragSpeedScaleFast = 10.0f; ScrollbarClickDeltaToGrabCenter = ImVec2(0.0f, 0.0f); memset(Tooltip, 0, sizeof(Tooltip)); From 6f7da2f9f288ac20e5e7fdcb6aa5fefdd9571059 Mon Sep 17 00:00:00 2001 From: ocornut Date: Sat, 16 Jul 2016 10:50:14 +0200 Subject: [PATCH 005/823] Popup: Fixed popup initial frame reading MousePos again instead of the value already stored within the CurrentPopupStack in the previous frame. Doesn't make a big difference here, but will do as gamepad/keyboard navigation will set its own popup position. (#323) --- imgui.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/imgui.cpp b/imgui.cpp index e2952a280c64..b80a6999bd7e 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -3937,7 +3937,7 @@ bool ImGui::Begin(const char* name, bool* p_open, const ImVec2& size_on_first_us // Popup first latch mouse position, will position itself when it appears next frame window->AutoPosLastDirection = -1; if ((flags & ImGuiWindowFlags_Popup) != 0 && !window_pos_set_by_api) - window->PosFloat = g.IO.MousePos; + window->PosFloat = g.CurrentPopupStack.back().MousePosOnOpen; } // Collapse window by double-clicking on title bar From 57841f417d09c2c6b75bd9425c57173984f94db9 Mon Sep 17 00:00:00 2001 From: ocornut Date: Sat, 16 Jul 2016 11:06:30 +0200 Subject: [PATCH 006/823] SliderBehavior, RoundScalar: split into separate functions for usage in upcoming nav commits. Testing power==1.0f without fabsf(). Maybe just use == 1.0f as well? (#323) --- imgui.cpp | 56 ++++++++++++++++++++++++++++++------------------------- 1 file changed, 31 insertions(+), 25 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index b80a6999bd7e..a8e976c3a462 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -6360,13 +6360,18 @@ int ImGui::ParseFormatPrecision(const char* fmt, int default_precision) return precision; } +static float GetMinimumStepAtDecimalPrecision(int decimal_precision) +{ + static const float min_steps[10] = { 1.0f, 0.1f, 0.01f, 0.001f, 0.0001f, 0.00001f, 0.000001f, 0.0000001f, 0.00000001f, 0.000000001f }; + return (decimal_precision >= 0 && decimal_precision < 10) ? min_steps[decimal_precision] : powf(10.0f, (float)-decimal_precision); +} + float ImGui::RoundScalar(float value, int decimal_precision) { // Round past decimal precision // So when our value is 1.99999 with a precision of 0.001 we'll end up rounding to 2.0 // FIXME: Investigate better rounding methods - static const float min_steps[10] = { 1.0f, 0.1f, 0.01f, 0.001f, 0.0001f, 0.00001f, 0.000001f, 0.0000001f, 0.00000001f, 0.000000001f }; - float min_step = (decimal_precision >= 0 && decimal_precision < 10) ? min_steps[decimal_precision] : powf(10.0f, (float)-decimal_precision); + const float min_step = GetMinimumStepAtDecimalPrecision(decimal_precision); bool negative = value < 0.0f; value = fabsf(value); float remainder = fmodf(value, min_step); @@ -6377,6 +6382,28 @@ float ImGui::RoundScalar(float value, int decimal_precision) return negative ? -value : value; } +static inline float SliderBehaviorCalcRatioFromValue(float v, float v_min, float v_max, float power, float linear_zero_pos) +{ + const bool is_non_linear = (power < 1.0f-0.00001f) && (power > 1.0f-0.00001f); + if (is_non_linear) + { + float v_clamped = ImClamp(v, v_min, v_max); + if (v_clamped < 0.0f) + { + const float f = 1.0f - (v_clamped - v_min) / (ImMin(0.0f,v_max) - v_min); + return (1.0f - powf(f, 1.0f/power)) * linear_zero_pos; + } + else + { + const float f = (v_clamped - ImMax(0.0f,v_min)) / (v_max - ImMax(0.0f,v_min)); + return linear_zero_pos + powf(f, 1.0f/power) * (1.0f - linear_zero_pos); + } + } + + // Linear slider + return (ImClamp(v, v_min, v_max) - v_min) / (v_max - v_min); +} + bool ImGui::SliderBehavior(const ImRect& frame_bb, ImGuiID id, float* v, float v_min, float v_max, float power, int decimal_precision, ImGuiSliderFlags flags) { ImGuiContext& g = *GImGui; @@ -6386,7 +6413,7 @@ bool ImGui::SliderBehavior(const ImRect& frame_bb, ImGuiID id, float* v, float v // Draw frame RenderFrame(frame_bb.Min, frame_bb.Max, GetColorU32(ImGuiCol_FrameBg), true, style.FrameRounding); - const bool is_non_linear = fabsf(power - 1.0f) > 0.0001f; + const bool is_non_linear = (power < 1.0f-0.00001f) && (power > 1.0f-0.00001f); const bool is_horizontal = (flags & ImGuiSliderFlags_Vertical) == 0; const float grab_padding = 2.0f; @@ -6469,29 +6496,8 @@ bool ImGui::SliderBehavior(const ImRect& frame_bb, ImGuiID id, float* v, float v } } - // Calculate slider grab positioning - float grab_t; - if (is_non_linear) - { - float v_clamped = ImClamp(*v, v_min, v_max); - if (v_clamped < 0.0f) - { - const float f = 1.0f - (v_clamped - v_min) / (ImMin(0.0f,v_max) - v_min); - grab_t = (1.0f - powf(f, 1.0f/power)) * linear_zero_pos; - } - else - { - const float f = (v_clamped - ImMax(0.0f,v_min)) / (v_max - ImMax(0.0f,v_min)); - grab_t = linear_zero_pos + powf(f, 1.0f/power) * (1.0f - linear_zero_pos); - } - } - else - { - // Linear slider - grab_t = (ImClamp(*v, v_min, v_max) - v_min) / (v_max - v_min); - } - // Draw + float grab_t = SliderBehaviorCalcRatioFromValue(*v, v_min, v_max, power, linear_zero_pos); if (!is_horizontal) grab_t = 1.0f - grab_t; const float grab_pos = ImLerp(slider_usable_pos_min, slider_usable_pos_max, grab_t); From 848e62bfe0fe6083668afebdfaa5ab234a4817d9 Mon Sep 17 00:00:00 2001 From: ocornut Date: Sat, 16 Jul 2016 11:22:49 +0200 Subject: [PATCH 007/823] InputText: don't process keys during the activation frame (this is mostly a workaround to that activation with enter doesn't validate immediately, which is turns triggers an assert in InputScalarAsWidgetReplacement - can't see an issue with changing it this way so trying out) + using local flag clear_active_id to only clear the active id at the end of the frame, which is one of the step that my stash for #701 requires. (#323) --- imgui.cpp | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index a8e976c3a462..cd1261c6e57c 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -7663,6 +7663,7 @@ bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2 const bool user_clicked = hovered && io.MouseClicked[0]; const bool user_scrolled = is_multiline && g.ActiveId == 0 && edit_state.Id == id && g.ActiveIdPreviousFrame == draw_window->GetIDNoKeepAlive("#SCROLLY"); + bool clear_active_id = false; bool select_all = (g.ActiveId != id) && (flags & ImGuiInputTextFlags_AutoSelectAll) != 0; if (focus_requested || user_clicked || user_scrolled) { @@ -7708,8 +7709,7 @@ bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2 else if (io.MouseClicked[0]) { // Release focus when we click outside - if (g.ActiveId == id) - SetActiveID(0); + clear_active_id = true; } bool value_changed = false; @@ -7781,9 +7781,12 @@ bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2 // Consume characters memset(g.IO.InputCharacters, 0, sizeof(g.IO.InputCharacters)); } + } - // Handle various key-presses - bool cancel_edit = false; + bool cancel_edit = false; + if (g.ActiveId == id && !g.ActiveIdIsJustActivated) + { + // Handle key-presses const int k_mask = (is_shift_down ? STB_TEXTEDIT_K_SHIFT : 0); const bool is_shortcutkey_only = (io.ShortcutsUseSuperKey ? (is_super_down && !is_alt_down && !is_shift_down && !is_ctrl_down) : (is_ctrl_down && !is_alt_down && !is_shift_down && !is_super_down)); const bool is_wordmove_key_down = (io.WordMovementUsesAltKey ? io.KeyAlt : io.KeyCtrl); @@ -7800,10 +7803,7 @@ bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2 { bool ctrl_enter_for_new_line = (flags & ImGuiInputTextFlags_CtrlEnterForNewLine) != 0; if (!is_multiline || (ctrl_enter_for_new_line && !is_ctrl_down) || (!ctrl_enter_for_new_line && is_ctrl_down)) - { - SetActiveID(0); - enter_pressed = true; - } + enter_pressed = clear_active_id = true; else if (is_editable) { unsigned int c = '\n'; // Insert new line @@ -7817,7 +7817,7 @@ bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2 if (InputTextFilterCharacter(&c, flags, callback, user_data)) edit_state.OnKeyPressed((int)c); } - else if (IsKeyPressedMap(ImGuiKey_Escape)) { SetActiveID(0); cancel_edit = true; } + else if (IsKeyPressedMap(ImGuiKey_Escape)) { clear_active_id = cancel_edit = true; } else if (is_shortcutkey_only && IsKeyPressedMap(ImGuiKey_Z) && is_editable) { edit_state.OnKeyPressed(STB_TEXTEDIT_K_UNDO); edit_state.ClearSelection(); } else if (is_shortcutkey_only && IsKeyPressedMap(ImGuiKey_Y) && is_editable) { edit_state.OnKeyPressed(STB_TEXTEDIT_K_REDO); edit_state.ClearSelection(); } else if (is_shortcutkey_only && IsKeyPressedMap(ImGuiKey_A)) { edit_state.SelectAll(); edit_state.CursorFollow = true; } @@ -7874,7 +7874,10 @@ bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2 } } } + } + if (g.ActiveId == id) + { if (cancel_edit) { // Restore initial value @@ -7972,6 +7975,10 @@ bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2 } } + // Release active ID at the end of the function (so e.g. pressing Return still does a final application of the value) + if (clear_active_id && g.ActiveId == id) + SetActiveID(0); + // Render // Select which buffer we are going to display. When ImGuiInputTextFlags_NoLiveEdit is set 'buf' might still be the old value. We set buf to NULL to prevent accidental usage from now on. const char* buf_display = (g.ActiveId == id && is_editable) ? edit_state.TempTextBuffer.Data : buf; buf = NULL; From 272745bd93c573ca774d44f1a03a27984becc0d7 Mon Sep 17 00:00:00 2001 From: ocornut Date: Sun, 17 Jul 2016 10:26:48 +0200 Subject: [PATCH 008/823] ImGuiIO: initializing fields in the same order as the declaration. --- imgui.cpp | 39 ++++++++++++++++++++++----------------- 1 file changed, 22 insertions(+), 17 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index cd1261c6e57c..489c0c4ec035 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -798,29 +798,32 @@ ImGuiIO::ImGuiIO() // Most fields are initialized with zero memset(this, 0, sizeof(*this)); + // Settings DisplaySize = ImVec2(-1.0f, -1.0f); DeltaTime = 1.0f/60.0f; IniSavingRate = 5.0f; IniFilename = "imgui.ini"; LogFilename = "imgui_log.txt"; - Fonts = &GImDefaultFontAtlas; - FontGlobalScale = 1.0f; - DisplayFramebufferScale = ImVec2(1.0f, 1.0f); - MousePos = ImVec2(-1,-1); - MousePosPrev = ImVec2(-1,-1); MouseDoubleClickTime = 0.30f; MouseDoubleClickMaxDist = 6.0f; - MouseDragThreshold = 6.0f; - for (int i = 0; i < IM_ARRAYSIZE(MouseDownDuration); i++) - MouseDownDuration[i] = MouseDownDurationPrev[i] = -1.0f; - for (int i = 0; i < IM_ARRAYSIZE(KeysDownDuration); i++) - KeysDownDuration[i] = KeysDownDurationPrev[i] = -1.0f; for (int i = 0; i < ImGuiKey_COUNT; i++) KeyMap[i] = -1; KeyRepeatDelay = 0.250f; KeyRepeatRate = 0.050f; UserData = NULL; + Fonts = &GImDefaultFontAtlas; + FontGlobalScale = 1.0f; + FontAllowUserScaling = false; + DisplayFramebufferScale = ImVec2(1.0f, 1.0f); + DisplayVisibleMin = DisplayVisibleMax = ImVec2(0.0f, 0.0f); +#ifdef __APPLE__ + WordMovementUsesAltKey = true; // OS X style: Text editing cursor movement using Alt instead of Ctrl + ShortcutsUseSuperKey = true; // OS X style: Shortcuts using Cmd/Super instead of Ctrl + DoubleClickSelectsWord = true; // OS X style: Double click selects by word instead of selecting whole text + MultiSelectUsesSuperKey = true; // OS X style: Multi-selection in lists uses Cmd/Super instead of Ctrl +#endif + // User functions RenderDrawListsFn = NULL; MemAllocFn = malloc; @@ -828,14 +831,16 @@ ImGuiIO::ImGuiIO() GetClipboardTextFn = GetClipboardTextFn_DefaultImpl; // Platform dependent default implementations SetClipboardTextFn = SetClipboardTextFn_DefaultImpl; ImeSetInputScreenPosFn = ImeSetInputScreenPosFn_DefaultImpl; + ImeWindowHandle = NULL; - // Set OS X style defaults based on __APPLE__ compile time flag -#ifdef __APPLE__ - WordMovementUsesAltKey = true; // OS X style: Text editing cursor movement using Alt instead of Ctrl - ShortcutsUseSuperKey = true; // OS X style: Shortcuts using Cmd/Super instead of Ctrl - DoubleClickSelectsWord = true; // OS X style: Double click selects by word instead of selecting whole text - MultiSelectUsesSuperKey = true; // OS X style: Multi-selection in lists uses Cmd/Super instead of Ctrl -#endif + // Input (NB: we already have memset zero the entire structure) + MousePos = ImVec2(-1,-1); + MousePosPrev = ImVec2(-1,-1); + MouseDragThreshold = 6.0f; + for (int i = 0; i < IM_ARRAYSIZE(MouseDownDuration); i++) + MouseDownDuration[i] = MouseDownDurationPrev[i] = -1.0f; + for (int i = 0; i < IM_ARRAYSIZE(KeysDownDuration); i++) + KeysDownDuration[i] = KeysDownDurationPrev[i] = -1.0f; } // Pass in translated ASCII characters for text input. From 267e54cf065abc98532190a1899b2ded971d0394 Mon Sep 17 00:00:00 2001 From: ocornut Date: Sun, 17 Jul 2016 10:35:17 +0200 Subject: [PATCH 009/823] NewFrame(): update activeid data and keyboard before mouse. Should have no side-effects! (So that later we can update Nav between Keyboard and Mouse) (#323) --- imgui.cpp | 33 +++++++++++++++++---------------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 489c0c4ec035..f4eb8d327630 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2095,7 +2095,22 @@ void ImGui::NewFrame() g.RenderDrawData.CmdLists = NULL; g.RenderDrawData.CmdListsCount = g.RenderDrawData.TotalVtxCount = g.RenderDrawData.TotalIdxCount = 0; - // Update inputs state + // Clear reference to active widget if the widget isn't alive anymore + g.HoveredIdPreviousFrame = g.HoveredId; + g.HoveredId = 0; + g.HoveredIdAllowOverlap = false; + if (!g.ActiveIdIsAlive && g.ActiveIdPreviousFrame == g.ActiveId && g.ActiveId != 0) + SetActiveID(0); + g.ActiveIdPreviousFrame = g.ActiveId; + g.ActiveIdIsAlive = false; + g.ActiveIdIsJustActivated = false; + + // Update keyboard input state + memcpy(g.IO.KeysDownDurationPrev, g.IO.KeysDownDuration, sizeof(g.IO.KeysDownDuration)); + for (int i = 0; i < IM_ARRAYSIZE(g.IO.KeysDown); i++) + g.IO.KeysDownDuration[i] = g.IO.KeysDown[i] ? (g.IO.KeysDownDuration[i] < 0.0f ? 0.0f : g.IO.KeysDownDuration[i] + g.IO.DeltaTime) : -1.0f; + + // Update mouse input state if (g.IO.MousePos.x < 0 && g.IO.MousePos.y < 0) g.IO.MousePos = ImVec2(-9999.0f, -9999.0f); if ((g.IO.MousePos.x < 0 && g.IO.MousePos.y < 0) || (g.IO.MousePosPrev.x < 0 && g.IO.MousePosPrev.y < 0)) // if mouse just appeared or disappeared (negative coordinate) we cancel out movement in MouseDelta @@ -2130,9 +2145,6 @@ void ImGui::NewFrame() g.IO.MouseDragMaxDistanceSqr[i] = ImMax(g.IO.MouseDragMaxDistanceSqr[i], ImLengthSqr(g.IO.MousePos - g.IO.MouseClickedPos[i])); } } - memcpy(g.IO.KeysDownDurationPrev, g.IO.KeysDownDuration, sizeof(g.IO.KeysDownDuration)); - for (int i = 0; i < IM_ARRAYSIZE(g.IO.KeysDown); i++) - g.IO.KeysDownDuration[i] = g.IO.KeysDown[i] ? (g.IO.KeysDownDuration[i] < 0.0f ? 0.0f : g.IO.KeysDownDuration[i] + g.IO.DeltaTime) : -1.0f; // Calculate frame-rate for the user, as a purely luxurious feature g.FramerateSecPerFrameAccum += g.IO.DeltaTime - g.FramerateSecPerFrame[g.FramerateSecPerFrameIdx]; @@ -2140,16 +2152,6 @@ void ImGui::NewFrame() g.FramerateSecPerFrameIdx = (g.FramerateSecPerFrameIdx + 1) % IM_ARRAYSIZE(g.FramerateSecPerFrame); g.IO.Framerate = 1.0f / (g.FramerateSecPerFrameAccum / (float)IM_ARRAYSIZE(g.FramerateSecPerFrame)); - // Clear reference to active widget if the widget isn't alive anymore - g.HoveredIdPreviousFrame = g.HoveredId; - g.HoveredId = 0; - g.HoveredIdAllowOverlap = false; - if (!g.ActiveIdIsAlive && g.ActiveIdPreviousFrame == g.ActiveId && g.ActiveId != 0) - SetActiveID(0); - g.ActiveIdPreviousFrame = g.ActiveId; - g.ActiveIdIsAlive = false; - g.ActiveIdIsJustActivated = false; - // Handle user moving window (at the beginning of the frame to avoid input lag or sheering). Only valid for root windows. if (g.MovedWindowMoveId && g.MovedWindowMoveId == g.ActiveId) { @@ -3276,8 +3278,7 @@ bool ImGui::IsAnyItemActive() bool ImGui::IsItemVisible() { ImGuiWindow* window = GetCurrentWindowRead(); - ImRect r(window->ClipRect); - return r.Overlaps(window->DC.LastItemRect); + return window->ClipRect.Overlaps(window->DC.LastItemRect); } // Allow last item to be overlapped by a subsequent item. Both may be activated during the same frame before the later one takes priority. From 068984691e11e1200ed5a908e17b6e1d7b99ee5f Mon Sep 17 00:00:00 2001 From: ocornut Date: Sun, 17 Jul 2016 12:53:11 +0200 Subject: [PATCH 010/823] Tab-key focusing inhibited when CTRL is held (#323) --- imgui.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index f4eb8d327630..1ccca0ac7f7e 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1923,7 +1923,7 @@ bool ImGui::FocusableItemRegister(ImGuiWindow* window, bool is_active, bool tab_ // Process keyboard input at this point: TAB, Shift-TAB switch focus // We can always TAB out of a widget that doesn't allow tabbing in. - if (tab_stop && window->FocusIdxAllRequestNext == INT_MAX && window->FocusIdxTabRequestNext == INT_MAX && is_active && IsKeyPressedMap(ImGuiKey_Tab)) + if (tab_stop && window->FocusIdxAllRequestNext == INT_MAX && window->FocusIdxTabRequestNext == INT_MAX && is_active && !g.IO.KeyCtrl && IsKeyPressedMap(ImGuiKey_Tab)) { // Modulo on index will be applied at the end of frame once we've got the total counter of items. window->FocusIdxTabRequestNext = window->FocusIdxTabCounter + (g.IO.KeyShift ? (allow_keyboard_focus ? -1 : 0) : +1); @@ -2268,7 +2268,7 @@ void ImGui::NewFrame() // Pressing TAB activate widget focus // NB: Don't discard FocusedWindow if it isn't active, so that a window that go on/off programatically won't lose its keyboard focus. - if (g.ActiveId == 0 && g.FocusedWindow != NULL && g.FocusedWindow->Active && IsKeyPressedMap(ImGuiKey_Tab, false)) + if (g.ActiveId == 0 && g.FocusedWindow != NULL && g.FocusedWindow->Active && !g.IO.KeyCtrl && IsKeyPressedMap(ImGuiKey_Tab, false)) g.FocusedWindow->FocusIdxTabRequestNext = 0; // Mark all windows as not visible From 2df229d0021436fef3dee8f0cd32f5853c4b0985 Mon Sep 17 00:00:00 2001 From: ocornut Date: Sun, 17 Jul 2016 14:26:01 +0200 Subject: [PATCH 011/823] Fixed incorrect comment for ParentWindow (#615, #604) --- imgui_internal.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/imgui_internal.h b/imgui_internal.h index 21a345bf1a16..2568aaaa39dd 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -367,7 +367,7 @@ struct ImGuiContext ImGuiID HoveredIdPreviousFrame; ImGuiID ActiveId; // Active widget ImGuiID ActiveIdPreviousFrame; - bool ActiveIdIsAlive; + bool ActiveIdIsAlive; // Active widget has been seen this frame bool ActiveIdIsJustActivated; // Set at the time of activation for one frame bool ActiveIdAllowOverlap; // Set only by active widget ImVec2 ActiveIdClickOffset; // Clicked offset from upper-left corner, if applicable (currently only set by ButtonBehavior) @@ -641,7 +641,7 @@ struct IMGUI_API ImGuiWindow ImDrawList* DrawList; ImGuiWindow* RootWindow; // If we are a child window, this is pointing to the first non-child parent window. Else point to ourself. ImGuiWindow* RootNonPopupWindow; // If we are a child window, this is pointing to the first non-child non-popup parent window. Else point to ourself. - ImGuiWindow* ParentWindow; // If we are a child window, this is pointing to our parent window. Else point to NULL. + ImGuiWindow* ParentWindow; // Immediate parent in the window stack *regardless* of whether this window is a child window or not) // Navigation / Focus int FocusIdxAllCounter; // Start at -1 and increase as assigned via FocusItemRegister() From 0300e73b3f07445e1e6bd154dedfad60f7aaf585 Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 18 Jul 2016 13:03:47 +0200 Subject: [PATCH 012/823] Comments --- imgui.h | 12 ++++++------ imgui_internal.h | 8 ++++---- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/imgui.h b/imgui.h index c4b8c35fa39d..19eae6a10e89 100644 --- a/imgui.h +++ b/imgui.h @@ -393,11 +393,11 @@ namespace ImGui IMGUI_API void PopClipRect(); // Utilities - IMGUI_API bool IsItemHovered(); // was the last item hovered by mouse? - IMGUI_API bool IsItemHoveredRect(); // was the last item hovered by mouse? even if another item is active or window is blocked by popup while we are hovering this - IMGUI_API bool IsItemActive(); // was the last item active? (e.g. button being held, text field being edited- items that don't interact will always return false) - IMGUI_API bool IsItemClicked(int mouse_button = 0); // was the last item clicked? (e.g. button/node just clicked on) - IMGUI_API bool IsItemVisible(); // was the last item visible? (aka not out of sight due to clipping/scrolling.) + IMGUI_API bool IsItemHovered(); // is the last item hovered by mouse? + IMGUI_API bool IsItemHoveredRect(); // is the last item hovered by mouse? even if another item is active or window is blocked by popup while we are hovering this + IMGUI_API bool IsItemActive(); // is the last item active? (e.g. button being held, text field being edited- items that don't interact will always return false) + IMGUI_API bool IsItemClicked(int mouse_button = 0); // is the last item clicked? (e.g. button/node just clicked on) + IMGUI_API bool IsItemVisible(); // is the last item visible? (aka not out of sight due to clipping/scrolling.) IMGUI_API bool IsAnyItemHovered(); IMGUI_API bool IsAnyItemActive(); IMGUI_API ImVec2 GetItemRectMin(); // get bounding rect of last item in screen space @@ -812,7 +812,7 @@ struct ImGuiIO bool WantCaptureMouse; // Mouse is hovering a window or widget is active (= ImGui will use your mouse input) bool WantCaptureKeyboard; // Widget is active (= ImGui will use your keyboard input) - bool WantTextInput; // Some text input widget is active, which will read input characters from the InputCharacters array. + bool WantTextInput; // Text input widget is active, which will read input characters from the InputCharacters array. float Framerate; // Framerate estimation, in frame per second. Rolling average estimation based on IO.DeltaTime over 120 frames int MetricsAllocs; // Number of active memory allocations int MetricsRenderVertices; // Vertices output during last call to Render() diff --git a/imgui_internal.h b/imgui_internal.h index 2568aaaa39dd..577993dc49c1 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -347,8 +347,8 @@ struct ImGuiContext ImGuiIO IO; ImGuiStyle Style; ImFont* Font; // (Shortcut) == FontStack.empty() ? IO.Font : FontStack.back() - float FontSize; // (Shortcut) == FontBaseSize * g.CurrentWindow->FontWindowScale == window->FontSize() - float FontBaseSize; // (Shortcut) == IO.FontGlobalScale * Font->Scale * Font->FontSize. Size of characters. + float FontSize; // (Shortcut) == FontBaseSize * g.CurrentWindow->FontWindowScale == window->FontSize(). Text height for current window. + float FontBaseSize; // (Shortcut) == IO.FontGlobalScale * Font->Scale * Font->FontSize. Base text height. ImVec2 FontTexUvWhitePixel; // (Shortcut) == Font->TexUvWhitePixel float Time; @@ -357,8 +357,8 @@ struct ImGuiContext int FrameCountRendered; ImVector Windows; ImVector WindowsSortBuffer; - ImGuiWindow* CurrentWindow; // Being drawn into ImVector CurrentWindowStack; + ImGuiWindow* CurrentWindow; // Being drawn into ImGuiWindow* FocusedWindow; // Will catch keyboard inputs ImGuiWindow* HoveredWindow; // Will catch mouse inputs ImGuiWindow* HoveredRootWindow; // Will catch mouse inputs (for focus/move only) @@ -369,7 +369,7 @@ struct ImGuiContext ImGuiID ActiveIdPreviousFrame; bool ActiveIdIsAlive; // Active widget has been seen this frame bool ActiveIdIsJustActivated; // Set at the time of activation for one frame - bool ActiveIdAllowOverlap; // Set only by active widget + bool ActiveIdAllowOverlap; // Active widget allows another widget to steal active id (generally for overlapping widgets, but not always) ImVec2 ActiveIdClickOffset; // Clicked offset from upper-left corner, if applicable (currently only set by ButtonBehavior) ImGuiWindow* ActiveIdWindow; ImGuiWindow* MovedWindow; // Track the child window we clicked on to move a window. From e72e3b2cbc1aebb7fc7fcbb20e1a264322f3e104 Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 18 Jul 2016 14:31:15 +0200 Subject: [PATCH 013/823] Demo: tweaks. --- imgui_demo.cpp | 42 ++++++++++++++++++++++++++---------------- 1 file changed, 26 insertions(+), 16 deletions(-) diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 20337f388f1d..3862e6280bd1 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -67,11 +67,17 @@ static void ShowExampleAppCustomRendering(bool* p_open); static void ShowExampleAppMainMenuBar(); static void ShowExampleMenuFile(); -static void ShowHelpMarker(const char* desc) +static void ShowHelpMarker(const char* desc, float wrap_width = 450.0f) { ImGui::TextDisabled("(?)"); if (ImGui::IsItemHovered()) - ImGui::SetTooltip(desc); + { + ImGui::BeginTooltip(); + ImGui::PushTextWrapPos(wrap_width); + ImGui::TextUnformatted(desc); + ImGui::PopTextWrapPos(); + ImGui::EndTooltip(); + } } void ImGui::ShowUserGuide() @@ -850,7 +856,8 @@ void ImGui::ShowTestWindow(bool* p_open) ImGui::NextColumn(); char buf[32]; sprintf(buf, "%08x", i*5731); - ImGui::Button(buf, ImVec2(-1.0f, 0.0f)); + if (ImGui::Button(buf, ImVec2(-1.0f, 0.0f))) + printf("Pressed '%s'\n", buf); } ImGui::EndChild(); ImGui::PopStyleVar(); @@ -1299,13 +1306,15 @@ void ImGui::ShowTestWindow(bool* p_open) ImGui::OpenPopup("Stacked 1"); if (ImGui::BeginPopupModal("Stacked 1")) { - ImGui::Text("Hello from Stacked The First"); + ImGui::Text("Hello from Stacked The First\nUsing style.Colors[ImGuiCol_ModalWindowDarkening] for darkening."); + static int item = 1; + ImGui::Combo("Combo", &item, "aaaa\0bbbb\0cccc\0dddd\0eeee\0\0"); - if (ImGui::Button("Another one..")) + if (ImGui::Button("Add another modal..")) ImGui::OpenPopup("Stacked 2"); if (ImGui::BeginPopupModal("Stacked 2")) { - ImGui::Text("Hello from Stacked The Second"); + ImGui::Text("Hello from Stacked The Second!\nWe are piling a modal over another here,\nand also testing if the menu-bar works."); if (ImGui::Button("Close")) ImGui::CloseCurrentPopup(); ImGui::EndPopup(); @@ -1458,7 +1467,7 @@ void ImGui::ShowTestWindow(bool* p_open) } bool node_open = ImGui::TreeNode("Tree within single cell"); - ImGui::SameLine(); ShowHelpMarker("NB: Tree node must be poped before ending the cell.\nThere's no storage of state per-cell."); + ImGui::SameLine(); ShowHelpMarker("NB: Tree node must be poped before ending the cell. There's no storage of state per-cell."); if (node_open) { ImGui::Columns(2, "tree items"); @@ -1488,6 +1497,10 @@ void ImGui::ShowTestWindow(bool* p_open) if (ImGui::CollapsingHeader("Keyboard, Mouse & Focus")) { + ImGuiIO& io = ImGui::GetIO(); + ImGui::Checkbox("io.MouseDrawCursor", &io.MouseDrawCursor); + ImGui::SameLine(); ShowHelpMarker("Request ImGui to render a mouse cursor for you in software. Note that a mouse cursor rendered via regular GPU rendering will feel more laggy than hardware cursor, but will be more in sync with your other visuals."); + if (ImGui::TreeNode("Tabbing")) { ImGui::Text("Use TAB/SHIFT+TAB to cycle through keyboard editable fields."); @@ -1541,11 +1554,11 @@ void ImGui::ShowTestWindow(bool* p_open) // Draw a line between the button and the mouse cursor ImDrawList* draw_list = ImGui::GetWindowDrawList(); draw_list->PushClipRectFullScreen(); - draw_list->AddLine(ImGui::CalcItemRectClosestPoint(ImGui::GetIO().MousePos, true, -2.0f), ImGui::GetIO().MousePos, ImColor(ImGui::GetStyle().Colors[ImGuiCol_Button]), 4.0f); + draw_list->AddLine(ImGui::CalcItemRectClosestPoint(io.MousePos, true, -2.0f), io.MousePos, ImColor(ImGui::GetStyle().Colors[ImGuiCol_Button]), 4.0f); draw_list->PopClipRect(); ImVec2 value_raw = ImGui::GetMouseDragDelta(0, 0.0f); ImVec2 value_with_lock_threshold = ImGui::GetMouseDragDelta(0); - ImVec2 mouse_delta = ImGui::GetIO().MouseDelta; + ImVec2 mouse_delta = io.MouseDelta; ImGui::SameLine(); ImGui::Text("Raw (%.1f, %.1f), WithLockThresold (%.1f, %.1f), MouseDelta (%.1f, %.1f)", value_raw.x, value_raw.y, value_with_lock_threshold.x, value_with_lock_threshold.y, mouse_delta.x, mouse_delta.y); } ImGui::TreePop(); @@ -1553,8 +1566,6 @@ void ImGui::ShowTestWindow(bool* p_open) if (ImGui::TreeNode("Keyboard & Mouse State")) { - ImGuiIO& io = ImGui::GetIO(); - ImGui::Text("MousePos: (%g, %g)", io.MousePos.x, io.MousePos.y); ImGui::Text("Mouse down:"); for (int i = 0; i < IM_ARRAYSIZE(io.MouseDown); i++) if (io.MouseDownDuration[i] >= 0.0f) { ImGui::SameLine(); ImGui::Text("b%d (%.02f secs)", i, io.MouseDownDuration[i]); } ImGui::Text("Mouse clicked:"); for (int i = 0; i < IM_ARRAYSIZE(io.MouseDown); i++) if (ImGui::IsMouseClicked(i)) { ImGui::SameLine(); ImGui::Text("b%d", i); } @@ -1567,9 +1578,9 @@ void ImGui::ShowTestWindow(bool* p_open) ImGui::Text("Keys release:"); for (int i = 0; i < IM_ARRAYSIZE(io.KeysDown); i++) if (ImGui::IsKeyReleased(i)) { ImGui::SameLine(); ImGui::Text("%d", i); } ImGui::Text("KeyMods: %s%s%s%s", io.KeyCtrl ? "CTRL " : "", io.KeyShift ? "SHIFT " : "", io.KeyAlt ? "ALT " : "", io.KeySuper ? "SUPER " : ""); - ImGui::Text("WantCaptureMouse: %s", io.WantCaptureMouse ? "true" : "false"); - ImGui::Text("WantCaptureKeyboard: %s", io.WantCaptureKeyboard ? "true" : "false"); - ImGui::Text("WantTextInput: %s", io.WantTextInput ? "true" : "false"); + ImGui::Text("WantCaptureMouse: %d", io.WantCaptureMouse); + ImGui::Text("WantCaptureKeyboard: %d", io.WantCaptureKeyboard); + ImGui::Text("WantTextInput: %d", io.WantTextInput); ImGui::Button("Hovering me sets the\nkeyboard capture flag"); if (ImGui::IsItemHovered()) @@ -1584,9 +1595,8 @@ void ImGui::ShowTestWindow(bool* p_open) if (ImGui::TreeNode("Mouse cursors")) { - ImGui::TextWrapped("Your application can render a different mouse cursor based on what ImGui::GetMouseCursor() returns. You can also set io.MouseDrawCursor to ask ImGui to render the cursor for you in software."); - ImGui::Checkbox("io.MouseDrawCursor", &ImGui::GetIO().MouseDrawCursor); ImGui::Text("Hover to see mouse cursors:"); + ImGui::SameLine(); ShowHelpMarker("Your application can render a different mouse cursor based on what ImGui::GetMouseCursor() returns. If software cursor rendering (io.MouseDrawCursor) is set ImGui will draw the right cursor for you, otherwise your backend needs to handle it."); for (int i = 0; i < ImGuiMouseCursor_Count_; i++) { char label[32]; From 24f79b91bd12a094aa6892fb8d3843ec58aeb736 Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 18 Jul 2016 14:37:38 +0200 Subject: [PATCH 014/823] Style: minor tweak to default color theme to make currently focused window more prominent (#323, #707) --- imgui.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 1ccca0ac7f7e..db6708fb0949 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -758,9 +758,9 @@ ImGuiStyle::ImGuiStyle() Colors[ImGuiCol_FrameBg] = ImVec4(0.80f, 0.80f, 0.80f, 0.30f); // Background of checkbox, radio button, plot, slider, text input Colors[ImGuiCol_FrameBgHovered] = ImVec4(0.90f, 0.80f, 0.80f, 0.40f); Colors[ImGuiCol_FrameBgActive] = ImVec4(0.90f, 0.65f, 0.65f, 0.45f); - Colors[ImGuiCol_TitleBg] = ImVec4(0.27f, 0.27f, 0.54f, 0.83f); + Colors[ImGuiCol_TitleBg] = ImVec4(0.24f, 0.24f, 0.50f, 0.83f); Colors[ImGuiCol_TitleBgCollapsed] = ImVec4(0.40f, 0.40f, 0.80f, 0.20f); - Colors[ImGuiCol_TitleBgActive] = ImVec4(0.32f, 0.32f, 0.63f, 0.87f); + Colors[ImGuiCol_TitleBgActive] = ImVec4(0.33f, 0.33f, 0.65f, 0.87f); Colors[ImGuiCol_MenuBarBg] = ImVec4(0.40f, 0.40f, 0.55f, 0.80f); Colors[ImGuiCol_ScrollbarBg] = ImVec4(0.20f, 0.25f, 0.30f, 0.60f); Colors[ImGuiCol_ScrollbarGrab] = ImVec4(0.40f, 0.40f, 0.80f, 0.30f); From e10ecfe28ae09abccb4fcbba08944104f08b207f Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 18 Jul 2016 15:52:08 +0200 Subject: [PATCH 015/823] BeginChild(): tweak to make the code easier to understand --- imgui.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index db6708fb0949..755e137ae709 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -3569,7 +3569,7 @@ bool ImGui::BeginPopupContextVoid(const char* str_id, int mouse_button) bool ImGui::BeginChild(const char* str_id, const ImVec2& size_arg, bool border, ImGuiWindowFlags extra_flags) { - ImGuiWindow* window = GetCurrentWindow(); + ImGuiWindow* parent_window = GetCurrentWindow(); ImGuiWindowFlags flags = ImGuiWindowFlags_NoTitleBar|ImGuiWindowFlags_NoResize|ImGuiWindowFlags_NoSavedSettings|ImGuiWindowFlags_ChildWindow; const ImVec2 content_avail = GetContentRegionAvail(); @@ -3591,12 +3591,13 @@ bool ImGui::BeginChild(const char* str_id, const ImVec2& size_arg, bool border, flags |= extra_flags; char title[256]; - ImFormatString(title, IM_ARRAYSIZE(title), "%s.%s", window->Name, str_id); + ImFormatString(title, IM_ARRAYSIZE(title), "%s.%s", parent_window->Name, str_id); bool ret = ImGui::Begin(title, NULL, size, -1.0f, flags); + ImGuiWindow* child_window = GetCurrentWindow(); + if (!(parent_window->Flags & ImGuiWindowFlags_ShowBorders)) + child_window->Flags &= ~ImGuiWindowFlags_ShowBorders; - if (!(window->Flags & ImGuiWindowFlags_ShowBorders)) - GetCurrentWindow()->Flags &= ~ImGuiWindowFlags_ShowBorders; return ret; } From c816e6c74250b8946333682663dc9365e4b14e13 Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 18 Jul 2016 16:55:20 +0200 Subject: [PATCH 016/823] Fixed SetScrollX() handling of center ratio (which actually wasn't exposed publicly). (#323, #246) --- imgui.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/imgui.cpp b/imgui.cpp index 755e137ae709..e0cc87e7d6bc 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -4113,7 +4113,8 @@ bool ImGui::Begin(const char* name, bool* p_open, const ImVec2& size_on_first_us // Apply scrolling if (window->ScrollTarget.x < FLT_MAX) { - window->Scroll.x = window->ScrollTarget.x; + float center_ratio = window->ScrollTargetCenterRatio.x; + window->Scroll.x = window->ScrollTarget.x - (center_ratio * window->SizeFull.x); window->ScrollTarget.x = FLT_MAX; } if (window->ScrollTarget.y < FLT_MAX) From eb405ab375f4b10109a003964425bebbabf96e5d Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 18 Jul 2016 17:09:22 +0200 Subject: [PATCH 017/823] DragBehavior: Moving code around, in what should be a no-op, to simplify upcoming Nav diff (#323, #180) --- imgui.cpp | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index e0cc87e7d6bc..097606c89f6b 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -6769,32 +6769,33 @@ bool ImGui::DragBehavior(const ImRect& frame_bb, ImGuiID id, float* v, float v_s g.DragLastMouseDelta = ImVec2(0.f, 0.f); } + if (v_speed == 0.0f && (v_max - v_min) != 0.0f && (v_max - v_min) < FLT_MAX) + v_speed = (v_max - v_min) * g.DragSpeedDefaultRatio; + float v_cur = g.DragCurrentValue; const ImVec2 mouse_drag_delta = GetMouseDragDelta(0, 1.0f); - if (fabsf(mouse_drag_delta.x - g.DragLastMouseDelta.x) > 0.0f) + float adjust_delta = mouse_drag_delta.x - g.DragLastMouseDelta.x; + if (g.IO.KeyShift && g.DragSpeedScaleFast >= 0.0f) + adjust_delta *= g.DragSpeedScaleFast; + if (g.IO.KeyAlt && g.DragSpeedScaleSlow >= 0.0f) + adjust_delta *= g.DragSpeedScaleSlow; + adjust_delta *= v_speed; + + if (fabsf(adjust_delta) > 0.0f) { - float speed = v_speed; - if (speed == 0.0f && (v_max - v_min) != 0.0f && (v_max - v_min) < FLT_MAX) - speed = (v_max - v_min) * g.DragSpeedDefaultRatio; - if (g.IO.KeyShift && g.DragSpeedScaleFast >= 0.0f) - speed = speed * g.DragSpeedScaleFast; - if (g.IO.KeyAlt && g.DragSpeedScaleSlow >= 0.0f) - speed = speed * g.DragSpeedScaleSlow; - - float delta = (mouse_drag_delta.x - g.DragLastMouseDelta.x) * speed; if (fabsf(power - 1.0f) > 0.001f) { // Logarithmic curve on both side of 0.0 float v0_abs = v_cur >= 0.0f ? v_cur : -v_cur; float v0_sign = v_cur >= 0.0f ? 1.0f : -1.0f; - float v1 = powf(v0_abs, 1.0f / power) + (delta * v0_sign); + float v1 = powf(v0_abs, 1.0f / power) + (adjust_delta * v0_sign); float v1_abs = v1 >= 0.0f ? v1 : -v1; float v1_sign = v1 >= 0.0f ? 1.0f : -1.0f; // Crossed sign line v_cur = powf(v1_abs, power) * v0_sign * v1_sign; // Reapply sign } else { - v_cur += delta; + v_cur += adjust_delta; } g.DragLastMouseDelta.x = mouse_drag_delta.x; From 23a81027e895a23702eef804c4ba719bc29f83cf Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 18 Jul 2016 17:17:51 +0200 Subject: [PATCH 018/823] Comment on invalid comment regarding preserving keyboard focus of a closed window, due to commit 19d02becef94e8e0f1d432a8bd55cd783876583c. This is probably still what we want. (followup #727) --- imgui.cpp | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 097606c89f6b..27735416b800 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1924,10 +1924,7 @@ bool ImGui::FocusableItemRegister(ImGuiWindow* window, bool is_active, bool tab_ // Process keyboard input at this point: TAB, Shift-TAB switch focus // We can always TAB out of a widget that doesn't allow tabbing in. if (tab_stop && window->FocusIdxAllRequestNext == INT_MAX && window->FocusIdxTabRequestNext == INT_MAX && is_active && !g.IO.KeyCtrl && IsKeyPressedMap(ImGuiKey_Tab)) - { - // Modulo on index will be applied at the end of frame once we've got the total counter of items. - window->FocusIdxTabRequestNext = window->FocusIdxTabCounter + (g.IO.KeyShift ? (allow_keyboard_focus ? -1 : 0) : +1); - } + window->FocusIdxTabRequestNext = window->FocusIdxTabCounter + (g.IO.KeyShift ? (allow_keyboard_focus ? -1 : 0) : +1); // Modulo on index will be applied at the end of frame once we've got the total counter of items. if (window->FocusIdxAllCounter == window->FocusIdxAllRequestCurrent) return true; @@ -2267,7 +2264,7 @@ void ImGui::NewFrame() } // Pressing TAB activate widget focus - // NB: Don't discard FocusedWindow if it isn't active, so that a window that go on/off programatically won't lose its keyboard focus. + //// NB: Don't discard FocusedWindow if it isn't active, so that a window that go on/off programatically won't lose its keyboard focus. // [2016/07/17] That comment was made invalid by 19d02becef94e8e0f1d432a8bd55cd783876583c if (g.ActiveId == 0 && g.FocusedWindow != NULL && g.FocusedWindow->Active && !g.IO.KeyCtrl && IsKeyPressedMap(ImGuiKey_Tab, false)) g.FocusedWindow->FocusIdxTabRequestNext = 0; From 88c1966629fff80f49bc6ffa0deb205f4856f3a3 Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 18 Jul 2016 18:24:23 +0200 Subject: [PATCH 019/823] Added IsAnyWindowFocused(). Renamed IsMouseHoveringAnyWindow() -> IsAnyWindowHovered(), IsPosHoveringAnyWindow() -> IsAnyWindowHoveredAtPos(), IsMouseHoveringWindow() -> IsWindowHoveredRect() for consistency. Kept inline rediection function. --- imgui.cpp | 28 +++++++++++++++++----------- imgui.h | 16 ++++++++++------ 2 files changed, 27 insertions(+), 17 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 27735416b800..8f679470cf34 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -150,6 +150,9 @@ Here is a change-log of API breaking changes, if you are using one of the functions listed, expect to have to fix some code. Also read releases logs https://github.com/ocornut/imgui/releases for more details. + - 2016/07/18 (1.50) - renamed IsMouseHoveringAnyWindow() to IsAnyWindowHovered() for consistency. Kept inline redirection function (will obsolete). + - renamed IsPosHoveringAnyWindow() to IsAnyWindowHoveredAtPos() for consistency. Kept inline redirection function (will obsolete). + - renamed IsMouseHoveringWindow() to IsWindowHoveredRect() for consistency. Kept inline redirection function (will obsolete). - 2016/05/12 (1.49) - title bar (using ImGuiCol_TitleBg/ImGuiCol_TitleBgActive colors) isn't rendered over a window background (ImGuiCol_WindowBg color) anymore. If your TitleBg/TitleBgActive alpha was 1.0f or you are using the default theme it will not affect you. However if your TitleBg/TitleBgActive alpha was <1.0f you need to tweak your custom theme to readjust for the fact that we don't draw a WindowBg background behind the title bar. @@ -391,7 +394,7 @@ A: You can read the 'io.WantCaptureXXX' flags in the ImGuiIO structure. Preferably read them after calling ImGui::NewFrame() to avoid those flags lagging by one frame, but either should be fine. When 'io.WantCaptureMouse' or 'io.WantCaptureKeyboard' flags are set you may want to discard/hide the inputs from the rest of your application. When 'io.WantInputsCharacters' is set to may want to notify your OS to popup an on-screen keyboard, if available. - ImGui is tracking dragging and widget activity that may occur outside the boundary of a window, so 'io.WantCaptureMouse' is a more accurate and complete than testing for ImGui::IsMouseHoveringAnyWindow(). + ImGui is tracking dragging and widget activity that may occur outside the boundary of a window, so 'io.WantCaptureMouse' is a more accurate and complete than testing for ImGui::IsAnyWindowHovered(). (Advanced note: text input releases focus on Return 'KeyDown', so the following Return 'KeyUp' event that your application receive will typically have 'io.WantcaptureKeyboard=false'. Depending on your application logic it may or not be inconvenient. You might want to track which key-downs were for ImGui (e.g. with an array of bool) and filter out the corresponding key-ups.) @@ -1889,7 +1892,6 @@ bool ImGui::IsClippedEx(const ImRect& bb, const ImGuiID* id, bool clip_even_when { ImGuiContext& g = *GImGui; ImGuiWindow* window = GetCurrentWindowRead(); - if (!bb.Overlaps(window->ClipRect)) if (!id || *id != GImGui->ActiveId) if (clip_even_when_logged || !g.LogEnabled) @@ -3053,19 +3055,22 @@ bool ImGui::IsMouseHoveringRect(const ImVec2& r_min, const ImVec2& r_max, bool c return rect_for_touch.Contains(g.IO.MousePos); } -bool ImGui::IsMouseHoveringWindow() +bool ImGui::IsWindowHoveredRect() { - ImGuiContext& g = *GImGui; - return g.HoveredWindow == g.CurrentWindow; + return GImGui->HoveredWindow == GImGui->CurrentWindow; } -bool ImGui::IsMouseHoveringAnyWindow() +bool ImGui::IsAnyWindowHovered() { - ImGuiContext& g = *GImGui; - return g.HoveredWindow != NULL; + return GImGui->HoveredWindow != NULL; +} + +bool ImGui::IsAnyWindowFocused() +{ + return GImGui->FocusedWindow != NULL; } -bool ImGui::IsPosHoveringAnyWindow(const ImVec2& pos) +bool ImGui::IsAnyWindowHoveredAtPos(const ImVec2& pos) { return FindHoveredWindow(pos, false) != NULL; } @@ -3550,7 +3555,7 @@ bool ImGui::BeginPopupContextItem(const char* str_id, int mouse_button) bool ImGui::BeginPopupContextWindow(bool also_over_items, const char* str_id, int mouse_button) { if (!str_id) str_id = "window_context_menu"; - if (IsMouseHoveringWindow() && IsMouseClicked(mouse_button)) + if (IsWindowHoveredRect() && IsMouseClicked(mouse_button)) if (also_over_items || !IsAnyItemHovered()) OpenPopupEx(str_id, true); return BeginPopup(str_id); @@ -3559,7 +3564,7 @@ bool ImGui::BeginPopupContextWindow(bool also_over_items, const char* str_id, in bool ImGui::BeginPopupContextVoid(const char* str_id, int mouse_button) { if (!str_id) str_id = "void_context_menu"; - if (!IsMouseHoveringAnyWindow() && IsMouseClicked(mouse_button)) + if (!IsAnyWindowHovered() && IsMouseClicked(mouse_button)) OpenPopupEx(str_id, true); return BeginPopup(str_id); } @@ -5476,6 +5481,7 @@ bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool return false; } + // Default behavior requires click+release on same spot if ((flags & (ImGuiButtonFlags_PressedOnClickRelease | ImGuiButtonFlags_PressedOnClick | ImGuiButtonFlags_PressedOnRelease | ImGuiButtonFlags_PressedOnDoubleClick)) == 0) flags |= ImGuiButtonFlags_PressedOnClickRelease; diff --git a/imgui.h b/imgui.h index 19eae6a10e89..2db1a3eadcf5 100644 --- a/imgui.h +++ b/imgui.h @@ -393,7 +393,7 @@ namespace ImGui IMGUI_API void PopClipRect(); // Utilities - IMGUI_API bool IsItemHovered(); // is the last item hovered by mouse? + IMGUI_API bool IsItemHovered(); // is the last item hovered by mouse, and usable? IMGUI_API bool IsItemHoveredRect(); // is the last item hovered by mouse? even if another item is active or window is blocked by popup while we are hovering this IMGUI_API bool IsItemActive(); // is the last item active? (e.g. button being held, text field being edited- items that don't interact will always return false) IMGUI_API bool IsItemClicked(int mouse_button = 0); // is the last item clicked? (e.g. button/node just clicked on) @@ -404,13 +404,16 @@ namespace ImGui IMGUI_API ImVec2 GetItemRectMax(); // " IMGUI_API ImVec2 GetItemRectSize(); // " IMGUI_API void SetItemAllowOverlap(); // allow last item to be overlapped by a subsequent item. sometimes useful with invisible buttons, selectables, etc. to catch unused area. - IMGUI_API bool IsWindowHovered(); // is current window hovered and hoverable (not blocked by a popup) (differentiate child windows from each others) IMGUI_API bool IsWindowFocused(); // is current window focused + IMGUI_API bool IsWindowHovered(); // is current window hovered and hoverable (not blocked by a popup) (differentiate child windows from each others) + IMGUI_API bool IsWindowHoveredRect(); // is current window hovered, disregarding of any consideration of being blocked by a popup. (unlike IsWindowHovered() this will return true even if the window is blocked because of a popup) IMGUI_API bool IsRootWindowFocused(); // is current root window focused (root = top-most parent of a child, otherwise self) IMGUI_API bool IsRootWindowOrAnyChildFocused(); // is current root window or any of its child (including current window) focused IMGUI_API bool IsRootWindowOrAnyChildHovered(); // is current root window or any of its child (including current window) hovered and hoverable (not blocked by a popup) + IMGUI_API bool IsAnyWindowFocused(); + IMGUI_API bool IsAnyWindowHovered(); // is mouse hovering any visible window + IMGUI_API bool IsAnyWindowHoveredAtPos(const ImVec2& pos); // is given position hovering any active imgui window IMGUI_API bool IsRectVisible(const ImVec2& size); // test if rectangle of given size starting from cursor pos is visible (not clipped). to perform coarse clipping on user's side (as an optimization) - IMGUI_API bool IsPosHoveringAnyWindow(const ImVec2& pos); // is given position hovering any active imgui window IMGUI_API float GetTime(); IMGUI_API int GetFrameCount(); IMGUI_API const char* GetStyleColName(ImGuiCol idx); @@ -436,10 +439,8 @@ namespace ImGui IMGUI_API bool IsMouseClicked(int button, bool repeat = false); // did mouse button clicked (went from !Down to Down) IMGUI_API bool IsMouseDoubleClicked(int button); // did mouse button double-clicked. a double-click returns false in IsMouseClicked(). uses io.MouseDoubleClickTime. IMGUI_API bool IsMouseReleased(int button); // did mouse button released (went from Down to !Down) - IMGUI_API bool IsMouseHoveringWindow(); // is mouse hovering current window ("window" in API names always refer to current window). disregarding of any consideration of being blocked by a popup. (unlike IsWindowHovered() this will return true even if the window is blocked because of a popup) - IMGUI_API bool IsMouseHoveringAnyWindow(); // is mouse hovering any visible window - IMGUI_API bool IsMouseHoveringRect(const ImVec2& r_min, const ImVec2& r_max, bool clip = true); // is mouse hovering given bounding rect (in screen space). clipped by current clipping settings. disregarding of consideration of focus/window ordering/blocked by a popup. IMGUI_API bool IsMouseDragging(int button = 0, float lock_threshold = -1.0f); // is mouse dragging. if lock_threshold < -1.0f uses io.MouseDraggingThreshold + IMGUI_API bool IsMouseHoveringRect(const ImVec2& r_min, const ImVec2& r_max, bool clip = true); // is mouse hovering given bounding rect (in screen space). clipped by current clipping settings. disregarding of consideration of focus/window ordering/blocked by a popup. IMGUI_API ImVec2 GetMousePos(); // shortcut to ImGui::GetIO().MousePos provided by user, to be consistent with other calls IMGUI_API ImVec2 GetMousePosOnOpeningCurrentPopup(); // retrieve backup of mouse positioning at the time of opening popup we have BeginPopup() into IMGUI_API ImVec2 GetMouseDragDelta(int button = 0, float lock_threshold = -1.0f); // dragging amount since clicking. if lock_threshold < -1.0f uses io.MouseDraggingThreshold @@ -465,6 +466,9 @@ namespace ImGui // Obsolete (will be removed) #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS + static inline bool IsPosHoveringAnyWindow(const ImVec2& pos) { return IsAnyWindowHoveredAtPos(pos); } // OBSOLETE 1.50+ + static inline bool IsMouseHoveringAnyWindow() { return IsAnyWindowHovered(); } // OBSOLETE 1.50+ + static inline bool IsMouseHoveringWindow() { return IsWindowHoveredRect(); } // OBSOLETE 1.50+ static inline bool CollapsingHeader(const char* label, const char* str_id, bool framed = true, bool default_open = false) { (void)str_id; (void)framed; ImGuiTreeNodeFlags default_open_flags = 1<<5; return CollapsingHeader(label, (default_open ? default_open_flags : 0)); } // OBSOLETE 1.49+ static inline ImFont* GetWindowFont() { return GetFont(); } // OBSOLETE 1.48+ static inline float GetWindowFontSize() { return GetFontSize(); } // OBSOLETE 1.48+ From 4a11cc35b901e7e49740cc60b5291dce72a5e9a5 Mon Sep 17 00:00:00 2001 From: ocornut Date: Tue, 19 Jul 2016 21:26:36 +0200 Subject: [PATCH 020/823] Updated code for repeat delay / repeat handling. GetKeyPressedAmount() now returns a count to support fast repeat rate (where DeltaTime > RepeatRate). Renamed from recently added IsKeyPressed() variant to GetKeyPressedAmount(). (no API breakage, added in branch, bbd3b7560922fe3ff68cf418ed7ada7370a31c79) (#323) --- imgui.cpp | 18 +++++++++--------- imgui.h | 2 +- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 8f679470cf34..bba5c176deed 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -3100,29 +3100,29 @@ bool ImGui::IsKeyDown(int key_index) return GImGui->IO.KeysDown[key_index]; } -bool ImGui::IsKeyPressed(int key_index, float repeat_delay, float repeat_rate) +int ImGui::GetKeyPressedAmount(int key_index, float repeat_delay, float repeat_rate) { ImGuiContext& g = *GImGui; if (key_index < 0) return false; IM_ASSERT(key_index >= 0 && key_index < IM_ARRAYSIZE(g.IO.KeysDown)); const float t = g.IO.KeysDownDuration[key_index]; if (t == 0.0f) - return true; - + return 1; if (t > repeat_delay && repeat_rate > 0.0f) - if ((fmodf(t - repeat_delay, repeat_rate) > repeat_rate*0.5f) != (fmodf(t - repeat_delay - g.IO.DeltaTime, repeat_rate) > repeat_rate*0.5f)) - return true; - - return false; + { + int count = (int)((t - repeat_delay) / repeat_rate) - (int)((t - repeat_delay - g.IO.DeltaTime) / repeat_rate); + return (count > 0) ? count : 0; + } + return 0; } bool ImGui::IsKeyPressed(int key_index, bool repeat) { ImGuiContext& g = *GImGui; if (repeat) - return IsKeyPressed(key_index, g.IO.KeyRepeatDelay, g.IO.KeyRepeatRate); + return GetKeyPressedAmount(key_index, g.IO.KeyRepeatDelay, g.IO.KeyRepeatRate) > 0; else - return IsKeyPressed(key_index, 0.0f, 0.0f); + return GetKeyPressedAmount(key_index, 0.0f, 0.0f) > 0; } bool ImGui::IsKeyReleased(int key_index) diff --git a/imgui.h b/imgui.h index 2db1a3eadcf5..994b663c7ae9 100644 --- a/imgui.h +++ b/imgui.h @@ -433,8 +433,8 @@ namespace ImGui IMGUI_API int GetKeyIndex(ImGuiKey key); // map ImGuiKey_* values into user's key index. == io.KeyMap[key] IMGUI_API bool IsKeyDown(int key_index); // key_index into the keys_down[] array, imgui doesn't know the semantic of each entry, uses your own indices! IMGUI_API bool IsKeyPressed(int key_index, bool repeat = true); // uses user's key indices as stored in the keys_down[] array. if repeat=true. uses io.KeyRepeatDelay / KeyRepeatRate - IMGUI_API bool IsKeyPressed(int key_index, float repeat_delay, float repeat_rate); // uses user's key indices as stored in the keys_down[] array. uses provided repeat rate/delay IMGUI_API bool IsKeyReleased(int key_index); // " + IMGUI_API int GetKeyPressedAmount(int key_index, float repeat_delay, float rate); // uses provided repeat rate/delay. return a count, typically 0 or 1 but may be >1 if RepeatRate is small enough that DeltaTime > RepeatRate IMGUI_API bool IsMouseDown(int button); // is mouse button held IMGUI_API bool IsMouseClicked(int button, bool repeat = false); // did mouse button clicked (went from !Down to Down) IMGUI_API bool IsMouseDoubleClicked(int button); // did mouse button double-clicked. a double-click returns false in IsMouseClicked(). uses io.MouseDoubleClickTime. From c2cb2a6928a436b1358f5e960844c02cbab0b3ba Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 20 Jul 2016 00:02:59 +0200 Subject: [PATCH 021/823] Gamepad/Keyboard navigation support, initial commit, WIP (#323) --- imgui.cpp | 877 +++++++++++++++++++++++++++++++++++++++++------ imgui.h | 23 +- imgui_demo.cpp | 13 +- imgui_internal.h | 82 ++++- 4 files changed, 878 insertions(+), 117 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index bba5c176deed..ad2007bdb12b 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1,6 +1,9 @@ // dear imgui, v1.50 WIP // (main code and documentation) +// ** EXPERIMENTAL GAMEPAD/KEYBOARD NAVIGATION BRANCH +// ** Grep for FIXME-NAVIGATION + // See ImGui::ShowTestWindow() in imgui_demo.cpp for demo code. // Newcomers, read 'Programmer guide' below for notes on how to setup ImGui in your codebase. // Get latest version at https://github.com/ocornut/imgui @@ -616,7 +619,6 @@ #include // toupper, isprint #include // NULL, malloc, free, qsort, atoi #include // vsnprintf, sscanf, printf -#include // INT_MIN, INT_MAX #if defined(_MSC_VER) && _MSC_VER <= 1500 // MSVC 2008 or earlier #include // intptr_t #else @@ -813,6 +815,7 @@ ImGuiIO::ImGuiIO() KeyMap[i] = -1; KeyRepeatDelay = 0.250f; KeyRepeatRate = 0.050f; + NavMovesMouse = false; UserData = NULL; Fonts = &GImDefaultFontAtlas; @@ -1736,6 +1739,7 @@ ImGuiWindow::ImGuiWindow(const char* name) SkipItems = false; BeginCount = 0; PopupId = 0; + NavLastId = 0; AutoFitFramesX = AutoFitFramesY = -1; AutoFitOnlyGrows = false; AutoPosLastDirection = -1; @@ -1790,6 +1794,13 @@ ImGuiID ImGuiWindow::GetIDNoKeepAlive(const char* str, const char* str_end) return ImHash(str, str_end ? (int)(str_end - str) : 0, seed); } +ImGuiID ImGuiWindow::GetChildID(ImGuiWindow* child_window) +{ + IM_ASSERT(child_window && child_window->ParentWindow == this); + ImGuiID seed = IDStack[0]; + return ImHash(&child_window->ID, sizeof(child_window->ID), seed); +} + //----------------------------------------------------------------------------- // Internal API exposed in imgui_internal.h //----------------------------------------------------------------------------- @@ -1814,8 +1825,31 @@ void ImGui::SetActiveID(ImGuiID id, ImGuiWindow* window = NULL) ImGuiContext& g = *GImGui; g.ActiveIdIsJustActivated = (g.ActiveId != id); g.ActiveId = id; + g.ActiveIdAllowNavMove = false; g.ActiveIdAllowOverlap = false; g.ActiveIdWindow = window; + if (id) + { + g.ActiveIdSource = (g.NavActivateId == id || g.NavInputId == id || g.NavTabbedId == id) ? ImGuiInputSource_Nav : ImGuiInputSource_Mouse; + if (g.ActiveIdSource == ImGuiInputSource_Nav) + g.NavDisableMouseHover = true; + else + g.NavDisableHighlight = true; + g.NavId = id; + if (window) + window->NavLastId = id; + } +} + +void ImGui::SetActiveIDNoNav(ImGuiID id, ImGuiWindow* window) +{ + ImGuiContext& g = *GImGui; + g.ActiveIdIsJustActivated = (g.ActiveId != id); + g.ActiveId = id; + g.ActiveIdAllowNavMove = false; + g.ActiveIdAllowOverlap = false; + g.ActiveIdWindow = window; + g.ActiveIdSource = (g.NavActivateId == id || g.NavInputId == id) ? ImGuiInputSource_Nav : ImGuiInputSource_Mouse; } void ImGui::SetHoveredID(ImGuiID id) @@ -1860,20 +1894,188 @@ void ImGui::ItemSize(const ImRect& bb, float text_offset_y) ItemSize(bb.GetSize(), text_offset_y); } +static ImGuiNavDir NavScoreItemGetQuadrant(float dx, float dy) +{ + if (fabsf(dx) > fabsf(dy)) + return (dx > 0.0f) ? ImGuiNavDir_E : ImGuiNavDir_W; + return (dy > 0.0f) ? ImGuiNavDir_S : ImGuiNavDir_N; +} + +static float NavScoreItemDistInterval(float a0, float a1, float b0, float b1) +{ + if (a1 < b0) return a1 - b0; + if (b1 < a0) return a0 - b1; + return 0.0f; +} + +// Scoring function for directional navigation. Based on https://gist.github.com/rygorous/6981057 +// FIXME-NAVIGATION: Pretty rough. +// FIXME-NAVIGATION: May want to handle the degenerate case that we have commented out. +static bool NavScoreItem(const ImRect& cand) +{ + ImGuiContext& g = *GImGui; + const ImRect& curr = g.NavScoringRectScreen; // Current modified source rect (NB: we've applied Max.x = Min.x in NavUpdate() to inhibit the effect of having lots of items with varied width) + + // Compute distance between boxes + // FIXME-NAVIGATION: Introducing various biases toward typical imgui uses cases, but we don't have any rigorous proof of their effect now. + float dbx = NavScoreItemDistInterval(cand.Min.x, cand.Max.x, curr.Min.x, curr.Max.x); + float dby = NavScoreItemDistInterval(ImLerp(cand.Min.y, cand.Max.y, 0.2f), ImLerp(cand.Min.y, cand.Max.y, 0.8f), ImLerp(curr.Min.y, curr.Max.y, 0.2f), ImLerp(curr.Min.y, curr.Max.y, 0.8f)); // Clamp down on Y to keep using box-distance for vertically touching items + //dbx /= 2; dby *= 4 // Bias for dy + if (dby) + dbx = (dbx > 0.0f) ? +0.0f : -0.0f; + float dist_box = fabsf(dbx) + fabsf(dby); + + // Compute distance between centers (this is off by a factor of 2, but we only compare center distances with each other so it doesn't matter) + float dcx = (cand.Min.x + cand.Max.x) - (curr.Min.x + curr.Max.x); + float dcy = (cand.Min.y + cand.Max.y) - (curr.Min.y + curr.Max.y); + float dist_center = fabsf(dcx) + fabsf(dcy); // L1 metric (need this for our connectedness guarantee) + + // Determine which quadrant of 'curr' our candidate item 'cand' lies in based on distance + ImGuiNavDir quadrant; + float dax = 0.0f, day = 0.0f, dist_axial = 0.0f; + if (dbx || dby) + { + // For non-overlapping boxes, use distance between boxes + dax = dbx; + day = dby; + dist_axial = dist_box; + quadrant = NavScoreItemGetQuadrant(dbx, dby); + } + else if (dcx || dcy) + { + // For overlapping boxes with different centers, use distance between centers + dax = dcx; + day = dcy; + dist_axial = dist_center; + quadrant = NavScoreItemGetQuadrant(dcx, dcy); + } + else + { + // Degenerate case: two overlapping buttons with same center, break ties using order + quadrant = (g.CurrentWindow->DC.LastItemId < g.NavId) ? ImGuiNavDir_W : ImGuiNavDir_E; + } + +#if 0 // [DEBUG] + //draw_list->AddRect(bb.Min, bb.Max, IM_COL32(255,0,255,200)); + if (ImGui::IsMouseHoveringRect(cand.Min, cand.Max)) + { + char buf[128]; + ImFormatString(buf, IM_ARRAYSIZE(buf), "db (%.0f,%.0f->%.1f) dc (%.0f,%.0f->%.1f) da (%.0f,%.0f->%.1f) quad %c", dbx, dby, dist_box, dcx, dcy, dist_center, dax, day, dist_axial, "WENS"[quadrant]); + g.OverlayDrawList.AddText(cand.Max, ~0U, buf); + } + #endif + + // Is it in the quadrant we're interesting in moving to? + bool new_best = false; + if (quadrant == g.NavMoveDir) + { + // Does it beat the current best candidate? + if (dist_box < g.NavMoveResultBestDistBox) + { + g.NavMoveResultBestDistBox = dist_box; + g.NavMoveResultBestDistCenter = dist_center; + return true; + } + if (dist_box == g.NavMoveResultBestDistBox) + { + // Try using distance between center points to break ties + if (dist_center < g.NavMoveResultBestDistCenter) + { + g.NavMoveResultBestDistCenter = dist_center; + new_best = true; + } + else if (dist_center == g.NavMoveResultBestDistCenter) + { + // Still tied! we need to be extra-careful to make sure everything gets linked properly. We consistently break ties by symbolically moving "later" buttons + // (with higher index) to the right/downwards by an infinitesimal amount since we the current "best" button already (so it must have a lower index), + // this is fairly easy. This rule ensures that all buttons with dx==dy==0 will end up being linked in order of appearance along the x axis. + if ((g.NavMoveDir >= ImGuiNavDir_N ? dby : dbx) < 0.0f) // moving bj to the right/down decreases distance + new_best = true; + } + } + } + + // Axial check: if 'curr' has no link at all in some direction and 'cand' lies roughly in that direction, add a tentative link. This will only be kept if no "real" matches + // are found, so it only augments the graph produced by the above method using extra links. (important, since it doesn't guarantee strong connectedness) + // This is just to avoid buttons having no links in a particular direction when there's a suitable neighbor. you get good graphs without this too. + if (g.NavMoveResultBestDistBox == FLT_MAX) + if (dist_axial < g.NavMoveResultBestDistAxial) // Check axial match + if ((g.NavMoveDir == ImGuiNavDir_W && dax < 0.0f) || (g.NavMoveDir == ImGuiNavDir_E && dax > 0.0f) || (g.NavMoveDir == ImGuiNavDir_N && day < 0.0f) || (g.NavMoveDir == ImGuiNavDir_S && day > 0.0f)) + g.NavMoveResultBestDistAxial = dist_axial, new_best = true; + + return new_best; +} + +static void RenderNavHighlight(ImU32 id, const ImRect& bb) +{ + ImGuiContext& g = *GImGui; + if (id != g.NavId || g.NavDisableHighlight) + return; + ImGuiWindow* window = ImGui::GetCurrentWindow(); + window->DrawList->PushClipRect(window->WindowRectClipped.Min - ImVec2(2,2), window->WindowRectClipped.Max + ImVec2(2,2)); + window->DrawList->AddRectFilled(bb.Min - ImVec2(2,2), bb.Max + ImVec2(2,2), ImGui::GetColorU32(ImGuiCol_HeaderHovered, 0.15f), g.Style.FrameRounding); + window->DrawList->AddRect(bb.Min - ImVec2(2,2), bb.Max + ImVec2(2,2), ImGui::GetColorU32(ImGuiCol_HeaderHovered), g.Style.FrameRounding); + //window->DrawList->AddRect(g.NavRefRectScreen.Min, g.NavRefRectScreen.Max, IM_COL32(255,0,0,255)); + window->DrawList->PopClipRect(); +} + // Declare item bounding box for clipping and interaction. // Note that the size can be different than the one provided to ItemSize(). Typically, widgets that spread over available surface // declares their minimum size requirement to ItemSize() and then use a larger region for drawing/interaction, which is passed to ItemAdd(). -bool ImGui::ItemAdd(const ImRect& bb, const ImGuiID* id) +bool ImGui::ItemAdd(const ImRect& bb, const ImGuiID* id, const ImRect* nav_bb_arg) { - ImGuiWindow* window = GetCurrentWindow(); + ImGuiContext& g = *GImGui; + ImGuiWindow* window = g.CurrentWindow; window->DC.LastItemId = id ? *id : 0; window->DC.LastItemRect = bb; window->DC.LastItemHoveredAndUsable = window->DC.LastItemHoveredRect = false; - if (IsClippedEx(bb, id, false)) + if (id != NULL) window->DC.NavHasItemsNext = true; + const bool is_clipped = IsClippedEx(bb, id, false); + + // Navigation processing runs prior to clipping early-out + // (a) So that NavInitDefaultRequest can be honored, for newly opened windows to select a default widget + // (b) So that we can scroll up/down past clipped items. This adds a small O(N) cost to regular navigation requests unfortunately, but it is still limited to one window. + // it may not scale very well for windows with ten of thousands of item, but at least the NavRequest is only performed on user interaction, aka maximum once a frame. + // We could early out with `if (is_clipped && !g.NavInitDefaultRequest) return false;` but when we wouldn't be able to reach unclipped widgets. This would work if user had explicit scrolling control (e.g. mapped on a stick) + // A more pragmatic solution for handling last lists is relying on the fact that they are likely evenly spread items (so that clipper can work) and we could nav at higher-level (apply index, etc.) + // So eventually we would like to provide the user will the primitives to be able to implement that sort of customized/efficient navigation handling whenever necessary. + // FIXME-NAVIGATION + if (id != NULL && g.NavWindow == window && g.IO.NavUsable) + { + if (g.NavInitDefaultRequest && window->DC.AllowNavDefaultFocus) + { + g.NavInitDefaultRequest = g.NavInitDefaultResultExplicit = false; // Clear flag immediately, first item gets default, also simplify the if() in ItemAdd() + g.NavInitDefaultResultId = *id; + } + + if (g.NavMoveRequest && g.NavId != *id) + { + //if (!g.NavMoveRequest) g.NavMoveDir = ImGuiNavDir_E; // [DEBUG] Removing if (g.NavMoveRequest) above allows debug scoring of all visible items. + const ImRect& nav_bb = nav_bb_arg ? *nav_bb_arg : bb; + if (NavScoreItem(nav_bb)) + { + g.NavMoveResultBestId = *id; + g.NavMoveResultBestRefRectRel = ImRect(nav_bb.Min - window->Pos, nav_bb.Max - window->Pos); + //g.OverlayDrawList.AddRectFilled(g.NavRefRectScreen.Min, g.NavRefRectScreen.Max+ImVec2(2,2), IM_COL32(255,255,0,255)); // [DEBUG] + //g.OverlayDrawList.AddRectFilled(nav_bb.Min, nav_bb.Max, IM_COL32(255,0,255,100)); // [DEBUG] + //g.OverlayDrawList.AddText(nav_bb.Min, ~0U, "new_best"); // [DEBUG] + } + } + + // Update window-relative bounding box of navigated item + if (g.NavId == *id) + { + const ImRect& nav_bb = nav_bb_arg ? *nav_bb_arg : bb; + g.NavRefRectRel = ImRect(nav_bb.Min - window->Pos, nav_bb.Max - window->Pos); + g.NavIdIsAlive = true; + g.NavIdTabCounter = window->FocusIdxTabCounter; + } + } + + if (is_clipped) return false; - // This is a sensible default, but widgets are free to override it after calling ItemAdd() - ImGuiContext& g = *GImGui; + // Setting LastItemHoveredAndUsable for IsItemHovered() if (IsMouseHoveringRect(bb.Min, bb.Max)) { // Matching the behavior of IsHovered() but allow if ActiveId==window->MoveID (we clicked on the window background) @@ -1881,7 +2083,7 @@ bool ImGui::ItemAdd(const ImRect& bb, const ImGuiID* id) window->DC.LastItemHoveredRect = true; if (g.HoveredRootWindow == window->RootWindow) if (g.ActiveId == 0 || (id && g.ActiveId == *id) || g.ActiveIdAllowOverlap || (g.ActiveId == window->MoveId)) - if (IsWindowContentHoverable(window)) + if (!g.NavDisableMouseHover && IsWindowContentHoverable(window)) window->DC.LastItemHoveredAndUsable = true; } @@ -1908,13 +2110,13 @@ bool ImGui::IsHovered(const ImRect& bb, ImGuiID id, bool flatten_childs) ImGuiWindow* window = GetCurrentWindowRead(); if (g.HoveredWindow == window || (flatten_childs && g.HoveredRootWindow == window->RootWindow)) if ((g.ActiveId == 0 || g.ActiveId == id || g.ActiveIdAllowOverlap) && IsMouseHoveringRect(bb.Min, bb.Max)) - if (IsWindowContentHoverable(g.HoveredRootWindow)) + if (!g.NavDisableMouseHover && IsWindowContentHoverable(g.HoveredRootWindow)) return true; } return false; } -bool ImGui::FocusableItemRegister(ImGuiWindow* window, bool is_active, bool tab_stop) +bool ImGui::FocusableItemRegister(ImGuiWindow* window, ImGuiID id, bool tab_stop) { ImGuiContext& g = *GImGui; @@ -1923,17 +2125,21 @@ bool ImGui::FocusableItemRegister(ImGuiWindow* window, bool is_active, bool tab_ if (allow_keyboard_focus) window->FocusIdxTabCounter++; - // Process keyboard input at this point: TAB, Shift-TAB switch focus - // We can always TAB out of a widget that doesn't allow tabbing in. - if (tab_stop && window->FocusIdxAllRequestNext == INT_MAX && window->FocusIdxTabRequestNext == INT_MAX && is_active && !g.IO.KeyCtrl && IsKeyPressedMap(ImGuiKey_Tab)) + // Process keyboard input at this point: TAB/Shift-TAB to tab out of the currently focused item. + // Note that we can always TAB out of a widget that doesn't allow tabbing in. + if (tab_stop && (g.ActiveId == id) && window->FocusIdxAllRequestNext == INT_MAX && window->FocusIdxTabRequestNext == INT_MAX && !g.IO.KeyCtrl && IsKeyPressedMap(ImGuiKey_Tab)) window->FocusIdxTabRequestNext = window->FocusIdxTabCounter + (g.IO.KeyShift ? (allow_keyboard_focus ? -1 : 0) : +1); // Modulo on index will be applied at the end of frame once we've got the total counter of items. if (window->FocusIdxAllCounter == window->FocusIdxAllRequestCurrent) + { + g.NavTabbedId = id; return true; - - if (allow_keyboard_focus) - if (window->FocusIdxTabCounter == window->FocusIdxTabRequestCurrent) - return true; + } + if (allow_keyboard_focus && window->FocusIdxTabCounter == window->FocusIdxTabRequestCurrent) + { + g.NavTabbedId = id; + return true; + } return false; } @@ -2058,6 +2264,191 @@ int ImGui::GetFrameCount() return GImGui->FrameCount; } +static void NavUpdate() +{ + ImGuiContext& g = *GImGui; + g.IO.WantMoveMouse = false; + + if (g.NavMousePosDirty && g.NavIdIsAlive) + { + // Set mouse position given our knowledge of the nav widget position from last frame + if (g.IO.NavMovesMouse) + { + g.IO.MousePos = g.IO.MousePosPrev = g.NavWindow->Pos + ImVec2(g.NavRefRectRel.Min.x + ImMin(g.Style.FramePadding.x*4, g.NavRefRectRel.GetWidth()), g.NavRefRectRel.Max.y - ImMin(g.Style.FramePadding.y, g.NavRefRectRel.GetHeight())); + g.IO.WantMoveMouse = true; + } + g.NavMousePosDirty = false; + } + g.NavIdIsAlive = false; + g.NavTabbedId = 0; + + if (g.NavInitDefaultResultId != 0 && (!g.NavDisableHighlight || g.NavInitDefaultResultExplicit)) + { + // Apply result from previous navigation init request (typically select the first item, unless SetItemDefaultFocus() has been called) + IM_ASSERT(g.NavWindow); + g.NavId = g.NavWindow->NavLastId = g.NavInitDefaultResultId; + //if (g.NavInitDefaultResultExplicit) + // g.NavDisableHighlight = false; + } + + if (g.NavMoveRequest) + { + // Scroll to keep newly navigated item fully into view + ImRect window_rect_rel(g.NavWindow->InnerRect.Min - g.NavWindow->Pos, g.NavWindow->InnerRect.Max - g.NavWindow->Pos); + window_rect_rel.Expand(1.0f); + //g.OverlayDrawList.AddRect(g.NavWindow->Pos + window_rect_rel.Min, g.NavWindow->Pos + window_rect_rel.Max, IM_COL32_WHITE); // [DEBUG] + if (g.NavWindow && g.NavMoveResultBestId != 0 && !window_rect_rel.Contains(g.NavMoveResultBestRefRectRel)) + { + if (g.NavWindow->ScrollbarX && g.NavMoveResultBestRefRectRel.Min.x < window_rect_rel.Min.x) + { + g.NavWindow->ScrollTarget.x = g.NavMoveResultBestRefRectRel.Min.x + g.NavWindow->Scroll.x - g.Style.ItemSpacing.x; + g.NavWindow->ScrollTargetCenterRatio.x = 0.0f; + } + else if (g.NavWindow->ScrollbarX && g.NavMoveResultBestRefRectRel.Max.x >= window_rect_rel.Max.x) + { + g.NavWindow->ScrollTarget.x = g.NavMoveResultBestRefRectRel.Max.x + g.NavWindow->Scroll.x + g.Style.ItemSpacing.x; + g.NavWindow->ScrollTargetCenterRatio.x = 1.0f; + } + if (g.NavMoveResultBestRefRectRel.Min.y < window_rect_rel.Min.y) + { + g.NavWindow->ScrollTarget.y = g.NavMoveResultBestRefRectRel.Min.y + g.NavWindow->Scroll.y - g.Style.ItemSpacing.y; + g.NavWindow->ScrollTargetCenterRatio.y = 0.0f; + } + else if (g.NavMoveResultBestRefRectRel.Max.y >= window_rect_rel.Max.y) + { + g.NavWindow->ScrollTarget.y = g.NavMoveResultBestRefRectRel.Max.y + g.NavWindow->Scroll.y + g.Style.ItemSpacing.y; + g.NavWindow->ScrollTargetCenterRatio.y = 1.0f; + } + } + } + + if (g.NavMoveRequest && g.NavMoveResultBestId != 0) + { + // Apply result from previous navigation directional move request + IM_ASSERT(g.NavWindow); + g.NavId = g.NavWindow->NavLastId = g.NavMoveResultBestId; + g.NavRefRectRel = g.NavMoveResultBestRefRectRel; + g.NavMousePosDirty = true; + g.NavDisableHighlight = false; + g.NavDisableMouseHover = true; + } + + // Navigation windowing mode (change focus, move/resize window) + if (!g.NavWindowingTarget && g.NavWindow && IsKeyPressedMap(ImGuiKey_NavWindowing, false)) + g.NavWindowingTarget = g.NavWindow->RootWindow; + if (g.NavWindowingTarget) + { + // FIXME-NAVIGATION: Need to clarify input semantic, naming is misleading/incorrect here. + int focus_change_dir = IsKeyPressedMap(ImGuiKey_NavTweakFaster, true) ? -1 : IsKeyPressedMap(ImGuiKey_NavTweakSlower, true) ? +1 : 0; + if (focus_change_dir != 0) + { + // FIXME-NAVIGATION FIXME-OPT: This is absolutely hideous and shouldn't stay. Pressed we should maintain a intrusive linked-list of visible windows. + int i_current = -1; + for (int i = g.Windows.Size-1; i >= 0 && i_current == -1; i--) + if (g.Windows[i] == g.NavWindowingTarget) + i_current = i; + int i_target = -1; + for (int i = i_current+focus_change_dir; i >= 0 && i < g.Windows.Size && i_target == -1; i += focus_change_dir) + if (g.Windows[i]->Active && !(g.Windows[i]->Flags & ImGuiWindowFlags_ChildWindow)) + i_target = i; + for (int i = (focus_change_dir < 0) ? (g.Windows.Size-1) : 0; i >= 0 && i < g.Windows.Size && i_target == -1 && i_target != i_current; i += focus_change_dir) + if (g.Windows[i]->Active && !(g.Windows[i]->Flags & ImGuiWindowFlags_ChildWindow)) + i_target = i; + if (i_target != -1) + { + IM_ASSERT(i_target != i_current); + g.NavWindowingTarget = g.Windows[i_target]; + } + } + + // End window select/focus mode and apply final focus + if (!IsKeyDownMap(ImGuiKey_NavWindowing)) + { + if (g.NavWindowingTarget) + if (!g.FocusedWindow || (g.NavWindowingTarget && g.NavWindowingTarget->RootWindow != g.FocusedWindow->RootWindow)) + ImGui::FocusWindow(g.NavWindowingTarget->RootWindow); + g.NavWindowingTarget = NULL; + } + } + + // Set output flags for user application + g.IO.NavUsable = g.FocusedWindow && !(g.FocusedWindow->Flags & ImGuiWindowFlags_NoNav); + g.IO.NavActive = g.IO.NavUsable && g.NavId != 0 && !g.NavDisableHighlight; + + // Process NavCancel input (to close a popup, get back to parent, clear focus) + if (g.ActiveId == 0 && IsKeyPressedMap(ImGuiKey_NavCancel)) + { + // Close open popup or move back to parent window + if (g.OpenPopupStack.Size > 0) + { + ClosePopupToLevel(g.OpenPopupStack.Size - 1); + } + else + { + // Clear NavId for popups but keep it for regular child window so we can leave one and come back where we were + if (g.FocusedWindow && ((g.FocusedWindow->Flags & ImGuiWindowFlags_Popup) || !(g.FocusedWindow->Flags & ImGuiWindowFlags_ChildWindow))) + g.FocusedWindow->NavLastId = 0; + + if (g.FocusedWindow && (g.FocusedWindow->Flags & ImGuiWindowFlags_ChildWindow) && g.FocusedWindow->ParentWindow) + { + // Exit child window + ImGuiWindow* child_window = g.FocusedWindow; + ImGuiWindow* parent_window = g.FocusedWindow->ParentWindow; + ImGui::FocusWindow(parent_window); + g.NavId = parent_window->NavLastId = parent_window->GetChildID(child_window); + g.NavIdIsAlive = false; + if (g.NavDisableMouseHover) + g.NavMousePosDirty = true; + } + else + { + g.NavId = 0; + } + } + } + + g.NavActivateId = (g.NavId && !g.NavDisableHighlight && g.ActiveId == 0 && IsKeyPressedMap(ImGuiKey_NavActivate)) ? g.NavId : 0; + g.NavInputId = (g.NavId && !g.NavDisableHighlight && g.ActiveId == 0 && IsKeyPressedMap(ImGuiKey_NavInput)) ? g.NavId : 0; + if (g.NavWindow && (g.NavWindow->Flags & ImGuiWindowFlags_NoNav)) + { + g.NavActivateId = g.NavInputId = 0; + g.NavDisableHighlight = true; + } + g.NavMoveRequest = false; + g.NavInitDefaultRequest = false; + g.NavInitDefaultResultExplicit = false; + g.NavInitDefaultResultId = 0; + + // Initiate directional inputs request + g.NavMoveDir = ImGuiNavDir_None; + if (g.FocusedWindow && !g.NavWindowingTarget && (g.ActiveId == 0 || g.ActiveIdAllowNavMove) && !(g.FocusedWindow->Flags & ImGuiWindowFlags_NoNav)) + { + if (IsKeyPressedMap(ImGuiKey_NavLeft, true)) g.NavMoveDir = ImGuiNavDir_W; + if (IsKeyPressedMap(ImGuiKey_NavRight, true)) g.NavMoveDir = ImGuiNavDir_E; + if (IsKeyPressedMap(ImGuiKey_NavUp, true)) g.NavMoveDir = ImGuiNavDir_N; + if (IsKeyPressedMap(ImGuiKey_NavDown, true)) g.NavMoveDir = ImGuiNavDir_S; + } + if (g.NavMoveDir != ImGuiNavDir_None) + { + g.NavMoveRequest = true; + g.NavWindow = g.FocusedWindow; + } + + // Fallback manual-scroll with NavUp/NavDown when window has no navigable item + if (g.FocusedWindow && !g.FocusedWindow->DC.NavHasItems && g.FocusedWindow->DC.NavHasScroll && !(g.FocusedWindow->Flags & ImGuiWindowFlags_NoNav) && g.NavMoveRequest && (g.NavMoveDir == ImGuiNavDir_N || g.NavMoveDir == ImGuiNavDir_S)) + { + float scroll_speed = ImFloor(g.FocusedWindow->CalcFontSize() * 100 * g.IO.DeltaTime + 0.5f); // We need round the scrolling speed because sub-pixel scroll isn't reliably supported. + g.FocusedWindow->Scroll.y = ImFloor(g.FocusedWindow->Scroll.y + ((g.NavMoveDir == ImGuiNavDir_N) ? -1.0f : +1.0f) * scroll_speed); + } + + // Reset search + g.NavMoveResultBestId = 0; + g.NavMoveResultBestDistAxial = g.NavMoveResultBestDistBox = g.NavMoveResultBestDistCenter = FLT_MAX; + g.NavScoringRectScreen = g.NavWindow ? ImRect(g.NavWindow->Pos + g.NavRefRectRel.Min, g.NavWindow->Pos + g.NavRefRectRel.Max) : ImRect(); + //g.OverlayDrawList.AddRect(g.NavRefRectScreen.Min, g.NavRefRectScreen.Max, IM_COL32(255,200,0,255)); // [DEBUG] + g.NavScoringRectScreen.Max.x = g.NavScoringRectScreen.Min.x; +} + void ImGui::NewFrame() { ImGuiContext& g = *GImGui; @@ -2109,6 +2500,9 @@ void ImGui::NewFrame() for (int i = 0; i < IM_ARRAYSIZE(g.IO.KeysDown); i++) g.IO.KeysDownDuration[i] = g.IO.KeysDown[i] ? (g.IO.KeysDownDuration[i] < 0.0f ? 0.0f : g.IO.KeysDownDuration[i] + g.IO.DeltaTime) : -1.0f; + // Update directional navigation which may override MousePos if 'NavMovesMouse=true' + NavUpdate(); + // Update mouse input state if (g.IO.MousePos.x < 0 && g.IO.MousePos.y < 0) g.IO.MousePos = ImVec2(-9999.0f, -9999.0f); @@ -2116,6 +2510,8 @@ void ImGui::NewFrame() g.IO.MouseDelta = ImVec2(0.0f, 0.0f); else g.IO.MouseDelta = g.IO.MousePos - g.IO.MousePosPrev; + if (g.IO.MouseDelta.x != 0.0f || g.IO.MouseDelta.y != 0.0f) + g.NavDisableMouseHover = false; g.IO.MousePosPrev = g.IO.MousePos; for (int i = 0; i < IM_ARRAYSIZE(g.IO.MouseDown); i++) { @@ -2143,6 +2539,8 @@ void ImGui::NewFrame() { g.IO.MouseDragMaxDistanceSqr[i] = ImMax(g.IO.MouseDragMaxDistanceSqr[i], ImLengthSqr(g.IO.MousePos - g.IO.MouseClickedPos[i])); } + if (g.IO.MouseDown[i]) // Pressing any mouse button reactivate mouse hovering which may have been deactivated by gamepad/keyboard navigation + g.NavDisableMouseHover = false; } // Calculate frame-rate for the user, as a purely luxurious feature @@ -2267,8 +2665,12 @@ void ImGui::NewFrame() // Pressing TAB activate widget focus //// NB: Don't discard FocusedWindow if it isn't active, so that a window that go on/off programatically won't lose its keyboard focus. // [2016/07/17] That comment was made invalid by 19d02becef94e8e0f1d432a8bd55cd783876583c - if (g.ActiveId == 0 && g.FocusedWindow != NULL && g.FocusedWindow->Active && !g.IO.KeyCtrl && IsKeyPressedMap(ImGuiKey_Tab, false)) - g.FocusedWindow->FocusIdxTabRequestNext = 0; + if (g.ActiveId == 0 && g.FocusedWindow != NULL && g.FocusedWindow->Active && !(g.FocusedWindow->Flags & ImGuiWindowFlags_NoNav) && !g.IO.KeyCtrl && IsKeyPressedMap(ImGuiKey_Tab, false)) + if (g.NavId != 0 && g.NavIdTabCounter != INT_MAX) + g.FocusedWindow->FocusIdxTabRequestNext = g.NavIdTabCounter + 1 + (g.IO.KeyShift ? -1 : 1); + else + g.FocusedWindow->FocusIdxTabRequestNext = g.IO.KeyShift ? -1 : 0; + g.NavIdTabCounter = INT_MAX; // Mark all windows as not visible for (int i = 0; i != g.Windows.Size; i++) @@ -2555,6 +2957,19 @@ static void AddWindowToRenderList(ImVector& out_render_list, ImGuiW } } +static void AddWindowToRenderListSelectLayer(ImGuiWindow* window) +{ + // FIXME: Generalize this with a proper layering system so e.g. user can draw in specific layers, below text, .. + ImGuiContext& g = *GImGui; + g.IO.MetricsActiveWindows++; + if (window->Flags & ImGuiWindowFlags_Popup) + AddWindowToRenderList(g.RenderDrawLists[1], window); + else if (window->Flags & ImGuiWindowFlags_Tooltip) + AddWindowToRenderList(g.RenderDrawLists[2], window); + else + AddWindowToRenderList(g.RenderDrawLists[0], window); +} + // When using this function it is sane to ensure that float are perfectly rounded to integer values, to that e.g. (int)(max.x-min.x) in user's render produce correct result. void ImGui::PushClipRect(const ImVec2& clip_rect_min, const ImVec2& clip_rect_max, bool intersect_with_current_clip_rect) { @@ -2606,11 +3021,16 @@ void ImGui::EndFrame() if (g.HoveredRootWindow != NULL) { FocusWindow(g.HoveredWindow); + if (g.NavWindow != g.HoveredWindow) + { + g.NavRefRectRel = ImRect(g.IO.MousePos - g.HoveredWindow->Pos, g.IO.MousePos - g.HoveredWindow->Pos); //ImRect(0,0,0,0); + g.NavDisableHighlight = true; + } if (!(g.HoveredWindow->Flags & ImGuiWindowFlags_NoMove)) { g.MovedWindow = g.HoveredWindow; g.MovedWindowMoveId = g.HoveredRootWindow->MoveId; - SetActiveID(g.MovedWindowMoveId, g.HoveredRootWindow); + SetActiveIDNoNav(g.MovedWindowMoveId, g.HoveredRootWindow); } } else if (g.FocusedWindow != NULL && GetFrontMostModalRootWindow() == NULL) @@ -2632,6 +3052,7 @@ void ImGui::EndFrame() continue; AddWindowToSortedBuffer(g.WindowsSortBuffer, window); } + IM_ASSERT(g.Windows.Size == g.WindowsSortBuffer.Size); // we done something wrong g.Windows.swap(g.WindowsSortBuffer); @@ -2662,18 +3083,11 @@ void ImGui::Render() for (int i = 0; i != g.Windows.Size; i++) { ImGuiWindow* window = g.Windows[i]; - if (window->Active && window->HiddenFrames <= 0 && (window->Flags & (ImGuiWindowFlags_ChildWindow)) == 0) - { - // FIXME: Generalize this with a proper layering system so e.g. user can draw in specific layers, below text, .. - g.IO.MetricsActiveWindows++; - if (window->Flags & ImGuiWindowFlags_Popup) - AddWindowToRenderList(g.RenderDrawLists[1], window); - else if (window->Flags & ImGuiWindowFlags_Tooltip) - AddWindowToRenderList(g.RenderDrawLists[2], window); - else - AddWindowToRenderList(g.RenderDrawLists[0], window); - } + if (window->Active && window->HiddenFrames <= 0 && (window->Flags & (ImGuiWindowFlags_ChildWindow)) == 0 && window != g.NavWindowingTarget) + AddWindowToRenderListSelectLayer(window); } + if (g.NavWindowingTarget && g.NavWindowingTarget->Active && g.NavWindowingTarget->HiddenFrames <= 0) // NavWindowing target is always displayed front-most + AddWindowToRenderListSelectLayer(g.NavWindowingTarget); // Flatten layers int n = g.RenderDrawLists[0].Size; @@ -3262,6 +3676,12 @@ bool ImGui::IsItemActive() return false; } +bool ImGui::IsItemFocused() +{ + ImGuiContext& g = *GImGui; + return g.NavId && !g.NavDisableHighlight && g.NavId == g.CurrentWindow->DC.LastItemId; +} + bool ImGui::IsItemClicked(int mouse_button) { return IsMouseClicked(mouse_button) && IsItemHovered(); @@ -3277,6 +3697,11 @@ bool ImGui::IsAnyItemActive() return GImGui->ActiveId != 0; } +bool ImGui::IsAnyItemFocused() +{ + return GImGui->NavId != 0 && !GImGui->NavDisableHighlight; +} + bool ImGui::IsItemVisible() { ImGuiWindow* window = GetCurrentWindowRead(); @@ -3293,6 +3718,19 @@ void ImGui::SetItemAllowOverlap() g.ActiveIdAllowOverlap = true; } +void ImGui::SetItemDefaultFocus() +{ + ImGuiContext& g = *GImGui; + if (g.NavWindow == g.CurrentWindow && (g.NavInitDefaultRequest || g.NavInitDefaultResultId != 0)) + { + g.NavInitDefaultRequest = false; + g.NavInitDefaultResultExplicit = true; + g.NavInitDefaultResultId = g.CurrentWindow->DC.LastItemId; + if (!IsItemVisible()) + SetScrollHere(); + } +} + ImVec2 ImGui::GetItemRectMin() { ImGuiWindow* window = GetCurrentWindowRead(); @@ -3371,7 +3809,9 @@ void ImGui::OpenPopupEx(const char* str_id, bool reopen_existing) ImGuiWindow* window = g.CurrentWindow; ImGuiID id = window->GetID(str_id); int current_stack_size = g.CurrentPopupStack.Size; - ImGuiPopupRef popup_ref = ImGuiPopupRef(id, window, window->GetID("##menus"), g.IO.MousePos); // Tagged as new ref because constructor sets Window to NULL (we are passing the ParentWindow info here) + ImVec2 mouse_pos = g.IO.MousePos; + ImVec2 popup_pos = (g.ActiveIdSource == ImGuiInputSource_Mouse || g.ActiveId == 0) ? mouse_pos : window->DC.LastItemRect.GetCenter(); + ImGuiPopupRef popup_ref = ImGuiPopupRef(id, window, window->GetID("##menus"), popup_pos, mouse_pos); // Tagged as new ref because constructor sets Window to NULL (we are passing the ParentWindow info here) if (g.OpenPopupStack.Size < current_stack_size + 1) g.OpenPopupStack.push_back(popup_ref); else if (reopen_existing || g.OpenPopupStack[current_stack_size].PopupId != id) @@ -3600,6 +4040,14 @@ bool ImGui::BeginChild(const char* str_id, const ImVec2& size_arg, bool border, if (!(parent_window->Flags & ImGuiWindowFlags_ShowBorders)) child_window->Flags &= ~ImGuiWindowFlags_ShowBorders; + // Process navigation-in immediately so NavInit can run on first frame + const ImGuiID id = parent_window->GetChildID(child_window); + if ((child_window->DC.NavHasItems || child_window->DC.NavHasScroll) && GImGui->NavActivateId == id) + { + FocusWindow(child_window); + NavInitWindow(child_window); + SetActiveIDNoNav(id+1, child_window); // Steal ActiveId with a dummy id so that key-press won't activate child item + } return ret; } @@ -3629,13 +4077,22 @@ void ImGui::EndChild() sz.x = ImMax(4.0f, sz.x); if (window->Flags & ImGuiWindowFlags_ChildWindowAutoFitY) sz.y = ImMax(4.0f, sz.y); - ImGui::End(); - window = GetCurrentWindow(); - ImRect bb(window->DC.CursorPos, window->DC.CursorPos + sz); + ImGuiWindow* parent_window = GetCurrentWindow(); + ImGuiID id = parent_window->GetChildID(window); + ImRect bb(parent_window->DC.CursorPos, parent_window->DC.CursorPos + sz); ItemSize(sz); - ItemAdd(bb, NULL); + ItemAdd(bb, (window->DC.NavHasItems || window->DC.NavHasScroll) ? &id : NULL); + if (window->DC.NavHasItems || window->DC.NavHasScroll) + { + //if (!window->DC.NavHasItems && window->DC.NavHasScroll && g.NavWindow == window) // As a special case, we render nav highlight of child when inside when only scrolling is possible + //{ + // bb.Expand(-1.0f); + // id = g.NavId; + //} + RenderNavHighlight(id, bb); + } } } @@ -3862,6 +4319,8 @@ bool ImGui::Begin(const char* name, bool* p_open, const ImVec2& size_on_first_us } const bool window_appearing_after_being_hidden = (window->HiddenFrames == 1); + if (window_appearing_after_being_hidden) + window->NavLastId = 0; // Process SetNextWindow***() calls bool window_pos_set_by_api = false, window_size_set_by_api = false; @@ -3946,7 +4405,7 @@ bool ImGui::Begin(const char* name, bool* p_open, const ImVec2& size_on_first_us // Popup first latch mouse position, will position itself when it appears next frame window->AutoPosLastDirection = -1; if ((flags & ImGuiWindowFlags_Popup) != 0 && !window_pos_set_by_api) - window->PosFloat = g.CurrentPopupStack.back().MousePosOnOpen; + window->PosFloat = g.CurrentPopupStack.back().PopupPosOnOpen; } // Collapse window by double-clicking on title bar @@ -4067,7 +4526,7 @@ bool ImGui::Begin(const char* name, bool* p_open, const ImVec2& size_on_first_us { IM_ASSERT(window_pos_set_by_api); ImRect rect_to_avoid; - if (parent_window->DC.MenuBarAppending) + if (parent_window && parent_window->DC.MenuBarAppending) rect_to_avoid = ImRect(-FLT_MAX, parent_window->Pos.y + parent_window->TitleBarHeight(), FLT_MAX, parent_window->Pos.y + parent_window->TitleBarHeight() + parent_window->MenuBarHeight()); else rect_to_avoid = ImRect(parent_window->Pos.x + style.ItemSpacing.x, -FLT_MAX, parent_window->Pos.x + parent_window->Size.x - style.ItemSpacing.x - parent_window->ScrollbarSizes.x, FLT_MAX); // We want some overlap to convey the relative depth of each popup (here hard-coded to 4) @@ -4082,10 +4541,11 @@ bool ImGui::Begin(const char* name, bool* p_open, const ImVec2& size_on_first_us // Position tooltip (always follows mouse) if ((flags & ImGuiWindowFlags_Tooltip) != 0 && !window_pos_set_by_api) { - ImRect rect_to_avoid(g.IO.MousePos.x - 16, g.IO.MousePos.y - 8, g.IO.MousePos.x + 24, g.IO.MousePos.y + 24); // FIXME: Completely hard-coded. Perhaps center on cursor hit-point instead? - window->PosFloat = FindBestPopupWindowPos(g.IO.MousePos, window->Size, &window->AutoPosLastDirection, rect_to_avoid); + ImVec2 ref_pos = (g.ActiveId == 0 || g.ActiveIdSource == ImGuiInputSource_Mouse) ? g.IO.MousePos : window->DC.LastItemRect.GetCenter(); + ImRect rect_to_avoid(ref_pos.x - 16, ref_pos.y - 8, ref_pos.x + 24, ref_pos.y + 24); // FIXME: Completely hard-coded. Perhaps center on cursor hit-point instead? + window->PosFloat = FindBestPopupWindowPos(ref_pos, window->Size, &window->AutoPosLastDirection, rect_to_avoid); if (window->AutoPosLastDirection == -1) - window->PosFloat = g.IO.MousePos + ImVec2(2,2); // If there's not enough room, for tooltip we prefer avoiding the cursor at all cost even if it means that part of the tooltip won't be visible. + window->PosFloat = ref_pos + ImVec2(2,2); // If there's not enough room, for tooltip we prefer avoiding the cursor at all cost even if it means that part of the tooltip won't be visible. } // Clamp position so it stays visible @@ -4133,6 +4593,16 @@ bool ImGui::Begin(const char* name, bool* p_open, const ImVec2& size_on_first_us if ((flags & ImGuiWindowFlags_Modal) != 0 && window == GetFrontMostModalRootWindow()) window->DrawList->AddRectFilled(fullscreen_rect.Min, fullscreen_rect.Max, GetColorU32(ImGuiCol_ModalWindowDarkening, g.ModalWindowDarkeningRatio)); + // Navigation windowing (via ImGuiKey_NavWindowing key) shows whole window selected + // FIXME-NAVIGATION: Styling + if (g.NavWindowingTarget == window) + { + ImRect bb = window->Rect(); + bb.Expand(g.FontSize); + window->DrawList->AddRectFilled(bb.Min, bb.Max, IM_COL32(255,255,255,30)/*ImGui::GetColorU32(ImGuiCol_HeaderHovered, 0.15f)*/, g.Style.WindowRounding); + window->DrawList->AddRect(bb.Min, bb.Max, ImGui::GetColorU32(ImGuiCol_HeaderHovered), g.Style.WindowRounding); + } + // Draw window + handle manual resize ImRect title_bar_rect = window->TitleBarRect(); const float window_rounding = (flags & ImGuiWindowFlags_ChildWindow) ? style.ChildWindowRounding : style.WindowRounding; @@ -4152,28 +4622,47 @@ bool ImGui::Begin(const char* name, bool* p_open, const ImVec2& size_on_first_us const ImRect resize_rect(br - ImVec2(resize_corner_size * 0.75f, resize_corner_size * 0.75f), br); const ImGuiID resize_id = window->GetID("#RESIZE"); bool hovered, held; - ButtonBehavior(resize_rect, resize_id, &hovered, &held, ImGuiButtonFlags_FlattenChilds); - resize_col = GetColorU32(held ? ImGuiCol_ResizeGripActive : hovered ? ImGuiCol_ResizeGripHovered : ImGuiCol_ResizeGrip); - + ButtonBehavior(resize_rect, resize_id, &hovered, &held, ImGuiButtonFlags_FlattenChilds | ImGuiButtonFlags_NoNavOverride); if (hovered || held) g.MouseCursor = ImGuiMouseCursor_ResizeNWSE; + ImVec2 nav_resize_delta(0.0f, 0.0f); + if (g.NavWindowingTarget == window) + { + const float resize_speed = ImFloor(40 * g.FontSize * g.IO.DeltaTime); + if (IsKeyDownMap(ImGuiKey_NavLeft)) nav_resize_delta.x -= resize_speed; + if (IsKeyDownMap(ImGuiKey_NavRight)) nav_resize_delta.x += resize_speed; + if (IsKeyDownMap(ImGuiKey_NavUp)) nav_resize_delta.y -= resize_speed; + if (IsKeyDownMap(ImGuiKey_NavDown)) nav_resize_delta.y += resize_speed; + } + + ImVec2 size_target(FLT_MAX,FLT_MAX); if (g.HoveredWindow == window && held && g.IO.MouseDoubleClicked[0]) { // Manual auto-fit when double-clicking - ApplySizeFullWithConstraint(window, size_auto_fit); - if (!(flags & ImGuiWindowFlags_NoSavedSettings)) - MarkSettingsDirty(); + size_target = size_auto_fit; SetActiveID(0); } + else if (nav_resize_delta.x != 0.0f || nav_resize_delta.y != 0.0f) + { + // FIXME-NAVIGATION: Should store and accumulate into a separate size buffer to handle sizing constraints properly + size_target = window->SizeFull + nav_resize_delta; + held = true; // For coloring + } else if (held) { // We don't use an incremental MouseDelta but rather compute an absolute target size based on mouse position - ApplySizeFullWithConstraint(window, (g.IO.MousePos - g.ActiveIdClickOffset + resize_rect.GetSize()) - window->Pos); + size_target = (g.IO.MousePos - g.ActiveIdClickOffset + resize_rect.GetSize()) - window->Pos; + } + + if (size_target.x != FLT_MAX && size_target.y != FLT_MAX) + { + ApplySizeFullWithConstraint(window, size_target); if (!(flags & ImGuiWindowFlags_NoSavedSettings)) MarkSettingsDirty(); } + resize_col = GetColorU32(held ? ImGuiCol_ResizeGripActive : hovered ? ImGuiCol_ResizeGripHovered : ImGuiCol_ResizeGrip); window->Size = window->SizeFull; title_bar_rect = window->TitleBarRect(); } @@ -4255,6 +4744,9 @@ bool ImGui::Begin(const char* name, bool* p_open, const ImVec2& size_on_first_us window->DC.CursorMaxPos = window->DC.CursorStartPos; window->DC.CurrentLineHeight = window->DC.PrevLineHeight = 0.0f; window->DC.CurrentLineTextBaseOffset = window->DC.PrevLineTextBaseOffset = 0.0f; + window->DC.NavHasItems = window->DC.NavHasItemsNext; + window->DC.NavHasItemsNext = false; + window->DC.NavHasScroll = (GetScrollMaxY() > 0.0f); window->DC.MenuBarAppending = false; window->DC.MenuBarOffsetX = ImMax(window->WindowPadding.x, style.ItemSpacing.x); window->DC.LogLinePosY = window->DC.CursorPos.y - 9999.0f; @@ -4263,6 +4755,7 @@ bool ImGui::Begin(const char* name, bool* p_open, const ImVec2& size_on_first_us window->DC.ItemWidth = window->ItemWidthDefault; window->DC.TextWrapPos = -1.0f; // disabled window->DC.AllowKeyboardFocus = true; + window->DC.AllowNavDefaultFocus = true; window->DC.ButtonRepeat = false; window->DC.ItemWidthStack.resize(0); window->DC.TextWrapPosStack.resize(0); @@ -4286,7 +4779,11 @@ bool ImGui::Begin(const char* name, bool* p_open, const ImVec2& size_on_first_us // New windows appears in front (we need to do that AFTER setting DC.CursorStartPos so our initial navigation reference rectangle can start around there) if (!window_was_active && !(flags & ImGuiWindowFlags_NoFocusOnAppearing)) if (!(flags & (ImGuiWindowFlags_ChildWindow|ImGuiWindowFlags_Tooltip)) || (flags & ImGuiWindowFlags_Popup)) + { FocusWindow(window); + IM_ASSERT(g.NavWindow == window); + NavInitWindow(window); + } // Title bar if (!(flags & ImGuiWindowFlags_NoTitleBar)) @@ -4329,16 +4826,23 @@ bool ImGui::Begin(const char* name, bool* p_open, const ImVec2& size_on_first_us */ } - // Inner clipping rectangle + // Inner rectangle and inner clipping rectangle // We set this up after processing the resize grip so that our clip rectangle doesn't lag by a frame // Note that if our window is collapsed we will end up with a null clipping rectangle which is the correct behavior. const ImRect title_bar_rect = window->TitleBarRect(); const float border_size = window->BorderSize; - ImRect clip_rect; // Force round to ensure that e.g. (int)(max.x-min.x) in user's render code produce correct result. - clip_rect.Min.x = ImFloor(0.5f + title_bar_rect.Min.x + ImMax(border_size, ImFloor(window->WindowPadding.x*0.5f))); - clip_rect.Min.y = ImFloor(0.5f + title_bar_rect.Max.y + window->MenuBarHeight() + border_size); - clip_rect.Max.x = ImFloor(0.5f + window->Pos.x + window->Size.x - window->ScrollbarSizes.x - ImMax(border_size, ImFloor(window->WindowPadding.x*0.5f))); - clip_rect.Max.y = ImFloor(0.5f + window->Pos.y + window->Size.y - window->ScrollbarSizes.y - border_size); + window->InnerRect.Min.x = title_bar_rect.Min.x; + window->InnerRect.Min.y = title_bar_rect.Max.y + window->MenuBarHeight(); + window->InnerRect.Max.x = window->Pos.x + window->Size.x - window->ScrollbarSizes.x; + window->InnerRect.Max.y = window->Pos.y + window->Size.y - window->ScrollbarSizes.y; + //window->DrawList->AddRect(window->InnerRect.Min, window->InnerRect.Max, IM_COL32_WHITE); + + // Force round operator last to ensure that e.g. (int)(max.x-min.x) in user's render code produce correct result. + ImRect clip_rect; + clip_rect.Min.x = ImFloor(0.5f + window->InnerRect.Min.x + ImMax(border_size, ImFloor(window->WindowPadding.x*0.5f))); + clip_rect.Min.y = ImFloor(0.5f + window->InnerRect.Min.y + border_size); + clip_rect.Max.x = ImFloor(0.5f + window->InnerRect.Max.x - ImMax(border_size, ImFloor(window->WindowPadding.x*0.5f))); + clip_rect.Max.y = ImFloor(0.5f + window->InnerRect.Max.y - border_size); PushClipRect(clip_rect.Min, clip_rect.Max, true); // Clear 'accessed' flag last thing @@ -4437,7 +4941,7 @@ static void Scrollbar(ImGuiWindow* window, bool horizontal) bool held = false; bool hovered = false; const bool previously_held = (g.ActiveId == id); - ImGui::ButtonBehavior(bb, id, &hovered, &held); + ImGui::ButtonBehavior(bb, id, &hovered, &held, ImGuiButtonFlags_NoNavOverride); float scroll_max = ImMax(1.0f, win_size_contents_v - win_size_avail_v); float scroll_ratio = ImSaturate(scroll_v / scroll_max); @@ -4498,6 +5002,16 @@ void ImGui::FocusWindow(ImGuiWindow* window) { ImGuiContext& g = *GImGui; + if (g.FocusedWindow != window) + { + g.NavId = window ? window->NavLastId : 0; + g.NavIdIsAlive = false; + if (window && g.NavDisableMouseHover) + g.NavMousePosDirty = true; + g.NavRefRectRel.Min = g.NavRefRectRel.Max = window ? (window->DC.CursorStartPos - window->Pos) : ImVec2(0,0); + g.NavWindow = window; + } + // Passing NULL allow to disable keyboard focus g.FocusedWindow = window; if (!window) @@ -4524,6 +5038,24 @@ void ImGui::FocusWindow(ImGuiWindow* window) g.Windows.push_back(window); } +// This needs to be called before we submit any widget (aka in or before Begin) +void ImGui::NavInitWindow(ImGuiWindow* window) +{ + ImGuiContext& g = *GImGui; + if (!(window->Flags & ImGuiWindowFlags_ChildWindow) || (window->Flags & ImGuiWindowFlags_Popup) || (window->NavLastId == 0)) + { + g.NavId = window->NavLastId = 0; + g.NavInitDefaultRequest = true; + g.NavInitDefaultResultExplicit = false; + g.NavInitDefaultResultId = 0; + } + else + { + g.NavId = window->NavLastId; + } + g.NavWindow = window; +} + void ImGui::PushItemWidth(float item_width) { ImGuiWindow* window = GetCurrentWindow(); @@ -5497,9 +6029,13 @@ bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool // PressedOnClick | | .. // PressedOnRelease | | .. (NOT on release) // PressedOnDoubleClick | | .. + // FIXME-NAVIGATION: We don't honor those different behaviors. if ((flags & ImGuiButtonFlags_PressedOnClickRelease) && g.IO.MouseClicked[0]) { - SetActiveID(id, window); // Hold on ID + if (flags & ImGuiButtonFlags_NoNavOverride) + SetActiveIDNoNav(id, window); + else + SetActiveID(id, window); // Hold on ID FocusWindow(window); g.ActiveIdClickOffset = g.IO.MousePos - bb.Min; } @@ -5521,10 +6057,29 @@ bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool if ((flags & ImGuiButtonFlags_Repeat) && g.ActiveId == id && g.IO.MouseDownDuration[0] > 0.0f && IsMouseClicked(0, true)) pressed = true; } + + if (pressed) + g.NavDisableHighlight = true; + } + + // Gamepad/Keyboard navigation + if (g.NavId == id && !g.NavDisableHighlight && (g.ActiveId == 0 || g.ActiveId == id)) + { + // We report navigated item as hovered but we don't set g.HoveredId to not interfere with mouse + hovered = true; + if (IsKeyDownMap(ImGuiKey_NavActivate)) + { + // Set active id so it can be queried by user via IsItemActive(), etc. but don't react to it ourselves + g.NavActivateId = g.NavId; + SetActiveID(g.NavId, window); + g.ActiveIdAllowNavMove = true; + } + if (IsKeyPressedMap(ImGuiKey_NavActivate, (flags & ImGuiButtonFlags_Repeat) != 0)) + pressed = true; } bool held = false; - if (g.ActiveId == id) + if (g.ActiveId == id && g.ActiveIdSource == ImGuiInputSource_Mouse) { if (g.IO.MouseDown[0]) { @@ -5537,7 +6092,12 @@ bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool pressed = true; SetActiveID(0); } + if (!(flags & ImGuiButtonFlags_NoNavOverride)) + g.NavDisableHighlight = true; } + if (g.ActiveId == id && g.ActiveIdSource == ImGuiInputSource_Nav) + if (!IsKeyDownMap(ImGuiKey_NavActivate)) + SetActiveID(0); // AllowOverlap mode (rarely used) requires previous frame HoveredId to be null or to match. This allows using patterns where a later submitted widget overlaps a previous one. if (hovered && (flags & ImGuiButtonFlags_AllowOverlapMode) && (g.HoveredIdPreviousFrame != id && g.HoveredIdPreviousFrame != 0)) @@ -5576,6 +6136,7 @@ bool ImGui::ButtonEx(const char* label, const ImVec2& size_arg, ImGuiButtonFlags // Render const ImU32 col = GetColorU32((hovered && held) ? ImGuiCol_ButtonActive : hovered ? ImGuiCol_ButtonHovered : ImGuiCol_Button); + RenderNavHighlight(id, bb); RenderFrame(bb.Min, bb.Max, col, true, style.FrameRounding); RenderTextClipped(bb.Min, bb.Max, label, NULL, &label_size, ImGuiAlign_Center | ImGuiAlign_VCenter); @@ -5629,6 +6190,12 @@ bool ImGui::CloseButton(ImGuiID id, const ImVec2& pos, float radius) ImGuiWindow* window = GetCurrentWindow(); const ImRect bb(pos - ImVec2(radius,radius), pos + ImVec2(radius,radius)); + const bool backup_allow_nav_default_focus = window->DC.AllowNavDefaultFocus; // We could exposethis as a flag to ItemAdd() but it is such a unique case for now + window->DC.AllowNavDefaultFocus = false; + const bool added = ItemAdd(bb, &id); // To allow navigation + window->DC.AllowNavDefaultFocus = backup_allow_nav_default_focus; + if (!added) + return false; bool hovered, held; bool pressed = ButtonBehavior(bb, id, &hovered, &held); @@ -5703,6 +6270,7 @@ bool ImGui::ImageButton(ImTextureID user_texture_id, const ImVec2& size, const I // Render const ImU32 col = GetColorU32((hovered && held) ? ImGuiCol_ButtonActive : hovered ? ImGuiCol_ButtonHovered : ImGuiCol_Button); + RenderNavHighlight(id, bb); RenderFrame(bb.Min, bb.Max, col, true, ImClamp((float)ImMin(padding.x, padding.y), 0.0f, style.FrameRounding)); if (bg_col.w > 0.0f) window->DrawList->AddRectFilled(image_bb.Min, image_bb.Max, GetColorU32(bg_col)); @@ -5916,9 +6484,9 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l bool hovered, held, pressed = ButtonBehavior(interact_bb, id, &hovered, &held, button_flags); if (pressed && !(flags & ImGuiTreeNodeFlags_Leaf)) { - bool toggled = !(flags & (ImGuiTreeNodeFlags_OpenOnArrow | ImGuiTreeNodeFlags_OpenOnDoubleClick)); + bool toggled = !(flags & (ImGuiTreeNodeFlags_OpenOnArrow | ImGuiTreeNodeFlags_OpenOnDoubleClick)) || (g.NavActivateId == id); if (flags & ImGuiTreeNodeFlags_OpenOnArrow) - toggled |= IsMouseHoveringRect(interact_bb.Min, ImVec2(interact_bb.Min.x + text_offset_x, interact_bb.Max.y)); + toggled |= IsMouseHoveringRect(interact_bb.Min, ImVec2(interact_bb.Min.x + text_offset_x, interact_bb.Max.y)) && (!g.NavDisableMouseHover); if (flags & ImGuiTreeNodeFlags_OpenOnDoubleClick) toggled |= g.IO.MouseDoubleClicked[0]; if (toggled) @@ -6326,7 +6894,7 @@ bool ImGui::InputScalarAsWidgetReplacement(const ImRect& aabb, const char* label ImGuiWindow* window = GetCurrentWindow(); // Our replacement widget will override the focus ID (registered previously to allow for a TAB focus to happen) - SetActiveID(g.ScalarAsInputTextId, window); + SetActiveIDNoNav(g.ScalarAsInputTextId, window); SetHoveredID(0); FocusableItemUnregister(window); @@ -6371,6 +6939,22 @@ int ImGui::ParseFormatPrecision(const char* fmt, int default_precision) return precision; } +// Adjustment delta for slider/drag/etc. +// FIXME-NAVIGATION: Accelerate over time? Expose more settings? Handle faster/slower modifiers here instead of widget level? +ImVec2 ImGui::NavGetTweakDelta() +{ + ImGuiContext& g = *GImGui; + float repeat_delay = g.IO.KeyRepeatDelay * 0.80f; + float repeat_rate = g.IO.KeyRepeatRate * 0.30f; + + ImVec2 delta(0.0f, 0.0f); + if (int count = GetKeyPressedAmount(g.IO.KeyMap[ImGuiKey_NavLeft], repeat_delay, repeat_rate)) delta.x = (float)-count; + if (int count = GetKeyPressedAmount(g.IO.KeyMap[ImGuiKey_NavRight], repeat_delay, repeat_rate)) delta.x = (float)+count; + if (int count = GetKeyPressedAmount(g.IO.KeyMap[ImGuiKey_NavUp], repeat_delay, repeat_rate)) delta.y = (float)-count; + if (int count = GetKeyPressedAmount(g.IO.KeyMap[ImGuiKey_NavDown], repeat_delay, repeat_rate)) delta.y = (float)+count; + return delta; +} + static float GetMinimumStepAtDecimalPrecision(int decimal_precision) { static const float min_steps[10] = { 1.0f, 0.1f, 0.01f, 0.001f, 0.0001f, 0.00001f, 0.000001f, 0.0000001f, 0.00000001f, 0.000000001f }; @@ -6422,7 +7006,9 @@ bool ImGui::SliderBehavior(const ImRect& frame_bb, ImGuiID id, float* v, float v const ImGuiStyle& style = g.Style; // Draw frame - RenderFrame(frame_bb.Min, frame_bb.Max, GetColorU32(ImGuiCol_FrameBg), true, style.FrameRounding); + const ImU32 frame_col = GetColorU32((g.ActiveId == id && g.ActiveIdSource == ImGuiInputSource_Nav) ? ImGuiCol_FrameBgActive : ImGuiCol_FrameBg); + RenderNavHighlight(id, frame_bb); + RenderFrame(frame_bb.Min, frame_bb.Max, frame_col, true, style.FrameRounding); const bool is_non_linear = (power < 1.0f-0.00001f) && (power > 1.0f-0.00001f); const bool is_horizontal = (flags & ImGuiSliderFlags_Vertical) == 0; @@ -6457,13 +7043,48 @@ bool ImGui::SliderBehavior(const ImRect& frame_bb, ImGuiID id, float* v, float v bool value_changed = false; if (g.ActiveId == id) { - if (g.IO.MouseDown[0]) + bool set_new_value = false; + float normalized_pos = 0.0f; + if (g.ActiveIdSource == ImGuiInputSource_Mouse && g.IO.MouseDown[0]) { const float mouse_abs_pos = is_horizontal ? g.IO.MousePos.x : g.IO.MousePos.y; - float normalized_pos = ImClamp((mouse_abs_pos - slider_usable_pos_min) / slider_usable_sz, 0.0f, 1.0f); + normalized_pos = ImClamp((mouse_abs_pos - slider_usable_pos_min) / slider_usable_sz, 0.0f, 1.0f); if (!is_horizontal) normalized_pos = 1.0f - normalized_pos; + set_new_value = true; + } + else if (g.ActiveIdSource == ImGuiInputSource_Nav && IsKeyDownMap(ImGuiKey_NavActivate)) + { + const ImVec2 delta2 = NavGetTweakDelta(); + if (float delta = is_horizontal ? delta2.x : -delta2.y) + { + normalized_pos = SliderBehaviorCalcRatioFromValue(*v, v_min, v_max, power, linear_zero_pos); + if (decimal_precision == 0 && !is_non_linear) + { + if (fabsf(v_max - v_min) <= 100.0f || IsKeyDownMap(ImGuiKey_NavTweakSlower)) + delta = ((delta < 0.0f) ? -1.0f : +1.0f) / (v_max - v_min); // Gamepad/keyboard tweak speeds in integer steps + else + delta /= 100.0f; + } + else + { + delta /= 100.0f; // Gamepad/keyboard tweak speeds in % of slider bounds + if (IsKeyDownMap(ImGuiKey_NavTweakSlower)) + delta /= 10.0f; + } + if (IsKeyDownMap(ImGuiKey_NavTweakFaster)) + delta *= 10.0f; + normalized_pos = ImSaturate(normalized_pos + delta); // FIXME-NAVIGATION: todo: cancel adjustment if current value already past edge and we are moving in edge direction, to avoid clamping value to edge. + set_new_value = true; + } + } + else + { + SetActiveID(0); + } + if (set_new_value) + { float new_value; if (is_non_linear) { @@ -6501,10 +7122,6 @@ bool ImGui::SliderBehavior(const ImRect& frame_bb, ImGuiID id, float* v, float v value_changed = true; } } - else - { - SetActiveID(0); - } } // Draw @@ -6543,7 +7160,7 @@ bool ImGui::SliderFloat(const char* label, float* v, float v_min, float v_max, c const ImRect total_bb(frame_bb.Min, frame_bb.Max + ImVec2(label_size.x > 0.0f ? style.ItemInnerSpacing.x + label_size.x : 0.0f, 0.0f)); // NB- we don't call ItemSize() yet because we may turn into a text edit box below - if (!ItemAdd(total_bb, &id)) + if (!ItemAdd(total_bb, &id, &frame_bb)) { ItemSize(total_bb, style.FramePadding.y); return false; @@ -6559,13 +7176,12 @@ bool ImGui::SliderFloat(const char* label, float* v, float v_min, float v_max, c // Tabbing or CTRL-clicking on Slider turns it into an input box bool start_text_input = false; - const bool tab_focus_requested = FocusableItemRegister(window, g.ActiveId == id); - if (tab_focus_requested || (hovered && g.IO.MouseClicked[0])) + const bool tab_focus_requested = FocusableItemRegister(window, id); + if (tab_focus_requested || (hovered && g.IO.MouseClicked[0]) || g.NavActivateId == id || g.NavInputId == id) { SetActiveID(id, window); FocusWindow(window); - - if (tab_focus_requested || g.IO.KeyCtrl) + if (tab_focus_requested || g.IO.KeyCtrl || g.NavInputId == id) { start_text_input = true; g.ScalarAsInputTextId = 0; @@ -6605,7 +7221,7 @@ bool ImGui::VSliderFloat(const char* label, const ImVec2& size, float* v, float const ImRect bb(frame_bb.Min, frame_bb.Max + ImVec2(label_size.x > 0.0f ? style.ItemInnerSpacing.x + label_size.x : 0.0f, 0.0f)); ItemSize(bb, style.FramePadding.y); - if (!ItemAdd(frame_bb, &id)) + if (!ItemAdd(frame_bb, &id, &frame_bb)) return false; const bool hovered = IsHovered(frame_bb, id); @@ -6616,7 +7232,7 @@ bool ImGui::VSliderFloat(const char* label, const ImVec2& size, float* v, float display_format = "%.3f"; int decimal_precision = ParseFormatPrecision(display_format, 3); - if (hovered && g.IO.MouseClicked[0]) + if ((hovered && g.IO.MouseClicked[0]) || g.NavActivateId == id || g.NavInputId == id) { SetActiveID(id, window); FocusWindow(window); @@ -6756,6 +7372,7 @@ bool ImGui::DragBehavior(const ImRect& frame_bb, ImGuiID id, float* v, float v_s // Draw frame const ImU32 frame_col = GetColorU32(g.ActiveId == id ? ImGuiCol_FrameBgActive : g.HoveredId == id ? ImGuiCol_FrameBgHovered : ImGuiCol_FrameBg); + RenderNavHighlight(id, frame_bb); RenderFrame(frame_bb.Min, frame_bb.Max, frame_col, true, style.FrameRounding); bool value_changed = false; @@ -6763,7 +7380,7 @@ bool ImGui::DragBehavior(const ImRect& frame_bb, ImGuiID id, float* v, float v_s // Process clicking on the drag if (g.ActiveId == id) { - if (g.IO.MouseDown[0]) + if (g.IO.MouseDown[0] || IsKeyDownMap(ImGuiKey_NavActivate)) { if (g.ActiveIdIsJustActivated) { @@ -6777,12 +7394,25 @@ bool ImGui::DragBehavior(const ImRect& frame_bb, ImGuiID id, float* v, float v_s float v_cur = g.DragCurrentValue; const ImVec2 mouse_drag_delta = GetMouseDragDelta(0, 1.0f); - float adjust_delta = mouse_drag_delta.x - g.DragLastMouseDelta.x; - if (g.IO.KeyShift && g.DragSpeedScaleFast >= 0.0f) - adjust_delta *= g.DragSpeedScaleFast; - if (g.IO.KeyAlt && g.DragSpeedScaleSlow >= 0.0f) - adjust_delta *= g.DragSpeedScaleSlow; + float adjust_delta = 0.0f; + if (g.ActiveIdSource == ImGuiInputSource_Mouse) + { + adjust_delta = mouse_drag_delta.x - g.DragLastMouseDelta.x; + if (g.IO.KeyShift && g.DragSpeedScaleFast >= 0.0f) + adjust_delta *= g.DragSpeedScaleFast; + if (g.IO.KeyAlt && g.DragSpeedScaleSlow >= 0.0f) + adjust_delta *= g.DragSpeedScaleSlow; + } + if (g.ActiveIdSource == ImGuiInputSource_Nav) + { + adjust_delta = NavGetTweakDelta().x; + if (IsKeyDownMap(ImGuiKey_NavTweakFaster) && g.DragSpeedScaleFast >= 0.0f) + adjust_delta *= 10.0f; + if (IsKeyDownMap(ImGuiKey_NavTweakSlower) && g.DragSpeedScaleSlow >= 0.0f) + adjust_delta /= 10.0f; + } adjust_delta *= v_speed; + g.DragLastMouseDelta.x = mouse_drag_delta.x; if (fabsf(adjust_delta) > 0.0f) { @@ -6800,7 +7430,6 @@ bool ImGui::DragBehavior(const ImRect& frame_bb, ImGuiID id, float* v, float v_s { v_cur += adjust_delta; } - g.DragLastMouseDelta.x = mouse_drag_delta.x; // Clamp if (v_min < v_max) @@ -6842,7 +7471,7 @@ bool ImGui::DragFloat(const char* label, float* v, float v_speed, float v_min, f const ImRect total_bb(frame_bb.Min, frame_bb.Max + ImVec2(label_size.x > 0.0f ? style.ItemInnerSpacing.x + label_size.x : 0.0f, 0.0f)); // NB- we don't call ItemSize() yet because we may turn into a text edit box below - if (!ItemAdd(total_bb, &id)) + if (!ItemAdd(total_bb, &id, &frame_bb)) { ItemSize(total_bb, style.FramePadding.y); return false; @@ -6858,13 +7487,12 @@ bool ImGui::DragFloat(const char* label, float* v, float v_speed, float v_min, f // Tabbing or CTRL-clicking on Drag turns it into an input box bool start_text_input = false; - const bool tab_focus_requested = FocusableItemRegister(window, g.ActiveId == id); - if (tab_focus_requested || (hovered && (g.IO.MouseClicked[0] | g.IO.MouseDoubleClicked[0]))) + const bool tab_focus_requested = FocusableItemRegister(window, id); + if (tab_focus_requested || (hovered && (g.IO.MouseClicked[0] || g.IO.MouseDoubleClicked[0])) || g.NavActivateId == id || g.NavInputId == id) { SetActiveID(id, window); FocusWindow(window); - - if (tab_focus_requested || g.IO.KeyCtrl || g.IO.MouseDoubleClicked[0]) + if (tab_focus_requested || g.IO.KeyCtrl || g.IO.MouseDoubleClicked[0] || g.NavInputId == id) { start_text_input = true; g.ScalarAsInputTextId = 0; @@ -7052,7 +7680,7 @@ void ImGui::PlotEx(ImGuiPlotType plot_type, const char* label, float (*values_ge const ImRect inner_bb(frame_bb.Min + style.FramePadding, frame_bb.Max - style.FramePadding); const ImRect total_bb(frame_bb.Min, frame_bb.Max + ImVec2(label_size.x > 0.0f ? style.ItemInnerSpacing.x + label_size.x : 0.0f, 0)); ItemSize(total_bb, style.FramePadding.y); - if (!ItemAdd(total_bb, NULL)) + if (!ItemAdd(total_bb, NULL, &frame_bb)) return; // Determine scale from values if not specified @@ -7242,6 +7870,7 @@ bool ImGui::Checkbox(const char* label, bool* v) if (pressed) *v = !(*v); + RenderNavHighlight(id, total_bb); RenderFrame(check_bb.Min, check_bb.Max, GetColorU32((held && hovered) ? ImGuiCol_FrameBgActive : hovered ? ImGuiCol_FrameBgHovered : ImGuiCol_FrameBg), true, style.FrameRounding); if (*v) { @@ -7308,6 +7937,7 @@ bool ImGui::RadioButton(const char* label, bool active) bool hovered, held; bool pressed = ButtonBehavior(total_bb, id, &hovered, &held); + RenderNavHighlight(id, total_bb); window->DrawList->AddCircleFilled(center, radius, GetColorU32((held && hovered) ? ImGuiCol_FrameBgActive : hovered ? ImGuiCol_FrameBgHovered : ImGuiCol_FrameBg), 16); if (active) { @@ -7634,7 +8264,7 @@ bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2 else { ItemSize(total_bb, style.FramePadding.y); - if (!ItemAdd(total_bb, &id)) + if (!ItemAdd(total_bb, &id, &frame_bb)) return false; } @@ -7662,7 +8292,7 @@ bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2 const bool is_shift_down = io.KeyShift; const bool is_alt_down = io.KeyAlt; const bool is_super_down = io.KeySuper; - const bool focus_requested = FocusableItemRegister(window, g.ActiveId == id, (flags & (ImGuiInputTextFlags_CallbackCompletion|ImGuiInputTextFlags_AllowTabInput)) == 0); // Using completion callback disable keyboard tabbing + const bool focus_requested = FocusableItemRegister(window, id, (flags & (ImGuiInputTextFlags_CallbackCompletion|ImGuiInputTextFlags_AllowTabInput)) == 0); // Using completion callback disable keyboard tabbing const bool focus_requested_by_code = focus_requested && (window->FocusIdxAllCounter == window->FocusIdxAllRequestCurrent); const bool focus_requested_by_tab = focus_requested && !focus_requested_by_code; @@ -7676,8 +8306,9 @@ bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2 const bool user_scrolled = is_multiline && g.ActiveId == 0 && edit_state.Id == id && g.ActiveIdPreviousFrame == draw_window->GetIDNoKeepAlive("#SCROLLY"); bool clear_active_id = false; - bool select_all = (g.ActiveId != id) && (flags & ImGuiInputTextFlags_AutoSelectAll) != 0; - if (focus_requested || user_clicked || user_scrolled) + + bool select_all = (g.ActiveId != id) && (((flags & ImGuiInputTextFlags_AutoSelectAll) != 0) || (g.NavInputId == id)); + if (focus_requested || user_clicked || user_scrolled || g.NavInputId == id) { if (g.ActiveId != id) { @@ -7815,7 +8446,9 @@ bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2 { bool ctrl_enter_for_new_line = (flags & ImGuiInputTextFlags_CtrlEnterForNewLine) != 0; if (!is_multiline || (ctrl_enter_for_new_line && !is_ctrl_down) || (!ctrl_enter_for_new_line && is_ctrl_down)) + { enter_pressed = clear_active_id = true; + } else if (is_editable) { unsigned int c = '\n'; // Insert new line @@ -7995,6 +8628,7 @@ bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2 // Select which buffer we are going to display. When ImGuiInputTextFlags_NoLiveEdit is set 'buf' might still be the old value. We set buf to NULL to prevent accidental usage from now on. const char* buf_display = (g.ActiveId == id && is_editable) ? edit_state.TempTextBuffer.Data : buf; buf = NULL; + RenderNavHighlight(id, frame_bb); if (!is_multiline) RenderFrame(frame_bb.Min, frame_bb.Max, GetColorU32(ImGuiCol_FrameBg), true, style.FrameRounding); @@ -8408,17 +9042,18 @@ bool ImGui::Combo(const char* label, int* current_item, bool (*items_getter)(voi const ImRect frame_bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(w, label_size.y + style.FramePadding.y*2.0f)); const ImRect total_bb(frame_bb.Min, frame_bb.Max + ImVec2(label_size.x > 0.0f ? style.ItemInnerSpacing.x + label_size.x : 0.0f, 0.0f)); ItemSize(total_bb, style.FramePadding.y); - if (!ItemAdd(total_bb, &id)) + if (!ItemAdd(total_bb, &id, &frame_bb)) return false; const float arrow_size = (g.FontSize + style.FramePadding.x * 2.0f); const bool hovered = IsHovered(frame_bb, id); + const bool navigated = g.NavId == id; bool popup_open = IsPopupOpen(id); - bool popup_opened_now = false; const ImRect value_bb(frame_bb.Min, frame_bb.Max - ImVec2(arrow_size, 0.0f)); + RenderNavHighlight(id, frame_bb); RenderFrame(frame_bb.Min, frame_bb.Max, GetColorU32(ImGuiCol_FrameBg), true, style.FrameRounding); - RenderFrame(ImVec2(frame_bb.Max.x-arrow_size, frame_bb.Min.y), frame_bb.Max, GetColorU32(popup_open || hovered ? ImGuiCol_ButtonHovered : ImGuiCol_Button), true, style.FrameRounding); // FIXME-ROUNDING + RenderFrame(ImVec2(frame_bb.Max.x-arrow_size, frame_bb.Min.y), frame_bb.Max, GetColorU32(popup_open || hovered || navigated ? ImGuiCol_ButtonHovered : ImGuiCol_Button), true, style.FrameRounding); // FIXME-ROUNDING RenderCollapseTriangle(ImVec2(frame_bb.Max.x-arrow_size, frame_bb.Min.y) + style.FramePadding, true); if (*current_item >= 0 && *current_item < items_count) @@ -8431,22 +9066,30 @@ bool ImGui::Combo(const char* label, int* current_item, bool (*items_getter)(voi if (label_size.x > 0) RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, frame_bb.Min.y + style.FramePadding.y), label); + bool popup_toggled = false; if (hovered) { SetHoveredID(id); if (g.IO.MouseClicked[0]) { SetActiveID(0); - if (IsPopupOpen(id)) - { - ClosePopup(id); - } - else - { - FocusWindow(window); - OpenPopup(label); - popup_open = popup_opened_now = true; - } + popup_toggled = true; + } + } + if (g.NavActivateId == id) + popup_toggled = true; + if (popup_toggled) + { + if (IsPopupOpen(id)) + { + ClosePopup(id); + } + else + { + window->NavLastId = id; + FocusWindow(window); + OpenPopup(label); + popup_open = true; } } @@ -8475,6 +9118,7 @@ bool ImGui::Combo(const char* label, int* current_item, bool (*items_getter)(voi if (BeginPopupEx(label, flags)) { // Display items + // FIXME-OPT: Use clipper Spacing(); for (int i = 0; i < items_count; i++) { @@ -8489,8 +9133,8 @@ bool ImGui::Combo(const char* label, int* current_item, bool (*items_getter)(voi value_changed = true; *current_item = i; } - if (item_selected && popup_opened_now) - SetScrollHere(); + if (item_selected && popup_toggled) + SetItemDefaultFocus(); //SetScrollHere(); PopID(); } EndPopup(); @@ -8540,7 +9184,7 @@ bool ImGui::Selectable(const char* label, bool selected, ImGuiSelectableFlags fl bb_with_spacing.Min.y -= spacing_U; bb_with_spacing.Max.x += spacing_R; bb_with_spacing.Max.y += spacing_D; - if (!ItemAdd(bb_with_spacing, &id)) + if (!ItemAdd(bb_with_spacing, (flags & ImGuiSelectableFlags_Disabled) ? NULL : &id)) { if ((flags & ImGuiSelectableFlags_SpanAllColumns) && window->DC.ColumnsCount > 1) PushColumnClipRect(); @@ -8662,7 +9306,7 @@ bool ImGui::ListBox(const char* label, int* current_item, bool (*items_getter)(v // Assume all items have even height (= 1 line of text). If you need items of different or variable sizes you can create a custom version of ListBox() in your code without using the clipper. bool value_changed = false; - ImGuiListClipper clipper(items_count, GetTextLineHeightWithSpacing()); + ImGuiListClipper clipper(items_count, GetTextLineHeightWithSpacing()); // We know exactly our line height here so we pass it as a minor optimization, but generally you don't need to. while (clipper.Step()) for (int i = clipper.DisplayStart; i < clipper.DisplayEnd; i++) { @@ -8677,6 +9321,8 @@ bool ImGui::ListBox(const char* label, int* current_item, bool (*items_getter)(v *current_item = i; value_changed = true; } + if (item_selected) + SetItemDefaultFocus(); PopID(); } ListBoxFooter(); @@ -8834,7 +9480,7 @@ bool ImGui::BeginMenu(const char* label, bool enabled) { // Implement http://bjk5.com/post/44698559168/breaking-down-amazons-mega-dropdown to avoid using timers, so menus feels more reactive. bool moving_within_opened_triangle = false; - if (g.HoveredWindow == window && g.OpenPopupStack.Size > g.CurrentPopupStack.Size && g.OpenPopupStack[g.CurrentPopupStack.Size].ParentWindow == window) + if (g.HoveredWindow == window && g.OpenPopupStack.Size > g.CurrentPopupStack.Size && g.OpenPopupStack[g.CurrentPopupStack.Size].ParentWindow == window && !(window->Flags & ImGuiWindowFlags_MenuBar)) { if (ImGuiWindow* next_window = g.OpenPopupStack[g.CurrentPopupStack.Size].Window) { @@ -8853,6 +9499,12 @@ bool ImGui::BeginMenu(const char* label, bool enabled) want_close = (menu_is_open && !hovered && g.HoveredWindow == window && g.HoveredIdPreviousFrame != 0 && g.HoveredIdPreviousFrame != id && !moving_within_opened_triangle); want_open = (!menu_is_open && hovered && !moving_within_opened_triangle) || (!menu_is_open && hovered && pressed); + + if (g.NavActivateId == id) + { + want_close = menu_is_open; + want_open = !menu_is_open; + } } else if (menu_is_open && pressed && menuset_is_open) // menu-bar: click open menu to close { @@ -8911,9 +9563,10 @@ bool ImGui::ColorButton(const ImVec4& col, bool small_height, bool outline_borde bool hovered, held; bool pressed = ButtonBehavior(bb, id, &hovered, &held); + RenderNavHighlight(id, bb); RenderFrame(bb.Min, bb.Max, GetColorU32(col), outline_border, style.FrameRounding); - if (hovered) + if (g.HoveredId == id) SetTooltip("Color:\n(%.2f,%.2f,%.2f,%.2f)\n#%02X%02X%02X%02X", col.x, col.y, col.z, col.w, IM_F32_TO_INT8_SAT(col.x), IM_F32_TO_INT8_SAT(col.y), IM_F32_TO_INT8_SAT(col.z), IM_F32_TO_INT8_SAT(col.z)); return pressed; @@ -9733,6 +10386,7 @@ void ImGui::ShowMetricsWindow(bool* p_open) NodeDrawList(window->DrawList, "DrawList"); ImGui::BulletText("Size: (%.1f,%.1f), SizeContents (%.1f,%.1f)", window->Size.x, window->Size.y, window->SizeContents.x, window->SizeContents.y); ImGui::BulletText("Scroll: (%.2f,%.2f)", window->Scroll.x, window->Scroll.y); + ImGui::BulletText("NavLastId: 0x%08x, NavHasItems: %d", window->NavLastId, window->DC.NavHasItems); if (window->RootWindow != window) NodeWindow(window->RootWindow, "RootWindow"); if (window->DC.ChildWindows.Size > 0) NodeWindows(window->DC.ChildWindows, "ChildWindows"); ImGui::BulletText("Storage: %d bytes", window->StateStorage.Data.Size * (int)sizeof(ImGuiStorage::Pair)); @@ -9763,7 +10417,10 @@ void ImGui::ShowMetricsWindow(bool* p_open) ImGui::Text("HoveredWindow: '%s'", g.HoveredWindow ? g.HoveredWindow->Name : "NULL"); ImGui::Text("HoveredRootWindow: '%s'", g.HoveredRootWindow ? g.HoveredRootWindow->Name : "NULL"); ImGui::Text("HoveredId: 0x%08X/0x%08X", g.HoveredId, g.HoveredIdPreviousFrame); // Data is "in-flight" so depending on when the Metrics window is called we may see current frame information or not - ImGui::Text("ActiveId: 0x%08X/0x%08X", g.ActiveId, g.ActiveIdPreviousFrame); + ImGui::Text("ActiveId: 0x%08X/0x%08X, ActiveIdWindow: %s", g.ActiveId, g.ActiveIdPreviousFrame, g.ActiveIdWindow ? g.ActiveIdWindow->Name : "NULL"); + ImGui::Text("NavId: 0x%08X, NavWindow: '%s'", g.NavId, g.NavWindow ? g.NavWindow->Name : "NULL"); + ImGui::Text("NavRefRectRel: (%.1f,%.1f)(%.1f,%.1f)", g.NavRefRectRel.Min.x, g.NavRefRectRel.Min.y, g.NavRefRectRel.Max.x, g.NavRefRectRel.Max.y); + ImGui::Text("NavDisableHighlight: %d, NavDisableMouseHover: %d", g.NavDisableHighlight, g.NavDisableMouseHover); ImGui::TreePop(); } } diff --git a/imgui.h b/imgui.h index 994b663c7ae9..3a9b1e69c9b0 100644 --- a/imgui.h +++ b/imgui.h @@ -167,7 +167,7 @@ namespace ImGui IMGUI_API void SetScrollY(float scroll_y); // set scrolling amount [0..GetScrollMaxY()] IMGUI_API void SetScrollHere(float center_y_ratio = 0.5f); // adjust scrolling amount to make current cursor position visible. center_y_ratio=0.0: top, 0.5: center, 1.0: bottom. IMGUI_API void SetScrollFromPosY(float pos_y, float center_y_ratio = 0.5f); // adjust scrolling amount to make given position valid. use GetCursorPos() or GetCursorStartPos()+offset to get valid positions. - IMGUI_API void SetKeyboardFocusHere(int offset = 0); // focus keyboard on the next widget. Use positive 'offset' to access sub components of a multiple component widget. Use negative 'offset' to access previous widgets. + IMGUI_API void SetKeyboardFocusHere(int offset = 0); // FIXME-NAVIGATION // focus keyboard on the next widget. Use positive 'offset' to access sub components of a multiple component widget. Use negative 'offset' to access previous widgets. IMGUI_API void SetStateStorage(ImGuiStorage* tree); // replace tree state storage with our own (if you want to manipulate it yourself, typically clear subsection of it) IMGUI_API ImGuiStorage* GetStateStorage(); @@ -396,14 +396,17 @@ namespace ImGui IMGUI_API bool IsItemHovered(); // is the last item hovered by mouse, and usable? IMGUI_API bool IsItemHoveredRect(); // is the last item hovered by mouse? even if another item is active or window is blocked by popup while we are hovering this IMGUI_API bool IsItemActive(); // is the last item active? (e.g. button being held, text field being edited- items that don't interact will always return false) + IMGUI_API bool IsItemFocused(); // is the last item focused for keyboard/gamepad navigation? IMGUI_API bool IsItemClicked(int mouse_button = 0); // is the last item clicked? (e.g. button/node just clicked on) IMGUI_API bool IsItemVisible(); // is the last item visible? (aka not out of sight due to clipping/scrolling.) IMGUI_API bool IsAnyItemHovered(); IMGUI_API bool IsAnyItemActive(); + IMGUI_API bool IsAnyItemFocused(); IMGUI_API ImVec2 GetItemRectMin(); // get bounding rect of last item in screen space IMGUI_API ImVec2 GetItemRectMax(); // " IMGUI_API ImVec2 GetItemRectSize(); // " IMGUI_API void SetItemAllowOverlap(); // allow last item to be overlapped by a subsequent item. sometimes useful with invisible buttons, selectables, etc. to catch unused area. + IMGUI_API void SetItemDefaultFocus(); // make last item the default focused item of a window IMGUI_API bool IsWindowFocused(); // is current window focused IMGUI_API bool IsWindowHovered(); // is current window hovered and hoverable (not blocked by a popup) (differentiate child windows from each others) IMGUI_API bool IsWindowHoveredRect(); // is current window hovered, disregarding of any consideration of being blocked by a popup. (unlike IsWindowHovered() this will return true even if the window is blocked because of a popup) @@ -506,6 +509,7 @@ enum ImGuiWindowFlags_ ImGuiWindowFlags_AlwaysVerticalScrollbar= 1 << 14, // Always show vertical scrollbar (even if ContentSize.y < Size.y) ImGuiWindowFlags_AlwaysHorizontalScrollbar=1<< 15, // Always show horizontal scrollbar (even if ContentSize.x < Size.x) ImGuiWindowFlags_AlwaysUseWindowPadding = 1 << 16, // Ensure child windows without border uses style.WindowPadding (ignored by default for non-bordered child windows, because more convenient) + ImGuiWindowFlags_NoNav = 1 << 17, // No directional gamepad/keyboard navigation // [Internal] ImGuiWindowFlags_ChildWindow = 1 << 20, // Don't use! For internal use by BeginChild() ImGuiWindowFlags_ChildWindowAutoFitX = 1 << 21, // Don't use! For internal use by BeginChild() @@ -590,6 +594,19 @@ enum ImGuiKey_ ImGuiKey_X, // for text edit CTRL+X: cut ImGuiKey_Y, // for text edit CTRL+Y: redo ImGuiKey_Z, // for text edit CTRL+Z: undo + + // Inputs for Gamepad/Keyboard navigation. Feed those buttons with the input of either or both peripherals involved. + ImGuiKey_NavActivate, // press button, tweak value // e.g. Space key, Circle button + ImGuiKey_NavCancel, // close menu/popup/child, unselect // e.g. Escape key, Cross button + ImGuiKey_NavInput, // text input // e.g. Enter key, Triangle button + ImGuiKey_NavWindowing, // change focus, move, resize // e.g. Square button + ImGuiKey_NavLeft, // e.g. Left arrow, D-Pad left + ImGuiKey_NavRight, // e.g. Right arrow, D-Pad right + ImGuiKey_NavUp, // e.g. Up arrow, D-Pad up + ImGuiKey_NavDown, // e.g. Down arrow, D-Pad down + ImGuiKey_NavTweakFaster,// e.g. Shift key, R-trigger + ImGuiKey_NavTweakSlower,// e.g. Alt key, L-trigger + ImGuiKey_COUNT }; @@ -751,6 +768,7 @@ struct ImGuiIO int KeyMap[ImGuiKey_COUNT]; // // Map of indices into the KeysDown[512] entries array float KeyRepeatDelay; // = 0.250f // When holding a key/button, time before it starts repeating, in seconds (for buttons in Repeat mode, etc.). float KeyRepeatRate; // = 0.020f // When holding a key/button, rate at which it repeats, in seconds. + bool NavMovesMouse; // = false // Directional navigation move the mouse cursor (update MousePos and set void* UserData; // = NULL // Store your own data for retrieval by callbacks. ImFontAtlas* Fonts; // // Load and assemble one or more fonts into a single tightly packed texture. Output to Fonts array. @@ -817,6 +835,9 @@ struct ImGuiIO bool WantCaptureMouse; // Mouse is hovering a window or widget is active (= ImGui will use your mouse input) bool WantCaptureKeyboard; // Widget is active (= ImGui will use your keyboard input) bool WantTextInput; // Text input widget is active, which will read input characters from the InputCharacters array. + bool WantMoveMouse; // MousePos has been altered, used only if 'NavMovesMouse=true', back-end can reposition mouse on next frame. + bool NavUsable; // Directional navigation is currently allowed (ImGuiKey_NavXXX events). + bool NavActive; // Directional navigation is active/visible and currently allowed (ImGuiKey_NavXXX events). float Framerate; // Framerate estimation, in frame per second. Rolling average estimation based on IO.DeltaTime over 120 frames int MetricsAllocs; // Number of active memory allocations int MetricsRenderVertices; // Vertices output during last call to Render() diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 3862e6280bd1..c17537a02eef 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -153,6 +153,7 @@ void ImGui::ShowTestWindow(bool* p_open) static bool no_scrollbar = false; static bool no_collapse = false; static bool no_menu = false; + static bool no_nav = false; // Demonstrate the various window flags. Typically you would just use the default. ImGuiWindowFlags window_flags = 0; @@ -163,6 +164,7 @@ void ImGui::ShowTestWindow(bool* p_open) if (no_scrollbar) window_flags |= ImGuiWindowFlags_NoScrollbar; if (no_collapse) window_flags |= ImGuiWindowFlags_NoCollapse; if (!no_menu) window_flags |= ImGuiWindowFlags_MenuBar; + if (no_nav) window_flags |= ImGuiWindowFlags_NoNav; ImGui::SetNextWindowSize(ImVec2(550,680), ImGuiSetCond_FirstUseEver); if (!ImGui::Begin("ImGui Demo", p_open, window_flags)) { @@ -224,7 +226,8 @@ void ImGui::ShowTestWindow(bool* p_open) ImGui::Checkbox("No move", &no_move); ImGui::SameLine(150); ImGui::Checkbox("No scrollbar", &no_scrollbar); ImGui::SameLine(300); ImGui::Checkbox("No collapse", &no_collapse); - ImGui::Checkbox("No menu", &no_menu); + ImGui::Checkbox("No menu", &no_menu); ImGui::SameLine(150); + ImGui::Checkbox("No nav", &no_nav); if (ImGui::TreeNode("Style")) { @@ -1297,6 +1300,7 @@ void ImGui::ShowTestWindow(bool* p_open) ImGui::PopStyleVar(); if (ImGui::Button("OK", ImVec2(120,0))) { ImGui::CloseCurrentPopup(); } + ImGui::SetItemDefaultFocus(); ImGui::SameLine(); if (ImGui::Button("Cancel", ImVec2(120,0))) { ImGui::CloseCurrentPopup(); } ImGui::EndPopup(); @@ -1498,6 +1502,9 @@ void ImGui::ShowTestWindow(bool* p_open) if (ImGui::CollapsingHeader("Keyboard, Mouse & Focus")) { ImGuiIO& io = ImGui::GetIO(); + ImGui::Checkbox("io.NavMovesMouse", &io.NavMovesMouse); + ImGui::SameLine(); ShowHelpMarker("Request ImGui to move your move cursor when using gamepad/keyboard navigation. NewFrame() will change io.MousePos and set the io.WantMoveMouse flag, your backend will need to apply the new mouse position."); + ImGui::Checkbox("io.MouseDrawCursor", &io.MouseDrawCursor); ImGui::SameLine(); ShowHelpMarker("Request ImGui to render a mouse cursor for you in software. Note that a mouse cursor rendered via regular GPU rendering will feel more laggy than hardware cursor, but will be more in sync with your other visuals."); @@ -1581,6 +1588,8 @@ void ImGui::ShowTestWindow(bool* p_open) ImGui::Text("WantCaptureMouse: %d", io.WantCaptureMouse); ImGui::Text("WantCaptureKeyboard: %d", io.WantCaptureKeyboard); ImGui::Text("WantTextInput: %d", io.WantTextInput); + ImGui::Text("WantMoveMouse: %d", io.WantMoveMouse); + ImGui::Text("NavUsable: %d, NavActive: %d", io.NavUsable, io.NavActive); ImGui::Button("Hovering me sets the\nkeyboard capture flag"); if (ImGui::IsItemHovered()) @@ -1602,7 +1611,7 @@ void ImGui::ShowTestWindow(bool* p_open) char label[32]; sprintf(label, "Mouse cursor %d", i); ImGui::Bullet(); ImGui::Selectable(label, false); - if (ImGui::IsItemHovered()) + if (ImGui::IsItemHovered() || ImGui::IsItemFocused()) ImGui::SetMouseCursor(i); } ImGui::TreePop(); diff --git a/imgui_internal.h b/imgui_internal.h index 577993dc49c1..6180891da02b 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -13,6 +13,7 @@ #include // FILE* #include // sqrtf, fabsf, fmodf, powf, floorf, ceilf, cosf, sinf +#include // INT_MIN, INT_MAX #ifdef _MSC_VER #pragma warning (push) @@ -159,7 +160,8 @@ enum ImGuiButtonFlags_ ImGuiButtonFlags_Disabled = 1 << 7, // disable interaction ImGuiButtonFlags_AlignTextBaseLine = 1 << 8, // vertically align button to match text baseline - ButtonEx() only ImGuiButtonFlags_NoKeyModifiers = 1 << 9, // disable interaction if a key modifier is held - ImGuiButtonFlags_AllowOverlapMode = 1 << 10 // require previous frame HoveredId to either match id or be null before being usable + ImGuiButtonFlags_AllowOverlapMode = 1 << 10, // require previous frame HoveredId to either match id or be null before being usable + ImGuiButtonFlags_NoNavOverride = 1 << 11 // don't override navigation id when activated }; enum ImGuiSliderFlags_ @@ -195,6 +197,22 @@ enum ImGuiDataType ImGuiDataType_Float }; +enum ImGuiInputSource +{ + ImGuiInputSource_None = 0, + ImGuiInputSource_Mouse, + ImGuiInputSource_Nav, +}; + +enum ImGuiNavDir +{ + ImGuiNavDir_None = -1, + ImGuiNavDir_W, // Needs to be 0..3 (using arithmetic op in NavScoreItem()) + ImGuiNavDir_E, + ImGuiNavDir_N, + ImGuiNavDir_S +}; + // 2D axis aligned bounding-box // NB: we can't rely on ImVec2 math operators being available here struct IMGUI_API ImRect @@ -335,9 +353,10 @@ struct ImGuiPopupRef ImGuiWindow* Window; // Resolved on BeginPopup() - may stay unresolved if user never calls OpenPopup() ImGuiWindow* ParentWindow; // Set on OpenPopup() ImGuiID ParentMenuSet; // Set on OpenPopup() + ImVec2 PopupPosOnOpen; // Preferred popup position (typically == MousePosOnOpen when using mouse) ImVec2 MousePosOnOpen; // Copy of mouse position at the time of opening popup - ImGuiPopupRef(ImGuiID id, ImGuiWindow* parent_window, ImGuiID parent_menu_set, const ImVec2& mouse_pos) { PopupId = id; Window = NULL; ParentWindow = parent_window; ParentMenuSet = parent_menu_set; MousePosOnOpen = mouse_pos; } + ImGuiPopupRef(ImGuiID id, ImGuiWindow* parent_window, ImGuiID parent_menu_set, const ImVec2& popup_pos, const ImVec2& mouse_pos) { PopupId = id; Window = NULL; ParentWindow = parent_window; ParentMenuSet = parent_menu_set; PopupPosOnOpen = popup_pos; MousePosOnOpen = mouse_pos; } }; // Main state for ImGui @@ -369,9 +388,11 @@ struct ImGuiContext ImGuiID ActiveIdPreviousFrame; bool ActiveIdIsAlive; // Active widget has been seen this frame bool ActiveIdIsJustActivated; // Set at the time of activation for one frame + bool ActiveIdAllowNavMove; // Active widget allows using directional navigation (e.g. can activate a button and move away from it) bool ActiveIdAllowOverlap; // Active widget allows another widget to steal active id (generally for overlapping widgets, but not always) ImVec2 ActiveIdClickOffset; // Clicked offset from upper-left corner, if applicable (currently only set by ButtonBehavior) ImGuiWindow* ActiveIdWindow; + ImGuiInputSource ActiveIdSource; // Activating with mouse or nav (gamepad/keyboard) ImGuiWindow* MovedWindow; // Track the child window we clicked on to move a window. ImGuiID MovedWindowMoveId; // == MovedWindow->RootWindow->MoveId ImVector Settings; // .ini Settings @@ -382,6 +403,29 @@ struct ImGuiContext ImVector OpenPopupStack; // Which popups are open (persistent) ImVector CurrentPopupStack; // Which level of BeginPopup() we are in (reset every frame) + // Navigation data (for gamepad/keyboard) + ImGuiID NavId; // Nav/focused widget for navigation + ImGuiID NavActivateId, NavInputId; // ~~ IsKeyPressedMap(ImGuiKey_NavActive) ? NavId : 0, etc. (to make widget code terser) + ImGuiID NavTabbedId; // + ImRect NavRefRectRel, NavScoringRectScreen;// Reference rectangle, in window space. Modified rectangle for directional navigation scoring, in screen space. + ImGuiWindow* NavWindow; // + ImGuiWindow* NavWindowingTarget; + int NavIdTabCounter; // == NavWindow->DC.FocusIdxTabCounter at time of NavId processing + bool NavIdIsAlive; // Nav widget has been seen this frame ~~ NavRefRectRel is valid + bool NavMousePosDirty; + bool NavDisableHighlight; // When user starts using mouse, we hide gamepad/keyboard functionalities + bool NavDisableMouseHover; // When user starts using gamepad/keyboard, we disable mouse hovering until mouse is touched again + bool NavInitDefaultRequest; // Init request for appearing window to select first item + ImGuiID NavInitDefaultResultId; + bool NavInitDefaultResultExplicit; // Whether the result was explicitly requested with SetItemDefaultFocus() + bool NavMoveRequest; // Move request for this frame + ImGuiNavDir NavMoveDir; // West/East/North/South + ImGuiID NavMoveResultBestId; // Best move request candidate + float NavMoveResultBestDistBox; // Best move request candidate box distance to current NavId + float NavMoveResultBestDistCenter; // Best move request candidate center distance to current NavId + float NavMoveResultBestDistAxial; + ImRect NavMoveResultBestRefRectRel; // Best move request candidate bounding box in window space + // Storage for SetNexWindow** and SetNextTreeNode*** functions ImVec2 SetNextWindowPosVal; ImVec2 SetNextWindowSizeVal; @@ -461,10 +505,28 @@ struct ImGuiContext ActiveIdAllowOverlap = false; ActiveIdClickOffset = ImVec2(-1,-1); ActiveIdWindow = NULL; + ActiveIdSource = ImGuiInputSource_None; MovedWindow = NULL; MovedWindowMoveId = 0; SettingsDirtyTimer = 0.0f; + NavId = NavActivateId = NavInputId = NavTabbedId = 0; + NavRefRectRel = NavScoringRectScreen = ImRect(); + NavWindow = NULL; + NavWindowingTarget = NULL; + NavIdTabCounter = INT_MAX; + NavIdIsAlive = false; + NavMousePosDirty = false; + NavDisableHighlight = true; + NavDisableMouseHover = false; + NavInitDefaultRequest = false; + NavInitDefaultResultId = 0; + NavInitDefaultResultExplicit = false; + NavMoveRequest = false; + NavMoveDir = ImGuiNavDir_None; + NavMoveResultBestId = 0; + NavMoveResultBestDistBox = NavMoveResultBestDistCenter = NavMoveResultBestDistAxial = 0.0f; + SetNextWindowPosVal = ImVec2(0.0f, 0.0f); SetNextWindowSizeVal = ImVec2(0.0f, 0.0f); SetNextWindowCollapsedVal = false; @@ -526,6 +588,8 @@ struct IMGUI_API ImGuiDrawContext ImRect LastItemRect; bool LastItemHoveredAndUsable; // Item rectangle is hovered, and its window is currently interactable with (not blocked by a popup preventing access to the window) bool LastItemHoveredRect; // Item rectangle is hovered, but its window may or not be currently interactable with (might be blocked by a popup preventing access to the window) + bool NavHasItems, NavHasItemsNext; // Set when has any navigatable item + bool NavHasScroll; // Set when scrolling can be used (ScrollMax > 0.0f) bool MenuBarAppending; float MenuBarOffsetX; ImVector ChildWindows; @@ -536,6 +600,7 @@ struct IMGUI_API ImGuiDrawContext float ItemWidth; // == ItemWidthStack.back(). 0.0: default, >0.0: width in pixels, <0.0: align xx pixels to the right of window float TextWrapPos; // == TextWrapPosStack.back() [empty == -1.0f] bool AllowKeyboardFocus; // == AllowKeyboardFocusStack.back() [empty == true] + bool AllowNavDefaultFocus; // (not exposed via stack) bool ButtonRepeat; // == ButtonRepeatStack.back() [empty == false] ImVector ItemWidthStack; ImVector TextWrapPosStack; @@ -568,6 +633,7 @@ struct IMGUI_API ImGuiDrawContext LastItemId = 0; LastItemRect = ImRect(0.0f,0.0f,0.0f,0.0f); LastItemHoveredAndUsable = LastItemHoveredRect = false; + NavHasItems = NavHasItemsNext = NavHasScroll = false; MenuBarAppending = false; MenuBarOffsetX = 0.0f; StateStorage = NULL; @@ -620,6 +686,7 @@ struct IMGUI_API ImGuiWindow bool SkipItems; // == Visible && !Collapsed int BeginCount; // Number of Begin() during the current frame (generally 0 or 1, 1+ if appending via multiple Begin/End pairs) ImGuiID PopupId; // ID in the popup stack when this window is used as a popup/menu (because we use generic Name/ID for recycling) + ImGuiID NavLastId; // Last known NavId for this window int AutoFitFramesX, AutoFitFramesY; bool AutoFitOnlyGrows; int AutoPosLastDirection; @@ -633,6 +700,7 @@ struct IMGUI_API ImGuiWindow ImVector IDStack; // ID stack. ID are hashes seeded with the value at the top of the stack ImRect ClipRect; // = DrawList->clip_rect_stack.back(). Scissoring / clipping rectangle. x1, y1, x2, y2. ImRect WindowRectClipped; // = WindowRect just after setup in Begin(). == window->Rect() for root window. + ImRect InnerRect; int LastFrameActive; float ItemWidthDefault; ImGuiSimpleColumns MenuColumns; // Simplified columns storage for menu items @@ -644,6 +712,7 @@ struct IMGUI_API ImGuiWindow ImGuiWindow* ParentWindow; // Immediate parent in the window stack *regardless* of whether this window is a child window or not) // Navigation / Focus + // FIXME-NAVIGATION: Merge all this with the new Nav system, at least the request variables should be moved to ImGuiContext int FocusIdxAllCounter; // Start at -1 and increase as assigned via FocusItemRegister() int FocusIdxTabCounter; // (same, but only count widgets which you can Tab through) int FocusIdxAllRequestCurrent; // Item being requested for focus @@ -658,6 +727,7 @@ struct IMGUI_API ImGuiWindow ImGuiID GetID(const char* str, const char* str_end = NULL); ImGuiID GetID(const void* ptr); ImGuiID GetIDNoKeepAlive(const char* str, const char* str_end = NULL); + ImGuiID GetChildID(ImGuiWindow* window); ImRect Rect() const { return ImRect(Pos.x, Pos.y, Pos.x+Size.x, Pos.y+Size.y); } float CalcFontSize() const { return GImGui->FontBaseSize * FontWindowScale; } @@ -687,21 +757,25 @@ namespace ImGui IMGUI_API void EndFrame(); // Ends the ImGui frame. Automatically called by Render()! you most likely don't need to ever call that yourself directly. If you don't need to render you can call EndFrame() but you'll have wasted CPU already. If you don't need to render, don't create any windows instead! IMGUI_API void SetActiveID(ImGuiID id, ImGuiWindow* window); + IMGUI_API void SetActiveIDNoNav(ImGuiID id, ImGuiWindow* window); IMGUI_API void SetHoveredID(ImGuiID id); IMGUI_API void KeepAliveID(ImGuiID id); IMGUI_API void ItemSize(const ImVec2& size, float text_offset_y = 0.0f); IMGUI_API void ItemSize(const ImRect& bb, float text_offset_y = 0.0f); - IMGUI_API bool ItemAdd(const ImRect& bb, const ImGuiID* id); + IMGUI_API bool ItemAdd(const ImRect& bb, const ImGuiID* id, const ImRect* nav_bb = NULL); IMGUI_API bool IsClippedEx(const ImRect& bb, const ImGuiID* id, bool clip_even_when_logged); IMGUI_API bool IsHovered(const ImRect& bb, ImGuiID id, bool flatten_childs = false); - IMGUI_API bool FocusableItemRegister(ImGuiWindow* window, bool is_active, bool tab_stop = true); // Return true if focus is requested + IMGUI_API bool FocusableItemRegister(ImGuiWindow* window, ImGuiID id, bool tab_stop = true); // Return true if focus is requested IMGUI_API void FocusableItemUnregister(ImGuiWindow* window); IMGUI_API ImVec2 CalcItemSize(ImVec2 size, float default_x, float default_y); IMGUI_API float CalcWrapWidthForPos(const ImVec2& pos, float wrap_pos_x); IMGUI_API void OpenPopupEx(const char* str_id, bool reopen_existing); + IMGUI_API void NavInitWindow(ImGuiWindow* window); + IMGUI_API ImVec2 NavGetTweakDelta(); + inline IMGUI_API ImU32 GetColorU32(ImGuiCol idx, float alpha_mul) { ImVec4 c = GImGui->Style.Colors[idx]; c.w *= GImGui->Style.Alpha * alpha_mul; return ImGui::ColorConvertFloat4ToU32(c); } inline IMGUI_API ImU32 GetColorU32(const ImVec4& col) { ImVec4 c = col; c.w *= GImGui->Style.Alpha; return ImGui::ColorConvertFloat4ToU32(c); } From 2cab404a81e022941376450131e78e014eb28e42 Mon Sep 17 00:00:00 2001 From: ocornut Date: Sat, 23 Jul 2016 15:44:56 +0200 Subject: [PATCH 022/823] Fixed tooltip positioning issues when using navigation (#323) --- imgui.cpp | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index ad2007bdb12b..cb10ab84fa55 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2264,6 +2264,14 @@ int ImGui::GetFrameCount() return GImGui->FrameCount; } +static ImVec2 NavCalcPreferredMousePos() +{ + ImGuiContext& g = *GImGui; + if (g.NavWindow) + return g.NavWindow->Pos + ImVec2(g.NavRefRectRel.Min.x + ImMin(g.Style.FramePadding.x*4, g.NavRefRectRel.GetWidth()), g.NavRefRectRel.Max.y - ImMin(g.Style.FramePadding.y, g.NavRefRectRel.GetHeight())); + return g.IO.MousePos; +} + static void NavUpdate() { ImGuiContext& g = *GImGui; @@ -2274,7 +2282,7 @@ static void NavUpdate() // Set mouse position given our knowledge of the nav widget position from last frame if (g.IO.NavMovesMouse) { - g.IO.MousePos = g.IO.MousePosPrev = g.NavWindow->Pos + ImVec2(g.NavRefRectRel.Min.x + ImMin(g.Style.FramePadding.x*4, g.NavRefRectRel.GetWidth()), g.NavRefRectRel.Max.y - ImMin(g.Style.FramePadding.y, g.NavRefRectRel.GetHeight())); + g.IO.MousePos = g.IO.MousePosPrev = NavCalcPreferredMousePos(); g.IO.WantMoveMouse = true; } g.NavMousePosDirty = false; @@ -3810,7 +3818,7 @@ void ImGui::OpenPopupEx(const char* str_id, bool reopen_existing) ImGuiID id = window->GetID(str_id); int current_stack_size = g.CurrentPopupStack.Size; ImVec2 mouse_pos = g.IO.MousePos; - ImVec2 popup_pos = (g.ActiveIdSource == ImGuiInputSource_Mouse || g.ActiveId == 0) ? mouse_pos : window->DC.LastItemRect.GetCenter(); + ImVec2 popup_pos = (g.ActiveIdSource == ImGuiInputSource_Nav) ? NavCalcPreferredMousePos() : mouse_pos; ImGuiPopupRef popup_ref = ImGuiPopupRef(id, window, window->GetID("##menus"), popup_pos, mouse_pos); // Tagged as new ref because constructor sets Window to NULL (we are passing the ParentWindow info here) if (g.OpenPopupStack.Size < current_stack_size + 1) g.OpenPopupStack.push_back(popup_ref); @@ -4541,7 +4549,7 @@ bool ImGui::Begin(const char* name, bool* p_open, const ImVec2& size_on_first_us // Position tooltip (always follows mouse) if ((flags & ImGuiWindowFlags_Tooltip) != 0 && !window_pos_set_by_api) { - ImVec2 ref_pos = (g.ActiveId == 0 || g.ActiveIdSource == ImGuiInputSource_Mouse) ? g.IO.MousePos : window->DC.LastItemRect.GetCenter(); + ImVec2 ref_pos = (g.ActiveIdSource == ImGuiInputSource_Nav) ? NavCalcPreferredMousePos() : g.IO.MousePos; ImRect rect_to_avoid(ref_pos.x - 16, ref_pos.y - 8, ref_pos.x + 24, ref_pos.y + 24); // FIXME: Completely hard-coded. Perhaps center on cursor hit-point instead? window->PosFloat = FindBestPopupWindowPos(ref_pos, window->Size, &window->AutoPosLastDirection, rect_to_avoid); if (window->AutoPosLastDirection == -1) From ad483090474b5314b1e2d437b1722b8f9a7ed6c8 Mon Sep 17 00:00:00 2001 From: ocornut Date: Sat, 23 Jul 2016 16:01:27 +0200 Subject: [PATCH 023/823] Navigation: Fixed using NavWindowed when a menu is open. (#323) --- imgui.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index cb10ab84fa55..37f7461d0148 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2343,7 +2343,7 @@ static void NavUpdate() // Navigation windowing mode (change focus, move/resize window) if (!g.NavWindowingTarget && g.NavWindow && IsKeyPressedMap(ImGuiKey_NavWindowing, false)) - g.NavWindowingTarget = g.NavWindow->RootWindow; + g.NavWindowingTarget = g.NavWindow->RootNonPopupWindow; if (g.NavWindowingTarget) { // FIXME-NAVIGATION: Need to clarify input semantic, naming is misleading/incorrect here. @@ -2357,10 +2357,10 @@ static void NavUpdate() i_current = i; int i_target = -1; for (int i = i_current+focus_change_dir; i >= 0 && i < g.Windows.Size && i_target == -1; i += focus_change_dir) - if (g.Windows[i]->Active && !(g.Windows[i]->Flags & ImGuiWindowFlags_ChildWindow)) + if (g.Windows[i]->Active && g.Windows[i] == g.Windows[i]->RootNonPopupWindow) i_target = i; for (int i = (focus_change_dir < 0) ? (g.Windows.Size-1) : 0; i >= 0 && i < g.Windows.Size && i_target == -1 && i_target != i_current; i += focus_change_dir) - if (g.Windows[i]->Active && !(g.Windows[i]->Flags & ImGuiWindowFlags_ChildWindow)) + if (g.Windows[i]->Active && g.Windows[i] == g.Windows[i]->RootNonPopupWindow) i_target = i; if (i_target != -1) { @@ -2369,12 +2369,12 @@ static void NavUpdate() } } - // End window select/focus mode and apply final focus + // Apply actual focus only when leaving NavWindowing mode (until then the window was merely rendered front-most) if (!IsKeyDownMap(ImGuiKey_NavWindowing)) { if (g.NavWindowingTarget) - if (!g.FocusedWindow || (g.NavWindowingTarget && g.NavWindowingTarget->RootWindow != g.FocusedWindow->RootWindow)) - ImGui::FocusWindow(g.NavWindowingTarget->RootWindow); + if (!g.FocusedWindow || (g.NavWindowingTarget->RootNonPopupWindow != g.FocusedWindow->RootNonPopupWindow)) + ImGui::FocusWindow(g.NavWindowingTarget->RootNonPopupWindow); g.NavWindowingTarget = NULL; } } @@ -4387,7 +4387,7 @@ bool ImGui::Begin(const char* name, bool* p_open, const ImVec2& size_on_first_us break; window->ParentWindow = parent_window; window->RootWindow = g.CurrentWindowStack[root_idx]; - window->RootNonPopupWindow = g.CurrentWindowStack[root_non_popup_idx]; // This is merely for displaying the TitleBgActive color. + window->RootNonPopupWindow = g.CurrentWindowStack[root_non_popup_idx]; // Used e.g. to keep displaying TitleBgActive color when menu is active, and for NavWindowing // When reusing window again multiple times a frame, just append content (don't need to setup again) if (first_begin_of_the_frame) From 2f1fb415796fa8cc0b7a8fe683e583199b89d2f9 Mon Sep 17 00:00:00 2001 From: ocornut Date: Sat, 23 Jul 2016 16:31:23 +0200 Subject: [PATCH 024/823] Navigation: Fixed automatic fallback scrolling from glitching near scroll limits because of miscalculation of SizeContents (#323) --- imgui.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 37f7461d0148..7e3412f6392d 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2446,7 +2446,7 @@ static void NavUpdate() if (g.FocusedWindow && !g.FocusedWindow->DC.NavHasItems && g.FocusedWindow->DC.NavHasScroll && !(g.FocusedWindow->Flags & ImGuiWindowFlags_NoNav) && g.NavMoveRequest && (g.NavMoveDir == ImGuiNavDir_N || g.NavMoveDir == ImGuiNavDir_S)) { float scroll_speed = ImFloor(g.FocusedWindow->CalcFontSize() * 100 * g.IO.DeltaTime + 0.5f); // We need round the scrolling speed because sub-pixel scroll isn't reliably supported. - g.FocusedWindow->Scroll.y = ImFloor(g.FocusedWindow->Scroll.y + ((g.NavMoveDir == ImGuiNavDir_N) ? -1.0f : +1.0f) * scroll_speed); + SetWindowScrollY(g.FocusedWindow, ImFloor(g.FocusedWindow->Scroll.y + ((g.NavMoveDir == ImGuiNavDir_N) ? -1.0f : +1.0f) * scroll_speed)); } // Reset search @@ -5372,7 +5372,7 @@ ImVec2 ImGui::GetWindowPos() static void SetWindowScrollY(ImGuiWindow* window, float new_scroll_y) { - window->DC.CursorMaxPos.y += window->Scroll.y; + window->DC.CursorMaxPos.y += window->Scroll.y; // SizeContents is generally computed based on CursorMaxPos which is affected by scroll position, so we need to apply our change to it. window->Scroll.y = new_scroll_y; window->DC.CursorMaxPos.y -= window->Scroll.y; } From 0cc20fca831e60b4898cf66e3ac595d8bdebb830 Mon Sep 17 00:00:00 2001 From: ocornut Date: Sat, 23 Jul 2016 19:24:56 +0200 Subject: [PATCH 025/823] Navigation: Scoring uses rectangle as clipped by parent. Fix selectable extending past parent column among other things (#323) --- imgui.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 7e3412f6392d..59a34b672181 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1911,10 +1911,11 @@ static float NavScoreItemDistInterval(float a0, float a1, float b0, float b1) // Scoring function for directional navigation. Based on https://gist.github.com/rygorous/6981057 // FIXME-NAVIGATION: Pretty rough. // FIXME-NAVIGATION: May want to handle the degenerate case that we have commented out. -static bool NavScoreItem(const ImRect& cand) +static bool NavScoreItem(ImRect cand) { ImGuiContext& g = *GImGui; const ImRect& curr = g.NavScoringRectScreen; // Current modified source rect (NB: we've applied Max.x = Min.x in NavUpdate() to inhibit the effect of having lots of items with varied width) + cand.Clip(g.CurrentWindow->ClipRect); // Compute distance between boxes // FIXME-NAVIGATION: Introducing various biases toward typical imgui uses cases, but we don't have any rigorous proof of their effect now. @@ -1960,7 +1961,9 @@ static bool NavScoreItem(const ImRect& cand) if (ImGui::IsMouseHoveringRect(cand.Min, cand.Max)) { char buf[128]; - ImFormatString(buf, IM_ARRAYSIZE(buf), "db (%.0f,%.0f->%.1f) dc (%.0f,%.0f->%.1f) da (%.0f,%.0f->%.1f) quad %c", dbx, dby, dist_box, dcx, dcy, dist_center, dax, day, dist_axial, "WENS"[quadrant]); + ImFormatString(buf, IM_ARRAYSIZE(buf), "db (%.0f,%.0f->%.5f) dc (%.0f,%.0f->%.5f) da (%.0f,%.0f->%.5f) quad %c", dbx, dby, dist_box, dcx, dcy, dist_center, dax, day, dist_axial, "WENS"[quadrant]); + g.OverlayDrawList.AddRect(cand.Min, cand.Max, IM_COL32(255,255,0,200)); + g.OverlayDrawList.AddRectFilled(cand.Max-ImVec2(4,4), cand.Max+ImGui::CalcTextSize(buf)+ImVec2(4,4), IM_COL32(40,0,0,150)); g.OverlayDrawList.AddText(cand.Max, ~0U, buf); } #endif @@ -2052,7 +2055,7 @@ bool ImGui::ItemAdd(const ImRect& bb, const ImGuiID* id, const ImRect* nav_bb_ar { //if (!g.NavMoveRequest) g.NavMoveDir = ImGuiNavDir_E; // [DEBUG] Removing if (g.NavMoveRequest) above allows debug scoring of all visible items. const ImRect& nav_bb = nav_bb_arg ? *nav_bb_arg : bb; - if (NavScoreItem(nav_bb)) + if (NavScoreItem(nav_bb)) //if (g.NavMoveRequest) // [DEBUG] { g.NavMoveResultBestId = *id; g.NavMoveResultBestRefRectRel = ImRect(nav_bb.Min - window->Pos, nav_bb.Max - window->Pos); From e74d96642f9f5b44d63114a3fbd96072860440fc Mon Sep 17 00:00:00 2001 From: ocornut Date: Sat, 23 Jul 2016 19:42:19 +0200 Subject: [PATCH 026/823] Navigation: mouse/popup position gets clamped within visible display (#323) --- imgui.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 59a34b672181..6ba30efc690a 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2270,9 +2270,11 @@ int ImGui::GetFrameCount() static ImVec2 NavCalcPreferredMousePos() { ImGuiContext& g = *GImGui; - if (g.NavWindow) - return g.NavWindow->Pos + ImVec2(g.NavRefRectRel.Min.x + ImMin(g.Style.FramePadding.x*4, g.NavRefRectRel.GetWidth()), g.NavRefRectRel.Max.y - ImMin(g.Style.FramePadding.y, g.NavRefRectRel.GetHeight())); - return g.IO.MousePos; + if (!g.NavWindow) + return g.IO.MousePos; + ImVec2 p = g.NavWindow->Pos + ImVec2(g.NavRefRectRel.Min.x + ImMin(g.Style.FramePadding.x*4, g.NavRefRectRel.GetWidth()), g.NavRefRectRel.Max.y - ImMin(g.Style.FramePadding.y, g.NavRefRectRel.GetHeight())); + ImRect r = GetVisibleRect(); + return ImClamp(p, r.Min, r.Max); } static void NavUpdate() From afadc7cf591168beaa502c9fc78708c031870a3d Mon Sep 17 00:00:00 2001 From: ocornut Date: Sat, 23 Jul 2016 20:05:17 +0200 Subject: [PATCH 027/823] Navigation: Scoring: Improved directional navigation. Not totally cancelling out dx. Better support for zero-spaced items. (#323) --- imgui.cpp | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 6ba30efc690a..b989cfcc061f 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1921,9 +1921,8 @@ static bool NavScoreItem(ImRect cand) // FIXME-NAVIGATION: Introducing various biases toward typical imgui uses cases, but we don't have any rigorous proof of their effect now. float dbx = NavScoreItemDistInterval(cand.Min.x, cand.Max.x, curr.Min.x, curr.Max.x); float dby = NavScoreItemDistInterval(ImLerp(cand.Min.y, cand.Max.y, 0.2f), ImLerp(cand.Min.y, cand.Max.y, 0.8f), ImLerp(curr.Min.y, curr.Max.y, 0.2f), ImLerp(curr.Min.y, curr.Max.y, 0.8f)); // Clamp down on Y to keep using box-distance for vertically touching items - //dbx /= 2; dby *= 4 // Bias for dy - if (dby) - dbx = (dbx > 0.0f) ? +0.0f : -0.0f; + if (dby && dbx) + dbx = (dbx/1000.0f) + ((dbx > 0.0f) ? +1.0f : -1.0f); float dist_box = fabsf(dbx) + fabsf(dby); // Compute distance between centers (this is off by a factor of 2, but we only compare center distances with each other so it doesn't matter) @@ -1957,7 +1956,6 @@ static bool NavScoreItem(ImRect cand) } #if 0 // [DEBUG] - //draw_list->AddRect(bb.Min, bb.Max, IM_COL32(255,0,255,200)); if (ImGui::IsMouseHoveringRect(cand.Min, cand.Max)) { char buf[128]; @@ -2042,7 +2040,6 @@ bool ImGui::ItemAdd(const ImRect& bb, const ImGuiID* id, const ImRect* nav_bb_ar // We could early out with `if (is_clipped && !g.NavInitDefaultRequest) return false;` but when we wouldn't be able to reach unclipped widgets. This would work if user had explicit scrolling control (e.g. mapped on a stick) // A more pragmatic solution for handling last lists is relying on the fact that they are likely evenly spread items (so that clipper can work) and we could nav at higher-level (apply index, etc.) // So eventually we would like to provide the user will the primitives to be able to implement that sort of customized/efficient navigation handling whenever necessary. - // FIXME-NAVIGATION if (id != NULL && g.NavWindow == window && g.IO.NavUsable) { if (g.NavInitDefaultRequest && window->DC.AllowNavDefaultFocus) @@ -2051,11 +2048,12 @@ bool ImGui::ItemAdd(const ImRect& bb, const ImGuiID* id, const ImRect* nav_bb_ar g.NavInitDefaultResultId = *id; } - if (g.NavMoveRequest && g.NavId != *id) + const bool DEBUG_NAV = false; // [DEBUG] Enable to test scoring on all items. + if ((g.NavMoveRequest || DEBUG_NAV) && g.NavId != *id) { - //if (!g.NavMoveRequest) g.NavMoveDir = ImGuiNavDir_E; // [DEBUG] Removing if (g.NavMoveRequest) above allows debug scoring of all visible items. + //if (DEBUG_NAV && !g.NavMoveRequest) g.NavMoveDir = ImGuiNavDir_N; const ImRect& nav_bb = nav_bb_arg ? *nav_bb_arg : bb; - if (NavScoreItem(nav_bb)) //if (g.NavMoveRequest) // [DEBUG] + if (NavScoreItem(nav_bb)) //if (!DEBUG || g.NavMoveRequest) { g.NavMoveResultBestId = *id; g.NavMoveResultBestRefRectRel = ImRect(nav_bb.Min - window->Pos, nav_bb.Max - window->Pos); @@ -2457,9 +2455,12 @@ static void NavUpdate() // Reset search g.NavMoveResultBestId = 0; g.NavMoveResultBestDistAxial = g.NavMoveResultBestDistBox = g.NavMoveResultBestDistCenter = FLT_MAX; + + // For scoring we use a single segment on the left side our current item bounding box (not touching the edge to avoid box overlap with zero-spaced items) g.NavScoringRectScreen = g.NavWindow ? ImRect(g.NavWindow->Pos + g.NavRefRectRel.Min, g.NavWindow->Pos + g.NavRefRectRel.Max) : ImRect(); - //g.OverlayDrawList.AddRect(g.NavRefRectScreen.Min, g.NavRefRectScreen.Max, IM_COL32(255,200,0,255)); // [DEBUG] + g.NavScoringRectScreen.Min.x = ImMin(g.NavScoringRectScreen.Min.x + 1.0f, g.NavScoringRectScreen.Max.x); g.NavScoringRectScreen.Max.x = g.NavScoringRectScreen.Min.x; + //g.OverlayDrawList.AddRect(g.NavScoringRectScreen.Min, g.NavScoringRectScreen.Max, IM_COL32(255,200,0,255)); // [DEBUG] } void ImGui::NewFrame() From 2f945635640db7031cf07402072384c86ce0dd6a Mon Sep 17 00:00:00 2001 From: ocornut Date: Sat, 23 Jul 2016 20:09:41 +0200 Subject: [PATCH 028/823] Navigation: Collapsed window uses ImGuiCol_TitleBgActive when navigation is active (#323) --- imgui.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index b989cfcc061f..3641e13542f0 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -4622,8 +4622,9 @@ bool ImGui::Begin(const char* name, bool* p_open, const ImVec2& size_on_first_us const float window_rounding = (flags & ImGuiWindowFlags_ChildWindow) ? style.ChildWindowRounding : style.WindowRounding; if (window->Collapsed) { - // Draw title bar only - RenderFrame(title_bar_rect.GetTL(), title_bar_rect.GetBR(), GetColorU32(ImGuiCol_TitleBgCollapsed), true, window_rounding); + // Title bar only + const bool is_focused = g.FocusedWindow && window->RootNonPopupWindow == g.FocusedWindow->RootNonPopupWindow && !g.NavDisableHighlight; + RenderFrame(title_bar_rect.GetTL(), title_bar_rect.GetBR(), GetColorU32(is_focused ? ImGuiCol_TitleBgActive : ImGuiCol_TitleBgCollapsed), true, window_rounding); } else { @@ -4704,8 +4705,9 @@ bool ImGui::Begin(const char* name, bool* p_open, const ImVec2& size_on_first_us window->DrawList->AddRectFilled(window->Pos+ImVec2(0,window->TitleBarHeight()), window->Pos+window->Size, ColorConvertFloat4ToU32(bg_color), window_rounding, (flags & ImGuiWindowFlags_NoTitleBar) ? 15 : 4|8); // Title bar + const bool is_focused = g.FocusedWindow && window->RootNonPopupWindow == g.FocusedWindow->RootNonPopupWindow; if (!(flags & ImGuiWindowFlags_NoTitleBar)) - window->DrawList->AddRectFilled(title_bar_rect.GetTL(), title_bar_rect.GetBR(), GetColorU32((g.FocusedWindow && window->RootNonPopupWindow == g.FocusedWindow->RootNonPopupWindow) ? ImGuiCol_TitleBgActive : ImGuiCol_TitleBg), window_rounding, 1|2); + window->DrawList->AddRectFilled(title_bar_rect.GetTL(), title_bar_rect.GetBR(), GetColorU32(is_focused ? ImGuiCol_TitleBgActive : ImGuiCol_TitleBg), window_rounding, 1|2); // Menu bar if (flags & ImGuiWindowFlags_MenuBar) From e9d8b48a4c233d3684f589018c830af6536338d6 Mon Sep 17 00:00:00 2001 From: ocornut Date: Sat, 23 Jul 2016 20:30:44 +0200 Subject: [PATCH 029/823] Navigation: Allow to navigate out of text input with direction or NavCancel (#323) --- imgui.cpp | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 3641e13542f0..c5322576e09a 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2337,6 +2337,7 @@ static void NavUpdate() { // Apply result from previous navigation directional move request IM_ASSERT(g.NavWindow); + ImGui::SetActiveID(0); g.NavId = g.NavWindow->NavLastId = g.NavMoveResultBestId; g.NavRefRectRel = g.NavMoveResultBestRefRectRel; g.NavMousePosDirty = true; @@ -2387,11 +2388,15 @@ static void NavUpdate() g.IO.NavActive = g.IO.NavUsable && g.NavId != 0 && !g.NavDisableHighlight; // Process NavCancel input (to close a popup, get back to parent, clear focus) - if (g.ActiveId == 0 && IsKeyPressedMap(ImGuiKey_NavCancel)) + if (IsKeyPressedMap(ImGuiKey_NavCancel)) { - // Close open popup or move back to parent window - if (g.OpenPopupStack.Size > 0) + if (g.ActiveId != 0) { + ImGui::SetActiveID(0); + } + else if (g.OpenPopupStack.Size > 0) + { + // Close open popup or move back to parent window ClosePopupToLevel(g.OpenPopupStack.Size - 1); } else @@ -6911,6 +6916,7 @@ bool ImGui::InputScalarAsWidgetReplacement(const ImRect& aabb, const char* label // Our replacement widget will override the focus ID (registered previously to allow for a TAB focus to happen) SetActiveIDNoNav(g.ScalarAsInputTextId, window); + g.ActiveIdAllowNavMove = true; SetHoveredID(0); FocusableItemUnregister(window); @@ -8363,6 +8369,7 @@ bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2 select_all = true; } SetActiveID(id, window); + g.ActiveIdAllowNavMove = true; FocusWindow(window); } else if (io.MouseClicked[0]) From 4bbdaa4e3c09688d58df472d76a91dcc5e2f90f3 Mon Sep 17 00:00:00 2001 From: ocornut Date: Sun, 24 Jul 2016 11:56:36 +0200 Subject: [PATCH 030/823] Navigation: Moving NavInitWindow() around and making it static (#323) --- imgui.cpp | 36 ++++++++++++++++++------------------ imgui_internal.h | 1 - 2 files changed, 18 insertions(+), 19 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index c5322576e09a..8d51f5e737f3 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2265,6 +2265,24 @@ int ImGui::GetFrameCount() return GImGui->FrameCount; } +// This needs to be called before we submit any widget (aka in or before Begin) +static void NavInitWindow(ImGuiWindow* window) +{ + ImGuiContext& g = *GImGui; + if (!(window->Flags & ImGuiWindowFlags_ChildWindow) || (window->Flags & ImGuiWindowFlags_Popup) || (window->NavLastId == 0)) + { + g.NavId = window->NavLastId = 0; + g.NavInitDefaultRequest = true; + g.NavInitDefaultResultExplicit = false; + g.NavInitDefaultResultId = 0; + } + else + { + g.NavId = window->NavLastId; + } + g.NavWindow = window; +} + static ImVec2 NavCalcPreferredMousePos() { ImGuiContext& g = *GImGui; @@ -5059,24 +5077,6 @@ void ImGui::FocusWindow(ImGuiWindow* window) g.Windows.push_back(window); } -// This needs to be called before we submit any widget (aka in or before Begin) -void ImGui::NavInitWindow(ImGuiWindow* window) -{ - ImGuiContext& g = *GImGui; - if (!(window->Flags & ImGuiWindowFlags_ChildWindow) || (window->Flags & ImGuiWindowFlags_Popup) || (window->NavLastId == 0)) - { - g.NavId = window->NavLastId = 0; - g.NavInitDefaultRequest = true; - g.NavInitDefaultResultExplicit = false; - g.NavInitDefaultResultId = 0; - } - else - { - g.NavId = window->NavLastId; - } - g.NavWindow = window; -} - void ImGui::PushItemWidth(float item_width) { ImGuiWindow* window = GetCurrentWindow(); diff --git a/imgui_internal.h b/imgui_internal.h index 6180891da02b..3da73debdbb8 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -773,7 +773,6 @@ namespace ImGui IMGUI_API void OpenPopupEx(const char* str_id, bool reopen_existing); - IMGUI_API void NavInitWindow(ImGuiWindow* window); IMGUI_API ImVec2 NavGetTweakDelta(); inline IMGUI_API ImU32 GetColorU32(ImGuiCol idx, float alpha_mul) { ImVec4 c = GImGui->Style.Colors[idx]; c.w *= GImGui->Style.Alpha * alpha_mul; return ImGui::ColorConvertFloat4ToU32(c); } From ba43310df105bcca90573093312622aeba281404 Mon Sep 17 00:00:00 2001 From: ocornut Date: Sun, 24 Jul 2016 12:46:25 +0200 Subject: [PATCH 031/823] Navigation: Renaming, shortened some unnecessary long fields names (#323) --- imgui.cpp | 54 ++++++++++++++++++++++++------------------------ imgui_internal.h | 14 ++++++------- 2 files changed, 34 insertions(+), 34 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 8d51f5e737f3..04684e9ede51 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1971,21 +1971,21 @@ static bool NavScoreItem(ImRect cand) if (quadrant == g.NavMoveDir) { // Does it beat the current best candidate? - if (dist_box < g.NavMoveResultBestDistBox) + if (dist_box < g.NavMoveResultDistBox) { - g.NavMoveResultBestDistBox = dist_box; - g.NavMoveResultBestDistCenter = dist_center; + g.NavMoveResultDistBox = dist_box; + g.NavMoveResultDistCenter = dist_center; return true; } - if (dist_box == g.NavMoveResultBestDistBox) + if (dist_box == g.NavMoveResultDistBox) { // Try using distance between center points to break ties - if (dist_center < g.NavMoveResultBestDistCenter) + if (dist_center < g.NavMoveResultDistCenter) { - g.NavMoveResultBestDistCenter = dist_center; + g.NavMoveResultDistCenter = dist_center; new_best = true; } - else if (dist_center == g.NavMoveResultBestDistCenter) + else if (dist_center == g.NavMoveResultDistCenter) { // Still tied! we need to be extra-careful to make sure everything gets linked properly. We consistently break ties by symbolically moving "later" buttons // (with higher index) to the right/downwards by an infinitesimal amount since we the current "best" button already (so it must have a lower index), @@ -1999,10 +1999,10 @@ static bool NavScoreItem(ImRect cand) // Axial check: if 'curr' has no link at all in some direction and 'cand' lies roughly in that direction, add a tentative link. This will only be kept if no "real" matches // are found, so it only augments the graph produced by the above method using extra links. (important, since it doesn't guarantee strong connectedness) // This is just to avoid buttons having no links in a particular direction when there's a suitable neighbor. you get good graphs without this too. - if (g.NavMoveResultBestDistBox == FLT_MAX) - if (dist_axial < g.NavMoveResultBestDistAxial) // Check axial match + if (g.NavMoveResultDistBox == FLT_MAX) + if (dist_axial < g.NavMoveResultDistAxial) // Check axial match if ((g.NavMoveDir == ImGuiNavDir_W && dax < 0.0f) || (g.NavMoveDir == ImGuiNavDir_E && dax > 0.0f) || (g.NavMoveDir == ImGuiNavDir_N && day < 0.0f) || (g.NavMoveDir == ImGuiNavDir_S && day > 0.0f)) - g.NavMoveResultBestDistAxial = dist_axial, new_best = true; + g.NavMoveResultDistAxial = dist_axial, new_best = true; return new_best; } @@ -2055,9 +2055,9 @@ bool ImGui::ItemAdd(const ImRect& bb, const ImGuiID* id, const ImRect* nav_bb_ar const ImRect& nav_bb = nav_bb_arg ? *nav_bb_arg : bb; if (NavScoreItem(nav_bb)) //if (!DEBUG || g.NavMoveRequest) { - g.NavMoveResultBestId = *id; - g.NavMoveResultBestRefRectRel = ImRect(nav_bb.Min - window->Pos, nav_bb.Max - window->Pos); - //g.OverlayDrawList.AddRectFilled(g.NavRefRectScreen.Min, g.NavRefRectScreen.Max+ImVec2(2,2), IM_COL32(255,255,0,255)); // [DEBUG] + g.NavMoveResultId = *id; + g.NavMoveResultRectRel = ImRect(nav_bb.Min - window->Pos, nav_bb.Max - window->Pos); + //g.OverlayDrawList.AddRectFilled(g.NavScoringRectScreen.Min, g.NavScoringRectScreen.Max+ImVec2(2,2), IM_COL32(255,255,0,255)); // [DEBUG] //g.OverlayDrawList.AddRectFilled(nav_bb.Min, nav_bb.Max, IM_COL32(255,0,255,100)); // [DEBUG] //g.OverlayDrawList.AddText(nav_bb.Min, ~0U, "new_best"); // [DEBUG] } @@ -2326,38 +2326,38 @@ static void NavUpdate() ImRect window_rect_rel(g.NavWindow->InnerRect.Min - g.NavWindow->Pos, g.NavWindow->InnerRect.Max - g.NavWindow->Pos); window_rect_rel.Expand(1.0f); //g.OverlayDrawList.AddRect(g.NavWindow->Pos + window_rect_rel.Min, g.NavWindow->Pos + window_rect_rel.Max, IM_COL32_WHITE); // [DEBUG] - if (g.NavWindow && g.NavMoveResultBestId != 0 && !window_rect_rel.Contains(g.NavMoveResultBestRefRectRel)) + if (g.NavWindow && g.NavMoveResultId != 0 && !window_rect_rel.Contains(g.NavMoveResultRectRel)) { - if (g.NavWindow->ScrollbarX && g.NavMoveResultBestRefRectRel.Min.x < window_rect_rel.Min.x) + if (g.NavWindow->ScrollbarX && g.NavMoveResultRectRel.Min.x < window_rect_rel.Min.x) { - g.NavWindow->ScrollTarget.x = g.NavMoveResultBestRefRectRel.Min.x + g.NavWindow->Scroll.x - g.Style.ItemSpacing.x; + g.NavWindow->ScrollTarget.x = g.NavMoveResultRectRel.Min.x + g.NavWindow->Scroll.x - g.Style.ItemSpacing.x; g.NavWindow->ScrollTargetCenterRatio.x = 0.0f; } - else if (g.NavWindow->ScrollbarX && g.NavMoveResultBestRefRectRel.Max.x >= window_rect_rel.Max.x) + else if (g.NavWindow->ScrollbarX && g.NavMoveResultRectRel.Max.x >= window_rect_rel.Max.x) { - g.NavWindow->ScrollTarget.x = g.NavMoveResultBestRefRectRel.Max.x + g.NavWindow->Scroll.x + g.Style.ItemSpacing.x; + g.NavWindow->ScrollTarget.x = g.NavMoveResultRectRel.Max.x + g.NavWindow->Scroll.x + g.Style.ItemSpacing.x; g.NavWindow->ScrollTargetCenterRatio.x = 1.0f; } - if (g.NavMoveResultBestRefRectRel.Min.y < window_rect_rel.Min.y) + if (g.NavMoveResultRectRel.Min.y < window_rect_rel.Min.y) { - g.NavWindow->ScrollTarget.y = g.NavMoveResultBestRefRectRel.Min.y + g.NavWindow->Scroll.y - g.Style.ItemSpacing.y; + g.NavWindow->ScrollTarget.y = g.NavMoveResultRectRel.Min.y + g.NavWindow->Scroll.y - g.Style.ItemSpacing.y; g.NavWindow->ScrollTargetCenterRatio.y = 0.0f; } - else if (g.NavMoveResultBestRefRectRel.Max.y >= window_rect_rel.Max.y) + else if (g.NavMoveResultRectRel.Max.y >= window_rect_rel.Max.y) { - g.NavWindow->ScrollTarget.y = g.NavMoveResultBestRefRectRel.Max.y + g.NavWindow->Scroll.y + g.Style.ItemSpacing.y; + g.NavWindow->ScrollTarget.y = g.NavMoveResultRectRel.Max.y + g.NavWindow->Scroll.y + g.Style.ItemSpacing.y; g.NavWindow->ScrollTargetCenterRatio.y = 1.0f; } } } - if (g.NavMoveRequest && g.NavMoveResultBestId != 0) + if (g.NavMoveRequest && g.NavMoveResultId != 0) { // Apply result from previous navigation directional move request IM_ASSERT(g.NavWindow); ImGui::SetActiveID(0); - g.NavId = g.NavWindow->NavLastId = g.NavMoveResultBestId; - g.NavRefRectRel = g.NavMoveResultBestRefRectRel; + g.NavId = g.NavWindow->NavLastId = g.NavMoveResultId; + g.NavRefRectRel = g.NavMoveResultRectRel; g.NavMousePosDirty = true; g.NavDisableHighlight = false; g.NavDisableMouseHover = true; @@ -2476,8 +2476,8 @@ static void NavUpdate() } // Reset search - g.NavMoveResultBestId = 0; - g.NavMoveResultBestDistAxial = g.NavMoveResultBestDistBox = g.NavMoveResultBestDistCenter = FLT_MAX; + g.NavMoveResultId = 0; + g.NavMoveResultDistAxial = g.NavMoveResultDistBox = g.NavMoveResultDistCenter = FLT_MAX; // For scoring we use a single segment on the left side our current item bounding box (not touching the edge to avoid box overlap with zero-spaced items) g.NavScoringRectScreen = g.NavWindow ? ImRect(g.NavWindow->Pos + g.NavRefRectRel.Min, g.NavWindow->Pos + g.NavRefRectRel.Max) : ImRect(); diff --git a/imgui_internal.h b/imgui_internal.h index 3da73debdbb8..fc6ffbd12558 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -420,11 +420,11 @@ struct ImGuiContext bool NavInitDefaultResultExplicit; // Whether the result was explicitly requested with SetItemDefaultFocus() bool NavMoveRequest; // Move request for this frame ImGuiNavDir NavMoveDir; // West/East/North/South - ImGuiID NavMoveResultBestId; // Best move request candidate - float NavMoveResultBestDistBox; // Best move request candidate box distance to current NavId - float NavMoveResultBestDistCenter; // Best move request candidate center distance to current NavId - float NavMoveResultBestDistAxial; - ImRect NavMoveResultBestRefRectRel; // Best move request candidate bounding box in window space + ImGuiID NavMoveResultId; // Best move request candidate + float NavMoveResultDistBox; // Best move request candidate box distance to current NavId + float NavMoveResultDistCenter; // Best move request candidate center distance to current NavId + float NavMoveResultDistAxial; + ImRect NavMoveResultRectRel; // Best move request candidate bounding box in window relative space // Storage for SetNexWindow** and SetNextTreeNode*** functions ImVec2 SetNextWindowPosVal; @@ -524,8 +524,8 @@ struct ImGuiContext NavInitDefaultResultExplicit = false; NavMoveRequest = false; NavMoveDir = ImGuiNavDir_None; - NavMoveResultBestId = 0; - NavMoveResultBestDistBox = NavMoveResultBestDistCenter = NavMoveResultBestDistAxial = 0.0f; + NavMoveResultId = 0; + NavMoveResultDistBox = NavMoveResultDistCenter = NavMoveResultDistAxial = 0.0f; SetNextWindowPosVal = ImVec2(0.0f, 0.0f); SetNextWindowSizeVal = ImVec2(0.0f, 0.0f); From 5cac4926c82a41253bd3540ce1bb4f50b0cfc146 Mon Sep 17 00:00:00 2001 From: ocornut Date: Sun, 24 Jul 2016 13:56:31 +0200 Subject: [PATCH 032/823] Fixed display of TitleBgActive color on window before a Modal window + modal window availability for navigation (#323) --- imgui.cpp | 4 ++-- imgui_internal.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 04684e9ede51..37282b2dd5fe 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -4412,11 +4412,11 @@ bool ImGui::Begin(const char* name, bool* p_open, const ImVec2& size_on_first_us if (!(g.CurrentWindowStack[root_idx]->Flags & ImGuiWindowFlags_ChildWindow)) break; for (root_non_popup_idx = root_idx; root_non_popup_idx > 0; root_non_popup_idx--) - if (!(g.CurrentWindowStack[root_non_popup_idx]->Flags & (ImGuiWindowFlags_ChildWindow | ImGuiWindowFlags_Popup))) + if (!(g.CurrentWindowStack[root_non_popup_idx]->Flags & (ImGuiWindowFlags_ChildWindow | ImGuiWindowFlags_Popup)) || (g.CurrentWindowStack[root_non_popup_idx]->Flags & ImGuiWindowFlags_Modal)) break; window->ParentWindow = parent_window; window->RootWindow = g.CurrentWindowStack[root_idx]; - window->RootNonPopupWindow = g.CurrentWindowStack[root_non_popup_idx]; // Used e.g. to keep displaying TitleBgActive color when menu is active, and for NavWindowing + window->RootNonPopupWindow = g.CurrentWindowStack[root_non_popup_idx]; // Used to display TitleBgActive color and for selecting which window to use for NavWindowing // When reusing window again multiple times a frame, just append content (don't need to setup again) if (first_begin_of_the_frame) diff --git a/imgui_internal.h b/imgui_internal.h index fc6ffbd12558..59381135e57e 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -708,7 +708,7 @@ struct IMGUI_API ImGuiWindow float FontWindowScale; // Scale multiplier per-window ImDrawList* DrawList; ImGuiWindow* RootWindow; // If we are a child window, this is pointing to the first non-child parent window. Else point to ourself. - ImGuiWindow* RootNonPopupWindow; // If we are a child window, this is pointing to the first non-child non-popup parent window. Else point to ourself. + ImGuiWindow* RootNonPopupWindow; // Used to display TitleBgActive color and for selecting which window to use for NavWindowing ImGuiWindow* ParentWindow; // Immediate parent in the window stack *regardless* of whether this window is a child window or not) // Navigation / Focus From 49ec65b1b55ebb3cacacfc1a67701a250b9b0364 Mon Sep 17 00:00:00 2001 From: ocornut Date: Sun, 24 Jul 2016 14:00:29 +0200 Subject: [PATCH 033/823] Navigation: can't manually focus out of a modal window with controller (#323) --- imgui.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 37282b2dd5fe..dffc3725d989 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2370,9 +2370,9 @@ static void NavUpdate() { // FIXME-NAVIGATION: Need to clarify input semantic, naming is misleading/incorrect here. int focus_change_dir = IsKeyPressedMap(ImGuiKey_NavTweakFaster, true) ? -1 : IsKeyPressedMap(ImGuiKey_NavTweakSlower, true) ? +1 : 0; - if (focus_change_dir != 0) + if (focus_change_dir != 0 && !(g.NavWindowingTarget->Flags & ImGuiWindowFlags_Modal)) { - // FIXME-NAVIGATION FIXME-OPT: This is absolutely hideous and shouldn't stay. Pressed we should maintain a intrusive linked-list of visible windows. + // FIXME-NAVIGATION FIXME-OPT: Code is absolutely hideous. Perhaps we should maintain a intrusive linked-list of visible windows. int i_current = -1; for (int i = g.Windows.Size-1; i >= 0 && i_current == -1; i--) if (g.Windows[i] == g.NavWindowingTarget) From a424d6f805f474e5faaf85eaae9e7a061c2063b7 Mon Sep 17 00:00:00 2001 From: ocornut Date: Sun, 24 Jul 2016 14:08:50 +0200 Subject: [PATCH 034/823] Navigation: Fixed missing initialization (had no side-effect, would be set in Begin) (#323) --- imgui_internal.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/imgui_internal.h b/imgui_internal.h index 59381135e57e..7f6de494d573 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -640,7 +640,7 @@ struct IMGUI_API ImGuiDrawContext LayoutType = ImGuiLayoutType_Vertical; ItemWidth = 0.0f; ButtonRepeat = false; - AllowKeyboardFocus = true; + AllowKeyboardFocus = AllowNavDefaultFocus = true; TextWrapPos = -1.0f; ColorEditMode = ImGuiColorEditMode_RGB; memset(StackSizesBackup, 0, sizeof(StackSizesBackup)); From 67feb5ac6c9c702ab576d00b20a370df44332074 Mon Sep 17 00:00:00 2001 From: ocornut Date: Sun, 24 Jul 2016 14:15:34 +0200 Subject: [PATCH 035/823] Navigation: comments + moving init block of code above in NavUpdate(), should have no side-effect (committed to simplify next commit) (#323) --- imgui.cpp | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index dffc3725d989..021ddd5f5c59 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2298,6 +2298,15 @@ static void NavUpdate() ImGuiContext& g = *GImGui; g.IO.WantMoveMouse = false; + // Process navigation init request (select first/default focus) + if (g.NavInitDefaultResultId != 0 && (!g.NavDisableHighlight || g.NavInitDefaultResultExplicit)) + { + // Apply result from previous navigation init request (typically select the first item, unless SetItemDefaultFocus() has been called) + IM_ASSERT(g.NavWindow); + g.NavId = g.NavWindow->NavLastId = g.NavInitDefaultResultId; + } + + // Apply application mouse position movement if (g.NavMousePosDirty && g.NavIdIsAlive) { // Set mouse position given our knowledge of the nav widget position from last frame @@ -2310,23 +2319,17 @@ static void NavUpdate() } g.NavIdIsAlive = false; g.NavTabbedId = 0; - - if (g.NavInitDefaultResultId != 0 && (!g.NavDisableHighlight || g.NavInitDefaultResultExplicit)) + + // Process navigation move request + if (g.NavMoveRequest && g.NavMoveResultId != 0) { - // Apply result from previous navigation init request (typically select the first item, unless SetItemDefaultFocus() has been called) IM_ASSERT(g.NavWindow); - g.NavId = g.NavWindow->NavLastId = g.NavInitDefaultResultId; - //if (g.NavInitDefaultResultExplicit) - // g.NavDisableHighlight = false; - } - if (g.NavMoveRequest) - { // Scroll to keep newly navigated item fully into view ImRect window_rect_rel(g.NavWindow->InnerRect.Min - g.NavWindow->Pos, g.NavWindow->InnerRect.Max - g.NavWindow->Pos); window_rect_rel.Expand(1.0f); //g.OverlayDrawList.AddRect(g.NavWindow->Pos + window_rect_rel.Min, g.NavWindow->Pos + window_rect_rel.Max, IM_COL32_WHITE); // [DEBUG] - if (g.NavWindow && g.NavMoveResultId != 0 && !window_rect_rel.Contains(g.NavMoveResultRectRel)) + if (!window_rect_rel.Contains(g.NavMoveResultRectRel)) { if (g.NavWindow->ScrollbarX && g.NavMoveResultRectRel.Min.x < window_rect_rel.Min.x) { @@ -2349,10 +2352,7 @@ static void NavUpdate() g.NavWindow->ScrollTargetCenterRatio.y = 1.0f; } } - } - if (g.NavMoveRequest && g.NavMoveResultId != 0) - { // Apply result from previous navigation directional move request IM_ASSERT(g.NavWindow); ImGui::SetActiveID(0); From 175f42420cccdc488682e3d608644b3dfe71c588 Mon Sep 17 00:00:00 2001 From: ocornut Date: Sun, 24 Jul 2016 14:41:27 +0200 Subject: [PATCH 036/823] Navigation: Can nav-out but not nav-in a window with ImGuiWindowFlags_NoNav flag (#323) --- imgui.cpp | 10 ++++------ imgui_internal.h | 1 + 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 021ddd5f5c59..d37d3f02441b 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2368,6 +2368,7 @@ static void NavUpdate() g.NavWindowingTarget = g.NavWindow->RootNonPopupWindow; if (g.NavWindowingTarget) { + // Select window to focus // FIXME-NAVIGATION: Need to clarify input semantic, naming is misleading/incorrect here. int focus_change_dir = IsKeyPressedMap(ImGuiKey_NavTweakFaster, true) ? -1 : IsKeyPressedMap(ImGuiKey_NavTweakSlower, true) ? +1 : 0; if (focus_change_dir != 0 && !(g.NavWindowingTarget->Flags & ImGuiWindowFlags_Modal)) @@ -2379,16 +2380,13 @@ static void NavUpdate() i_current = i; int i_target = -1; for (int i = i_current+focus_change_dir; i >= 0 && i < g.Windows.Size && i_target == -1; i += focus_change_dir) - if (g.Windows[i]->Active && g.Windows[i] == g.Windows[i]->RootNonPopupWindow) + if (g.Windows[i]->IsNavigableTo()) i_target = i; for (int i = (focus_change_dir < 0) ? (g.Windows.Size-1) : 0; i >= 0 && i < g.Windows.Size && i_target == -1 && i_target != i_current; i += focus_change_dir) - if (g.Windows[i]->Active && g.Windows[i] == g.Windows[i]->RootNonPopupWindow) + if (g.Windows[i]->IsNavigableTo()) i_target = i; - if (i_target != -1) - { - IM_ASSERT(i_target != i_current); + if (i_target != -1 && i_target != i_current) // i_target might be == i_current in rare situation where we only have 1 navigable window g.NavWindowingTarget = g.Windows[i_target]; - } } // Apply actual focus only when leaving NavWindowing mode (until then the window was merely rendered front-most) diff --git a/imgui_internal.h b/imgui_internal.h index 7f6de494d573..084196dcba40 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -735,6 +735,7 @@ struct IMGUI_API ImGuiWindow ImRect TitleBarRect() const { return ImRect(Pos, ImVec2(Pos.x + SizeFull.x, Pos.y + TitleBarHeight())); } float MenuBarHeight() const { return (Flags & ImGuiWindowFlags_MenuBar) ? CalcFontSize() + GImGui->Style.FramePadding.y * 2.0f : 0.0f; } ImRect MenuBarRect() const { float y1 = Pos.y + TitleBarHeight(); return ImRect(Pos.x, y1, Pos.x + SizeFull.x, y1 + MenuBarHeight()); } + bool IsNavigableTo() const { return Active && this == this->RootNonPopupWindow && (!(Flags & ImGuiWindowFlags_NoNav) || this == GImGui->FocusedWindow); } }; //----------------------------------------------------------------------------- From c3aa36d9ab6f7834ab0d197ff31920648e53652c Mon Sep 17 00:00:00 2001 From: ocornut Date: Sun, 24 Jul 2016 14:49:16 +0200 Subject: [PATCH 037/823] Navigation: Renamed ImGuiKey_NavWindowing to ImGuiKey_NavMenu (#323) --- imgui.cpp | 4 ++-- imgui.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index d37d3f02441b..aec8dac5623b 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2364,7 +2364,7 @@ static void NavUpdate() } // Navigation windowing mode (change focus, move/resize window) - if (!g.NavWindowingTarget && g.NavWindow && IsKeyPressedMap(ImGuiKey_NavWindowing, false)) + if (!g.NavWindowingTarget && g.NavWindow && IsKeyPressedMap(ImGuiKey_NavMenu, false)) g.NavWindowingTarget = g.NavWindow->RootNonPopupWindow; if (g.NavWindowingTarget) { @@ -2390,7 +2390,7 @@ static void NavUpdate() } // Apply actual focus only when leaving NavWindowing mode (until then the window was merely rendered front-most) - if (!IsKeyDownMap(ImGuiKey_NavWindowing)) + if (!IsKeyDownMap(ImGuiKey_NavMenu)) { if (g.NavWindowingTarget) if (!g.FocusedWindow || (g.NavWindowingTarget->RootNonPopupWindow != g.FocusedWindow->RootNonPopupWindow)) diff --git a/imgui.h b/imgui.h index a415deeccdcc..a8569c327137 100644 --- a/imgui.h +++ b/imgui.h @@ -599,7 +599,7 @@ enum ImGuiKey_ ImGuiKey_NavActivate, // press button, tweak value // e.g. Space key, Circle button ImGuiKey_NavCancel, // close menu/popup/child, unselect // e.g. Escape key, Cross button ImGuiKey_NavInput, // text input // e.g. Enter key, Triangle button - ImGuiKey_NavWindowing, // change focus, move, resize // e.g. Square button + ImGuiKey_NavMenu, // access menu, focus, move, resize // e.g. Square button ImGuiKey_NavLeft, // e.g. Left arrow, D-Pad left ImGuiKey_NavRight, // e.g. Right arrow, D-Pad right ImGuiKey_NavUp, // e.g. Up arrow, D-Pad up From aeabda5a5feb2eab16e886b767c4a347b6df9b71 Mon Sep 17 00:00:00 2001 From: ocornut Date: Sun, 24 Jul 2016 14:56:14 +0200 Subject: [PATCH 038/823] Navigation: Tap NavMenu to access menu and close buttons, hold to focus/resize (#323) Introducing a concept of NavLayer to filter navigable items --- imgui.cpp | 168 +++++++++++++++++++++++++++++++++-------------- imgui_internal.h | 21 ++++-- 2 files changed, 133 insertions(+), 56 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index aec8dac5623b..8d187da9c5a2 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1837,6 +1837,8 @@ void ImGui::SetActiveID(ImGuiID id, ImGuiWindow* window = NULL) g.NavDisableHighlight = true; g.NavId = id; if (window) + g.NavLayer = window->DC.NavLayerCurrent; + if (window && window->DC.NavLayerCurrent == 0) // (Assume that id correspond to the current NavLayer, which should be the case) window->NavLastId = id; } } @@ -1914,8 +1916,12 @@ static float NavScoreItemDistInterval(float a0, float a1, float b0, float b1) static bool NavScoreItem(ImRect cand) { ImGuiContext& g = *GImGui; + ImGuiWindow* window = g.CurrentWindow; + if (g.NavLayer != window->DC.NavLayerCurrent) + return false; + const ImRect& curr = g.NavScoringRectScreen; // Current modified source rect (NB: we've applied Max.x = Min.x in NavUpdate() to inhibit the effect of having lots of items with varied width) - cand.Clip(g.CurrentWindow->ClipRect); + cand.Clip(window->ClipRect); // Compute distance between boxes // FIXME-NAVIGATION: Introducing various biases toward typical imgui uses cases, but we don't have any rigorous proof of their effect now. @@ -1952,7 +1958,7 @@ static bool NavScoreItem(ImRect cand) else { // Degenerate case: two overlapping buttons with same center, break ties using order - quadrant = (g.CurrentWindow->DC.LastItemId < g.NavId) ? ImGuiNavDir_W : ImGuiNavDir_E; + quadrant = (window->DC.LastItemId < g.NavId) ? ImGuiNavDir_W : ImGuiNavDir_E; } #if 0 // [DEBUG] @@ -2030,8 +2036,9 @@ bool ImGui::ItemAdd(const ImRect& bb, const ImGuiID* id, const ImRect* nav_bb_ar window->DC.LastItemId = id ? *id : 0; window->DC.LastItemRect = bb; window->DC.LastItemHoveredAndUsable = window->DC.LastItemHoveredRect = false; - if (id != NULL) window->DC.NavHasItemsNext = true; const bool is_clipped = IsClippedEx(bb, id, false); + if (id != NULL) + window->DC.NavLayerActiveFlagsNext |= (1 << window->DC.NavLayerCurrent); // Navigation processing runs prior to clipping early-out // (a) So that NavInitDefaultRequest can be honored, for newly opened windows to select a default widget @@ -2042,32 +2049,31 @@ bool ImGui::ItemAdd(const ImRect& bb, const ImGuiID* id, const ImRect* nav_bb_ar // So eventually we would like to provide the user will the primitives to be able to implement that sort of customized/efficient navigation handling whenever necessary. if (id != NULL && g.NavWindow == window && g.IO.NavUsable) { - if (g.NavInitDefaultRequest && window->DC.AllowNavDefaultFocus) + const ImRect& nav_bb = nav_bb_arg ? *nav_bb_arg : bb; + const ImRect nav_bb_rel(nav_bb.Min - window->Pos, nav_bb.Max - window->Pos); + + if (g.NavInitDefaultRequest && g.NavLayer == window->DC.NavLayerCurrent && window->DC.AllowNavDefaultFocus) { g.NavInitDefaultRequest = g.NavInitDefaultResultExplicit = false; // Clear flag immediately, first item gets default, also simplify the if() in ItemAdd() g.NavInitDefaultResultId = *id; + g.NavInitDefaultResultRectRel = nav_bb_rel; } const bool DEBUG_NAV = false; // [DEBUG] Enable to test scoring on all items. if ((g.NavMoveRequest || DEBUG_NAV) && g.NavId != *id) { //if (DEBUG_NAV && !g.NavMoveRequest) g.NavMoveDir = ImGuiNavDir_N; - const ImRect& nav_bb = nav_bb_arg ? *nav_bb_arg : bb; if (NavScoreItem(nav_bb)) //if (!DEBUG || g.NavMoveRequest) { g.NavMoveResultId = *id; - g.NavMoveResultRectRel = ImRect(nav_bb.Min - window->Pos, nav_bb.Max - window->Pos); - //g.OverlayDrawList.AddRectFilled(g.NavScoringRectScreen.Min, g.NavScoringRectScreen.Max+ImVec2(2,2), IM_COL32(255,255,0,255)); // [DEBUG] - //g.OverlayDrawList.AddRectFilled(nav_bb.Min, nav_bb.Max, IM_COL32(255,0,255,100)); // [DEBUG] - //g.OverlayDrawList.AddText(nav_bb.Min, ~0U, "new_best"); // [DEBUG] + g.NavMoveResultRectRel = nav_bb_rel; } } // Update window-relative bounding box of navigated item if (g.NavId == *id) { - const ImRect& nav_bb = nav_bb_arg ? *nav_bb_arg : bb; - g.NavRefRectRel = ImRect(nav_bb.Min - window->Pos, nav_bb.Max - window->Pos); + g.NavRefRectRel = nav_bb_rel; g.NavIdIsAlive = true; g.NavIdTabCounter = window->FocusIdxTabCounter; } @@ -2266,21 +2272,24 @@ int ImGui::GetFrameCount() } // This needs to be called before we submit any widget (aka in or before Begin) -static void NavInitWindow(ImGuiWindow* window) +static void NavInitWindow(ImGuiWindow* window, bool force_reinit) { ImGuiContext& g = *GImGui; - if (!(window->Flags & ImGuiWindowFlags_ChildWindow) || (window->Flags & ImGuiWindowFlags_Popup) || (window->NavLastId == 0)) + IM_ASSERT(window == g.NavWindow); + if (!(window->Flags & ImGuiWindowFlags_ChildWindow) || (window->Flags & ImGuiWindowFlags_Popup) || (window->NavLastId == 0) || force_reinit) { - g.NavId = window->NavLastId = 0; + g.NavId = 0; + if (g.NavLayer == 0) + window->NavLastId = 0; g.NavInitDefaultRequest = true; - g.NavInitDefaultResultExplicit = false; g.NavInitDefaultResultId = 0; + g.NavInitDefaultResultExplicit = false; + g.NavInitDefaultResultRectRel = ImRect(); } else { g.NavId = window->NavLastId; } - g.NavWindow = window; } static ImVec2 NavCalcPreferredMousePos() @@ -2293,6 +2302,18 @@ static ImVec2 NavCalcPreferredMousePos() return ImClamp(p, r.Min, r.Max); } +static void SetNavIdMoveMouse(ImGuiID id, const ImRect& rect_rel) +{ + ImGuiContext& g = *GImGui; + g.NavId = id; + if (g.NavLayer == 0) + g.NavWindow->NavLastId = g.NavId; + g.NavRefRectRel = rect_rel; + g.NavMousePosDirty = true; + g.NavDisableHighlight = false; + g.NavDisableMouseHover = true; +} + static void NavUpdate() { ImGuiContext& g = *GImGui; @@ -2303,8 +2324,15 @@ static void NavUpdate() { // Apply result from previous navigation init request (typically select the first item, unless SetItemDefaultFocus() has been called) IM_ASSERT(g.NavWindow); - g.NavId = g.NavWindow->NavLastId = g.NavInitDefaultResultId; + g.NavId = g.NavInitDefaultResultId; + g.NavRefRectRel = g.NavInitDefaultResultRectRel; + g.NavMousePosDirty = true; + if (g.NavLayer == 0) + g.NavWindow->NavLastId = g.NavId; } + g.NavInitDefaultRequest = false; + g.NavInitDefaultResultExplicit = false; + g.NavInitDefaultResultId = 0; // Apply application mouse position movement if (g.NavMousePosDirty && g.NavIdIsAlive) @@ -2329,7 +2357,7 @@ static void NavUpdate() ImRect window_rect_rel(g.NavWindow->InnerRect.Min - g.NavWindow->Pos, g.NavWindow->InnerRect.Max - g.NavWindow->Pos); window_rect_rel.Expand(1.0f); //g.OverlayDrawList.AddRect(g.NavWindow->Pos + window_rect_rel.Min, g.NavWindow->Pos + window_rect_rel.Max, IM_COL32_WHITE); // [DEBUG] - if (!window_rect_rel.Contains(g.NavMoveResultRectRel)) + if (g.NavLayer == 0 && !window_rect_rel.Contains(g.NavMoveResultRectRel)) { if (g.NavWindow->ScrollbarX && g.NavMoveResultRectRel.Min.x < window_rect_rel.Min.x) { @@ -2354,20 +2382,24 @@ static void NavUpdate() } // Apply result from previous navigation directional move request - IM_ASSERT(g.NavWindow); ImGui::SetActiveID(0); - g.NavId = g.NavWindow->NavLastId = g.NavMoveResultId; - g.NavRefRectRel = g.NavMoveResultRectRel; - g.NavMousePosDirty = true; - g.NavDisableHighlight = false; - g.NavDisableMouseHover = true; + SetNavIdMoveMouse(g.NavMoveResultId, g.NavMoveResultRectRel); } // Navigation windowing mode (change focus, move/resize window) if (!g.NavWindowingTarget && g.NavWindow && IsKeyPressedMap(ImGuiKey_NavMenu, false)) + { g.NavWindowingTarget = g.NavWindow->RootNonPopupWindow; + g.NavWindowingDisplayAlpha = 0.0f; + g.NavWindowingToggleLayer = true; + } if (g.NavWindowingTarget) { + // Visuals only appears after a brief time holding the button, so that a fast tap (to toggle NavLayer) doesn't add visual noise + const float pressed_duration = g.IO.KeysDownDuration[g.IO.KeyMap[ImGuiKey_NavMenu]]; + g.NavWindowingDisplayAlpha = ImMax(g.NavWindowingDisplayAlpha, ImSaturate((pressed_duration - 0.20f) / 0.05f)); + g.NavWindowingToggleLayer &= (g.NavWindowingDisplayAlpha < 1.0f); // Once button is held long enough we don't consider it a tag-to-toggle-layer press anymore. + // Select window to focus // FIXME-NAVIGATION: Need to clarify input semantic, naming is misleading/incorrect here. int focus_change_dir = IsKeyPressedMap(ImGuiKey_NavTweakFaster, true) ? -1 : IsKeyPressedMap(ImGuiKey_NavTweakSlower, true) ? +1 : 0; @@ -2387,14 +2419,35 @@ static void NavUpdate() i_target = i; if (i_target != -1 && i_target != i_current) // i_target might be == i_current in rare situation where we only have 1 navigable window g.NavWindowingTarget = g.Windows[i_target]; + g.NavWindowingToggleLayer = false; + g.NavWindowingDisplayAlpha = 1.0f; } - // Apply actual focus only when leaving NavWindowing mode (until then the window was merely rendered front-most) if (!IsKeyDownMap(ImGuiKey_NavMenu)) { - if (g.NavWindowingTarget) - if (!g.FocusedWindow || (g.NavWindowingTarget->RootNonPopupWindow != g.FocusedWindow->RootNonPopupWindow)) - ImGui::FocusWindow(g.NavWindowingTarget->RootNonPopupWindow); + // Apply actual focus only when releasing the NavMenu button (until then the window was merely rendered front-most) + if (g.NavWindowingTarget && (!g.FocusedWindow || g.NavWindowingTarget != g.FocusedWindow->RootNonPopupWindow)) + { + ImGui::FocusWindow(g.NavWindowingTarget); + g.NavDisableHighlight = false; + g.NavDisableMouseHover = true; + if (g.NavWindowingTarget->NavLastId == 0) + NavInitWindow(g.NavWindowingTarget, false); + } + + // Single press toggles NavLayer + if (g.NavWindowingToggleLayer) + { + if ((g.NavWindow->DC.NavLayerActiveFlags & (1<<1)) == 0 && (g.NavWindow->RootWindow->DC.NavLayerActiveFlags & (1<<1)) != 0) + ImGui::FocusWindow(g.NavWindow->RootWindow); + g.NavLayer = (g.NavWindow->DC.NavLayerActiveFlags & (1<<1)) ? (g.NavLayer ^ 1) : 0; + g.NavDisableHighlight = false; + g.NavDisableMouseHover = true; + if (g.NavLayer == 0 && g.NavWindow->NavLastId) + SetNavIdMoveMouse(g.NavWindow->NavLastId, ImRect()); + else + NavInitWindow(g.NavWindow, true); + } g.NavWindowingTarget = NULL; } } @@ -2415,6 +2468,14 @@ static void NavUpdate() // Close open popup or move back to parent window ClosePopupToLevel(g.OpenPopupStack.Size - 1); } + else if (g.NavLayer != 0) + { + g.NavLayer = 0; + if (g.NavWindow->NavLastId) + SetNavIdMoveMouse(g.NavWindow->NavLastId, ImRect()); + else + NavInitWindow(g.NavWindow, true); + } else { // Clear NavId for popups but keep it for regular child window so we can leave one and come back where we were @@ -2427,7 +2488,9 @@ static void NavUpdate() ImGuiWindow* child_window = g.FocusedWindow; ImGuiWindow* parent_window = g.FocusedWindow->ParentWindow; ImGui::FocusWindow(parent_window); - g.NavId = parent_window->NavLastId = parent_window->GetChildID(child_window); + g.NavId = parent_window->GetChildID(child_window); + if (g.NavLayer == 0) + parent_window->NavLastId = g.NavId; g.NavIdIsAlive = false; if (g.NavDisableMouseHover) g.NavMousePosDirty = true; @@ -2447,9 +2510,6 @@ static void NavUpdate() g.NavDisableHighlight = true; } g.NavMoveRequest = false; - g.NavInitDefaultRequest = false; - g.NavInitDefaultResultExplicit = false; - g.NavInitDefaultResultId = 0; // Initiate directional inputs request g.NavMoveDir = ImGuiNavDir_None; @@ -2467,7 +2527,7 @@ static void NavUpdate() } // Fallback manual-scroll with NavUp/NavDown when window has no navigable item - if (g.FocusedWindow && !g.FocusedWindow->DC.NavHasItems && g.FocusedWindow->DC.NavHasScroll && !(g.FocusedWindow->Flags & ImGuiWindowFlags_NoNav) && g.NavMoveRequest && (g.NavMoveDir == ImGuiNavDir_N || g.NavMoveDir == ImGuiNavDir_S)) + if (g.FocusedWindow && !g.FocusedWindow->DC.NavLayerActiveFlags && g.FocusedWindow->DC.NavHasScroll && !(g.FocusedWindow->Flags & ImGuiWindowFlags_NoNav) && g.NavMoveRequest && (g.NavMoveDir == ImGuiNavDir_N || g.NavMoveDir == ImGuiNavDir_S)) { float scroll_speed = ImFloor(g.FocusedWindow->CalcFontSize() * 100 * g.IO.DeltaTime + 0.5f); // We need round the scrolling speed because sub-pixel scroll isn't reliably supported. SetWindowScrollY(g.FocusedWindow, ImFloor(g.FocusedWindow->Scroll.y + ((g.NavMoveDir == ImGuiNavDir_N) ? -1.0f : +1.0f) * scroll_speed)); @@ -3760,7 +3820,8 @@ void ImGui::SetItemDefaultFocus() { g.NavInitDefaultRequest = false; g.NavInitDefaultResultExplicit = true; - g.NavInitDefaultResultId = g.CurrentWindow->DC.LastItemId; + g.NavInitDefaultResultId = g.NavWindow->DC.LastItemId; + g.NavInitDefaultResultRectRel = ImRect(g.NavWindow->DC.LastItemRect.Min - g.NavWindow->Pos, g.NavWindow->DC.LastItemRect.Max - g.NavWindow->Pos); if (!IsItemVisible()) SetScrollHere(); } @@ -4077,10 +4138,10 @@ bool ImGui::BeginChild(const char* str_id, const ImVec2& size_arg, bool border, // Process navigation-in immediately so NavInit can run on first frame const ImGuiID id = parent_window->GetChildID(child_window); - if ((child_window->DC.NavHasItems || child_window->DC.NavHasScroll) && GImGui->NavActivateId == id) + if ((child_window->DC.NavLayerActiveFlags != 0 || child_window->DC.NavHasScroll) && GImGui->NavActivateId == id) { FocusWindow(child_window); - NavInitWindow(child_window); + NavInitWindow(child_window, false); SetActiveIDNoNav(id+1, child_window); // Steal ActiveId with a dummy id so that key-press won't activate child item } @@ -4118,8 +4179,8 @@ void ImGui::EndChild() ImGuiID id = parent_window->GetChildID(window); ImRect bb(parent_window->DC.CursorPos, parent_window->DC.CursorPos + sz); ItemSize(sz); - ItemAdd(bb, (window->DC.NavHasItems || window->DC.NavHasScroll) ? &id : NULL); - if (window->DC.NavHasItems || window->DC.NavHasScroll) + ItemAdd(bb, (window->DC.NavLayerActiveFlags != 0 || window->DC.NavHasScroll) ? &id : NULL); + if (window->DC.NavLayerActiveFlags != 0 || window->DC.NavHasScroll) { //if (!window->DC.NavHasItems && window->DC.NavHasScroll && g.NavWindow == window) // As a special case, we render nav highlight of child when inside when only scrolling is possible //{ @@ -4634,8 +4695,8 @@ bool ImGui::Begin(const char* name, bool* p_open, const ImVec2& size_on_first_us { ImRect bb = window->Rect(); bb.Expand(g.FontSize); - window->DrawList->AddRectFilled(bb.Min, bb.Max, IM_COL32(255,255,255,30)/*ImGui::GetColorU32(ImGuiCol_HeaderHovered, 0.15f)*/, g.Style.WindowRounding); - window->DrawList->AddRect(bb.Min, bb.Max, ImGui::GetColorU32(ImGuiCol_HeaderHovered), g.Style.WindowRounding); + window->DrawList->AddRectFilled(bb.Min, bb.Max, IM_COL32(255,255,255,(int)(30 * g.NavWindowingDisplayAlpha))/*ImGui::GetColorU32(ImGuiCol_HeaderHovered, 0.15f)*/, g.Style.WindowRounding); + window->DrawList->AddRect(bb.Min, bb.Max, ImGui::GetColorU32(ImGuiCol_HeaderHovered, g.NavWindowingDisplayAlpha), g.Style.WindowRounding); } // Draw window + handle manual resize @@ -4682,6 +4743,7 @@ bool ImGui::Begin(const char* name, bool* p_open, const ImVec2& size_on_first_us else if (nav_resize_delta.x != 0.0f || nav_resize_delta.y != 0.0f) { // FIXME-NAVIGATION: Should store and accumulate into a separate size buffer to handle sizing constraints properly + g.NavWindowingToggleLayer = false; size_target = window->SizeFull + nav_resize_delta; held = true; // For coloring } @@ -4781,8 +4843,8 @@ bool ImGui::Begin(const char* name, bool* p_open, const ImVec2& size_on_first_us window->DC.CursorMaxPos = window->DC.CursorStartPos; window->DC.CurrentLineHeight = window->DC.PrevLineHeight = 0.0f; window->DC.CurrentLineTextBaseOffset = window->DC.PrevLineTextBaseOffset = 0.0f; - window->DC.NavHasItems = window->DC.NavHasItemsNext; - window->DC.NavHasItemsNext = false; + window->DC.NavLayerActiveFlags = window->DC.NavLayerActiveFlagsNext; + window->DC.NavLayerActiveFlagsNext = 0x00; window->DC.NavHasScroll = (GetScrollMaxY() > 0.0f); window->DC.MenuBarAppending = false; window->DC.MenuBarOffsetX = ImMax(window->WindowPadding.x, style.ItemSpacing.x); @@ -4791,8 +4853,7 @@ bool ImGui::Begin(const char* name, bool* p_open, const ImVec2& size_on_first_us window->DC.LayoutType = ImGuiLayoutType_Vertical; window->DC.ItemWidth = window->ItemWidthDefault; window->DC.TextWrapPos = -1.0f; // disabled - window->DC.AllowKeyboardFocus = true; - window->DC.AllowNavDefaultFocus = true; + window->DC.AllowKeyboardFocus = window->DC.AllowNavDefaultFocus = true; window->DC.ButtonRepeat = false; window->DC.ItemWidthStack.resize(0); window->DC.TextWrapPosStack.resize(0); @@ -4818,8 +4879,7 @@ bool ImGui::Begin(const char* name, bool* p_open, const ImVec2& size_on_first_us if (!(flags & (ImGuiWindowFlags_ChildWindow|ImGuiWindowFlags_Tooltip)) || (flags & ImGuiWindowFlags_Popup)) { FocusWindow(window); - IM_ASSERT(g.NavWindow == window); - NavInitWindow(window); + NavInitWindow(window, false); } // Title bar @@ -4829,8 +4889,10 @@ bool ImGui::Begin(const char* name, bool* p_open, const ImVec2& size_on_first_us { const float pad = 2.0f; const float rad = (window->TitleBarHeight() - pad*2.0f) * 0.5f; + window->DC.NavLayerCurrent++; if (CloseButton(window->GetID("#CLOSE"), window->Rect().GetTR() + ImVec2(-pad - rad, pad + rad), rad)) *p_open = false; + window->DC.NavLayerCurrent--; } const ImVec2 text_size = CalcTextSize(name, NULL, true); @@ -5041,8 +5103,9 @@ void ImGui::FocusWindow(ImGuiWindow* window) if (g.FocusedWindow != window) { - g.NavId = window ? window->NavLastId : 0; + g.NavId = window ? window->NavLastId : 0; // Restore NavId g.NavIdIsAlive = false; + g.NavLayer = 0; if (window && g.NavDisableMouseHover) g.NavMousePosDirty = true; g.NavRefRectRel.Min = g.NavRefRectRel.Max = window ? (window->DC.CursorStartPos - window->Pos) : ImVec2(0,0); @@ -6210,7 +6273,8 @@ bool ImGui::CloseButton(ImGuiID id, const ImVec2& pos, float radius) const ImRect bb(pos - ImVec2(radius,radius), pos + ImVec2(radius,radius)); const bool backup_allow_nav_default_focus = window->DC.AllowNavDefaultFocus; // We could exposethis as a flag to ItemAdd() but it is such a unique case for now - window->DC.AllowNavDefaultFocus = false; + if (window->Flags & ImGuiWindowFlags_MenuBar) + window->DC.AllowNavDefaultFocus = false; const bool added = ItemAdd(bb, &id); // To allow navigation window->DC.AllowNavDefaultFocus = backup_allow_nav_default_focus; if (!added) @@ -9107,7 +9171,8 @@ bool ImGui::Combo(const char* label, int* current_item, bool (*items_getter)(voi } else { - window->NavLastId = id; + if (window->DC.NavLayerCurrent == 0) + window->NavLastId = id; FocusWindow(window); OpenPopup(label); popup_open = true; @@ -9428,6 +9493,7 @@ bool ImGui::BeginMenuBar() PushClipRect(ImVec2(ImFloor(rect.Min.x+0.5f), ImFloor(rect.Min.y + window->BorderSize + 0.5f)), ImVec2(ImFloor(rect.Max.x+0.5f), ImFloor(rect.Max.y+0.5f)), false); window->DC.CursorPos = ImVec2(rect.Min.x + window->DC.MenuBarOffsetX, rect.Min.y);// + g.Style.FramePadding.y); window->DC.LayoutType = ImGuiLayoutType_Horizontal; + window->DC.NavLayerCurrent++; window->DC.MenuBarAppending = true; AlignFirstTextHeightToWidgets(); return true; @@ -9447,6 +9513,7 @@ void ImGui::EndMenuBar() window->DC.GroupStack.back().AdvanceCursor = false; EndGroup(); window->DC.LayoutType = ImGuiLayoutType_Vertical; + window->DC.NavLayerCurrent--; window->DC.MenuBarAppending = false; } @@ -10327,6 +10394,7 @@ void ImGui::ShowMetricsWindow(bool* p_open) ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate); ImGui::Text("%d vertices, %d indices (%d triangles)", ImGui::GetIO().MetricsRenderVertices, ImGui::GetIO().MetricsRenderIndices, ImGui::GetIO().MetricsRenderIndices / 3); ImGui::Text("%d allocations", ImGui::GetIO().MetricsAllocs); + ImGui::Text("sizeof(ImGuiContext) = %u, sizeof(ImGuiWindow) = %u", sizeof(ImGuiContext), sizeof(ImGuiWindow)); static bool show_clip_rects = true; ImGui::Checkbox("Show clipping rectangles when hovering a ImDrawCmd", &show_clip_rects); ImGui::Separator(); @@ -10407,7 +10475,7 @@ void ImGui::ShowMetricsWindow(bool* p_open) NodeDrawList(window->DrawList, "DrawList"); ImGui::BulletText("Size: (%.1f,%.1f), SizeContents (%.1f,%.1f)", window->Size.x, window->Size.y, window->SizeContents.x, window->SizeContents.y); ImGui::BulletText("Scroll: (%.2f,%.2f)", window->Scroll.x, window->Scroll.y); - ImGui::BulletText("NavLastId: 0x%08x, NavHasItems: %d", window->NavLastId, window->DC.NavHasItems); + ImGui::BulletText("NavLastId: 0x%08x, NavLayerActiveFlags: %02X", window->NavLastId, window->DC.NavLayerActiveFlags); if (window->RootWindow != window) NodeWindow(window->RootWindow, "RootWindow"); if (window->DC.ChildWindows.Size > 0) NodeWindows(window->DC.ChildWindows, "ChildWindows"); ImGui::BulletText("Storage: %d bytes", window->StateStorage.Data.Size * (int)sizeof(ImGuiStorage::Pair)); diff --git a/imgui_internal.h b/imgui_internal.h index 084196dcba40..67523c41abab 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -410,6 +410,9 @@ struct ImGuiContext ImRect NavRefRectRel, NavScoringRectScreen;// Reference rectangle, in window space. Modified rectangle for directional navigation scoring, in screen space. ImGuiWindow* NavWindow; // ImGuiWindow* NavWindowingTarget; + float NavWindowingDisplayAlpha; + bool NavWindowingToggleLayer; + int NavLayer; // Layer we are navigating on. For now the system is hard-coded for 0=main contents and 1=menu/title bar, may expose layers later. int NavIdTabCounter; // == NavWindow->DC.FocusIdxTabCounter at time of NavId processing bool NavIdIsAlive; // Nav widget has been seen this frame ~~ NavRefRectRel is valid bool NavMousePosDirty; @@ -417,6 +420,7 @@ struct ImGuiContext bool NavDisableMouseHover; // When user starts using gamepad/keyboard, we disable mouse hovering until mouse is touched again bool NavInitDefaultRequest; // Init request for appearing window to select first item ImGuiID NavInitDefaultResultId; + ImRect NavInitDefaultResultRectRel; bool NavInitDefaultResultExplicit; // Whether the result was explicitly requested with SetItemDefaultFocus() bool NavMoveRequest; // Move request for this frame ImGuiNavDir NavMoveDir; // West/East/North/South @@ -514,6 +518,8 @@ struct ImGuiContext NavRefRectRel = NavScoringRectScreen = ImRect(); NavWindow = NULL; NavWindowingTarget = NULL; + NavWindowingDisplayAlpha = 0.0f; + NavWindowingToggleLayer = false; NavIdTabCounter = INT_MAX; NavIdIsAlive = false; NavMousePosDirty = false; @@ -586,10 +592,11 @@ struct IMGUI_API ImGuiDrawContext int TreeDepth; ImGuiID LastItemId; ImRect LastItemRect; - bool LastItemHoveredAndUsable; // Item rectangle is hovered, and its window is currently interactable with (not blocked by a popup preventing access to the window) - bool LastItemHoveredRect; // Item rectangle is hovered, but its window may or not be currently interactable with (might be blocked by a popup preventing access to the window) - bool NavHasItems, NavHasItemsNext; // Set when has any navigatable item - bool NavHasScroll; // Set when scrolling can be used (ScrollMax > 0.0f) + bool LastItemHoveredAndUsable; // Item rectangle is hovered, and its window is currently interactable with (not blocked by a popup preventing access to the window) + bool LastItemHoveredRect; // Item rectangle is hovered, but its window may or not be currently interactable with (might be blocked by a popup preventing access to the window) + bool NavHasScroll; // Set when scrolling can be used (ScrollMax > 0.0f) + int NavLayerCurrent; // Current layer, 0..31 (we currently only use 0..1) + int NavLayerActiveFlags, NavLayerActiveFlagsNext; // Which layer have been written to. bool MenuBarAppending; float MenuBarOffsetX; ImVector ChildWindows; @@ -633,7 +640,9 @@ struct IMGUI_API ImGuiDrawContext LastItemId = 0; LastItemRect = ImRect(0.0f,0.0f,0.0f,0.0f); LastItemHoveredAndUsable = LastItemHoveredRect = false; - NavHasItems = NavHasItemsNext = NavHasScroll = false; + NavHasScroll = false; + NavLayerActiveFlags = NavLayerActiveFlagsNext = 0x00; + NavLayerCurrent = 0; MenuBarAppending = false; MenuBarOffsetX = 0.0f; StateStorage = NULL; @@ -686,7 +695,7 @@ struct IMGUI_API ImGuiWindow bool SkipItems; // == Visible && !Collapsed int BeginCount; // Number of Begin() during the current frame (generally 0 or 1, 1+ if appending via multiple Begin/End pairs) ImGuiID PopupId; // ID in the popup stack when this window is used as a popup/menu (because we use generic Name/ID for recycling) - ImGuiID NavLastId; // Last known NavId for this window + ImGuiID NavLastId; // Last known NavId for this window, for nav layer 0 only. int AutoFitFramesX, AutoFitFramesY; bool AutoFitOnlyGrows; int AutoPosLastDirection; From f34d7ea1993a5c46cdefc175c8e4fd17dcfdaf4d Mon Sep 17 00:00:00 2001 From: ocornut Date: Fri, 29 Jul 2016 11:23:04 +0200 Subject: [PATCH 039/823] Fixed bad merge --- imgui.cpp | 6 ------ 1 file changed, 6 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 2ad9b2e82b98..416426975c3c 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -823,12 +823,6 @@ ImGuiIO::ImGuiIO() FontAllowUserScaling = false; DisplayFramebufferScale = ImVec2(1.0f, 1.0f); DisplayVisibleMin = DisplayVisibleMax = ImVec2(0.0f, 0.0f); -#ifdef __APPLE__ - WordMovementUsesAltKey = true; // OS X style: Text editing cursor movement using Alt instead of Ctrl - ShortcutsUseSuperKey = true; // OS X style: Shortcuts using Cmd/Super instead of Ctrl - DoubleClickSelectsWord = true; // OS X style: Double click selects by word instead of selecting whole text - MultiSelectUsesSuperKey = true; // OS X style: Multi-selection in lists uses Cmd/Super instead of Ctrl -#endif // User functions RenderDrawListsFn = NULL; From 20a0fde0124c08a7ead82357c9346acec0bafda6 Mon Sep 17 00:00:00 2001 From: ocornut Date: Sat, 30 Jul 2016 10:02:46 +0200 Subject: [PATCH 040/823] Tidying up default clipboard handler for non Windows-OS --- imgui.cpp | 19 ++++++------------- imgui_internal.h | 3 +-- 2 files changed, 7 insertions(+), 15 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 416426975c3c..3064e3a691e6 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2833,11 +2833,7 @@ void ImGui::Shutdown() g.RenderDrawLists[i].clear(); g.OverlayDrawList.ClearFreeMemory(); g.ColorEditModeStorage.Clear(); - if (g.PrivateClipboard) - { - ImGui::MemFree(g.PrivateClipboard); - g.PrivateClipboard = NULL; - } + g.PrivateClipboard.clear(); g.InputTextState.Text.clear(); g.InputTextState.InitialText.clear(); g.InputTextState.TempTextBuffer.clear(); @@ -10336,21 +10332,18 @@ static void SetClipboardTextFn_DefaultImpl(const char* text) // Local ImGui-only clipboard implementation, if user hasn't defined better clipboard handlers static const char* GetClipboardTextFn_DefaultImpl() { - return GImGui->PrivateClipboard; + ImGuiContext& g = *GImGui; + return g.PrivateClipboard.empty() ? NULL : g.PrivateClipboard.begin(); } // Local ImGui-only clipboard implementation, if user hasn't defined better clipboard handlers static void SetClipboardTextFn_DefaultImpl(const char* text) { ImGuiContext& g = *GImGui; - if (g.PrivateClipboard) - { - ImGui::MemFree(g.PrivateClipboard); - g.PrivateClipboard = NULL; - } + g.PrivateClipboard.clear(); const char* text_end = text + strlen(text); - g.PrivateClipboard = (char*)ImGui::MemAlloc((size_t)(text_end - text) + 1); - memcpy(g.PrivateClipboard, text, (size_t)(text_end - text)); + g.PrivateClipboard.resize((size_t)(text_end - text) + 1); + memcpy(&g.PrivateClipboard[0], text, (size_t)(text_end - text)); g.PrivateClipboard[(int)(text_end - text)] = 0; } diff --git a/imgui_internal.h b/imgui_internal.h index 67523c41abab..34cc0cb73403 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -467,7 +467,7 @@ struct ImGuiContext float DragSpeedScaleFast; ImVec2 ScrollbarClickDeltaToGrabCenter; // Distance between mouse and center of grab box, normalized in parent space. Use storage? char Tooltip[1024]; - char* PrivateClipboard; // If no custom clipboard handler is defined + ImVector PrivateClipboard; // If no custom clipboard handler is defined ImVec2 OsImePosRequest, OsImePosSet; // Cursor position request & last passed to the OS Input Method Editor // Logging @@ -554,7 +554,6 @@ struct ImGuiContext DragSpeedScaleFast = 10.0f; ScrollbarClickDeltaToGrabCenter = ImVec2(0.0f, 0.0f); memset(Tooltip, 0, sizeof(Tooltip)); - PrivateClipboard = NULL; OsImePosRequest = OsImePosSet = ImVec2(-1.0f, -1.0f); ModalWindowDarkeningRatio = 0.0f; From 47358020963a10135ff6784402e5f28288b6f1f5 Mon Sep 17 00:00:00 2001 From: ocornut Date: Sat, 30 Jul 2016 10:26:57 +0200 Subject: [PATCH 041/823] Shallow tidying up ctrl+wheel scaling code in NewFrame() --- imgui.cpp | 27 ++++++++++++--------------- 1 file changed, 12 insertions(+), 15 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 3064e3a691e6..542a80c8f584 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2733,23 +2733,20 @@ void ImGui::NewFrame() if (g.HoveredWindow && g.IO.MouseWheel != 0.0f && !g.HoveredWindow->Collapsed) { ImGuiWindow* window = g.HoveredWindow; - if (g.IO.KeyCtrl) + if (g.IO.KeyCtrl && g.IO.FontAllowUserScaling) { - if (g.IO.FontAllowUserScaling) - { - // Zoom / Scale window - float new_font_scale = ImClamp(window->FontWindowScale + g.IO.MouseWheel * 0.10f, 0.50f, 2.50f); - float scale = new_font_scale / window->FontWindowScale; - window->FontWindowScale = new_font_scale; - - const ImVec2 offset = window->Size * (1.0f - scale) * (g.IO.MousePos - window->Pos) / window->Size; - window->Pos += offset; - window->PosFloat += offset; - window->Size *= scale; - window->SizeFull *= scale; - } + // Zoom / Scale window + const float new_font_scale = ImClamp(window->FontWindowScale + g.IO.MouseWheel * 0.10f, 0.50f, 2.50f); + const float scale = new_font_scale / window->FontWindowScale; + window->FontWindowScale = new_font_scale; + + const ImVec2 offset = window->Size * (1.0f - scale) * (g.IO.MousePos - window->Pos) / window->Size; + window->Pos += offset; + window->PosFloat += offset; + window->Size *= scale; + window->SizeFull *= scale; } - else if (!(window->Flags & ImGuiWindowFlags_NoScrollWithMouse)) + else if (!g.IO.KeyCtrl && !(window->Flags & ImGuiWindowFlags_NoScrollWithMouse)) { // Scroll const int scroll_lines = (window->Flags & ImGuiWindowFlags_ComboBox) ? 3 : 5; From b2aaab873d850e37baefb5b09fd610c1bd6fcd19 Mon Sep 17 00:00:00 2001 From: ocornut Date: Sat, 30 Jul 2016 10:56:52 +0200 Subject: [PATCH 042/823] Nav: collapse button is interactve, allow collapsing, tidying up, resize speed takes account of framebuffer scale (#323) --- imgui.cpp | 69 +++++++++++++++++++++++++++++++----------------- imgui_internal.h | 2 ++ 2 files changed, 47 insertions(+), 24 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 542a80c8f584..612840712145 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1718,14 +1718,13 @@ ImGuiWindow::ImGuiWindow(const char* name) Name = ImStrdup(name); ID = ImHash(name, 0); IDStack.push_back(ID); - MoveId = GetID("#MOVE"); - Flags = 0; IndexWithinParent = 0; PosFloat = Pos = ImVec2(0.0f, 0.0f); Size = SizeFull = ImVec2(0.0f, 0.0f); SizeContents = SizeContentsExplicit = ImVec2(0.0f, 0.0f); WindowPadding = ImVec2(0.0f, 0.0f); + MoveId = GetID("#MOVE"); Scroll = ImVec2(0.0f, 0.0f); ScrollTarget = ImVec2(FLT_MAX, FLT_MAX); ScrollTargetCenterRatio = ImVec2(0.5f, 0.5f); @@ -1735,6 +1734,7 @@ ImGuiWindow::ImGuiWindow(const char* name) Active = WasActive = false; Accessed = false; Collapsed = false; + CollapseToggleWanted = false; SkipItems = false; BeginCount = 0; PopupId = 0; @@ -2514,10 +2514,10 @@ static void NavUpdate() g.NavMoveDir = ImGuiNavDir_None; if (g.FocusedWindow && !g.NavWindowingTarget && (g.ActiveId == 0 || g.ActiveIdAllowNavMove) && !(g.FocusedWindow->Flags & ImGuiWindowFlags_NoNav)) { - if (IsKeyPressedMap(ImGuiKey_NavLeft, true)) g.NavMoveDir = ImGuiNavDir_W; + if (IsKeyPressedMap(ImGuiKey_NavLeft, true)) g.NavMoveDir = ImGuiNavDir_W; if (IsKeyPressedMap(ImGuiKey_NavRight, true)) g.NavMoveDir = ImGuiNavDir_E; - if (IsKeyPressedMap(ImGuiKey_NavUp, true)) g.NavMoveDir = ImGuiNavDir_N; - if (IsKeyPressedMap(ImGuiKey_NavDown, true)) g.NavMoveDir = ImGuiNavDir_S; + if (IsKeyPressedMap(ImGuiKey_NavUp, true)) g.NavMoveDir = ImGuiNavDir_N; + if (IsKeyPressedMap(ImGuiKey_NavDown, true)) g.NavMoveDir = ImGuiNavDir_S; } if (g.NavMoveDir != ImGuiNavDir_None) { @@ -4501,7 +4501,7 @@ bool ImGui::Begin(const char* name, bool* p_open, const ImVec2& size_on_first_us if (!(flags & ImGuiWindowFlags_NoTitleBar) && !(flags & ImGuiWindowFlags_NoCollapse)) { ImRect title_bar_rect = window->TitleBarRect(); - if (g.HoveredWindow == window && IsMouseHoveringRect(title_bar_rect.Min, title_bar_rect.Max) && g.IO.MouseDoubleClicked[0]) + if (window->CollapseToggleWanted || (g.HoveredWindow == window && IsMouseHoveringRect(title_bar_rect.Min, title_bar_rect.Max) && g.IO.MouseDoubleClicked[0])) { window->Collapsed = !window->Collapsed; if (!(flags & ImGuiWindowFlags_NoSavedSettings)) @@ -4513,6 +4513,7 @@ bool ImGui::Begin(const char* name, bool* p_open, const ImVec2& size_on_first_us { window->Collapsed = false; } + window->CollapseToggleWanted = false; // SIZE @@ -4718,11 +4719,9 @@ bool ImGui::Begin(const char* name, bool* p_open, const ImVec2& size_on_first_us ImVec2 nav_resize_delta(0.0f, 0.0f); if (g.NavWindowingTarget == window) { - const float resize_speed = ImFloor(40 * g.FontSize * g.IO.DeltaTime); - if (IsKeyDownMap(ImGuiKey_NavLeft)) nav_resize_delta.x -= resize_speed; - if (IsKeyDownMap(ImGuiKey_NavRight)) nav_resize_delta.x += resize_speed; - if (IsKeyDownMap(ImGuiKey_NavUp)) nav_resize_delta.y -= resize_speed; - if (IsKeyDownMap(ImGuiKey_NavDown)) nav_resize_delta.y += resize_speed; + const float resize_speed = ImFloor(600 * g.IO.DeltaTime * ImMin(g.IO.DisplayFramebufferScale.x, g.IO.DisplayFramebufferScale.y)); + nav_resize_delta = NavGetMovingDir() * resize_speed; + held |= (nav_resize_delta.x != 0.0f || nav_resize_delta.y != 0.0f); // For coloring } ImVec2 size_target(FLT_MAX,FLT_MAX); @@ -4737,7 +4736,6 @@ bool ImGui::Begin(const char* name, bool* p_open, const ImVec2& size_on_first_us // FIXME-NAVIGATION: Should store and accumulate into a separate size buffer to handle sizing constraints properly g.NavWindowingToggleLayer = false; size_target = window->SizeFull + nav_resize_delta; - held = true; // For coloring } else if (held) { @@ -4877,20 +4875,38 @@ bool ImGui::Begin(const char* name, bool* p_open, const ImVec2& size_on_first_us // Title bar if (!(flags & ImGuiWindowFlags_NoTitleBar)) { + // Close & collapse button are on layer 1 (same as menus) and don't default focus + const bool backup_allow_nav_default_focus = window->DC.AllowNavDefaultFocus; + if (window->Flags & ImGuiWindowFlags_MenuBar) + window->DC.AllowNavDefaultFocus = false; + window->DC.NavLayerCurrent++; + + // Close button if (p_open != NULL) { - const float pad = 2.0f; - const float rad = (window->TitleBarHeight() - pad*2.0f) * 0.5f; - window->DC.NavLayerCurrent++; - if (CloseButton(window->GetID("#CLOSE"), window->Rect().GetTR() + ImVec2(-pad - rad, pad + rad), rad)) + const float PAD = 2.0f; + const float rad = (window->TitleBarHeight() - PAD*2.0f) * 0.5f; + if (CloseButton(window->GetID("#CLOSE"), window->Rect().GetTR() + ImVec2(-PAD - rad, PAD + rad), rad)) *p_open = false; - window->DC.NavLayerCurrent--; } + // Collapse button const ImVec2 text_size = CalcTextSize(name, NULL, true); - if (!(flags & ImGuiWindowFlags_NoCollapse)) + if (!(flags & ImGuiWindowFlags_NoCollapse) && g.IO.NavUsable) + { + ImGuiID id = window->GetID("#COLLAPSE"); + ImRect bb(window->Pos + style.FramePadding + ImVec2(1,1), window->Pos + style.FramePadding + ImVec2(g.FontSize,g.FontSize) - ImVec2(1,1)); + ItemAdd(bb, &id); // To allow navigation + if (ButtonBehavior(bb, id, NULL, NULL)) + window->CollapseToggleWanted = true; // Defer collapsing to next frame as we are too far in the Begin() function + RenderNavHighlight(id, bb); RenderCollapseTriangle(window->Pos + style.FramePadding, !window->Collapsed, 1.0f, true); + } + + window->DC.NavLayerCurrent--; + window->DC.AllowNavDefaultFocus = backup_allow_nav_default_focus; + // Title text (FIXME: refactor text alignment facilities along with RenderText helpers) ImVec2 text_min = window->Pos + style.FramePadding; ImVec2 text_max = window->Pos + ImVec2(window->Size.x - style.FramePadding.x, style.FramePadding.y*2 + text_size.y); ImVec2 clip_max = ImVec2(window->Pos.x + window->Size.x - (p_open ? title_bar_rect.GetHeight() - 3 : style.FramePadding.x), text_max.y); // Match the size of CloseWindowButton() @@ -6264,12 +6280,7 @@ bool ImGui::CloseButton(ImGuiID id, const ImVec2& pos, float radius) ImGuiWindow* window = GetCurrentWindow(); const ImRect bb(pos - ImVec2(radius,radius), pos + ImVec2(radius,radius)); - const bool backup_allow_nav_default_focus = window->DC.AllowNavDefaultFocus; // We could exposethis as a flag to ItemAdd() but it is such a unique case for now - if (window->Flags & ImGuiWindowFlags_MenuBar) - window->DC.AllowNavDefaultFocus = false; - const bool added = ItemAdd(bb, &id); // To allow navigation - window->DC.AllowNavDefaultFocus = backup_allow_nav_default_focus; - if (!added) + if (!ItemAdd(bb, &id)) // To allow navigation return false; bool hovered, held; @@ -7015,6 +7026,16 @@ int ImGui::ParseFormatPrecision(const char* fmt, int default_precision) return precision; } +ImVec2 ImGui::NavGetMovingDir() +{ + ImVec2 dir(0.0f, 0.0f); + if (IsKeyDownMap(ImGuiKey_NavLeft)) dir.x -= 1.0f; + if (IsKeyDownMap(ImGuiKey_NavRight)) dir.x += 1.0f; + if (IsKeyDownMap(ImGuiKey_NavUp)) dir.y -= 1.0f; + if (IsKeyDownMap(ImGuiKey_NavDown)) dir.y += 1.0f; + return dir; +} + // Adjustment delta for slider/drag/etc. // FIXME-NAVIGATION: Accelerate over time? Expose more settings? Handle faster/slower modifiers here instead of widget level? ImVec2 ImGui::NavGetTweakDelta() diff --git a/imgui_internal.h b/imgui_internal.h index 34cc0cb73403..eefda8c7741b 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -691,6 +691,7 @@ struct IMGUI_API ImGuiWindow bool WasActive; bool Accessed; // Set to true when any widget access the current window bool Collapsed; // Set when collapsing window to become only title-bar + bool CollapseToggleWanted; bool SkipItems; // == Visible && !Collapsed int BeginCount; // Number of Begin() during the current frame (generally 0 or 1, 1+ if appending via multiple Begin/End pairs) ImGuiID PopupId; // ID in the popup stack when this window is used as a popup/menu (because we use generic Name/ID for recycling) @@ -783,6 +784,7 @@ namespace ImGui IMGUI_API void OpenPopupEx(const char* str_id, bool reopen_existing); IMGUI_API ImVec2 NavGetTweakDelta(); + IMGUI_API ImVec2 NavGetMovingDir(); inline IMGUI_API ImU32 GetColorU32(ImGuiCol idx, float alpha_mul) { ImVec4 c = GImGui->Style.Colors[idx]; c.w *= GImGui->Style.Alpha * alpha_mul; return ImGui::ColorConvertFloat4ToU32(c); } inline IMGUI_API ImU32 GetColorU32(const ImVec4& col) { ImVec4 c = col; c.w *= GImGui->Style.Alpha; return ImGui::ColorConvertFloat4ToU32(c); } From b3ddae07d13807602b830696df7f09d9eb0e1899 Mon Sep 17 00:00:00 2001 From: ocornut Date: Sat, 30 Jul 2016 11:11:17 +0200 Subject: [PATCH 043/823] Nav: not activating widgets with NavActivate when NavMenu is held (#323) --- imgui.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 612840712145..3a8dc7c8a3e2 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2501,8 +2501,8 @@ static void NavUpdate() } } - g.NavActivateId = (g.NavId && !g.NavDisableHighlight && g.ActiveId == 0 && IsKeyPressedMap(ImGuiKey_NavActivate)) ? g.NavId : 0; - g.NavInputId = (g.NavId && !g.NavDisableHighlight && g.ActiveId == 0 && IsKeyPressedMap(ImGuiKey_NavInput)) ? g.NavId : 0; + g.NavActivateId = (g.NavId && !g.NavDisableHighlight && !g.NavWindowingTarget && g.ActiveId == 0 && IsKeyPressedMap(ImGuiKey_NavActivate)) ? g.NavId : 0; + g.NavInputId = (g.NavId && !g.NavDisableHighlight && !g.NavWindowingTarget && g.ActiveId == 0 && IsKeyPressedMap(ImGuiKey_NavInput)) ? g.NavId : 0; if (g.NavWindow && (g.NavWindow->Flags & ImGuiWindowFlags_NoNav)) { g.NavActivateId = g.NavInputId = 0; @@ -6157,15 +6157,15 @@ bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool { // We report navigated item as hovered but we don't set g.HoveredId to not interfere with mouse hovered = true; - if (IsKeyDownMap(ImGuiKey_NavActivate)) + if (!g.NavWindowingTarget && IsKeyDownMap(ImGuiKey_NavActivate)) { // Set active id so it can be queried by user via IsItemActive(), etc. but don't react to it ourselves g.NavActivateId = g.NavId; SetActiveID(g.NavId, window); g.ActiveIdAllowNavMove = true; + if (IsKeyPressedMap(ImGuiKey_NavActivate, (flags & ImGuiButtonFlags_Repeat) != 0)) + pressed = true; } - if (IsKeyPressedMap(ImGuiKey_NavActivate, (flags & ImGuiButtonFlags_Repeat) != 0)) - pressed = true; } bool held = false; From cbe03e3108386c5b4f4c28b5399f5ab34f4ba797 Mon Sep 17 00:00:00 2001 From: ocornut Date: Sat, 30 Jul 2016 11:22:18 +0200 Subject: [PATCH 044/823] Nav: CalcListClipping/ImGuiListClipper: fix to ensure we can navigate clipped lists (#323) --- imgui.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/imgui.cpp b/imgui.cpp index 3a8dc7c8a3e2..01aa4659d766 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -3509,6 +3509,11 @@ void ImGui::CalcListClipping(int items_count, float items_height, int* out_items const ImVec2 pos = window->DC.CursorPos; int start = (int)((window->ClipRect.Min.y - pos.y) / items_height); int end = (int)((window->ClipRect.Max.y - pos.y) / items_height); + if (g.NavMoveRequest && g.NavMoveDir == ImGuiNavDir_N) // When performing a navigation request, ensure we have one item extra in the direction we are moving to + start--; + if (g.NavMoveRequest && g.NavMoveDir == ImGuiNavDir_S) + end++; + start = ImClamp(start, 0, items_count); end = ImClamp(end + 1, start, items_count); *out_items_display_start = start; From d9d6b0e629118aff7c11a78405de7b261c1d180a Mon Sep 17 00:00:00 2001 From: ocornut Date: Sat, 30 Jul 2016 13:45:46 +0200 Subject: [PATCH 045/823] Nav: Renamed private ImGuiNavDir_ enum to use left/right/up/down to be consistent with key enums (#323) --- imgui.cpp | 26 +++++++++++++------------- imgui_internal.h | 10 +++++----- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 01aa4659d766..08195ca08994 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1898,8 +1898,8 @@ void ImGui::ItemSize(const ImRect& bb, float text_offset_y) static ImGuiNavDir NavScoreItemGetQuadrant(float dx, float dy) { if (fabsf(dx) > fabsf(dy)) - return (dx > 0.0f) ? ImGuiNavDir_E : ImGuiNavDir_W; - return (dy > 0.0f) ? ImGuiNavDir_S : ImGuiNavDir_N; + return (dx > 0.0f) ? ImGuiNavDir_Right : ImGuiNavDir_Left; + return (dy > 0.0f) ? ImGuiNavDir_Down : ImGuiNavDir_Up; } static float NavScoreItemDistInterval(float a0, float a1, float b0, float b1) @@ -1957,7 +1957,7 @@ static bool NavScoreItem(ImRect cand) else { // Degenerate case: two overlapping buttons with same center, break ties using order - quadrant = (window->DC.LastItemId < g.NavId) ? ImGuiNavDir_W : ImGuiNavDir_E; + quadrant = (window->DC.LastItemId < g.NavId) ? ImGuiNavDir_Left : ImGuiNavDir_Right; } #if 0 // [DEBUG] @@ -1995,7 +1995,7 @@ static bool NavScoreItem(ImRect cand) // Still tied! we need to be extra-careful to make sure everything gets linked properly. We consistently break ties by symbolically moving "later" buttons // (with higher index) to the right/downwards by an infinitesimal amount since we the current "best" button already (so it must have a lower index), // this is fairly easy. This rule ensures that all buttons with dx==dy==0 will end up being linked in order of appearance along the x axis. - if ((g.NavMoveDir >= ImGuiNavDir_N ? dby : dbx) < 0.0f) // moving bj to the right/down decreases distance + if (((g.NavMoveDir == ImGuiNavDir_Up || g.NavMoveDir == ImGuiNavDir_Down) ? dby : dbx) < 0.0f) // moving bj to the right/down decreases distance new_best = true; } } @@ -2006,7 +2006,7 @@ static bool NavScoreItem(ImRect cand) // This is just to avoid buttons having no links in a particular direction when there's a suitable neighbor. you get good graphs without this too. if (g.NavMoveResultDistBox == FLT_MAX) if (dist_axial < g.NavMoveResultDistAxial) // Check axial match - if ((g.NavMoveDir == ImGuiNavDir_W && dax < 0.0f) || (g.NavMoveDir == ImGuiNavDir_E && dax > 0.0f) || (g.NavMoveDir == ImGuiNavDir_N && day < 0.0f) || (g.NavMoveDir == ImGuiNavDir_S && day > 0.0f)) + if ((g.NavMoveDir == ImGuiNavDir_Left && dax < 0.0f) || (g.NavMoveDir == ImGuiNavDir_Right && dax > 0.0f) || (g.NavMoveDir == ImGuiNavDir_Up && day < 0.0f) || (g.NavMoveDir == ImGuiNavDir_Down && day > 0.0f)) g.NavMoveResultDistAxial = dist_axial, new_best = true; return new_best; @@ -2514,10 +2514,10 @@ static void NavUpdate() g.NavMoveDir = ImGuiNavDir_None; if (g.FocusedWindow && !g.NavWindowingTarget && (g.ActiveId == 0 || g.ActiveIdAllowNavMove) && !(g.FocusedWindow->Flags & ImGuiWindowFlags_NoNav)) { - if (IsKeyPressedMap(ImGuiKey_NavLeft, true)) g.NavMoveDir = ImGuiNavDir_W; - if (IsKeyPressedMap(ImGuiKey_NavRight, true)) g.NavMoveDir = ImGuiNavDir_E; - if (IsKeyPressedMap(ImGuiKey_NavUp, true)) g.NavMoveDir = ImGuiNavDir_N; - if (IsKeyPressedMap(ImGuiKey_NavDown, true)) g.NavMoveDir = ImGuiNavDir_S; + if (IsKeyPressedMap(ImGuiKey_NavLeft, true)) g.NavMoveDir = ImGuiNavDir_Left; + if (IsKeyPressedMap(ImGuiKey_NavRight, true)) g.NavMoveDir = ImGuiNavDir_Right; + if (IsKeyPressedMap(ImGuiKey_NavUp, true)) g.NavMoveDir = ImGuiNavDir_Up; + if (IsKeyPressedMap(ImGuiKey_NavDown, true)) g.NavMoveDir = ImGuiNavDir_Down; } if (g.NavMoveDir != ImGuiNavDir_None) { @@ -2526,10 +2526,10 @@ static void NavUpdate() } // Fallback manual-scroll with NavUp/NavDown when window has no navigable item - if (g.FocusedWindow && !g.FocusedWindow->DC.NavLayerActiveFlags && g.FocusedWindow->DC.NavHasScroll && !(g.FocusedWindow->Flags & ImGuiWindowFlags_NoNav) && g.NavMoveRequest && (g.NavMoveDir == ImGuiNavDir_N || g.NavMoveDir == ImGuiNavDir_S)) + if (g.FocusedWindow && !g.FocusedWindow->DC.NavLayerActiveFlags && g.FocusedWindow->DC.NavHasScroll && !(g.FocusedWindow->Flags & ImGuiWindowFlags_NoNav) && g.NavMoveRequest && (g.NavMoveDir == ImGuiNavDir_Up || g.NavMoveDir == ImGuiNavDir_Down)) { float scroll_speed = ImFloor(g.FocusedWindow->CalcFontSize() * 100 * g.IO.DeltaTime + 0.5f); // We need round the scrolling speed because sub-pixel scroll isn't reliably supported. - SetWindowScrollY(g.FocusedWindow, ImFloor(g.FocusedWindow->Scroll.y + ((g.NavMoveDir == ImGuiNavDir_N) ? -1.0f : +1.0f) * scroll_speed)); + SetWindowScrollY(g.FocusedWindow, ImFloor(g.FocusedWindow->Scroll.y + ((g.NavMoveDir == ImGuiNavDir_Up) ? -1.0f : +1.0f) * scroll_speed)); } // Reset search @@ -3509,9 +3509,9 @@ void ImGui::CalcListClipping(int items_count, float items_height, int* out_items const ImVec2 pos = window->DC.CursorPos; int start = (int)((window->ClipRect.Min.y - pos.y) / items_height); int end = (int)((window->ClipRect.Max.y - pos.y) / items_height); - if (g.NavMoveRequest && g.NavMoveDir == ImGuiNavDir_N) // When performing a navigation request, ensure we have one item extra in the direction we are moving to + if (g.NavMoveRequest && g.NavMoveDir == ImGuiNavDir_Up) // When performing a navigation request, ensure we have one item extra in the direction we are moving to start--; - if (g.NavMoveRequest && g.NavMoveDir == ImGuiNavDir_S) + if (g.NavMoveRequest && g.NavMoveDir == ImGuiNavDir_Down) end++; start = ImClamp(start, 0, items_count); diff --git a/imgui_internal.h b/imgui_internal.h index eefda8c7741b..3b9558544cce 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -206,11 +206,11 @@ enum ImGuiInputSource enum ImGuiNavDir { - ImGuiNavDir_None = -1, - ImGuiNavDir_W, // Needs to be 0..3 (using arithmetic op in NavScoreItem()) - ImGuiNavDir_E, - ImGuiNavDir_N, - ImGuiNavDir_S + ImGuiNavDir_None = -1, + ImGuiNavDir_Left = 0, + ImGuiNavDir_Right = 1, + ImGuiNavDir_Up = 2, + ImGuiNavDir_Down = 3, }; // 2D axis aligned bounding-box From d6ce800a209152b00adfc0bfd15056a132095bf1 Mon Sep 17 00:00:00 2001 From: ocornut Date: Sat, 30 Jul 2016 14:31:34 +0200 Subject: [PATCH 046/823] Nav: ActiveIdAllowNavMove -> ActiveIdAllowNavDirFlags for more flexibility (nav up/down typically allowed on a single-line text input) (#323) --- imgui.cpp | 22 ++++++++++++---------- imgui_internal.h | 2 +- 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 08195ca08994..bbf803525c0c 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1824,7 +1824,7 @@ void ImGui::SetActiveID(ImGuiID id, ImGuiWindow* window = NULL) ImGuiContext& g = *GImGui; g.ActiveIdIsJustActivated = (g.ActiveId != id); g.ActiveId = id; - g.ActiveIdAllowNavMove = false; + g.ActiveIdAllowNavDirFlags = 0; g.ActiveIdAllowOverlap = false; g.ActiveIdWindow = window; if (id) @@ -1847,7 +1847,7 @@ void ImGui::SetActiveIDNoNav(ImGuiID id, ImGuiWindow* window) ImGuiContext& g = *GImGui; g.ActiveIdIsJustActivated = (g.ActiveId != id); g.ActiveId = id; - g.ActiveIdAllowNavMove = false; + g.ActiveIdAllowNavDirFlags = 0; g.ActiveIdAllowOverlap = false; g.ActiveIdWindow = window; g.ActiveIdSource = (g.NavActivateId == id || g.NavInputId == id) ? ImGuiInputSource_Nav : ImGuiInputSource_Mouse; @@ -2511,13 +2511,14 @@ static void NavUpdate() g.NavMoveRequest = false; // Initiate directional inputs request + const int allowed_dir_flags = (g.ActiveId == 0) ? ~0 : g.ActiveIdAllowNavDirFlags; g.NavMoveDir = ImGuiNavDir_None; - if (g.FocusedWindow && !g.NavWindowingTarget && (g.ActiveId == 0 || g.ActiveIdAllowNavMove) && !(g.FocusedWindow->Flags & ImGuiWindowFlags_NoNav)) + if (g.FocusedWindow && !g.NavWindowingTarget && allowed_dir_flags && !(g.FocusedWindow->Flags & ImGuiWindowFlags_NoNav)) { - if (IsKeyPressedMap(ImGuiKey_NavLeft, true)) g.NavMoveDir = ImGuiNavDir_Left; - if (IsKeyPressedMap(ImGuiKey_NavRight, true)) g.NavMoveDir = ImGuiNavDir_Right; - if (IsKeyPressedMap(ImGuiKey_NavUp, true)) g.NavMoveDir = ImGuiNavDir_Up; - if (IsKeyPressedMap(ImGuiKey_NavDown, true)) g.NavMoveDir = ImGuiNavDir_Down; + if ((allowed_dir_flags & (1< Date: Sat, 30 Jul 2016 14:38:33 +0200 Subject: [PATCH 047/823] ImRect: fixed Clip() function being the other way around (INTERNAL API BREAKING CHANGE- wasn't exposed, hoping nobody uses that) + actually fixes the function behavior. --- imgui.cpp | 15 ++++++++------- imgui_internal.h | 2 +- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index bbf803525c0c..80bd9ec34519 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1920,7 +1920,7 @@ static bool NavScoreItem(ImRect cand) return false; const ImRect& curr = g.NavScoringRectScreen; // Current modified source rect (NB: we've applied Max.x = Min.x in NavUpdate() to inhibit the effect of having lots of items with varied width) - cand.Clip(window->ClipRect); + window->ClipRect.Clip(cand); // Compute distance between boxes // FIXME-NAVIGATION: Introducing various biases toward typical imgui uses cases, but we don't have any rigorous proof of their effect now. @@ -3555,7 +3555,7 @@ bool ImGui::IsMouseHoveringRect(const ImVec2& r_min, const ImVec2& r_max, bool c // Clip ImRect rect_clipped(r_min, r_max); if (clip) - rect_clipped.Clip(window->ClipRect); + window->ClipRect.Clip(rect_clipped); // Expand for touch input const ImRect rect_for_touch(rect_clipped.Min - g.Style.TouchExtraPadding, rect_clipped.Max + g.Style.TouchExtraPadding); @@ -4927,7 +4927,7 @@ bool ImGui::Begin(const char* name, bool* p_open, const ImVec2& size_on_first_us // Save clipped aabb so we can access it in constant-time in FindHoveredWindow() window->WindowRectClipped = window->Rect(); - window->WindowRectClipped.Clip(window->ClipRect); + window->ClipRect.Clip(window->WindowRectClipped); // Pressing CTRL+C while holding on a window copy its content to the clipboard // This works but 1. doesn't handle multiple Begin/End pairs, 2. recursing into another Begin/End pair - so we need to work that out and add better logging scope. @@ -8857,10 +8857,11 @@ bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2 { ImVec2 rect_size = InputTextCalcTextSizeW(p, text_selected_end, &p, NULL, true); if (rect_size.x <= 0.0f) rect_size.x = (float)(int)(g.Font->GetCharAdvance((unsigned short)' ') * 0.50f); // So we can see selected empty lines - ImRect rect(rect_pos + ImVec2(0.0f, bg_offy_up - g.FontSize), rect_pos +ImVec2(rect_size.x, bg_offy_dn)); - rect.Clip(clip_rect); - if (rect.Overlaps(clip_rect)) - draw_window->DrawList->AddRectFilled(rect.Min, rect.Max, bg_color); + ImRect cursor_rect(rect_pos + ImVec2(0.0f, bg_offy_up - g.FontSize), rect_pos +ImVec2(rect_size.x, bg_offy_dn)); + ImRect clip_rect_r(clip_rect); + clip_rect_r.Clip(cursor_rect); + if (cursor_rect.Overlaps(clip_rect_r)) + draw_window->DrawList->AddRectFilled(cursor_rect.Min, cursor_rect.Max, bg_color); } rect_pos.x = render_pos.x - render_scroll.x; rect_pos.y += g.FontSize; diff --git a/imgui_internal.h b/imgui_internal.h index e51a60b16adb..44ee941c32fe 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -241,7 +241,7 @@ struct IMGUI_API ImRect void Expand(const float amount) { Min.x -= amount; Min.y -= amount; Max.x += amount; Max.y += amount; } void Expand(const ImVec2& amount) { Min.x -= amount.x; Min.y -= amount.y; Max.x += amount.x; Max.y += amount.y; } void Reduce(const ImVec2& amount) { Min.x += amount.x; Min.y += amount.y; Max.x -= amount.x; Max.y -= amount.y; } - void Clip(const ImRect& clip) { if (Min.x < clip.Min.x) Min.x = clip.Min.x; if (Min.y < clip.Min.y) Min.y = clip.Min.y; if (Max.x > clip.Max.x) Max.x = clip.Max.x; if (Max.y > clip.Max.y) Max.y = clip.Max.y; } + void Clip(ImRect& r) const { r.Min.x = ImClamp(r.Min.x, Min.x, Max.x); r.Min.y = ImClamp(r.Min.y, Min.y, Max.y); r.Max.x = ImClamp(r.Max.x, Min.x, Max.x); r.Max.y = ImClamp(r.Max.y, Min.y, Max.y); } void Floor() { Min.x = (float)(int)Min.x; Min.y = (float)(int)Min.y; Max.x = (float)(int)Max.x; Max.y = (float)(int)Max.y; } ImVec2 GetClosestPoint(ImVec2 p, bool on_edge) const { From f2d1472481725d0a89e27be6f2bc0db32a92fccf Mon Sep 17 00:00:00 2001 From: ocornut Date: Sat, 30 Jul 2016 15:17:12 +0200 Subject: [PATCH 048/823] Nav: Fixed navigating outside of current scrolling bounds (bug from 0cc20fca831e60b4898cf66e3ac595d8bdebb830) (#323) + spaces --- imgui.cpp | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 80bd9ec34519..b36ee9153fec 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1920,7 +1920,18 @@ static bool NavScoreItem(ImRect cand) return false; const ImRect& curr = g.NavScoringRectScreen; // Current modified source rect (NB: we've applied Max.x = Min.x in NavUpdate() to inhibit the effect of having lots of items with varied width) - window->ClipRect.Clip(cand); + + // We perform scoring on items bounding box clipped by their parent window on the other axis (clipping on our movement axis would give us equal scores for all clipped items) + if (g.NavMoveDir == ImGuiNavDir_Left || g.NavMoveDir == ImGuiNavDir_Right) + { + cand.Min.y = ImClamp(cand.Min.y, window->ClipRect.Min.y, window->ClipRect.Max.y); + cand.Max.y = ImClamp(cand.Max.y, window->ClipRect.Min.y, window->ClipRect.Max.y); + } + else + { + cand.Min.x = ImClamp(cand.Min.x, window->ClipRect.Min.x, window->ClipRect.Max.x); + cand.Max.x = ImClamp(cand.Max.x, window->ClipRect.Min.x, window->ClipRect.Max.x); + } // Compute distance between boxes // FIXME-NAVIGATION: Introducing various biases toward typical imgui uses cases, but we don't have any rigorous proof of their effect now. @@ -6168,7 +6179,7 @@ bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool // Set active id so it can be queried by user via IsItemActive(), etc. but don't react to it ourselves g.NavActivateId = g.NavId; SetActiveID(g.NavId, window); - g.ActiveIdAllowNavDirFlags = (1< Date: Sat, 30 Jul 2016 16:25:45 +0200 Subject: [PATCH 049/823] Clarifying that MovedWindow* apply to mouse moving only --- imgui.cpp | 4 ++-- imgui_internal.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index b36ee9153fec..8bee35694468 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2655,8 +2655,8 @@ void ImGui::NewFrame() g.FramerateSecPerFrameIdx = (g.FramerateSecPerFrameIdx + 1) % IM_ARRAYSIZE(g.FramerateSecPerFrame); g.IO.Framerate = 1.0f / (g.FramerateSecPerFrameAccum / (float)IM_ARRAYSIZE(g.FramerateSecPerFrame)); - // Handle user moving window (at the beginning of the frame to avoid input lag or sheering). Only valid for root windows. - if (g.MovedWindowMoveId && g.MovedWindowMoveId == g.ActiveId) + // Handle user moving window with mouse (at the beginning of the frame to avoid input lag or sheering). Only valid for root windows. + if (g.MovedWindowMoveId && g.MovedWindowMoveId == g.ActiveId && g.ActiveIdSource == ImGuiInputSource_Mouse) { KeepAliveID(g.MovedWindowMoveId); IM_ASSERT(g.MovedWindow && g.MovedWindow->RootWindow); diff --git a/imgui_internal.h b/imgui_internal.h index 44ee941c32fe..b78494c507f4 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -393,7 +393,7 @@ struct ImGuiContext ImVec2 ActiveIdClickOffset; // Clicked offset from upper-left corner, if applicable (currently only set by ButtonBehavior) ImGuiWindow* ActiveIdWindow; ImGuiInputSource ActiveIdSource; // Activating with mouse or nav (gamepad/keyboard) - ImGuiWindow* MovedWindow; // Track the child window we clicked on to move a window. + ImGuiWindow* MovedWindow; // Track the child window we clicked on to move a window (only apply to moving with mouse) ImGuiID MovedWindowMoveId; // == MovedWindow->RootWindow->MoveId ImVector Settings; // .ini Settings float SettingsDirtyTimer; // Save .ini Settings on disk when time reaches zero From 04157da2919b657aa77a6b07863ae2007ceefe5f Mon Sep 17 00:00:00 2001 From: ocornut Date: Sat, 30 Jul 2016 17:18:34 +0200 Subject: [PATCH 050/823] Nav: first committed pass for manual moving and manual scrolling (after a bunch of attempts) (#323) --- imgui.cpp | 92 ++++++++++++++++++++++++++++++++++++++++-------- imgui.h | 5 +++ imgui_demo.cpp | 2 +- imgui_internal.h | 3 +- 4 files changed, 86 insertions(+), 16 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 8bee35694468..45b278813e01 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -662,6 +662,7 @@ static bool IsKeyPressedMap(ImGuiKey key, bool repeat = true); static void SetCurrentFont(ImFont* font); static void SetCurrentWindow(ImGuiWindow* window); +static void SetWindowScrollX(ImGuiWindow* window, float new_scroll_x); static void SetWindowScrollY(ImGuiWindow* window, float new_scroll_y); static void SetWindowPos(ImGuiWindow* window, const ImVec2& pos, ImGuiSetCond cond); static void SetWindowSize(ImGuiWindow* window, const ImVec2& size, ImGuiSetCond cond); @@ -2364,8 +2365,7 @@ static void NavUpdate() IM_ASSERT(g.NavWindow); // Scroll to keep newly navigated item fully into view - ImRect window_rect_rel(g.NavWindow->InnerRect.Min - g.NavWindow->Pos, g.NavWindow->InnerRect.Max - g.NavWindow->Pos); - window_rect_rel.Expand(1.0f); + ImRect window_rect_rel(g.NavWindow->InnerRect.Min - g.NavWindow->Pos - ImVec2(1,1), g.NavWindow->InnerRect.Max - g.NavWindow->Pos + ImVec2(1,1)); //g.OverlayDrawList.AddRect(g.NavWindow->Pos + window_rect_rel.Min, g.NavWindow->Pos + window_rect_rel.Max, IM_COL32_WHITE); // [DEBUG] if (g.NavLayer == 0 && !window_rect_rel.Contains(g.NavMoveResultRectRel)) { @@ -2394,6 +2394,7 @@ static void NavUpdate() // Apply result from previous navigation directional move request ImGui::SetActiveID(0); SetNavIdMoveMouse(g.NavMoveResultId, g.NavMoveResultRectRel); + g.NavMoveFromClampedRefRect = false; } // Navigation windowing mode (change focus, move/resize window) @@ -2433,6 +2434,19 @@ static void NavUpdate() g.NavWindowingDisplayAlpha = 1.0f; } + // Move window + if (g.NavWindowingTarget && !(g.NavWindowingTarget->Flags & ImGuiWindowFlags_NoMove)) + { + const ImVec2 move_delta = ImGui::NavGetMovingDir(1); + if (move_delta.x != 0.0f || move_delta.y != 0.0f) + { + const float move_speed = ImFloor(600 * g.IO.DeltaTime * ImMin(g.IO.DisplayFramebufferScale.x, g.IO.DisplayFramebufferScale.y)); + g.NavWindowingTarget->PosFloat += move_delta * move_speed; + if (!(g.NavWindowingTarget->Flags & ImGuiWindowFlags_NoSavedSettings)) + MarkSettingsDirty(); + } + } + if (!IsKeyDownMap(ImGuiKey_NavMenu)) { // Apply actual focus only when releasing the NavMenu button (until then the window was merely rendered front-most) @@ -2537,16 +2551,44 @@ static void NavUpdate() g.NavWindow = g.FocusedWindow; } - // Fallback manual-scroll with NavUp/NavDown when window has no navigable item - if (g.FocusedWindow && !g.FocusedWindow->DC.NavLayerActiveFlags && g.FocusedWindow->DC.NavHasScroll && !(g.FocusedWindow->Flags & ImGuiWindowFlags_NoNav) && g.NavMoveRequest && (g.NavMoveDir == ImGuiNavDir_Up || g.NavMoveDir == ImGuiNavDir_Down)) + // Scrolling + if (g.FocusedWindow && !(g.FocusedWindow->Flags & ImGuiWindowFlags_NoNav)) { - float scroll_speed = ImFloor(g.FocusedWindow->CalcFontSize() * 100 * g.IO.DeltaTime + 0.5f); // We need round the scrolling speed because sub-pixel scroll isn't reliably supported. - SetWindowScrollY(g.FocusedWindow, ImFloor(g.FocusedWindow->Scroll.y + ((g.NavMoveDir == ImGuiNavDir_Up) ? -1.0f : +1.0f) * scroll_speed)); + // Fallback manual-scroll with NavUp/NavDown when window has no navigable item + const float scroll_speed = ImFloor(g.FocusedWindow->CalcFontSize() * 100 * g.IO.DeltaTime + 0.5f); // We need round the scrolling speed because sub-pixel scroll isn't reliably supported. + if (!g.FocusedWindow->DC.NavLayerActiveFlags && g.FocusedWindow->DC.NavHasScroll && g.NavMoveRequest && (g.NavMoveDir == ImGuiNavDir_Up || g.NavMoveDir == ImGuiNavDir_Down)) + SetWindowScrollY(g.FocusedWindow, ImFloor(g.FocusedWindow->Scroll.y + ((g.NavMoveDir == ImGuiNavDir_Up) ? -1.0f : +1.0f) * scroll_speed)); + + // Manual scroll with NavScrollXXX keys + ImVec2 scroll_dir = ImGui::NavGetMovingDir(1, 1.0f/10.0f, 10.0f); + if (scroll_dir.x != 0.0f && g.NavWindow->ScrollbarX) + { + SetWindowScrollX(g.FocusedWindow, ImFloor(g.FocusedWindow->Scroll.x + scroll_dir.x * scroll_speed)); + g.NavMoveFromClampedRefRect = true; + } + if (scroll_dir.y != 0.0f) + { + SetWindowScrollY(g.FocusedWindow, ImFloor(g.FocusedWindow->Scroll.y + scroll_dir.y * scroll_speed)); + g.NavMoveFromClampedRefRect = true; + } } // Reset search g.NavMoveResultId = 0; g.NavMoveResultDistAxial = g.NavMoveResultDistBox = g.NavMoveResultDistCenter = FLT_MAX; + if (g.NavMoveRequest && g.NavMoveFromClampedRefRect && g.NavLayer == 0) + { + // When we have manually scrolled and NavId is out of bounds, we clamp its bounding box (used for search) to the visible area to restart navigation within visible items + ImRect window_rect_rel(g.NavWindow->InnerRect.Min - g.NavWindow->Pos - ImVec2(1,1), g.NavWindow->InnerRect.Max - g.NavWindow->Pos + ImVec2(1,1)); + if (!window_rect_rel.Contains(g.NavRefRectRel)) + { + float pad = g.NavWindow->CalcFontSize() * 0.5f; + window_rect_rel.Expand(ImVec2(-ImMin(window_rect_rel.GetWidth(), pad), -ImMin(window_rect_rel.GetHeight(), pad))); // Terrible approximation for the intend of starting navigation from first fully visible item + window_rect_rel.Clip(g.NavRefRectRel); + g.NavId = 0; + } + g.NavMoveFromClampedRefRect = false; + } // For scoring we use a single segment on the left side our current item bounding box (not touching the edge to avoid box overlap with zero-spaced items) g.NavScoringRectScreen = g.NavWindow ? ImRect(g.NavWindow->Pos + g.NavRefRectRel.Min, g.NavWindow->Pos + g.NavRefRectRel.Max) : ImRect(); @@ -4737,7 +4779,7 @@ bool ImGui::Begin(const char* name, bool* p_open, const ImVec2& size_on_first_us if (g.NavWindowingTarget == window) { const float resize_speed = ImFloor(600 * g.IO.DeltaTime * ImMin(g.IO.DisplayFramebufferScale.x, g.IO.DisplayFramebufferScale.y)); - nav_resize_delta = NavGetMovingDir() * resize_speed; + nav_resize_delta = NavGetMovingDir(0) * resize_speed; held |= (nav_resize_delta.x != 0.0f || nav_resize_delta.y != 0.0f); // For coloring } @@ -5469,6 +5511,13 @@ ImVec2 ImGui::GetWindowPos() return window->Pos; } +static void SetWindowScrollX(ImGuiWindow* window, float new_scroll_x) +{ + window->DC.CursorMaxPos.x += window->Scroll.x; // SizeContents is generally computed based on CursorMaxPos which is affected by scroll position, so we need to apply our change to it. + window->Scroll.x = new_scroll_x; + window->DC.CursorMaxPos.x -= window->Scroll.x; +} + static void SetWindowScrollY(ImGuiWindow* window, float new_scroll_y) { window->DC.CursorMaxPos.y += window->Scroll.y; // SizeContents is generally computed based on CursorMaxPos which is affected by scroll position, so we need to apply our change to it. @@ -7043,13 +7092,28 @@ int ImGui::ParseFormatPrecision(const char* fmt, int default_precision) return precision; } -ImVec2 ImGui::NavGetMovingDir() +ImVec2 ImGui::NavGetMovingDir(int stick_no, float slow_factor, float fast_factor) { + IM_ASSERT(stick_no >= 0 && stick_no < 2); ImVec2 dir(0.0f, 0.0f); - if (IsKeyDownMap(ImGuiKey_NavLeft)) dir.x -= 1.0f; - if (IsKeyDownMap(ImGuiKey_NavRight)) dir.x += 1.0f; - if (IsKeyDownMap(ImGuiKey_NavUp)) dir.y -= 1.0f; - if (IsKeyDownMap(ImGuiKey_NavDown)) dir.y += 1.0f; + if (stick_no == 0) + { + if (IsKeyDownMap(ImGuiKey_NavLeft)) dir.x -= 1.0f; + if (IsKeyDownMap(ImGuiKey_NavRight)) dir.x += 1.0f; + if (IsKeyDownMap(ImGuiKey_NavUp)) dir.y -= 1.0f; + if (IsKeyDownMap(ImGuiKey_NavDown)) dir.y += 1.0f; + } + if (stick_no == 1) + { + if (IsKeyDownMap(ImGuiKey_NavScrollLeft)) dir.x -= 1.0f; + if (IsKeyDownMap(ImGuiKey_NavScrollRight)) dir.x += 1.0f; + if (IsKeyDownMap(ImGuiKey_NavScrollUp)) dir.y -= 1.0f; + if (IsKeyDownMap(ImGuiKey_NavScrollDown)) dir.y += 1.0f; + } + if (slow_factor != 0.0f && IsKeyDownMap(ImGuiKey_NavTweakSlower)) + dir *= slow_factor; + if (fast_factor != 0.0f && IsKeyDownMap(ImGuiKey_NavTweakFaster)) + dir *= fast_factor; return dir; } @@ -10458,7 +10522,7 @@ void ImGui::ShowMetricsWindow(bool* p_open) } ImDrawIdx* idx_buffer = (draw_list->IdxBuffer.Size > 0) ? draw_list->IdxBuffer.Data : NULL; bool pcmd_node_open = ImGui::TreeNode((void*)(pcmd - draw_list->CmdBuffer.begin()), "Draw %-4d %s vtx, tex = %p, clip_rect = (%.0f,%.0f)..(%.0f,%.0f)", pcmd->ElemCount, draw_list->IdxBuffer.Size > 0 ? "indexed" : "non-indexed", pcmd->TextureId, pcmd->ClipRect.x, pcmd->ClipRect.y, pcmd->ClipRect.z, pcmd->ClipRect.w); - if (show_clip_rects && ImGui::IsItemHovered()) + if (show_clip_rects && (ImGui::IsItemHovered() || ImGui::IsItemFocused())) { ImRect clip_rect = pcmd->ClipRect; ImRect vtxs_rect; @@ -10482,7 +10546,7 @@ void ImGui::ShowMetricsWindow(bool* p_open) buf_p += sprintf(buf_p, "%s %04d { pos = (%8.2f,%8.2f), uv = (%.6f,%.6f), col = %08X }\n", (n == 0) ? "vtx" : " ", vtx_i, v.pos.x, v.pos.y, v.uv.x, v.uv.y, v.col); } ImGui::Selectable(buf, false); - if (ImGui::IsItemHovered()) + if (ImGui::IsItemHovered() || ImGui::IsItemFocused()) overlay_draw_list->AddPolyline(triangles_pos, 3, IM_COL32(255,255,0,255), true, 1.0f, false); // Add triangle without AA, more readable for large-thin triangle } ImGui::TreePop(); diff --git a/imgui.h b/imgui.h index a0e6ea8c65f5..19650ec2681c 100644 --- a/imgui.h +++ b/imgui.h @@ -604,8 +604,13 @@ enum ImGuiKey_ ImGuiKey_NavRight, // e.g. Right arrow, D-Pad right ImGuiKey_NavUp, // e.g. Up arrow, D-Pad up ImGuiKey_NavDown, // e.g. Down arrow, D-Pad down + ImGuiKey_NavScrollLeft, // e.g. Analog left + ImGuiKey_NavScrollRight,// e.g. Analog right + ImGuiKey_NavScrollUp, // e.g. Analog up + ImGuiKey_NavScrollDown, // e.g. Analog down ImGuiKey_NavTweakFaster,// e.g. Shift key, R-trigger ImGuiKey_NavTweakSlower,// e.g. Alt key, L-trigger + ImGuiKey_NavLast_, ImGuiKey_COUNT }; diff --git a/imgui_demo.cpp b/imgui_demo.cpp index c17537a02eef..db58ac080c1e 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -1904,7 +1904,7 @@ static void ShowExampleAppConstrainedResize(bool* p_open) static void ShowExampleAppFixedOverlay(bool* p_open) { ImGui::SetNextWindowPos(ImVec2(10,10)); - if (!ImGui::Begin("Example: Fixed Overlay", p_open, ImVec2(0,0), 0.3f, ImGuiWindowFlags_NoTitleBar|ImGuiWindowFlags_NoResize|ImGuiWindowFlags_NoMove|ImGuiWindowFlags_NoSavedSettings)) + if (!ImGui::Begin("Example: Fixed Overlay", p_open, ImVec2(0,0), 0.3f, ImGuiWindowFlags_NoTitleBar|ImGuiWindowFlags_NoResize|ImGuiWindowFlags_NoMove|ImGuiWindowFlags_NoSavedSettings|ImGuiWindowFlags_NoNav)) { ImGui::End(); return; diff --git a/imgui_internal.h b/imgui_internal.h index b78494c507f4..1f08a1769f14 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -423,6 +423,7 @@ struct ImGuiContext ImRect NavInitDefaultResultRectRel; bool NavInitDefaultResultExplicit; // Whether the result was explicitly requested with SetItemDefaultFocus() bool NavMoveRequest; // Move request for this frame + bool NavMoveFromClampedRefRect; // Set by manual scrolling, if we scroll to a point where NavId isn't visible we reset navigation from visible items ImGuiNavDir NavMoveDir; // West/East/North/South ImGuiID NavMoveResultId; // Best move request candidate float NavMoveResultDistBox; // Best move request candidate box distance to current NavId @@ -784,7 +785,7 @@ namespace ImGui IMGUI_API void OpenPopupEx(const char* str_id, bool reopen_existing); IMGUI_API ImVec2 NavGetTweakDelta(); - IMGUI_API ImVec2 NavGetMovingDir(); + IMGUI_API ImVec2 NavGetMovingDir(int stick_no, float slow_factor = 0.0f, float fast_factor = 0.0f); inline IMGUI_API ImU32 GetColorU32(ImGuiCol idx, float alpha_mul) { ImVec4 c = GImGui->Style.Colors[idx]; c.w *= GImGui->Style.Alpha * alpha_mul; return ImGui::ColorConvertFloat4ToU32(c); } inline IMGUI_API ImU32 GetColorU32(const ImVec4& col) { ImVec4 c = col; c.w *= GImGui->Style.Alpha; return ImGui::ColorConvertFloat4ToU32(c); } From 3672105b87d1cc4513f5968d863699b94ca852c7 Mon Sep 17 00:00:00 2001 From: ocornut Date: Sat, 30 Jul 2016 17:20:59 +0200 Subject: [PATCH 051/823] Tidying up --- imgui.cpp | 24 ++++++++++-------------- 1 file changed, 10 insertions(+), 14 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 45b278813e01..a3157ab2c2af 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -682,7 +682,7 @@ static ImGuiIniData* FindWindowSettings(const char* name); static ImGuiIniData* AddWindowSettings(const char* name); static void LoadSettings(); static void SaveSettings(); -static void MarkSettingsDirty(); +static void MarkSettingsDirty(ImGuiWindow* window); static void PushColumnClipRect(int column_index = -1); static ImRect GetVisibleRect(); @@ -2442,8 +2442,7 @@ static void NavUpdate() { const float move_speed = ImFloor(600 * g.IO.DeltaTime * ImMin(g.IO.DisplayFramebufferScale.x, g.IO.DisplayFramebufferScale.y)); g.NavWindowingTarget->PosFloat += move_delta * move_speed; - if (!(g.NavWindowingTarget->Flags & ImGuiWindowFlags_NoSavedSettings)) - MarkSettingsDirty(); + MarkSettingsDirty(g.NavWindowingTarget); } } @@ -2708,8 +2707,7 @@ void ImGui::NewFrame() if (!(g.MovedWindow->Flags & ImGuiWindowFlags_NoMove)) { g.MovedWindow->PosFloat += g.IO.MouseDelta; - if (!(g.MovedWindow->Flags & ImGuiWindowFlags_NoSavedSettings)) - MarkSettingsDirty(); + MarkSettingsDirty(g.MovedWindow); } FocusWindow(g.MovedWindow); } @@ -3018,11 +3016,12 @@ static void SaveSettings() fclose(f); } -static void MarkSettingsDirty() +static void MarkSettingsDirty(ImGuiWindow* window) { ImGuiContext& g = *GImGui; - if (g.SettingsDirtyTimer <= 0.0f) - g.SettingsDirtyTimer = g.IO.IniSavingRate; + if (!(window->Flags & ImGuiWindowFlags_NoSavedSettings)) + if (g.SettingsDirtyTimer <= 0.0f) + g.SettingsDirtyTimer = g.IO.IniSavingRate; } // FIXME: Add a more explicit sort order in the window structure. @@ -4563,8 +4562,7 @@ bool ImGui::Begin(const char* name, bool* p_open, const ImVec2& size_on_first_us if (window->CollapseToggleWanted || (g.HoveredWindow == window && IsMouseHoveringRect(title_bar_rect.Min, title_bar_rect.Max) && g.IO.MouseDoubleClicked[0])) { window->Collapsed = !window->Collapsed; - if (!(flags & ImGuiWindowFlags_NoSavedSettings)) - MarkSettingsDirty(); + MarkSettingsDirty(window); FocusWindow(window); } } @@ -4639,8 +4637,7 @@ bool ImGui::Begin(const char* name, bool* p_open, const ImVec2& size_on_first_us window->SizeFull.x = window->AutoFitOnlyGrows ? ImMax(window->SizeFull.x, size_auto_fit.x) : size_auto_fit.x; if (window->AutoFitFramesY > 0) window->SizeFull.y = window->AutoFitOnlyGrows ? ImMax(window->SizeFull.y, size_auto_fit.y) : size_auto_fit.y; - if (!(flags & ImGuiWindowFlags_NoSavedSettings)) - MarkSettingsDirty(); + MarkSettingsDirty(window); } } @@ -4805,8 +4802,7 @@ bool ImGui::Begin(const char* name, bool* p_open, const ImVec2& size_on_first_us if (size_target.x != FLT_MAX && size_target.y != FLT_MAX) { ApplySizeFullWithConstraint(window, size_target); - if (!(flags & ImGuiWindowFlags_NoSavedSettings)) - MarkSettingsDirty(); + MarkSettingsDirty(window); } resize_col = GetColorU32(held ? ImGuiCol_ResizeGripActive : hovered ? ImGuiCol_ResizeGripHovered : ImGuiCol_ResizeGrip); From 4c4d750caef80aa92780fac29419f16509f7c7ae Mon Sep 17 00:00:00 2001 From: ocornut Date: Sat, 30 Jul 2016 18:05:14 +0200 Subject: [PATCH 052/823] Nav: Fixed Collapse icon disappearing when Nav is disabled (since b2aaab873d850e37baefb5b09fd610c1bd6fcd19) (#323) --- imgui.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/imgui.cpp b/imgui.cpp index a3157ab2c2af..ec2a8137fecd 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -4947,7 +4947,7 @@ bool ImGui::Begin(const char* name, bool* p_open, const ImVec2& size_on_first_us // Collapse button const ImVec2 text_size = CalcTextSize(name, NULL, true); - if (!(flags & ImGuiWindowFlags_NoCollapse) && g.IO.NavUsable) + if (!(flags & ImGuiWindowFlags_NoCollapse)) { ImGuiID id = window->GetID("#COLLAPSE"); ImRect bb(window->Pos + style.FramePadding + ImVec2(1,1), window->Pos + style.FramePadding + ImVec2(g.FontSize,g.FontSize) - ImVec2(1,1)); From e2dd48ae65521db418757b103c61898cc3765920 Mon Sep 17 00:00:00 2001 From: ocornut Date: Sat, 30 Jul 2016 18:06:05 +0200 Subject: [PATCH 053/823] Nav: Split _NoNav window flag into _NoNavInputs and _NoNavFocus (#323) --- imgui.cpp | 10 +++++----- imgui.h | 3 ++- imgui_demo.cpp | 4 ++-- imgui_internal.h | 2 +- 4 files changed, 10 insertions(+), 9 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index ec2a8137fecd..bc8da2f453d9 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2476,7 +2476,7 @@ static void NavUpdate() } // Set output flags for user application - g.IO.NavUsable = g.FocusedWindow && !(g.FocusedWindow->Flags & ImGuiWindowFlags_NoNav); + g.IO.NavUsable = g.FocusedWindow && !(g.FocusedWindow->Flags & ImGuiWindowFlags_NoNavInputs); g.IO.NavActive = g.IO.NavUsable && g.NavId != 0 && !g.NavDisableHighlight; // Process NavCancel input (to close a popup, get back to parent, clear focus) @@ -2527,7 +2527,7 @@ static void NavUpdate() g.NavActivateId = (g.NavId && !g.NavDisableHighlight && !g.NavWindowingTarget && g.ActiveId == 0 && IsKeyPressedMap(ImGuiKey_NavActivate)) ? g.NavId : 0; g.NavInputId = (g.NavId && !g.NavDisableHighlight && !g.NavWindowingTarget && g.ActiveId == 0 && IsKeyPressedMap(ImGuiKey_NavInput)) ? g.NavId : 0; - if (g.NavWindow && (g.NavWindow->Flags & ImGuiWindowFlags_NoNav)) + if (g.NavWindow && (g.NavWindow->Flags & ImGuiWindowFlags_NoNavInputs)) { g.NavActivateId = g.NavInputId = 0; g.NavDisableHighlight = true; @@ -2537,7 +2537,7 @@ static void NavUpdate() // Initiate directional inputs request const int allowed_dir_flags = (g.ActiveId == 0) ? ~0 : g.ActiveIdAllowNavDirFlags; g.NavMoveDir = ImGuiNavDir_None; - if (g.FocusedWindow && !g.NavWindowingTarget && allowed_dir_flags && !(g.FocusedWindow->Flags & ImGuiWindowFlags_NoNav)) + if (g.FocusedWindow && !g.NavWindowingTarget && allowed_dir_flags && !(g.FocusedWindow->Flags & ImGuiWindowFlags_NoNavInputs)) { if ((allowed_dir_flags & (1<Flags & ImGuiWindowFlags_NoNav)) + if (g.FocusedWindow && !(g.FocusedWindow->Flags & ImGuiWindowFlags_NoNavInputs)) { // Fallback manual-scroll with NavUp/NavDown when window has no navigable item const float scroll_speed = ImFloor(g.FocusedWindow->CalcFontSize() * 100 * g.IO.DeltaTime + 0.5f); // We need round the scrolling speed because sub-pixel scroll isn't reliably supported. @@ -2808,7 +2808,7 @@ void ImGui::NewFrame() // Pressing TAB activate widget focus //// NB: Don't discard FocusedWindow if it isn't active, so that a window that go on/off programatically won't lose its keyboard focus. // [2016/07/17] That comment was made invalid by 19d02becef94e8e0f1d432a8bd55cd783876583c - if (g.ActiveId == 0 && g.FocusedWindow != NULL && g.FocusedWindow->Active && !(g.FocusedWindow->Flags & ImGuiWindowFlags_NoNav) && !g.IO.KeyCtrl && IsKeyPressedMap(ImGuiKey_Tab, false)) + if (g.ActiveId == 0 && g.FocusedWindow != NULL && g.FocusedWindow->Active && !(g.FocusedWindow->Flags & ImGuiWindowFlags_NoNavInputs) && !g.IO.KeyCtrl && IsKeyPressedMap(ImGuiKey_Tab, false)) if (g.NavId != 0 && g.NavIdTabCounter != INT_MAX) g.FocusedWindow->FocusIdxTabRequestNext = g.NavIdTabCounter + 1 + (g.IO.KeyShift ? -1 : 1); else diff --git a/imgui.h b/imgui.h index 19650ec2681c..2f80b5b448d3 100644 --- a/imgui.h +++ b/imgui.h @@ -509,7 +509,8 @@ enum ImGuiWindowFlags_ ImGuiWindowFlags_AlwaysVerticalScrollbar= 1 << 14, // Always show vertical scrollbar (even if ContentSize.y < Size.y) ImGuiWindowFlags_AlwaysHorizontalScrollbar=1<< 15, // Always show horizontal scrollbar (even if ContentSize.x < Size.x) ImGuiWindowFlags_AlwaysUseWindowPadding = 1 << 16, // Ensure child windows without border uses style.WindowPadding (ignored by default for non-bordered child windows, because more convenient) - ImGuiWindowFlags_NoNav = 1 << 17, // No directional gamepad/keyboard navigation + ImGuiWindowFlags_NoNavFocus = 1 << 17, // No focusing of this window with gamepad/keyboard navigation + ImGuiWindowFlags_NoNavInputs = 1 << 18, // No gamepad/keyboard navigation within the window // [Internal] ImGuiWindowFlags_ChildWindow = 1 << 20, // Don't use! For internal use by BeginChild() ImGuiWindowFlags_ChildWindowAutoFitX = 1 << 21, // Don't use! For internal use by BeginChild() diff --git a/imgui_demo.cpp b/imgui_demo.cpp index db58ac080c1e..a6cd92d01a0b 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -164,7 +164,7 @@ void ImGui::ShowTestWindow(bool* p_open) if (no_scrollbar) window_flags |= ImGuiWindowFlags_NoScrollbar; if (no_collapse) window_flags |= ImGuiWindowFlags_NoCollapse; if (!no_menu) window_flags |= ImGuiWindowFlags_MenuBar; - if (no_nav) window_flags |= ImGuiWindowFlags_NoNav; + if (no_nav) window_flags |= ImGuiWindowFlags_NoNavInputs; ImGui::SetNextWindowSize(ImVec2(550,680), ImGuiSetCond_FirstUseEver); if (!ImGui::Begin("ImGui Demo", p_open, window_flags)) { @@ -1904,7 +1904,7 @@ static void ShowExampleAppConstrainedResize(bool* p_open) static void ShowExampleAppFixedOverlay(bool* p_open) { ImGui::SetNextWindowPos(ImVec2(10,10)); - if (!ImGui::Begin("Example: Fixed Overlay", p_open, ImVec2(0,0), 0.3f, ImGuiWindowFlags_NoTitleBar|ImGuiWindowFlags_NoResize|ImGuiWindowFlags_NoMove|ImGuiWindowFlags_NoSavedSettings|ImGuiWindowFlags_NoNav)) + if (!ImGui::Begin("Example: Fixed Overlay", p_open, ImVec2(0,0), 0.3f, ImGuiWindowFlags_NoTitleBar|ImGuiWindowFlags_NoResize|ImGuiWindowFlags_NoMove|ImGuiWindowFlags_NoSavedSettings|ImGuiWindowFlags_NoFocusOnAppearing|ImGuiWindowFlags_NoNavFocus|ImGuiWindowFlags_NoNavInputs)) { ImGui::End(); return; diff --git a/imgui_internal.h b/imgui_internal.h index 1f08a1769f14..fa0d8c2bd230 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -745,7 +745,7 @@ struct IMGUI_API ImGuiWindow ImRect TitleBarRect() const { return ImRect(Pos, ImVec2(Pos.x + SizeFull.x, Pos.y + TitleBarHeight())); } float MenuBarHeight() const { return (Flags & ImGuiWindowFlags_MenuBar) ? CalcFontSize() + GImGui->Style.FramePadding.y * 2.0f : 0.0f; } ImRect MenuBarRect() const { float y1 = Pos.y + TitleBarHeight(); return ImRect(Pos.x, y1, Pos.x + SizeFull.x, y1 + MenuBarHeight()); } - bool IsNavigableTo() const { return Active && this == this->RootNonPopupWindow && (!(Flags & ImGuiWindowFlags_NoNav) || this == GImGui->FocusedWindow); } + bool IsNavigableTo() const { return Active && this == this->RootNonPopupWindow && (!(Flags & ImGuiWindowFlags_NoNavFocus) || this == GImGui->FocusedWindow); } }; //----------------------------------------------------------------------------- From 8d0186c82b40d867a10a0b2a658b4d443c22a82c Mon Sep 17 00:00:00 2001 From: ocornut Date: Sat, 30 Jul 2016 19:08:20 +0200 Subject: [PATCH 054/823] Nav: programmatic call to SetKeyboardFocusHere() doesn't quality as a nav input (doesn't position mouse) (#323) --- imgui.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index bc8da2f453d9..635a1516d84d 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2149,10 +2149,7 @@ bool ImGui::FocusableItemRegister(ImGuiWindow* window, ImGuiID id, bool tab_stop window->FocusIdxTabRequestNext = window->FocusIdxTabCounter + (g.IO.KeyShift ? (allow_keyboard_focus ? -1 : 0) : +1); // Modulo on index will be applied at the end of frame once we've got the total counter of items. if (window->FocusIdxAllCounter == window->FocusIdxAllRequestCurrent) - { - g.NavTabbedId = id; return true; - } if (allow_keyboard_focus && window->FocusIdxTabCounter == window->FocusIdxTabRequestCurrent) { g.NavTabbedId = id; From cc66731c39a9ba1c0fc22c298a88db86a84804a2 Mon Sep 17 00:00:00 2001 From: ocornut Date: Sat, 30 Jul 2016 19:15:12 +0200 Subject: [PATCH 055/823] Nav: Calling SetItemDefaultFocus() doesn't make mouse cursor dirty if nav highlight is off (#323) --- imgui.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 635a1516d84d..81f1933e7ec7 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2062,7 +2062,6 @@ bool ImGui::ItemAdd(const ImRect& bb, const ImGuiID* id, const ImRect* nav_bb_ar { const ImRect& nav_bb = nav_bb_arg ? *nav_bb_arg : bb; const ImRect nav_bb_rel(nav_bb.Min - window->Pos, nav_bb.Max - window->Pos); - if (g.NavInitDefaultRequest && g.NavLayer == window->DC.NavLayerCurrent && window->DC.AllowNavDefaultFocus) { g.NavInitDefaultRequest = g.NavInitDefaultResultExplicit = false; // Clear flag immediately, first item gets default, also simplify the if() in ItemAdd() @@ -2334,7 +2333,8 @@ static void NavUpdate() IM_ASSERT(g.NavWindow); g.NavId = g.NavInitDefaultResultId; g.NavRefRectRel = g.NavInitDefaultResultRectRel; - g.NavMousePosDirty = true; + if (!g.NavDisableHighlight) + g.NavMousePosDirty = true; if (g.NavLayer == 0) g.NavWindow->NavLastId = g.NavId; } From 3cc1419df34a12a9aef37d074f434fd20d3b1aea Mon Sep 17 00:00:00 2001 From: ocornut Date: Sat, 30 Jul 2016 19:16:41 +0200 Subject: [PATCH 056/823] Nav: making io.NavActive more suitable for end-user detecting if they should pass inputs to game (#323) --- imgui.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/imgui.cpp b/imgui.cpp index 81f1933e7ec7..1e1be8d052f4 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2474,7 +2474,7 @@ static void NavUpdate() // Set output flags for user application g.IO.NavUsable = g.FocusedWindow && !(g.FocusedWindow->Flags & ImGuiWindowFlags_NoNavInputs); - g.IO.NavActive = g.IO.NavUsable && g.NavId != 0 && !g.NavDisableHighlight; + g.IO.NavActive = (g.IO.NavUsable && g.NavId != 0 && !g.NavDisableHighlight) || (g.NavWindowingTarget != NULL) || g.NavMoveRequest || g.NavInitDefaultRequest; // Process NavCancel input (to close a popup, get back to parent, clear focus) if (IsKeyPressedMap(ImGuiKey_NavCancel)) @@ -10598,6 +10598,7 @@ void ImGui::ShowMetricsWindow(bool* p_open) ImGui::Text("ActiveId: 0x%08X/0x%08X, ActiveIdWindow: %s", g.ActiveId, g.ActiveIdPreviousFrame, g.ActiveIdWindow ? g.ActiveIdWindow->Name : "NULL"); ImGui::Text("NavId: 0x%08X, NavWindow: '%s'", g.NavId, g.NavWindow ? g.NavWindow->Name : "NULL"); ImGui::Text("NavRefRectRel: (%.1f,%.1f)(%.1f,%.1f)", g.NavRefRectRel.Min.x, g.NavRefRectRel.Min.y, g.NavRefRectRel.Max.x, g.NavRefRectRel.Max.y); + ImGui::Text("NavUsable: %d, NavActive: %d", g.IO.NavUsable, g.IO.NavActive); ImGui::Text("NavDisableHighlight: %d, NavDisableMouseHover: %d", g.NavDisableHighlight, g.NavDisableMouseHover); ImGui::TreePop(); } From d88dcc26cc42146f72ce4259950341a14e072756 Mon Sep 17 00:00:00 2001 From: ocornut Date: Sat, 30 Jul 2016 19:17:26 +0200 Subject: [PATCH 057/823] Demo: console text input keeps focus in a less harsher and more navigation friendly way (#323) --- imgui_demo.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/imgui_demo.cpp b/imgui_demo.cpp index a6cd92d01a0b..7ec06dacd9c5 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -2159,6 +2159,7 @@ struct ExampleAppConsole ImGui::Separator(); // Command-line + bool reclaim_focus = false; if (ImGui::InputText("Input", InputBuf, IM_ARRAYSIZE(InputBuf), ImGuiInputTextFlags_EnterReturnsTrue|ImGuiInputTextFlags_CallbackCompletion|ImGuiInputTextFlags_CallbackHistory, &TextEditCallbackStub, (void*)this)) { char* input_end = InputBuf+strlen(InputBuf); @@ -2166,10 +2167,12 @@ struct ExampleAppConsole if (InputBuf[0]) ExecCommand(InputBuf); strcpy(InputBuf, ""); + reclaim_focus = true; } - // Demonstrate keeping auto focus on the input box - if (ImGui::IsItemHovered() || (ImGui::IsRootWindowOrAnyChildFocused() && !ImGui::IsAnyItemActive() && !ImGui::IsMouseClicked(0))) + // Demonstrate keeping focus on the input box + ImGui::SetItemDefaultFocus(); + if (ImGui::IsItemHovered() || reclaim_focus) ImGui::SetKeyboardFocusHere(-1); // Auto focus previous widget ImGui::End(); From 79e7ece259a2eb62feb7b4ccced33cc9b1462fb0 Mon Sep 17 00:00:00 2001 From: ocornut Date: Sat, 30 Jul 2016 23:17:11 +0200 Subject: [PATCH 058/823] Nav/Examples: honoring the io.WantMoveMouse flag in most common examples (#323) Missing support Vulkan (#549), Apple (#575, #247), SDL (#58, #356), Allegro, Marmalade (#368, #375) --- examples/README.txt | 1 + examples/directx10_example/imgui_impl_dx10.cpp | 8 ++++++++ examples/directx11_example/imgui_impl_dx11.cpp | 8 ++++++++ examples/directx9_example/imgui_impl_dx9.cpp | 8 ++++++++ examples/opengl3_example/imgui_impl_glfw_gl3.cpp | 13 ++++++++++--- examples/opengl_example/imgui_impl_glfw.cpp | 13 ++++++++++--- 6 files changed, 45 insertions(+), 6 deletions(-) diff --git a/examples/README.txt b/examples/README.txt index df2e86dab842..b58f43434fff 100644 --- a/examples/README.txt +++ b/examples/README.txt @@ -84,3 +84,4 @@ vulkan_example/ Vulkan example. This is quite long and tedious, because: Vulkan. +TODO: Apple, SDL GL/GL3, Allegro, Marmalade, Vulkan examples do not honor the io.WantMoveMouse flag. diff --git a/examples/directx10_example/imgui_impl_dx10.cpp b/examples/directx10_example/imgui_impl_dx10.cpp index bccee87e3dcf..cc664be36ca8 100644 --- a/examples/directx10_example/imgui_impl_dx10.cpp +++ b/examples/directx10_example/imgui_impl_dx10.cpp @@ -572,6 +572,14 @@ void ImGui_ImplDX10_NewFrame() // io.MouseDown : filled by WM_*BUTTON* events // io.MouseWheel : filled by WM_MOUSEWHEEL events + // Set OS mouse position if requested last frame by io.WantMoveMouse flag (used when io.NavMovesTrue is enabled by user and using directional navigation) + if (io.WantMoveMouse) + { + POINT pos = { (int)io.MousePos.x, (int)io.MousePos.y }; + ClientToScreen(g_hWnd, &pos); + SetCursorPos(pos.x, pos.y); + } + // Hide OS mouse cursor if ImGui is drawing it SetCursor(io.MouseDrawCursor ? NULL : LoadCursor(NULL, IDC_ARROW)); diff --git a/examples/directx11_example/imgui_impl_dx11.cpp b/examples/directx11_example/imgui_impl_dx11.cpp index 11f66f0e9ca3..d77d5c3fcec7 100644 --- a/examples/directx11_example/imgui_impl_dx11.cpp +++ b/examples/directx11_example/imgui_impl_dx11.cpp @@ -575,6 +575,14 @@ void ImGui_ImplDX11_NewFrame() // io.MouseDown : filled by WM_*BUTTON* events // io.MouseWheel : filled by WM_MOUSEWHEEL events + // Set OS mouse position if requested last frame by io.WantMoveMouse flag (used when io.NavMovesTrue is enabled by user and using directional navigation) + if (io.WantMoveMouse) + { + POINT pos = { (int)io.MousePos.x, (int)io.MousePos.y }; + ClientToScreen(g_hWnd, &pos); + SetCursorPos(pos.x, pos.y); + } + // Hide OS mouse cursor if ImGui is drawing it SetCursor(io.MouseDrawCursor ? NULL : LoadCursor(NULL, IDC_ARROW)); diff --git a/examples/directx9_example/imgui_impl_dx9.cpp b/examples/directx9_example/imgui_impl_dx9.cpp index bb309a867a74..6341a2a869db 100644 --- a/examples/directx9_example/imgui_impl_dx9.cpp +++ b/examples/directx9_example/imgui_impl_dx9.cpp @@ -338,6 +338,14 @@ void ImGui_ImplDX9_NewFrame() // io.MouseDown : filled by WM_*BUTTON* events // io.MouseWheel : filled by WM_MOUSEWHEEL events + // Set OS mouse position if requested last frame by io.WantMoveMouse flag (used when io.NavMovesTrue is enabled by user and using directional navigation) + if (io.WantMoveMouse) + { + POINT pos = { (int)io.MousePos.x, (int)io.MousePos.y }; + ClientToScreen(g_hWnd, &pos); + SetCursorPos(pos.x, pos.y); + } + // Hide OS mouse cursor if ImGui is drawing it SetCursor(io.MouseDrawCursor ? NULL : LoadCursor(NULL, IDC_ARROW)); diff --git a/examples/opengl3_example/imgui_impl_glfw_gl3.cpp b/examples/opengl3_example/imgui_impl_glfw_gl3.cpp index 0e3a754cbbce..4b9ab6a1a05e 100644 --- a/examples/opengl3_example/imgui_impl_glfw_gl3.cpp +++ b/examples/opengl3_example/imgui_impl_glfw_gl3.cpp @@ -371,9 +371,16 @@ void ImGui_ImplGlfwGL3_NewFrame() // (we already got mouse wheel, keyboard keys & characters from glfw callbacks polled in glfwPollEvents()) if (glfwGetWindowAttrib(g_Window, GLFW_FOCUSED)) { - double mouse_x, mouse_y; - glfwGetCursorPos(g_Window, &mouse_x, &mouse_y); - io.MousePos = ImVec2((float)mouse_x, (float)mouse_y); // Mouse position in screen coordinates (set to -1,-1 if no mouse / on another screen, etc.) + if (io.WantMoveMouse) + { + glfwSetCursorPos(g_Window, (double)io.MousePos.x, (double)io.MousePos.y); // Set mouse position if requested by io.WantMoveMouse flag (used when io.NavMovesTrue is enabled by user and using directional navigation) + } + else + { + double mouse_x, mouse_y; + glfwGetCursorPos(g_Window, &mouse_x, &mouse_y); + io.MousePos = ImVec2((float)mouse_x, (float)mouse_y); // Get mouse position in screen coordinates (set to -1,-1 if no mouse / on another screen, etc.) + } } else { diff --git a/examples/opengl_example/imgui_impl_glfw.cpp b/examples/opengl_example/imgui_impl_glfw.cpp index 2d1f5c1a0933..d7463150ce74 100644 --- a/examples/opengl_example/imgui_impl_glfw.cpp +++ b/examples/opengl_example/imgui_impl_glfw.cpp @@ -262,9 +262,16 @@ void ImGui_ImplGlfw_NewFrame() // (we already got mouse wheel, keyboard keys & characters from glfw callbacks polled in glfwPollEvents()) if (glfwGetWindowAttrib(g_Window, GLFW_FOCUSED)) { - double mouse_x, mouse_y; - glfwGetCursorPos(g_Window, &mouse_x, &mouse_y); - io.MousePos = ImVec2((float)mouse_x, (float)mouse_y); // Mouse position in screen coordinates (set to -1,-1 if no mouse / on another screen, etc.) + if (io.WantMoveMouse) + { + glfwSetCursorPos(g_Window, (double)io.MousePos.x, (double)io.MousePos.y); // Set mouse position if requested by io.WantMoveMouse flag (used when io.NavMovesTrue is enabled by user and using directional navigation) + } + else + { + double mouse_x, mouse_y; + glfwGetCursorPos(g_Window, &mouse_x, &mouse_y); + io.MousePos = ImVec2((float)mouse_x, (float)mouse_y); // Get mouse position in screen coordinates (set to -1,-1 if no mouse / on another screen, etc.) + } } else { From 68b73b61b5547c496ee94e8b27b27d1a5b7072e6 Mon Sep 17 00:00:00 2001 From: ocornut Date: Sat, 30 Jul 2016 23:17:32 +0200 Subject: [PATCH 059/823] Nav: Comment (#323) --- imgui.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/imgui.h b/imgui.h index 2f80b5b448d3..b657d80a1e0f 100644 --- a/imgui.h +++ b/imgui.h @@ -774,7 +774,7 @@ struct ImGuiIO int KeyMap[ImGuiKey_COUNT]; // // Map of indices into the KeysDown[512] entries array float KeyRepeatDelay; // = 0.250f // When holding a key/button, time before it starts repeating, in seconds (for buttons in Repeat mode, etc.). float KeyRepeatRate; // = 0.020f // When holding a key/button, rate at which it repeats, in seconds. - bool NavMovesMouse; // = false // Directional navigation move the mouse cursor (update MousePos and set + bool NavMovesMouse; // = false // Directional navigation can move the mouse cursor. Updates MousePos and set WantMoveMouse=true. If enabled you MUST honor those requests in your binding, otherwise ImGui will react as if mouse is jumping around. void* UserData; // = NULL // Store your own data for retrieval by callbacks. ImFontAtlas* Fonts; // // Load and assemble one or more fonts into a single tightly packed texture. Output to Fonts array. From a88d189f181a30078cb08fa3051ac9a8f8c5c94f Mon Sep 17 00:00:00 2001 From: ocornut Date: Sat, 30 Jul 2016 23:52:03 +0200 Subject: [PATCH 060/823] Nav: MoveRequest doesn't affect io.NavUsable so that navigation failure doesn't trigger false positive & not needed (undo part of 3cc1419df) --- imgui.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/imgui.cpp b/imgui.cpp index 0d5b3688236e..543ad9efab3c 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2475,7 +2475,7 @@ static void NavUpdate() // Set output flags for user application g.IO.NavUsable = g.FocusedWindow && !(g.FocusedWindow->Flags & ImGuiWindowFlags_NoNavInputs); - g.IO.NavActive = (g.IO.NavUsable && g.NavId != 0 && !g.NavDisableHighlight) || (g.NavWindowingTarget != NULL) || g.NavMoveRequest || g.NavInitDefaultRequest; + g.IO.NavActive = (g.IO.NavUsable && g.NavId != 0 && !g.NavDisableHighlight) || (g.NavWindowingTarget != NULL) || g.NavInitDefaultRequest; // Process NavCancel input (to close a popup, get back to parent, clear focus) if (IsKeyPressedMap(ImGuiKey_NavCancel)) From 769a1dd748fa9a6c87bae26adf168434eb17bf61 Mon Sep 17 00:00:00 2001 From: ocornut Date: Sun, 31 Jul 2016 10:41:41 +0200 Subject: [PATCH 061/823] Nav: No scrolling while using windowing functionalities (#323) --- imgui.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 543ad9efab3c..7230828364ef 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2549,23 +2549,23 @@ static void NavUpdate() } // Scrolling - if (g.FocusedWindow && !(g.FocusedWindow->Flags & ImGuiWindowFlags_NoNavInputs)) + if (g.NavWindow && !(g.NavWindow->Flags & ImGuiWindowFlags_NoNavInputs) && !g.NavWindowingTarget) { // Fallback manual-scroll with NavUp/NavDown when window has no navigable item - const float scroll_speed = ImFloor(g.FocusedWindow->CalcFontSize() * 100 * g.IO.DeltaTime + 0.5f); // We need round the scrolling speed because sub-pixel scroll isn't reliably supported. - if (!g.FocusedWindow->DC.NavLayerActiveFlags && g.FocusedWindow->DC.NavHasScroll && g.NavMoveRequest && (g.NavMoveDir == ImGuiNavDir_Up || g.NavMoveDir == ImGuiNavDir_Down)) - SetWindowScrollY(g.FocusedWindow, ImFloor(g.FocusedWindow->Scroll.y + ((g.NavMoveDir == ImGuiNavDir_Up) ? -1.0f : +1.0f) * scroll_speed)); + const float scroll_speed = ImFloor(g.NavWindow->CalcFontSize() * 100 * g.IO.DeltaTime + 0.5f); // We need round the scrolling speed because sub-pixel scroll isn't reliably supported. + if (!g.NavWindow->DC.NavLayerActiveFlags && g.NavWindow->DC.NavHasScroll && g.NavMoveRequest && (g.NavMoveDir == ImGuiNavDir_Up || g.NavMoveDir == ImGuiNavDir_Down)) + SetWindowScrollY(g.NavWindow, ImFloor(g.NavWindow->Scroll.y + ((g.NavMoveDir == ImGuiNavDir_Up) ? -1.0f : +1.0f) * scroll_speed)); // Manual scroll with NavScrollXXX keys ImVec2 scroll_dir = ImGui::NavGetMovingDir(1, 1.0f/10.0f, 10.0f); if (scroll_dir.x != 0.0f && g.NavWindow->ScrollbarX) { - SetWindowScrollX(g.FocusedWindow, ImFloor(g.FocusedWindow->Scroll.x + scroll_dir.x * scroll_speed)); + SetWindowScrollX(g.NavWindow, ImFloor(g.NavWindow->Scroll.x + scroll_dir.x * scroll_speed)); g.NavMoveFromClampedRefRect = true; } if (scroll_dir.y != 0.0f) { - SetWindowScrollY(g.FocusedWindow, ImFloor(g.FocusedWindow->Scroll.y + scroll_dir.y * scroll_speed)); + SetWindowScrollY(g.NavWindow, ImFloor(g.NavWindow->Scroll.y + scroll_dir.y * scroll_speed)); g.NavMoveFromClampedRefRect = true; } } From b3cba62b80038bd8c8fd722ba5e4e13c83bfb8bc Mon Sep 17 00:00:00 2001 From: ocornut Date: Sun, 31 Jul 2016 12:55:23 +0200 Subject: [PATCH 062/823] Nav: Added experiment ImGuiWindowFlags_NavFlattened flag to cross over between parent and non-scrolling child windows (#323) --- imgui.cpp | 40 +++++++++++++++++++++++----------------- imgui.h | 1 + imgui_demo.cpp | 2 +- imgui_internal.h | 7 ++++--- 4 files changed, 29 insertions(+), 21 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 7230828364ef..dcf3ea5ffd06 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1755,9 +1755,10 @@ ImGuiWindow::ImGuiWindow(const char* name) DrawList = (ImDrawList*)ImGui::MemAlloc(sizeof(ImDrawList)); IM_PLACEMENT_NEW(DrawList) ImDrawList(); DrawList->_OwnerName = Name; + ParentWindow = NULL; RootWindow = NULL; RootNonPopupWindow = NULL; - ParentWindow = NULL; + RootNavWindow = NULL; FocusIdxAllCounter = FocusIdxTabCounter = -1; FocusIdxAllRequestCurrent = FocusIdxTabRequestCurrent = INT_MAX; @@ -1917,7 +1918,7 @@ static float NavScoreItemDistInterval(float a0, float a1, float b0, float b1) static bool NavScoreItem(ImRect cand) { ImGuiContext& g = *GImGui; - ImGuiWindow* window = g.CurrentWindow; + ImGuiWindow* window = g.NavWindow; if (g.NavLayer != window->DC.NavLayerCurrent) return false; @@ -2059,10 +2060,10 @@ bool ImGui::ItemAdd(const ImRect& bb, const ImGuiID* id, const ImRect* nav_bb_ar // We could early out with `if (is_clipped && !g.NavInitDefaultRequest) return false;` but when we wouldn't be able to reach unclipped widgets. This would work if user had explicit scrolling control (e.g. mapped on a stick) // A more pragmatic solution for handling last lists is relying on the fact that they are likely evenly spread items (so that clipper can work) and we could nav at higher-level (apply index, etc.) // So eventually we would like to provide the user will the primitives to be able to implement that sort of customized/efficient navigation handling whenever necessary. - if (id != NULL && g.NavWindow == window && g.IO.NavUsable) + if (id != NULL && g.NavWindow == window->RootNavWindow && g.IO.NavUsable) { const ImRect& nav_bb = nav_bb_arg ? *nav_bb_arg : bb; - const ImRect nav_bb_rel(nav_bb.Min - window->Pos, nav_bb.Max - window->Pos); + const ImRect nav_bb_rel(nav_bb.Min - g.NavWindow->Pos, nav_bb.Max - g.NavWindow->Pos); if (g.NavInitDefaultRequest && g.NavLayer == window->DC.NavLayerCurrent && window->DC.AllowNavDefaultFocus) { g.NavInitDefaultRequest = g.NavInitDefaultResultExplicit = false; // Clear flag immediately, first item gets default, also simplify the if() in ItemAdd() @@ -2070,8 +2071,8 @@ bool ImGui::ItemAdd(const ImRect& bb, const ImGuiID* id, const ImRect* nav_bb_ar g.NavInitDefaultResultRectRel = nav_bb_rel; } - const bool DEBUG_NAV = false; // [DEBUG] Enable to test scoring on all items. - if ((g.NavMoveRequest || DEBUG_NAV) && g.NavId != *id) + //const bool DEBUG_NAV = false; // [DEBUG] Enable to test scoring on all items. + if ((g.NavMoveRequest /*|| DEBUG_NAV*/) && g.NavId != *id) { //if (DEBUG_NAV && !g.NavMoveRequest) g.NavMoveDir = ImGuiNavDir_N; if (NavScoreItem(nav_bb)) //if (!DEBUG || g.NavMoveRequest) @@ -2389,7 +2390,7 @@ static void NavUpdate() } } - // Apply result from previous navigation directional move request + // Apply result from previous frame navigation directional move request ImGui::SetActiveID(0); SetNavIdMoveMouse(g.NavMoveResultId, g.NavMoveResultRectRel); g.NavMoveFromClampedRefRect = false; @@ -3864,7 +3865,7 @@ void ImGui::SetItemAllowOverlap() void ImGui::SetItemDefaultFocus() { ImGuiContext& g = *GImGui; - if (g.NavWindow == g.CurrentWindow && (g.NavInitDefaultRequest || g.NavInitDefaultResultId != 0)) + if (g.NavWindow == g.CurrentWindow->RootNavWindow && (g.NavInitDefaultRequest || g.NavInitDefaultResultId != 0)) { g.NavInitDefaultRequest = false; g.NavInitDefaultResultExplicit = true; @@ -4186,7 +4187,7 @@ bool ImGui::BeginChild(const char* str_id, const ImVec2& size_arg, bool border, // Process navigation-in immediately so NavInit can run on first frame const ImGuiID id = parent_window->GetChildID(child_window); - if ((child_window->DC.NavLayerActiveFlags != 0 || child_window->DC.NavHasScroll) && GImGui->NavActivateId == id) + if (!(flags & ImGuiWindowFlags_NavFlattened) && (child_window->DC.NavLayerActiveFlags != 0 || child_window->DC.NavHasScroll) && GImGui->NavActivateId == id) { FocusWindow(child_window); NavInitWindow(child_window, false); @@ -4227,16 +4228,15 @@ void ImGui::EndChild() ImGuiID id = parent_window->GetChildID(window); ImRect bb(parent_window->DC.CursorPos, parent_window->DC.CursorPos + sz); ItemSize(sz); - ItemAdd(bb, (window->DC.NavLayerActiveFlags != 0 || window->DC.NavHasScroll) ? &id : NULL); - if (window->DC.NavLayerActiveFlags != 0 || window->DC.NavHasScroll) - { - //if (!window->DC.NavHasItems && window->DC.NavHasScroll && g.NavWindow == window) // As a special case, we render nav highlight of child when inside when only scrolling is possible - //{ - // bb.Expand(-1.0f); - // id = g.NavId; - //} + if (!(window->Flags & ImGuiWindowFlags_NavFlattened) && (window->DC.NavLayerActiveFlags != 0 || window->DC.NavHasScroll)) + { + ItemAdd(bb, &id); RenderNavHighlight(id, bb); } + else + { + ItemAdd(bb, NULL); + } } } @@ -4428,6 +4428,9 @@ bool ImGui::Begin(const char* name, bool* p_open, const ImVec2& size_on_first_us if (flags & ImGuiWindowFlags_NoInputs) flags |= ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize; + if (flags & ImGuiWindowFlags_NavFlattened) + IM_ASSERT(flags & ImGuiWindowFlags_ChildWindow); + // Find or create bool window_is_new = false; ImGuiWindow* window = FindWindowByName(name); @@ -4524,6 +4527,9 @@ bool ImGui::Begin(const char* name, bool* p_open, const ImVec2& size_on_first_us window->ParentWindow = parent_window; window->RootWindow = g.CurrentWindowStack[root_idx]; window->RootNonPopupWindow = g.CurrentWindowStack[root_non_popup_idx]; // Used to display TitleBgActive color and for selecting which window to use for NavWindowing + window->RootNavWindow = window; + while (window->RootNavWindow->Flags & ImGuiWindowFlags_NavFlattened) + window->RootNavWindow = window->RootNavWindow->ParentWindow; // When reusing window again multiple times a frame, just append content (don't need to setup again) if (first_begin_of_the_frame) diff --git a/imgui.h b/imgui.h index b657d80a1e0f..6da6cecd21b5 100644 --- a/imgui.h +++ b/imgui.h @@ -511,6 +511,7 @@ enum ImGuiWindowFlags_ ImGuiWindowFlags_AlwaysUseWindowPadding = 1 << 16, // Ensure child windows without border uses style.WindowPadding (ignored by default for non-bordered child windows, because more convenient) ImGuiWindowFlags_NoNavFocus = 1 << 17, // No focusing of this window with gamepad/keyboard navigation ImGuiWindowFlags_NoNavInputs = 1 << 18, // No gamepad/keyboard navigation within the window + ImGuiWindowFlags_NavFlattened = 1 << 19, // Allow gamepad/keyboard navigation to cross over parent border to this child (only use on child that have no scrolling!) // [Internal] ImGuiWindowFlags_ChildWindow = 1 << 20, // Don't use! For internal use by BeginChild() ImGuiWindowFlags_ChildWindowAutoFitX = 1 << 21, // Don't use! For internal use by BeginChild() diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 7ec06dacd9c5..07b7dea9d091 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -2443,7 +2443,7 @@ static void ShowExampleAppLayout(bool* p_open) ImGui::Separator(); ImGui::TextWrapped("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. "); ImGui::EndChild(); - ImGui::BeginChild("buttons"); + ImGui::BeginChild("buttons", ImVec2(0,0), false, ImGuiWindowFlags_NavFlattened); if (ImGui::Button("Revert")) {} ImGui::SameLine(); if (ImGui::Button("Save")) {} diff --git a/imgui_internal.h b/imgui_internal.h index 622d4b15184f..4b192fa1a775 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -718,9 +718,10 @@ struct IMGUI_API ImGuiWindow ImGuiStorage StateStorage; float FontWindowScale; // Scale multiplier per-window ImDrawList* DrawList; - ImGuiWindow* RootWindow; // If we are a child window, this is pointing to the first non-child parent window. Else point to ourself. - ImGuiWindow* RootNonPopupWindow; // Used to display TitleBgActive color and for selecting which window to use for NavWindowing ImGuiWindow* ParentWindow; // Immediate parent in the window stack *regardless* of whether this window is a child window or not) + ImGuiWindow* RootWindow; // Generally point to ourself. If we are a child window, this is pointing to the first non-child parent window. + ImGuiWindow* RootNonPopupWindow; // Generally point to ourself. Used to display TitleBgActive color and for selecting which window to use for NavWindowing + ImGuiWindow* RootNavWindow; // Generally point to ourself. If we are a child window with the ImGuiWindowFlags_NavFlattenedChild flag, point to parent. Used to display TitleBgActive color and for selecting which window to use for NavWindowing. // Navigation / Focus // FIXME-NAVIGATION: Merge all this with the new Nav system, at least the request variables should be moved to ImGuiContext @@ -746,7 +747,7 @@ struct IMGUI_API ImGuiWindow ImRect TitleBarRect() const { return ImRect(Pos, ImVec2(Pos.x + SizeFull.x, Pos.y + TitleBarHeight())); } float MenuBarHeight() const { return (Flags & ImGuiWindowFlags_MenuBar) ? CalcFontSize() + GImGui->Style.FramePadding.y * 2.0f : 0.0f; } ImRect MenuBarRect() const { float y1 = Pos.y + TitleBarHeight(); return ImRect(Pos.x, y1, Pos.x + SizeFull.x, y1 + MenuBarHeight()); } - bool IsNavigableTo() const { return Active && this == this->RootNonPopupWindow && (!(Flags & ImGuiWindowFlags_NoNavFocus) || this == GImGui->FocusedWindow); } + bool IsNavigableTo() const { return Active && this == RootNonPopupWindow && (!(Flags & ImGuiWindowFlags_NoNavFocus) || this == GImGui->FocusedWindow); } }; //----------------------------------------------------------------------------- From 2545d75c3b978638329ac65cc1851f3f5998bb5b Mon Sep 17 00:00:00 2001 From: ocornut Date: Sun, 31 Jul 2016 13:05:13 +0200 Subject: [PATCH 063/823] Tidying up, removed two unnecessary window flags from being exposed in imgui.h --- imgui.cpp | 15 +++++---------- imgui.h | 4 +--- imgui_internal.h | 1 + 3 files changed, 7 insertions(+), 13 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index dcf3ea5ffd06..4fbc1b9e1a6c 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1743,6 +1743,7 @@ ImGuiWindow::ImGuiWindow(const char* name) NavLastId = 0; AutoFitFramesX = AutoFitFramesY = -1; AutoFitOnlyGrows = false; + AutoFitChildAxises = 0x00; AutoPosLastDirection = -1; HiddenFrames = 0; SetWindowPosAllowFlags = SetWindowSizeAllowFlags = SetWindowCollapsedAllowFlags = ImGuiSetCond_Always | ImGuiSetCond_Once | ImGuiSetCond_FirstUseEver | ImGuiSetCond_Appearing; @@ -4161,18 +4162,11 @@ bool ImGui::BeginChild(const char* str_id, const ImVec2& size_arg, bool border, const ImVec2 content_avail = GetContentRegionAvail(); ImVec2 size = ImFloor(size_arg); + const int auto_fit_axises = ((size.x == 0.0f) ? 0x01 : 0x00) | ((size.y == 0.0f) ? 0x02 : 0x00); if (size.x <= 0.0f) - { - if (size.x == 0.0f) - flags |= ImGuiWindowFlags_ChildWindowAutoFitX; size.x = ImMax(content_avail.x, 4.0f) - fabsf(size.x); // Arbitrary minimum zero-ish child size of 4.0f (0.0f causing too much issues) - } if (size.y <= 0.0f) - { - if (size.y == 0.0f) - flags |= ImGuiWindowFlags_ChildWindowAutoFitY; size.y = ImMax(content_avail.y, 4.0f) - fabsf(size.y); - } if (border) flags |= ImGuiWindowFlags_ShowBorders; flags |= extra_flags; @@ -4182,6 +4176,7 @@ bool ImGui::BeginChild(const char* str_id, const ImVec2& size_arg, bool border, bool ret = ImGui::Begin(title, NULL, size, -1.0f, flags); ImGuiWindow* child_window = GetCurrentWindow(); + child_window->AutoFitChildAxises = auto_fit_axises; if (!(parent_window->Flags & ImGuiWindowFlags_ShowBorders)) child_window->Flags &= ~ImGuiWindowFlags_ShowBorders; @@ -4218,9 +4213,9 @@ void ImGui::EndChild() { // When using auto-filling child window, we don't provide full width/height to ItemSize so that it doesn't feed back into automatic size-fitting. ImVec2 sz = GetWindowSize(); - if (window->Flags & ImGuiWindowFlags_ChildWindowAutoFitX) // Arbitrary minimum zero-ish child size of 4.0f causes less trouble than a 0.0f + if (window->AutoFitChildAxises & 0x01) // Arbitrary minimum zero-ish child size of 4.0f causes less trouble than a 0.0f sz.x = ImMax(4.0f, sz.x); - if (window->Flags & ImGuiWindowFlags_ChildWindowAutoFitY) + if (window->AutoFitChildAxises & 0x02) sz.y = ImMax(4.0f, sz.y); ImGui::End(); diff --git a/imgui.h b/imgui.h index 6da6cecd21b5..d3719ad739ef 100644 --- a/imgui.h +++ b/imgui.h @@ -513,9 +513,7 @@ enum ImGuiWindowFlags_ ImGuiWindowFlags_NoNavInputs = 1 << 18, // No gamepad/keyboard navigation within the window ImGuiWindowFlags_NavFlattened = 1 << 19, // Allow gamepad/keyboard navigation to cross over parent border to this child (only use on child that have no scrolling!) // [Internal] - ImGuiWindowFlags_ChildWindow = 1 << 20, // Don't use! For internal use by BeginChild() - ImGuiWindowFlags_ChildWindowAutoFitX = 1 << 21, // Don't use! For internal use by BeginChild() - ImGuiWindowFlags_ChildWindowAutoFitY = 1 << 22, // Don't use! For internal use by BeginChild() + ImGuiWindowFlags_ChildWindow = 1 << 22, // Don't use! For internal use by BeginChild() ImGuiWindowFlags_ComboBox = 1 << 23, // Don't use! For internal use by ComboBox() ImGuiWindowFlags_Tooltip = 1 << 24, // Don't use! For internal use by BeginTooltip() ImGuiWindowFlags_Popup = 1 << 25, // Don't use! For internal use by BeginPopup() diff --git a/imgui_internal.h b/imgui_internal.h index 4b192fa1a775..b8d211cad7b2 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -700,6 +700,7 @@ struct IMGUI_API ImGuiWindow ImGuiID NavLastId; // Last known NavId for this window, for nav layer 0 only. int AutoFitFramesX, AutoFitFramesY; bool AutoFitOnlyGrows; + int AutoFitChildAxises; int AutoPosLastDirection; int HiddenFrames; int SetWindowPosAllowFlags; // bit ImGuiSetCond_*** specify if SetWindowPos() call will succeed with this particular flag. From 08a28c16ae71d6e5f40c5143929f19343c9ac22f Mon Sep 17 00:00:00 2001 From: ocornut Date: Sun, 31 Jul 2016 13:38:57 +0200 Subject: [PATCH 064/823] Nav: Merge FocusedWindow and NavWindow that were basically duplicate at this point (#323) --- imgui.cpp | 65 ++++++++++++++++++++++-------------------------- imgui_internal.h | 10 +++----- 2 files changed, 34 insertions(+), 41 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 4fbc1b9e1a6c..dd3ec4a94cd9 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2449,7 +2449,7 @@ static void NavUpdate() if (!IsKeyDownMap(ImGuiKey_NavMenu)) { // Apply actual focus only when releasing the NavMenu button (until then the window was merely rendered front-most) - if (g.NavWindowingTarget && (!g.FocusedWindow || g.NavWindowingTarget != g.FocusedWindow->RootNonPopupWindow)) + if (g.NavWindowingTarget && (!g.NavWindow || g.NavWindowingTarget != g.NavWindow->RootNonPopupWindow)) { ImGui::FocusWindow(g.NavWindowingTarget); g.NavDisableHighlight = false; @@ -2476,7 +2476,7 @@ static void NavUpdate() } // Set output flags for user application - g.IO.NavUsable = g.FocusedWindow && !(g.FocusedWindow->Flags & ImGuiWindowFlags_NoNavInputs); + g.IO.NavUsable = g.NavWindow && !(g.NavWindow->Flags & ImGuiWindowFlags_NoNavInputs); g.IO.NavActive = (g.IO.NavUsable && g.NavId != 0 && !g.NavDisableHighlight) || (g.NavWindowingTarget != NULL) || g.NavInitDefaultRequest; // Process NavCancel input (to close a popup, get back to parent, clear focus) @@ -2502,14 +2502,14 @@ static void NavUpdate() else { // Clear NavId for popups but keep it for regular child window so we can leave one and come back where we were - if (g.FocusedWindow && ((g.FocusedWindow->Flags & ImGuiWindowFlags_Popup) || !(g.FocusedWindow->Flags & ImGuiWindowFlags_ChildWindow))) - g.FocusedWindow->NavLastId = 0; + if (g.NavWindow && ((g.NavWindow->Flags & ImGuiWindowFlags_Popup) || !(g.NavWindow->Flags & ImGuiWindowFlags_ChildWindow))) + g.NavWindow->NavLastId = 0; - if (g.FocusedWindow && (g.FocusedWindow->Flags & ImGuiWindowFlags_ChildWindow) && g.FocusedWindow->ParentWindow) + if (g.NavWindow && (g.NavWindow->Flags & ImGuiWindowFlags_ChildWindow) && g.NavWindow->ParentWindow) { // Exit child window - ImGuiWindow* child_window = g.FocusedWindow; - ImGuiWindow* parent_window = g.FocusedWindow->ParentWindow; + ImGuiWindow* child_window = g.NavWindow; + ImGuiWindow* parent_window = g.NavWindow->ParentWindow; ImGui::FocusWindow(parent_window); g.NavId = parent_window->GetChildID(child_window); if (g.NavLayer == 0) @@ -2537,7 +2537,7 @@ static void NavUpdate() // Initiate directional inputs request const int allowed_dir_flags = (g.ActiveId == 0) ? ~0 : g.ActiveIdAllowNavDirFlags; g.NavMoveDir = ImGuiNavDir_None; - if (g.FocusedWindow && !g.NavWindowingTarget && allowed_dir_flags && !(g.FocusedWindow->Flags & ImGuiWindowFlags_NoNavInputs)) + if (g.NavWindow && !g.NavWindowingTarget && allowed_dir_flags && !(g.NavWindow->Flags & ImGuiWindowFlags_NoNavInputs)) { if ((allowed_dir_flags & (1<Flags & ImGuiWindowFlags_NoNavInputs) && !g.NavWindowingTarget) @@ -2808,11 +2805,11 @@ void ImGui::NewFrame() // Pressing TAB activate widget focus //// NB: Don't discard FocusedWindow if it isn't active, so that a window that go on/off programatically won't lose its keyboard focus. // [2016/07/17] That comment was made invalid by 19d02becef94e8e0f1d432a8bd55cd783876583c - if (g.ActiveId == 0 && g.FocusedWindow != NULL && g.FocusedWindow->Active && !(g.FocusedWindow->Flags & ImGuiWindowFlags_NoNavInputs) && !g.IO.KeyCtrl && IsKeyPressedMap(ImGuiKey_Tab, false)) + if (g.ActiveId == 0 && g.NavWindow != NULL && g.NavWindow->Active && !(g.NavWindow->Flags & ImGuiWindowFlags_NoNavInputs) && !g.IO.KeyCtrl && IsKeyPressedMap(ImGuiKey_Tab, false)) if (g.NavId != 0 && g.NavIdTabCounter != INT_MAX) - g.FocusedWindow->FocusIdxTabRequestNext = g.NavIdTabCounter + 1 + (g.IO.KeyShift ? -1 : 1); + g.NavWindow->FocusIdxTabRequestNext = g.NavIdTabCounter + 1 + (g.IO.KeyShift ? -1 : 1); else - g.FocusedWindow->FocusIdxTabRequestNext = g.IO.KeyShift ? -1 : 0; + g.NavWindow->FocusIdxTabRequestNext = g.IO.KeyShift ? -1 : 0; g.NavIdTabCounter = INT_MAX; // Mark all windows as not visible @@ -2825,7 +2822,7 @@ void ImGui::NewFrame() } // Closing the focused window restore focus to the first active root window in descending z-order - if (g.FocusedWindow && !g.FocusedWindow->WasActive) + if (g.NavWindow && !g.NavWindow->WasActive) for (int i = g.Windows.Size-1; i >= 0; i--) if (g.Windows[i]->WasActive && !(g.Windows[i]->Flags & ImGuiWindowFlags_ChildWindow)) { @@ -2867,7 +2864,7 @@ void ImGui::Shutdown() g.Windows.clear(); g.WindowsSortBuffer.clear(); g.CurrentWindowStack.clear(); - g.FocusedWindow = NULL; + g.NavWindow = NULL; g.HoveredWindow = NULL; g.HoveredRootWindow = NULL; for (int i = 0; i < g.Settings.Size; i++) @@ -3156,7 +3153,7 @@ void ImGui::EndFrame() // Click to focus window and start moving (after we're done with all our widgets) if (g.ActiveId == 0 && g.HoveredId == 0 && g.IO.MouseClicked[0]) { - if (!(g.FocusedWindow && !g.FocusedWindow->WasActive && g.FocusedWindow->Active)) // Unless we just made a popup appear + if (!(g.NavWindow && !g.NavWindow->WasActive && g.NavWindow->Active)) // Unless we just made a popup appear { if (g.HoveredRootWindow != NULL) { @@ -3173,7 +3170,7 @@ void ImGui::EndFrame() SetActiveIDNoNav(g.MovedWindowMoveId, g.HoveredRootWindow); } } - else if (g.FocusedWindow != NULL && GetFrontMostModalRootWindow() == NULL) + else if (g.NavWindow != NULL && GetFrontMostModalRootWindow() == NULL) { // Clicking on void disable focus FocusWindow(NULL); @@ -3626,7 +3623,7 @@ bool ImGui::IsAnyWindowHovered() bool ImGui::IsAnyWindowFocused() { - return GImGui->FocusedWindow != NULL; + return GImGui->NavWindow != NULL; } bool ImGui::IsAnyWindowHoveredAtPos(const ImVec2& pos) @@ -3981,7 +3978,7 @@ static void CloseInactivePopups() // When popups are stacked, clicking on a lower level popups puts focus back to it and close popups above it. // Don't close our own child popup windows int n = 0; - if (g.FocusedWindow) + if (g.NavWindow) { for (n = 0; n < g.OpenPopupStack.Size; n++) { @@ -3994,7 +3991,7 @@ static void CloseInactivePopups() bool has_focus = false; for (int m = n; m < g.OpenPopupStack.Size && !has_focus; m++) - has_focus = (g.OpenPopupStack[m].Window && g.OpenPopupStack[m].Window->RootWindow == g.FocusedWindow->RootWindow); + has_focus = (g.OpenPopupStack[m].Window && g.OpenPopupStack[m].Window->RootWindow == g.NavWindow->RootWindow); if (!has_focus) break; } @@ -4753,7 +4750,7 @@ bool ImGui::Begin(const char* name, bool* p_open, const ImVec2& size_on_first_us if (window->Collapsed) { // Title bar only - const bool is_focused = g.FocusedWindow && window->RootNonPopupWindow == g.FocusedWindow->RootNonPopupWindow && !g.NavDisableHighlight; + const bool is_focused = g.NavWindow && window->RootNonPopupWindow == g.NavWindow->RootNonPopupWindow && !g.NavDisableHighlight; RenderFrame(title_bar_rect.GetTL(), title_bar_rect.GetBR(), GetColorU32(is_focused ? ImGuiCol_TitleBgActive : ImGuiCol_TitleBgCollapsed), true, window_rounding); } else @@ -4832,7 +4829,7 @@ bool ImGui::Begin(const char* name, bool* p_open, const ImVec2& size_on_first_us window->DrawList->AddRectFilled(window->Pos+ImVec2(0,window->TitleBarHeight()), window->Pos+window->Size, ColorConvertFloat4ToU32(bg_color), window_rounding, (flags & ImGuiWindowFlags_NoTitleBar) ? 15 : 4|8); // Title bar - const bool is_focused = g.FocusedWindow && window->RootNonPopupWindow == g.FocusedWindow->RootNonPopupWindow; + const bool is_focused = g.NavWindow && window->RootNonPopupWindow == g.NavWindow->RootNonPopupWindow; if (!(flags & ImGuiWindowFlags_NoTitleBar)) window->DrawList->AddRectFilled(title_bar_rect.GetTL(), title_bar_rect.GetBR(), GetColorU32(is_focused ? ImGuiCol_TitleBgActive : ImGuiCol_TitleBg), window_rounding, 1|2); @@ -5164,7 +5161,7 @@ void ImGui::FocusWindow(ImGuiWindow* window) { ImGuiContext& g = *GImGui; - if (g.FocusedWindow != window) + if (g.NavWindow != window) { g.NavId = window ? window->NavLastId : 0; // Restore NavId g.NavIdIsAlive = false; @@ -5176,7 +5173,6 @@ void ImGui::FocusWindow(ImGuiWindow* window) } // Passing NULL allow to disable keyboard focus - g.FocusedWindow = window; if (!window) return; @@ -5467,19 +5463,19 @@ bool ImGui::IsWindowHovered() bool ImGui::IsWindowFocused() { ImGuiContext& g = *GImGui; - return g.FocusedWindow == g.CurrentWindow; + return g.NavWindow == g.CurrentWindow; } bool ImGui::IsRootWindowFocused() { ImGuiContext& g = *GImGui; - return g.FocusedWindow == g.CurrentWindow->RootWindow; + return g.NavWindow == g.CurrentWindow->RootWindow; } bool ImGui::IsRootWindowOrAnyChildFocused() { ImGuiContext& g = *GImGui; - return g.FocusedWindow && g.FocusedWindow->RootWindow == g.CurrentWindow->RootWindow; + return g.NavWindow && g.NavWindow->RootWindow == g.CurrentWindow->RootWindow; } bool ImGui::IsRootWindowOrAnyChildHovered() @@ -6144,8 +6140,8 @@ static inline bool IsWindowContentHoverable(ImGuiWindow* window) { // An active popup disable hovering on other windows (apart from its own children) ImGuiContext& g = *GImGui; - if (ImGuiWindow* focused_window = g.FocusedWindow) - if (ImGuiWindow* focused_root_window = focused_window->RootWindow) + if (g.NavWindow) + if (ImGuiWindow* focused_root_window = g.NavWindow->RootWindow) if ((focused_root_window->Flags & ImGuiWindowFlags_Popup) != 0 && focused_root_window->WasActive && focused_root_window != window->RootWindow) return false; @@ -9623,13 +9619,13 @@ bool ImGui::BeginMenu(const char* label, bool enabled) const ImGuiID id = window->GetID(label); ImVec2 label_size = CalcTextSize(label, NULL, true); - ImGuiWindow* backed_focused_window = g.FocusedWindow; bool pressed; bool menu_is_open = IsPopupOpen(id); bool menuset_is_open = !(window->Flags & ImGuiWindowFlags_Popup) && (g.OpenPopupStack.Size > g.CurrentPopupStack.Size && g.OpenPopupStack[g.CurrentPopupStack.Size].ParentMenuSet == window->GetID("##menus")); + ImGuiWindow* backed_nav_window = g.NavWindow; if (menuset_is_open) - g.FocusedWindow = window; + g.NavWindow = window; ImVec2 popup_pos, pos = window->DC.CursorPos; if (window->DC.LayoutType == ImGuiLayoutType_Horizontal) @@ -9656,7 +9652,7 @@ bool ImGui::BeginMenu(const char* label, bool enabled) bool hovered = enabled && IsHovered(window->DC.LastItemRect, id); if (menuset_is_open) - g.FocusedWindow = backed_focused_window; + g.NavWindow = backed_nav_window; bool want_open = false, want_close = false; if (window->Flags & (ImGuiWindowFlags_Popup|ImGuiWindowFlags_ChildMenu)) @@ -10596,12 +10592,11 @@ void ImGui::ShowMetricsWindow(bool* p_open) } if (ImGui::TreeNode("Basic state")) { - ImGui::Text("FocusedWindow: '%s'", g.FocusedWindow ? g.FocusedWindow->Name : "NULL"); ImGui::Text("HoveredWindow: '%s'", g.HoveredWindow ? g.HoveredWindow->Name : "NULL"); ImGui::Text("HoveredRootWindow: '%s'", g.HoveredRootWindow ? g.HoveredRootWindow->Name : "NULL"); ImGui::Text("HoveredId: 0x%08X/0x%08X", g.HoveredId, g.HoveredIdPreviousFrame); // Data is "in-flight" so depending on when the Metrics window is called we may see current frame information or not ImGui::Text("ActiveId: 0x%08X/0x%08X, ActiveIdWindow: %s", g.ActiveId, g.ActiveIdPreviousFrame, g.ActiveIdWindow ? g.ActiveIdWindow->Name : "NULL"); - ImGui::Text("NavId: 0x%08X, NavWindow: '%s'", g.NavId, g.NavWindow ? g.NavWindow->Name : "NULL"); + ImGui::Text("NavWindow: '%s', NavId: 0x%08X", g.NavWindow ? g.NavWindow->Name : "NULL", g.NavId); ImGui::Text("NavRefRectRel: (%.1f,%.1f)(%.1f,%.1f)", g.NavRefRectRel.Min.x, g.NavRefRectRel.Min.y, g.NavRefRectRel.Max.x, g.NavRefRectRel.Max.y); ImGui::Text("NavUsable: %d, NavActive: %d", g.IO.NavUsable, g.IO.NavActive); ImGui::Text("NavDisableHighlight: %d, NavDisableMouseHover: %d", g.NavDisableHighlight, g.NavDisableMouseHover); diff --git a/imgui_internal.h b/imgui_internal.h index b8d211cad7b2..60aa32154e93 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -378,7 +378,6 @@ struct ImGuiContext ImVector WindowsSortBuffer; ImVector CurrentWindowStack; ImGuiWindow* CurrentWindow; // Being drawn into - ImGuiWindow* FocusedWindow; // Will catch keyboard inputs ImGuiWindow* HoveredWindow; // Will catch mouse inputs ImGuiWindow* HoveredRootWindow; // Will catch mouse inputs (for focus/move only) ImGuiID HoveredId; // Hovered widget @@ -404,11 +403,11 @@ struct ImGuiContext ImVector CurrentPopupStack; // Which level of BeginPopup() we are in (reset every frame) // Navigation data (for gamepad/keyboard) - ImGuiID NavId; // Nav/focused widget for navigation + ImGuiWindow* NavWindow; // Nav/focused window for navigation + ImGuiID NavId; // Nav/focused item for navigation ImGuiID NavActivateId, NavInputId; // ~~ IsKeyPressedMap(ImGuiKey_NavActive) ? NavId : 0, etc. (to make widget code terser) ImGuiID NavTabbedId; // ImRect NavRefRectRel, NavScoringRectScreen;// Reference rectangle, in window space. Modified rectangle for directional navigation scoring, in screen space. - ImGuiWindow* NavWindow; // ImGuiWindow* NavWindowingTarget; float NavWindowingDisplayAlpha; bool NavWindowingToggleLayer; @@ -497,7 +496,6 @@ struct ImGuiContext FrameCount = 0; FrameCountEnded = FrameCountRendered = -1; CurrentWindow = NULL; - FocusedWindow = NULL; HoveredWindow = NULL; HoveredRootWindow = NULL; HoveredId = 0; @@ -515,9 +513,9 @@ struct ImGuiContext MovedWindowMoveId = 0; SettingsDirtyTimer = 0.0f; + NavWindow = NULL; NavId = NavActivateId = NavInputId = NavTabbedId = 0; NavRefRectRel = NavScoringRectScreen = ImRect(); - NavWindow = NULL; NavWindowingTarget = NULL; NavWindowingDisplayAlpha = 0.0f; NavWindowingToggleLayer = false; @@ -748,7 +746,7 @@ struct IMGUI_API ImGuiWindow ImRect TitleBarRect() const { return ImRect(Pos, ImVec2(Pos.x + SizeFull.x, Pos.y + TitleBarHeight())); } float MenuBarHeight() const { return (Flags & ImGuiWindowFlags_MenuBar) ? CalcFontSize() + GImGui->Style.FramePadding.y * 2.0f : 0.0f; } ImRect MenuBarRect() const { float y1 = Pos.y + TitleBarHeight(); return ImRect(Pos.x, y1, Pos.x + SizeFull.x, y1 + MenuBarHeight()); } - bool IsNavigableTo() const { return Active && this == RootNonPopupWindow && (!(Flags & ImGuiWindowFlags_NoNavFocus) || this == GImGui->FocusedWindow); } + bool IsNavigableTo() const { return Active && this == RootNonPopupWindow && (!(Flags & ImGuiWindowFlags_NoNavFocus) || this == GImGui->NavWindow); } }; //----------------------------------------------------------------------------- From a154625a5657975b43d2559bc786f07cbab0faa5 Mon Sep 17 00:00:00 2001 From: ocornut Date: Sun, 31 Jul 2016 13:40:14 +0200 Subject: [PATCH 065/823] Nav: Not exposing ImGuiWindowFlags_NavFlattened because it requires much more work (#323) --- imgui.cpp | 12 ++++++------ imgui.h | 2 +- imgui_demo.cpp | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index dd3ec4a94cd9..851d93fa8c32 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -4179,7 +4179,7 @@ bool ImGui::BeginChild(const char* str_id, const ImVec2& size_arg, bool border, // Process navigation-in immediately so NavInit can run on first frame const ImGuiID id = parent_window->GetChildID(child_window); - if (!(flags & ImGuiWindowFlags_NavFlattened) && (child_window->DC.NavLayerActiveFlags != 0 || child_window->DC.NavHasScroll) && GImGui->NavActivateId == id) + if (/*!(flags & ImGuiWindowFlags_NavFlattened) &&*/ (child_window->DC.NavLayerActiveFlags != 0 || child_window->DC.NavHasScroll) && GImGui->NavActivateId == id) { FocusWindow(child_window); NavInitWindow(child_window, false); @@ -4220,7 +4220,7 @@ void ImGui::EndChild() ImGuiID id = parent_window->GetChildID(window); ImRect bb(parent_window->DC.CursorPos, parent_window->DC.CursorPos + sz); ItemSize(sz); - if (!(window->Flags & ImGuiWindowFlags_NavFlattened) && (window->DC.NavLayerActiveFlags != 0 || window->DC.NavHasScroll)) + if (/*!(window->Flags & ImGuiWindowFlags_NavFlattened) &&*/ (window->DC.NavLayerActiveFlags != 0 || window->DC.NavHasScroll)) { ItemAdd(bb, &id); RenderNavHighlight(id, bb); @@ -4420,8 +4420,8 @@ bool ImGui::Begin(const char* name, bool* p_open, const ImVec2& size_on_first_us if (flags & ImGuiWindowFlags_NoInputs) flags |= ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize; - if (flags & ImGuiWindowFlags_NavFlattened) - IM_ASSERT(flags & ImGuiWindowFlags_ChildWindow); + //if (flags & ImGuiWindowFlags_NavFlattened) + // IM_ASSERT(flags & ImGuiWindowFlags_ChildWindow); // Find or create bool window_is_new = false; @@ -4520,8 +4520,8 @@ bool ImGui::Begin(const char* name, bool* p_open, const ImVec2& size_on_first_us window->RootWindow = g.CurrentWindowStack[root_idx]; window->RootNonPopupWindow = g.CurrentWindowStack[root_non_popup_idx]; // Used to display TitleBgActive color and for selecting which window to use for NavWindowing window->RootNavWindow = window; - while (window->RootNavWindow->Flags & ImGuiWindowFlags_NavFlattened) - window->RootNavWindow = window->RootNavWindow->ParentWindow; + //while (window->RootNavWindow->Flags & ImGuiWindowFlags_NavFlattened) + // window->RootNavWindow = window->RootNavWindow->ParentWindow; // When reusing window again multiple times a frame, just append content (don't need to setup again) if (first_begin_of_the_frame) diff --git a/imgui.h b/imgui.h index d3719ad739ef..3745d5f4caa9 100644 --- a/imgui.h +++ b/imgui.h @@ -511,7 +511,7 @@ enum ImGuiWindowFlags_ ImGuiWindowFlags_AlwaysUseWindowPadding = 1 << 16, // Ensure child windows without border uses style.WindowPadding (ignored by default for non-bordered child windows, because more convenient) ImGuiWindowFlags_NoNavFocus = 1 << 17, // No focusing of this window with gamepad/keyboard navigation ImGuiWindowFlags_NoNavInputs = 1 << 18, // No gamepad/keyboard navigation within the window - ImGuiWindowFlags_NavFlattened = 1 << 19, // Allow gamepad/keyboard navigation to cross over parent border to this child (only use on child that have no scrolling!) + //ImGuiWindowFlags_NavFlattened = 1 << 19, // Allow gamepad/keyboard navigation to cross over parent border to this child (only use on child that have no scrolling!) // [Internal] ImGuiWindowFlags_ChildWindow = 1 << 22, // Don't use! For internal use by BeginChild() ImGuiWindowFlags_ComboBox = 1 << 23, // Don't use! For internal use by ComboBox() diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 07b7dea9d091..7ec06dacd9c5 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -2443,7 +2443,7 @@ static void ShowExampleAppLayout(bool* p_open) ImGui::Separator(); ImGui::TextWrapped("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. "); ImGui::EndChild(); - ImGui::BeginChild("buttons", ImVec2(0,0), false, ImGuiWindowFlags_NavFlattened); + ImGui::BeginChild("buttons"); if (ImGui::Button("Revert")) {} ImGui::SameLine(); if (ImGui::Button("Save")) {} From 1ecbf73c972ca48ec7ef4d36409287e87a5e3e26 Mon Sep 17 00:00:00 2001 From: ocornut Date: Sun, 31 Jul 2016 15:41:51 +0200 Subject: [PATCH 066/823] Nav: working on early bits of documentation (#323) --- imgui.cpp | 190 ++++++++++++++++++++++++++++++++---------------------- 1 file changed, 112 insertions(+), 78 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 851d93fa8c32..a9a79fd280d5 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -51,22 +51,21 @@ Designed for developers and content-creators, not the typical end-user! Some of the weaknesses includes: - doesn't look fancy, doesn't animate - limited layout features, intricate layouts are typically crafted in code - - occasionally uses statically sized buffers for string manipulations - won't crash, but some very long pieces of text may be clipped. functions like ImGui::TextUnformatted() don't have such restriction. END-USER GUIDE ============== - - double-click title bar to collapse window - - click upper right corner to close a window, available when 'bool* p_open' is passed to ImGui::Begin() - - click and drag on lower right corner to resize window - - click and drag on any empty space to move window - - double-click/double-tap on lower right corner grip to auto-fit to content + - Double-click title bar to collapse window + - Click upper right corner to close a window, available when 'bool* p_open' is passed to ImGui::Begin() + - Click and drag on lower right corner to resize window + - Click and drag on any empty space to move window + - Double-click/double-tap on lower right corner grip to auto-fit to content - TAB/SHIFT+TAB to cycle through keyboard editable fields - - use mouse wheel to scroll - - use CTRL+mouse wheel to zoom window contents (if IO.FontAllowScaling is true) + - Use mouse wheel to scroll + - Use CTRL+mouse wheel to zoom window contents (if io.FontAllowScaling is true) - CTRL+Click on a slider or drag box to input value as text - - text editor: + - Text editor: - Hold SHIFT or use mouse to select text. - CTRL+Left/Right to word jump - CTRL+Shift+Left/Right to select words @@ -75,75 +74,109 @@ - CTRL+Z,CTRL+Y to undo/redo - ESCAPE to revert text to its original value - You can apply arithmetic operators +,*,/ on numerical values. Use +- to subtract (because - would set a negative value!) + - Controls are automatically adjusted for OSX to match standard OSX text editing operations. + - Gamepad/keyboard navigation are in beta-phase, see Programmer Guide below. PROGRAMMER GUIDE ================ - - read the FAQ below this section! - - your code creates the UI, if your code doesn't run the UI is gone! == very dynamic UI, no construction/destructions steps, less data retention on your side, no state duplication, less sync, less bugs. - - call and read ImGui::ShowTestWindow() for demo code demonstrating most features. - - see examples/ folder for standalone sample applications. Prefer reading examples/opengl_example/ first as it is the simplest. - you may be able to grab and copy a ready made imgui_impl_*** file from the examples/. - - customization: PushStyleColor()/PushStyleVar() or the style editor to tweak the look of the interface (e.g. if you want a more compact UI or a different color scheme). - - - getting started: - - init: call ImGui::GetIO() to retrieve the ImGuiIO structure and fill the fields marked 'Settings'. - - init: call io.Fonts->GetTexDataAsRGBA32(...) and load the font texture pixels into graphics memory. - - every frame: - 1/ in your mainloop or right after you got your keyboard/mouse info, call ImGui::GetIO() and fill the fields marked 'Input' - 2/ call ImGui::NewFrame() as early as you can! - 3/ use any ImGui function you want between NewFrame() and Render() - 4/ call ImGui::Render() as late as you can to end the frame and finalize render data. it will call your RenderDrawListFn handler that you set in the IO structure. - (if you don't need to render, you still need to call Render() and ignore the callback, or call EndFrame() instead. if you call neither some aspects of windows focusing/moving will appear broken.) - - all rendering information are stored into command-lists until ImGui::Render() is called. - - ImGui never touches or know about your GPU state. the only function that knows about GPU is the RenderDrawListFn handler that you provide. - - effectively it means you can create widgets at any time in your code, regardless of considerations of being in "update" vs "render" phases of your own application. - - refer to the examples applications in the examples/ folder for instruction on how to setup your code. - - a typical application skeleton may be: - - // Application init - ImGuiIO& io = ImGui::GetIO(); - io.DisplaySize.x = 1920.0f; - io.DisplaySize.y = 1280.0f; - io.IniFilename = "imgui.ini"; - io.RenderDrawListsFn = my_render_function; // Setup a render function, or set to NULL and call GetDrawData() after Render() to access the render data. - // TODO: Fill others settings of the io structure - - // Load texture atlas - // There is a default font so you don't need to care about choosing a font yet - unsigned char* pixels; - int width, height; - io.Fonts->GetTexDataAsRGBA32(pixels, &width, &height); - // TODO: At this points you've got a texture pointed to by 'pixels' and you need to upload that your your graphic system - // TODO: Store your texture pointer/identifier (whatever your engine uses) in 'io.Fonts->TexID' - - // Application main loop - while (true) - { - // 1) get low-level inputs (e.g. on Win32, GetKeyboardState(), or poll your events, etc.) - // TODO: fill all fields of IO structure and call NewFrame - ImGuiIO& io = ImGui::GetIO(); - io.DeltaTime = 1.0f/60.0f; - io.MousePos = mouse_pos; - io.MouseDown[0] = mouse_button_0; - io.MouseDown[1] = mouse_button_1; - io.KeysDown[i] = ... - - // 2) call NewFrame(), after this point you can use ImGui::* functions anytime - ImGui::NewFrame(); - - // 3) most of your application code here - MyGameUpdate(); // may use any ImGui functions, e.g. ImGui::Begin("My window"); ImGui::Text("Hello, world!"); ImGui::End(); - MyGameRender(); // may use any ImGui functions - - // 4) render & swap video buffers - ImGui::Render(); - SwapBuffers(); - } - - - You can read back 'io.WantCaptureMouse', 'io.WantCaptureKeybord' etc. flags from the IO structure to tell how ImGui intends to use your - inputs and to know if you should share them or hide them from the rest of your application. Read the FAQ below for more information. + READ FIRST + + - Read the FAQ below this section! + - Your code creates the UI, if your code doesn't run the UI is gone! == very dynamic UI, no construction/destructions steps, less data retention on your side, no state duplication, less sync, less bugs. + - Call and read ImGui::ShowTestWindow() for demo code demonstrating most features. + - Customization: PushStyleColor()/PushStyleVar() or the style editor to tweak the look of the interface (e.g. if you want a more compact UI or a different color scheme). + + GETTING STARTED WITH INTEGRATING IN YOUR ENGINE + + - See examples/ folder for standalone sample applications. Prefer reading examples/opengl_example/ first as it is the simplest. + You may be able to grab and copy a ready made imgui_impl_*** file from the examples/. + - Init: call ImGui::GetIO() to retrieve the ImGuiIO structure and fill the fields marked 'Settings'. + - Init: call io.Fonts->GetTexDataAsRGBA32(...) and load the font texture pixels into graphics memory. + - Every frame: + 1/ in your mainloop or right after you got your keyboard/mouse info, call ImGui::GetIO() and fill the fields marked 'Input' + 2/ call ImGui::NewFrame() as early as you can! + 3/ use any ImGui function you want between NewFrame() and Render() + 4/ call ImGui::Render() as late as you can to end the frame and finalize render data. it will call your RenderDrawListFn handler that you set in the IO structure. + (if you don't need to render, you still need to call Render() and ignore the callback, or call EndFrame() instead. if you call neither some aspects of windows focusing/moving will appear broken.) + - All rendering information are stored into command-lists until ImGui::Render() is called. + - ImGui never touches or know about your GPU state. the only function that knows about GPU is the RenderDrawListFn handler that you provide. + - Effectively it means you can create widgets at any time in your code, regardless of considerations of being in "update" vs "render" phases of your own application. + - Refer to the examples applications in the examples/ folder for instruction on how to setup your code. + - A typical application skeleton may be: + + // Application init + ImGuiIO& io = ImGui::GetIO(); + io.DisplaySize.x = 1920.0f; + io.DisplaySize.y = 1280.0f; + io.IniFilename = "imgui.ini"; + io.RenderDrawListsFn = my_render_function; // Setup a render function, or set to NULL and call GetDrawData() after Render() to access the render data. + // TODO: Fill others settings of the io structure + + // Load texture atlas (there is a default font so you don't need to care about choosing a font yet) + unsigned char* pixels; + int width, height; + io.Fonts->GetTexDataAsRGBA32(pixels, &width, &height); + // TODO: At this points you've got a texture pointed to by 'pixels' and you need to upload that your your graphic system + // TODO: Store your texture pointer/identifier (whatever your engine uses) in 'io.Fonts->TexID' + + // Application main loop + while (true) + { + // 1) get low-level inputs (e.g. on Win32, GetKeyboardState(), or poll your events, etc.) + // TODO: fill all fields of IO structure and call NewFrame + ImGuiIO& io = ImGui::GetIO(); + io.DeltaTime = 1.0f/60.0f; + io.MousePos = mouse_pos; + io.MouseDown[0] = mouse_button_0; + io.MouseDown[1] = mouse_button_1; + io.KeysDown[i] = ... + + // 2) call NewFrame(), after this point you can use ImGui::* functions anytime + ImGui::NewFrame(); + + // 3) most of your application code here + MyGameUpdate(); // may use any ImGui functions, e.g. ImGui::Begin("My window"); ImGui::Text("Hello, world!"); ImGui::End(); + MyGameRender(); // may use any ImGui functions + + // 4) render & swap video buffers + ImGui::Render(); + SwapBuffers(); + } + + - You can read back 'io.WantCaptureMouse', 'io.WantCaptureKeybord' etc. flags from the IO structure to tell how ImGui intends to use your + inputs and to know if you should share them or hide them from the rest of your application. Read the FAQ below for more information. + + USING GAMEPAD/KEYBOARD NAVIGATION [BETA] + + - Gamepad/keyboard navigation support is available, it is currently in Beta and has issues. Your feedback and bug reports are welcome. + - See https://github.com/ocornut/imgui/issues/323 for discussion thread and ask questions. + - The current primary focus is to support game controllers. + - Consider emulating a mouse cursor with DualShock4 touch pad or a spare analog stick as a mouse-emulation fallback. + - Consider using Synergy host (on your computer) + uSynergy.c (in your console/tablet/phone app) to use PC mouse/keyboard. + - Being able to share and transition inputs between imgui navigation and your own game/application is tricky, and may requires further work on imgui. + For gamepad use, the easiest approach is to go all-or-nothing, with a buttons combo that toggle your inputs between imgui and your game/application. + For more advanced uses, you may want to use: + - io.NavUsable: true when a window is focused and it doesn't have the ImGuiWindowFlags_NoNavInputs flag set. + - io.NavActive: true when the navigation cursor is visible (and usually goes false when mouse is used). + - query focus information with IsWindowFocused(), IsAnyWindowFocused(), IsAnyItemFocused() functions. + The reality is more complex than what those flags can express. Please discuss your issues and usage scenario in the thread above. + As we head toward more keyboard-oriented development this aspect will need to be improved. + - It is recommended that you enable the 'io.NavMovesMouse' option. Enabling it instructs ImGui that it can request moving your move cursor to track navigated items and ease readability. + When enabled and using directional navigation (with d-pad or arrow keys), the NewFrame() functions may alter 'io.MousePos' and set 'io.WantMoveMouse' to notify you that it did so. + When that happens your back-end will need to move the OS mouse cursor on the _next_ frame. The examples binding in examples/ do that. + + // Application init + io.NavMovesMouse = true; + + // Application main loop + if (io.WantMoveMouse) + MyFuncToSetMousePosition(io.MousePos.x, io.MousePos.y); + ImGui::NewFrame(); + + In a setup when you may not have easy control over the mouse cursor (e.g. uSynergy doesn't expose changing remote mouse cursor), + you might want to set a boolean to request ignoring your other external mouse positions until they move again. API BREAKING CHANGES @@ -266,7 +299,7 @@ Q: How can I help? A: - If you are experienced enough with ImGui and with C/C++, look at the todo list and see how you want/can help! - - Become a Patron/donate. Convince your company to become a Patron or provide serious funding for development time. + - Become a Patron/donate! Convince your company to become a Patron or provide serious funding for development time! See http://www.patreon.com/imgui Q: How do I update to a newer version of ImGui? A: Overwrite the following files: @@ -480,9 +513,9 @@ - window/tooltip: allow to set the width of a tooltip to allow TextWrapped() etc. while keeping the height automatic. - window: increase minimum size of a window with menus or fix the menu rendering so that it doesn't look odd. - draw-list: maintaining bounding box per command would allow to merge draw command when clipping isn't relied on (typical non-scrolling window or non-overflowing column would merge with previous command). -!- scrolling: allow immediately effective change of scroll if we haven't appended items yet +!- scrolling: allow immediately effective change of scroll after Begin() if we haven't appended items yet - splitter/separator: formalize the splitter idiom into an official api (we want to handle n-way split) (#319) - - widgets: display mode: widget-label, label-widget (aligned on column or using fixed size), label-newline-tab-widget etc. + - widgets: display mode: widget-label, label-widget (aligned on column or using fixed size), label-newline-tab-widget etc. (#395) - widgets: clean up widgets internal toward exposing everything. - widgets: add disabled and read-only modes (#211) - main: considering adding an Init() function? some constructs are awkward in the implementation because of the lack of them. @@ -532,7 +565,6 @@ - popups: border options. richer api like BeginChild() perhaps? (#197) - tooltip: tooltip that doesn't fit in entire screen seems to lose their "last prefered button" and may teleport when moving mouse - menus: local shortcuts, global shortcuts (#456, #126) - - menus: icons - menus: menubars: some sort of priority / effect of main menu-bar on desktop size? - menus: calling BeginMenu() twice with a same name doesn't seem to append nicely - statusbar: add a per-window status bar helper similar to what menubar does. @@ -563,6 +595,7 @@ - textwrapped: figure out better way to use TextWrapped() in an always auto-resize context (tooltip, etc.) (#249) - settings: write more decent code to allow saving/loading new fields - settings: api for per-tool simple persistent data (bool,int,float,columns sizes,etc.) in .ini file + - stb: add defines to disable stb implementations - style: add window shadows. - style/optimization: store rounded corners in texture to use 1 quad per corner (filled and wireframe) to lower the cost of rounding. - style: color-box not always square? @@ -570,7 +603,7 @@ - style: try to make PushStyleVar() more robust to incorrect parameters (to be more friendly to edit & continues situation). - style/opt: PopStyleVar could be optimized by having GetStyleVar returns the type, using a table mapping stylevar enum to data type. - style: global scale setting. - - style: WindowPadding needs to be EVEN needs the 0.5 multiplier probably have a subtle effect on clip rectangle + - style: WindowPadding needs to be EVEN as the 0.5 multiplier used on this value probably have a subtle effect on clip rectangle - text: simple markup language for color change? - font: dynamic font atlas to avoid baking huge ranges into bitmap and make scaling easier. - font: small opt: for monospace font (like the defalt one) we can trim IndexXAdvance as long as trailing value is == FallbackXAdvance @@ -583,6 +616,7 @@ - log: let user copy any window content to clipboard easily (CTRL+C on windows? while moving it? context menu?). code is commented because it fails with multiple Begin/End pairs. - filters: set a current filter that tree node can automatically query to hide themselves - filters: handle wildcards (with implicit leading/trailing *), regexps + - filters: fuzzy matches (may use code at blog.forrestthewoods.com/4cffeed33fdb) - shortcuts: add a shortcut api, e.g. parse "&Save" and/or "Save (CTRL+S)", pass in to widgets or provide simple ways to use (button=activate, input=focus) !- keyboard: tooltip & combo boxes are messing up / not honoring keyboard tabbing - keyboard: full keyboard navigation and focus. (#323) From e9c881e4de58154b42decc51e4d413dba673e671 Mon Sep 17 00:00:00 2001 From: ocornut Date: Sun, 31 Jul 2016 16:07:58 +0200 Subject: [PATCH 067/823] Nav: fixed using NavMenu/windowing select when no window is already focused + cleanup code (#323) --- imgui.cpp | 54 ++++++++++++++++++++++++++++++++---------------- imgui_internal.h | 1 - 2 files changed, 36 insertions(+), 19 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index a9a79fd280d5..e0f5a2426eff 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2358,6 +2358,27 @@ static void SetNavIdMoveMouse(ImGuiID id, const ImRect& rect_rel) g.NavDisableMouseHover = true; } +static int FindWindowIndex(ImGuiWindow* window) // FIXME-OPT O(N) +{ + ImGuiContext& g = *GImGui; + for (int i = g.Windows.Size-1; i >= 0; i--) + if (g.Windows[i] == window) + return i; + return -1; +} + +static ImGuiWindow* FindWindowNavigable(int i_start, int i_stop, int dir) // FIXME-OPT O(N) +{ + ImGuiContext& g = *GImGui; + for (int i = i_start; i >= 0 && i < g.Windows.Size && i != i_stop; i += dir) + { + ImGuiWindow* window = g.Windows[i]; + if (window->Active && window == window->RootNonPopupWindow && (!(window->Flags & ImGuiWindowFlags_NoNavFocus) || window == g.NavWindow)) + return window; + } + return NULL; +} + static void NavUpdate() { ImGuiContext& g = *GImGui; @@ -2432,11 +2453,17 @@ static void NavUpdate() } // Navigation windowing mode (change focus, move/resize window) - if (!g.NavWindowingTarget && g.NavWindow && IsKeyPressedMap(ImGuiKey_NavMenu, false)) + if (!g.NavWindowingTarget && IsKeyPressedMap(ImGuiKey_NavMenu, false)) { - g.NavWindowingTarget = g.NavWindow->RootNonPopupWindow; - g.NavWindowingDisplayAlpha = 0.0f; - g.NavWindowingToggleLayer = true; + ImGuiWindow* window = g.NavWindow; + if (!window) + window = FindWindowNavigable(g.Windows.Size-1, -1, -1); + if (window) + { + g.NavWindowingTarget = window->RootNonPopupWindow; + g.NavWindowingDisplayAlpha = 0.0f; + g.NavWindowingToggleLayer = true; + } } if (g.NavWindowingTarget) { @@ -2450,20 +2477,11 @@ static void NavUpdate() int focus_change_dir = IsKeyPressedMap(ImGuiKey_NavTweakFaster, true) ? -1 : IsKeyPressedMap(ImGuiKey_NavTweakSlower, true) ? +1 : 0; if (focus_change_dir != 0 && !(g.NavWindowingTarget->Flags & ImGuiWindowFlags_Modal)) { - // FIXME-NAVIGATION FIXME-OPT: Code is absolutely hideous. Perhaps we should maintain a intrusive linked-list of visible windows. - int i_current = -1; - for (int i = g.Windows.Size-1; i >= 0 && i_current == -1; i--) - if (g.Windows[i] == g.NavWindowingTarget) - i_current = i; - int i_target = -1; - for (int i = i_current+focus_change_dir; i >= 0 && i < g.Windows.Size && i_target == -1; i += focus_change_dir) - if (g.Windows[i]->IsNavigableTo()) - i_target = i; - for (int i = (focus_change_dir < 0) ? (g.Windows.Size-1) : 0; i >= 0 && i < g.Windows.Size && i_target == -1 && i_target != i_current; i += focus_change_dir) - if (g.Windows[i]->IsNavigableTo()) - i_target = i; - if (i_target != -1 && i_target != i_current) // i_target might be == i_current in rare situation where we only have 1 navigable window - g.NavWindowingTarget = g.Windows[i_target]; + const int i_current = FindWindowIndex(g.NavWindowingTarget); + ImGuiWindow* window_target = FindWindowNavigable(i_current + focus_change_dir, -1, focus_change_dir); + if (!window_target) + window_target = FindWindowNavigable((focus_change_dir < 0) ? (g.Windows.Size-1) : 0, i_current, focus_change_dir); + g.NavWindowingTarget = window_target; g.NavWindowingToggleLayer = false; g.NavWindowingDisplayAlpha = 1.0f; } diff --git a/imgui_internal.h b/imgui_internal.h index 60aa32154e93..35a206f1853e 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -746,7 +746,6 @@ struct IMGUI_API ImGuiWindow ImRect TitleBarRect() const { return ImRect(Pos, ImVec2(Pos.x + SizeFull.x, Pos.y + TitleBarHeight())); } float MenuBarHeight() const { return (Flags & ImGuiWindowFlags_MenuBar) ? CalcFontSize() + GImGui->Style.FramePadding.y * 2.0f : 0.0f; } ImRect MenuBarRect() const { float y1 = Pos.y + TitleBarHeight(); return ImRect(Pos.x, y1, Pos.x + SizeFull.x, y1 + MenuBarHeight()); } - bool IsNavigableTo() const { return Active && this == RootNonPopupWindow && (!(Flags & ImGuiWindowFlags_NoNavFocus) || this == GImGui->NavWindow); } }; //----------------------------------------------------------------------------- From 8b190f11006d4588c1ad2bec5ff51a197c8ecd6f Mon Sep 17 00:00:00 2001 From: ocornut Date: Sun, 31 Jul 2016 16:12:01 +0200 Subject: [PATCH 068/823] Nav: quick tap on NavMenu with no focused window doesn't focus one (holding still does) (#323) --- imgui.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index e0f5a2426eff..65001eb5b362 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2501,7 +2501,7 @@ static void NavUpdate() if (!IsKeyDownMap(ImGuiKey_NavMenu)) { // Apply actual focus only when releasing the NavMenu button (until then the window was merely rendered front-most) - if (g.NavWindowingTarget && (!g.NavWindow || g.NavWindowingTarget != g.NavWindow->RootNonPopupWindow)) + if (g.NavWindowingTarget && !g.NavWindowingToggleLayer && (!g.NavWindow || g.NavWindowingTarget != g.NavWindow->RootNonPopupWindow)) { ImGui::FocusWindow(g.NavWindowingTarget); g.NavDisableHighlight = false; @@ -2511,7 +2511,7 @@ static void NavUpdate() } // Single press toggles NavLayer - if (g.NavWindowingToggleLayer) + if (g.NavWindowingToggleLayer && g.NavWindow) { if ((g.NavWindow->DC.NavLayerActiveFlags & (1<<1)) == 0 && (g.NavWindow->RootWindow->DC.NavLayerActiveFlags & (1<<1)) != 0) ImGui::FocusWindow(g.NavWindow->RootWindow); From d0801057ba42c49c397a1a997ff9579d372c1d41 Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 1 Aug 2016 20:55:54 +0200 Subject: [PATCH 069/823] Demo: Tweak handling of "animate" flag in graph demo so it doesn't keep running. --- imgui_demo.cpp | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 7ec06dacd9c5..2ad2b8f11c5d 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -774,16 +774,16 @@ void ImGui::ShowTestWindow(bool* p_open) // Tip: If your float aren't contiguous but part of a structure, you can pass a pointer to your first float and the sizeof() of your structure in the Stride parameter. static float values[90] = { 0 }; static int values_offset = 0; - if (animate) - { - static float refresh_time = ImGui::GetTime(); // Create dummy data at fixed 60 hz rate for the demo - for (; ImGui::GetTime() > refresh_time + 1.0f/60.0f; refresh_time += 1.0f/60.0f) - { - static float phase = 0.0f; - values[values_offset] = cosf(phase); - values_offset = (values_offset+1) % IM_ARRAYSIZE(values); - phase += 0.10f*values_offset; - } + static float refresh_time = 0.0f; + if (!animate || refresh_time == 0.0f) + refresh_time = ImGui::GetTime(); + while (refresh_time < ImGui::GetTime()) // Create dummy data at fixed 60 hz rate for the demo + { + static float phase = 0.0f; + values[values_offset] = cosf(phase); + values_offset = (values_offset+1) % IM_ARRAYSIZE(values); + phase += 0.10f*values_offset; + refresh_time += 1.0f/60.0f; } ImGui::PlotLines("Lines", values, IM_ARRAYSIZE(values), values_offset, "avg 0.0", -1.0f, 1.0f, ImVec2(0,80)); ImGui::PlotHistogram("Histogram", arr, IM_ARRAYSIZE(arr), 0, NULL, 0.0f, 1.0f, ImVec2(0,80)); From 36fa2b95232911bca069f582bfdac2067547452c Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 1 Aug 2016 22:23:56 +0200 Subject: [PATCH 070/823] Nav: DragBehavior removed bogus test (#323) --- imgui.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index dc1f114279d7..08c215e35081 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -7627,9 +7627,9 @@ bool ImGui::DragBehavior(const ImRect& frame_bb, ImGuiID id, float* v, float v_s if (g.ActiveIdSource == ImGuiInputSource_Nav) { adjust_delta = NavGetTweakDelta().x; - if (IsKeyDownMap(ImGuiKey_NavTweakFaster) && g.DragSpeedScaleFast >= 0.0f) + if (IsKeyDownMap(ImGuiKey_NavTweakFaster)) adjust_delta *= 10.0f; - if (IsKeyDownMap(ImGuiKey_NavTweakSlower) && g.DragSpeedScaleSlow >= 0.0f) + if (IsKeyDownMap(ImGuiKey_NavTweakSlower)) adjust_delta /= 10.0f; } adjust_delta *= v_speed; From 4e91b521ee6108d07ee5c3d3aa0eb427496614f9 Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 3 Aug 2016 20:55:54 +0200 Subject: [PATCH 071/823] Demo: Arrange some inputs panels. --- imgui_demo.cpp | 65 +++++++++++++++++++++++++------------------------- 1 file changed, 33 insertions(+), 32 deletions(-) diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 2ad2b8f11c5d..3050a2c43b88 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -1499,7 +1499,7 @@ void ImGui::ShowTestWindow(bool* p_open) ImGui::BulletText("%s", lines[i]); } - if (ImGui::CollapsingHeader("Keyboard, Mouse & Focus")) + if (ImGui::CollapsingHeader("Inputs, Navigation & Focus")) { ImGuiIO& io = ImGui::GetIO(); ImGui::Checkbox("io.NavMovesMouse", &io.NavMovesMouse); @@ -1508,6 +1508,38 @@ void ImGui::ShowTestWindow(bool* p_open) ImGui::Checkbox("io.MouseDrawCursor", &io.MouseDrawCursor); ImGui::SameLine(); ShowHelpMarker("Request ImGui to render a mouse cursor for you in software. Note that a mouse cursor rendered via regular GPU rendering will feel more laggy than hardware cursor, but will be more in sync with your other visuals."); + ImGui::Text("WantCaptureMouse: %d", io.WantCaptureMouse); + ImGui::Text("WantCaptureKeyboard: %d", io.WantCaptureKeyboard); + ImGui::Text("WantTextInput: %d", io.WantTextInput); + ImGui::Text("WantMoveMouse: %d", io.WantMoveMouse); + + if (ImGui::TreeNode("Keyboard, Mouse & Navigation State")) + { + ImGui::Text("Mouse pos: (%g, %g)", io.MousePos.x, io.MousePos.y); + ImGui::Text("Mouse down:"); for (int i = 0; i < IM_ARRAYSIZE(io.MouseDown); i++) if (io.MouseDownDuration[i] >= 0.0f) { ImGui::SameLine(); ImGui::Text("b%d (%.02f secs)", i, io.MouseDownDuration[i]); } + ImGui::Text("Mouse clicked:"); for (int i = 0; i < IM_ARRAYSIZE(io.MouseDown); i++) if (ImGui::IsMouseClicked(i)) { ImGui::SameLine(); ImGui::Text("b%d", i); } + ImGui::Text("Mouse dbl-clicked:"); for (int i = 0; i < IM_ARRAYSIZE(io.MouseDown); i++) if (ImGui::IsMouseDoubleClicked(i)) { ImGui::SameLine(); ImGui::Text("b%d", i); } + ImGui::Text("Mouse released:"); for (int i = 0; i < IM_ARRAYSIZE(io.MouseDown); i++) if (ImGui::IsMouseReleased(i)) { ImGui::SameLine(); ImGui::Text("b%d", i); } + ImGui::Text("Mouse wheel: %.1f", io.MouseWheel); + + ImGui::Text("Keys down:"); for (int i = 0; i < IM_ARRAYSIZE(io.KeysDown); i++) if (io.KeysDownDuration[i] >= 0.0f) { ImGui::SameLine(); ImGui::Text("%d (%.02f secs)", i, io.KeysDownDuration[i]); } + ImGui::Text("Keys pressed:"); for (int i = 0; i < IM_ARRAYSIZE(io.KeysDown); i++) if (ImGui::IsKeyPressed(i)) { ImGui::SameLine(); ImGui::Text("%d", i); } + ImGui::Text("Keys release:"); for (int i = 0; i < IM_ARRAYSIZE(io.KeysDown); i++) if (ImGui::IsKeyReleased(i)) { ImGui::SameLine(); ImGui::Text("%d", i); } + ImGui::Text("Keys mods: %s%s%s%s", io.KeyCtrl ? "CTRL " : "", io.KeyShift ? "SHIFT " : "", io.KeyAlt ? "ALT " : "", io.KeySuper ? "SUPER " : ""); + + ImGui::Text("NavUsable: %d, NavActive: %d", io.NavUsable, io.NavActive); + + ImGui::Button("Hovering me sets the\nkeyboard capture flag"); + if (ImGui::IsItemHovered()) + ImGui::CaptureKeyboardFromApp(true); + ImGui::SameLine(); + ImGui::Button("Holding me clears the\nthe keyboard capture flag"); + if (ImGui::IsItemActive()) + ImGui::CaptureKeyboardFromApp(false); + + ImGui::TreePop(); + } + if (ImGui::TreeNode("Tabbing")) { ImGui::Text("Use TAB/SHIFT+TAB to cycle through keyboard editable fields."); @@ -1571,37 +1603,6 @@ void ImGui::ShowTestWindow(bool* p_open) ImGui::TreePop(); } - if (ImGui::TreeNode("Keyboard & Mouse State")) - { - ImGui::Text("MousePos: (%g, %g)", io.MousePos.x, io.MousePos.y); - ImGui::Text("Mouse down:"); for (int i = 0; i < IM_ARRAYSIZE(io.MouseDown); i++) if (io.MouseDownDuration[i] >= 0.0f) { ImGui::SameLine(); ImGui::Text("b%d (%.02f secs)", i, io.MouseDownDuration[i]); } - ImGui::Text("Mouse clicked:"); for (int i = 0; i < IM_ARRAYSIZE(io.MouseDown); i++) if (ImGui::IsMouseClicked(i)) { ImGui::SameLine(); ImGui::Text("b%d", i); } - ImGui::Text("Mouse dbl-clicked:"); for (int i = 0; i < IM_ARRAYSIZE(io.MouseDown); i++) if (ImGui::IsMouseDoubleClicked(i)) { ImGui::SameLine(); ImGui::Text("b%d", i); } - ImGui::Text("Mouse released:"); for (int i = 0; i < IM_ARRAYSIZE(io.MouseDown); i++) if (ImGui::IsMouseReleased(i)) { ImGui::SameLine(); ImGui::Text("b%d", i); } - ImGui::Text("MouseWheel: %.1f", io.MouseWheel); - - ImGui::Text("Keys down:"); for (int i = 0; i < IM_ARRAYSIZE(io.KeysDown); i++) if (io.KeysDownDuration[i] >= 0.0f) { ImGui::SameLine(); ImGui::Text("%d (%.02f secs)", i, io.KeysDownDuration[i]); } - ImGui::Text("Keys pressed:"); for (int i = 0; i < IM_ARRAYSIZE(io.KeysDown); i++) if (ImGui::IsKeyPressed(i)) { ImGui::SameLine(); ImGui::Text("%d", i); } - ImGui::Text("Keys release:"); for (int i = 0; i < IM_ARRAYSIZE(io.KeysDown); i++) if (ImGui::IsKeyReleased(i)) { ImGui::SameLine(); ImGui::Text("%d", i); } - ImGui::Text("KeyMods: %s%s%s%s", io.KeyCtrl ? "CTRL " : "", io.KeyShift ? "SHIFT " : "", io.KeyAlt ? "ALT " : "", io.KeySuper ? "SUPER " : ""); - - ImGui::Text("WantCaptureMouse: %d", io.WantCaptureMouse); - ImGui::Text("WantCaptureKeyboard: %d", io.WantCaptureKeyboard); - ImGui::Text("WantTextInput: %d", io.WantTextInput); - ImGui::Text("WantMoveMouse: %d", io.WantMoveMouse); - ImGui::Text("NavUsable: %d, NavActive: %d", io.NavUsable, io.NavActive); - - ImGui::Button("Hovering me sets the\nkeyboard capture flag"); - if (ImGui::IsItemHovered()) - ImGui::CaptureKeyboardFromApp(true); - ImGui::SameLine(); - ImGui::Button("Holding me clears the\nthe keyboard capture flag"); - if (ImGui::IsItemActive()) - ImGui::CaptureKeyboardFromApp(false); - - ImGui::TreePop(); - } - if (ImGui::TreeNode("Mouse cursors")) { ImGui::Text("Hover to see mouse cursors:"); From c0dcef4e1657036905cc2b6a808a0561332ea364 Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 3 Aug 2016 21:02:27 +0200 Subject: [PATCH 072/823] Nav: Moving window with nav stick disables mouse hover (#323) --- imgui.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/imgui.cpp b/imgui.cpp index 08c215e35081..2efa6f89945a 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2493,6 +2493,7 @@ static void NavUpdate() { const float move_speed = ImFloor(600 * g.IO.DeltaTime * ImMin(g.IO.DisplayFramebufferScale.x, g.IO.DisplayFramebufferScale.y)); g.NavWindowingTarget->PosFloat += move_delta * move_speed; + g.NavDisableMouseHover = true; MarkSettingsDirty(g.NavWindowingTarget); } } From 4ccc87c91d6079b7c59c5fb18b0d7bc6173660d3 Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 3 Aug 2016 21:53:07 +0200 Subject: [PATCH 073/823] Typo in commented default-value --- imgui.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/imgui.h b/imgui.h index bee4b4652fe9..d43cd8cd2bfb 100644 --- a/imgui.h +++ b/imgui.h @@ -772,7 +772,7 @@ struct ImGuiIO float MouseDragThreshold; // = 6.0f // Distance threshold before considering we are dragging int KeyMap[ImGuiKey_COUNT]; // // Map of indices into the KeysDown[512] entries array float KeyRepeatDelay; // = 0.250f // When holding a key/button, time before it starts repeating, in seconds (for buttons in Repeat mode, etc.). - float KeyRepeatRate; // = 0.020f // When holding a key/button, rate at which it repeats, in seconds. + float KeyRepeatRate; // = 0.050f // When holding a key/button, rate at which it repeats, in seconds. bool NavMovesMouse; // = false // Directional navigation can move the mouse cursor. Updates MousePos and set WantMoveMouse=true. If enabled you MUST honor those requests in your binding, otherwise ImGui will react as if mouse is jumping around. void* UserData; // = NULL // Store your own data for retrieval by callbacks. From dcff032429c3afbca0d59e3ed68c37b60f1328a4 Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 3 Aug 2016 23:23:04 +0200 Subject: [PATCH 074/823] Nav: Moving all nav inputs to io.NavInputs[] float array, new enum labelled for gamepad. (#323) --- imgui.cpp | 188 ++++++++++++++++++++++++++--------------------- imgui.h | 50 +++++++------ imgui_demo.cpp | 3 + imgui_internal.h | 3 +- 4 files changed, 136 insertions(+), 108 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 2efa6f89945a..52cab7054f20 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -873,10 +873,9 @@ ImGuiIO::ImGuiIO() MousePos = ImVec2(-1,-1); MousePosPrev = ImVec2(-1,-1); MouseDragThreshold = 6.0f; - for (int i = 0; i < IM_ARRAYSIZE(MouseDownDuration); i++) - MouseDownDuration[i] = MouseDownDurationPrev[i] = -1.0f; - for (int i = 0; i < IM_ARRAYSIZE(KeysDownDuration); i++) - KeysDownDuration[i] = KeysDownDurationPrev[i] = -1.0f; + for (int i = 0; i < IM_ARRAYSIZE(MouseDownDuration); i++) MouseDownDuration[i] = MouseDownDurationPrev[i] = -1.0f; + for (int i = 0; i < IM_ARRAYSIZE(KeysDownDuration); i++) KeysDownDuration[i] = KeysDownDurationPrev[i] = -1.0f; + for (int i = 0; i < IM_ARRAYSIZE(NavInputsDownDuration); i++) NavInputsDownDuration[i] = -1.0f; // Set OS X style defaults based on __APPLE__ compile time flag #ifdef __APPLE__ @@ -2378,6 +2377,60 @@ static ImGuiWindow* FindWindowNavigable(int i_start, int i_stop, int dir) // FIX return NULL; } +enum ImGuiNavReadMode +{ + ImGuiNavReadMode_Down, + ImGuiNavReadMode_Pressed, + ImGuiNavReadMode_Repeat, + ImGuiNavReadMode_RepeatSlow, + ImGuiNavReadMode_RepeatFast +}; + +// FIXME-NAVIGATION: Expose navigation repeat delay/rate +static float GetNavInputAmount(ImGuiNavInput n, ImGuiNavReadMode mode) +{ + ImGuiContext& g = *GImGui; + if (mode == ImGuiNavReadMode_Down) + return g.IO.NavInputs[n]; // Instant, read analog input (0.0f..1.0f, as provided by user) + const float t = g.IO.NavInputsDownDuration[n]; // Duration pressed + if (mode == ImGuiNavReadMode_Pressed) // Return 1.0f when just pressed, no repeat, ignore analog input (we don't need it for Pressed logic) + return (t == 0.0f) ? 1.0f : 0.0f; + if (mode == ImGuiNavReadMode_Repeat) + return (float)ImGui::CalcTypematicPressedRepeatAmount(t, t - g.IO.DeltaTime, g.IO.KeyRepeatDelay * 0.80f, g.IO.KeyRepeatRate * 0.80f); + if (mode == ImGuiNavReadMode_RepeatSlow) + return (float)ImGui::CalcTypematicPressedRepeatAmount(t, t - g.IO.DeltaTime, g.IO.KeyRepeatDelay * 1.00f, g.IO.KeyRepeatRate * 2.00f); + if (mode == ImGuiNavReadMode_RepeatFast) + return (float)ImGui::CalcTypematicPressedRepeatAmount(t, t - g.IO.DeltaTime, g.IO.KeyRepeatDelay * 0.80f, g.IO.KeyRepeatRate * 0.30f); + return 0.0f; +} + +// Equivalent of IsKeyDown() for NavInputs[] +static bool IsNavInputDown(ImGuiNavInput n) +{ + return GImGui->IO.NavInputs[n] > 0.0f; +} + +// Equivalent of IsKeyPressed() for NavInputs[] +static bool IsNavInputPressed(ImGuiNavInput n, ImGuiNavReadMode mode)// = ImGuiNavReadMode_Re) +{ + return GetNavInputAmount(n, mode) > 0.0f; +} + +static ImVec2 GetNavInputAmount2d(int stick_no, ImGuiNavReadMode mode, float slow_factor = 0.0f, float fast_factor = 0.0f) +{ + IM_ASSERT(ImGuiNavInput_PadScrollUp == ImGuiNavInput_PadUp + 4); + IM_ASSERT(stick_no >= 0 && stick_no < 2); + + ImVec2 delta; + delta.x = GetNavInputAmount(ImGuiNavInput_PadRight + stick_no*4, mode) - GetNavInputAmount(ImGuiNavInput_PadLeft + stick_no*4, mode); + delta.y = GetNavInputAmount(ImGuiNavInput_PadDown + stick_no*4, mode) - GetNavInputAmount(ImGuiNavInput_PadUp + stick_no*4, mode); + if (slow_factor != 0.0f && IsNavInputDown(ImGuiNavInput_PadTweakSlow)) + delta *= slow_factor; + if (fast_factor != 0.0f && IsNavInputDown(ImGuiNavInput_PadTweakFast)) + delta *= fast_factor; + return delta; +} + static void NavUpdate() { ImGuiContext& g = *GImGui; @@ -2452,7 +2505,7 @@ static void NavUpdate() } // Navigation windowing mode (change focus, move/resize window) - if (!g.NavWindowingTarget && IsKeyPressedMap(ImGuiKey_NavMenu, false)) + if (!g.NavWindowingTarget && IsNavInputPressed(ImGuiNavInput_PadMenu, ImGuiNavReadMode_Pressed)) { ImGuiWindow* window = g.NavWindow; if (!window) @@ -2467,13 +2520,13 @@ static void NavUpdate() if (g.NavWindowingTarget) { // Visuals only appears after a brief time holding the button, so that a fast tap (to toggle NavLayer) doesn't add visual noise - const float pressed_duration = g.IO.KeysDownDuration[g.IO.KeyMap[ImGuiKey_NavMenu]]; + const float pressed_duration = g.IO.NavInputsDownDuration[ImGuiNavInput_PadMenu]; g.NavWindowingDisplayAlpha = ImMax(g.NavWindowingDisplayAlpha, ImSaturate((pressed_duration - 0.20f) / 0.05f)); g.NavWindowingToggleLayer &= (g.NavWindowingDisplayAlpha < 1.0f); // Once button is held long enough we don't consider it a tag-to-toggle-layer press anymore. // Select window to focus // FIXME-NAVIGATION: Need to clarify input semantic, naming is misleading/incorrect here. - int focus_change_dir = IsKeyPressedMap(ImGuiKey_NavTweakFaster, true) ? -1 : IsKeyPressedMap(ImGuiKey_NavTweakSlower, true) ? +1 : 0; + const int focus_change_dir = (int)IsNavInputPressed(ImGuiNavInput_PadFocusPrev, ImGuiNavReadMode_RepeatSlow) - (int)IsNavInputPressed(ImGuiNavInput_PadFocusNext, ImGuiNavReadMode_RepeatSlow); if (focus_change_dir != 0 && !(g.NavWindowingTarget->Flags & ImGuiWindowFlags_Modal)) { const int i_current = FindWindowIndex(g.NavWindowingTarget); @@ -2488,7 +2541,7 @@ static void NavUpdate() // Move window if (g.NavWindowingTarget && !(g.NavWindowingTarget->Flags & ImGuiWindowFlags_NoMove)) { - const ImVec2 move_delta = ImGui::NavGetMovingDir(1); + const ImVec2 move_delta = GetNavInputAmount2d(1, ImGuiNavReadMode_Down); if (move_delta.x != 0.0f || move_delta.y != 0.0f) { const float move_speed = ImFloor(600 * g.IO.DeltaTime * ImMin(g.IO.DisplayFramebufferScale.x, g.IO.DisplayFramebufferScale.y)); @@ -2498,7 +2551,7 @@ static void NavUpdate() } } - if (!IsKeyDownMap(ImGuiKey_NavMenu)) + if (!IsNavInputDown(ImGuiNavInput_PadMenu)) { // Apply actual focus only when releasing the NavMenu button (until then the window was merely rendered front-most) if (g.NavWindowingTarget && !g.NavWindowingToggleLayer && (!g.NavWindow || g.NavWindowingTarget != g.NavWindow->RootNonPopupWindow)) @@ -2532,7 +2585,7 @@ static void NavUpdate() g.IO.NavActive = (g.IO.NavUsable && g.NavId != 0 && !g.NavDisableHighlight) || (g.NavWindowingTarget != NULL) || g.NavInitDefaultRequest; // Process NavCancel input (to close a popup, get back to parent, clear focus) - if (IsKeyPressedMap(ImGuiKey_NavCancel)) + if (IsNavInputPressed(ImGuiNavInput_PadCancel, ImGuiNavReadMode_Pressed)) { if (g.ActiveId != 0) { @@ -2577,8 +2630,8 @@ static void NavUpdate() } } - g.NavActivateId = (g.NavId && !g.NavDisableHighlight && !g.NavWindowingTarget && g.ActiveId == 0 && IsKeyPressedMap(ImGuiKey_NavActivate)) ? g.NavId : 0; - g.NavInputId = (g.NavId && !g.NavDisableHighlight && !g.NavWindowingTarget && g.ActiveId == 0 && IsKeyPressedMap(ImGuiKey_NavInput)) ? g.NavId : 0; + g.NavActivateId = (g.NavId && !g.NavDisableHighlight && !g.NavWindowingTarget && g.ActiveId == 0 && IsNavInputPressed(ImGuiNavInput_PadActivate, ImGuiNavReadMode_Repeat)) ? g.NavId : 0; + g.NavInputId = (g.NavId && !g.NavDisableHighlight && !g.NavWindowingTarget && g.ActiveId == 0 && IsNavInputPressed(ImGuiNavInput_PadInput, ImGuiNavReadMode_Repeat)) ? g.NavId : 0; if (g.NavWindow && (g.NavWindow->Flags & ImGuiWindowFlags_NoNavInputs)) { g.NavActivateId = g.NavInputId = 0; @@ -2591,10 +2644,10 @@ static void NavUpdate() g.NavMoveDir = ImGuiNavDir_None; if (g.NavWindow && !g.NavWindowingTarget && allowed_dir_flags && !(g.NavWindow->Flags & ImGuiWindowFlags_NoNavInputs)) { - if ((allowed_dir_flags & (1<Scroll.y + ((g.NavMoveDir == ImGuiNavDir_Up) ? -1.0f : +1.0f) * scroll_speed)); // Manual scroll with NavScrollXXX keys - ImVec2 scroll_dir = ImGui::NavGetMovingDir(1, 1.0f/10.0f, 10.0f); + ImVec2 scroll_dir = GetNavInputAmount2d(1, ImGuiNavReadMode_Down, 1.0f/10.0f, 10.0f); if (scroll_dir.x != 0.0f && g.NavWindow->ScrollbarX) { SetWindowScrollX(g.NavWindow, ImFloor(g.NavWindow->Scroll.x + scroll_dir.x * scroll_speed)); @@ -2695,6 +2748,9 @@ void ImGui::NewFrame() memcpy(g.IO.KeysDownDurationPrev, g.IO.KeysDownDuration, sizeof(g.IO.KeysDownDuration)); for (int i = 0; i < IM_ARRAYSIZE(g.IO.KeysDown); i++) g.IO.KeysDownDuration[i] = g.IO.KeysDown[i] ? (g.IO.KeysDownDuration[i] < 0.0f ? 0.0f : g.IO.KeysDownDuration[i] + g.IO.DeltaTime) : -1.0f; + memcpy(g.IO.NavInputsPrev, g.IO.NavInputs, sizeof(g.IO.NavInputs)); + for (int i = 0; i < IM_ARRAYSIZE(g.IO.NavInputs); i++) + g.IO.NavInputsDownDuration[i] = (g.IO.NavInputs[i] > 0.0f) ? (g.IO.NavInputsDownDuration[i] < 0.0f ? 0.0f : g.IO.NavInputsDownDuration[i] + g.IO.DeltaTime) : -1.0f; // Update directional navigation which may override MousePos if 'NavMovesMouse=true' NavUpdate(); @@ -3708,20 +3764,23 @@ bool ImGui::IsKeyDown(int key_index) return GImGui->IO.KeysDown[key_index]; } +int ImGui::CalcTypematicPressedRepeatAmount(float t, float t_prev, float repeat_delay, float repeat_rate) +{ + if (t == 0.0f) + return 1; + if (t <= repeat_delay || repeat_rate <= 0.0f) + return 0; + const int count = (int)((t - repeat_delay) / repeat_rate) - (int)((t_prev - repeat_delay) / repeat_rate); + return (count > 0) ? count : 0; +} + int ImGui::GetKeyPressedAmount(int key_index, float repeat_delay, float repeat_rate) { ImGuiContext& g = *GImGui; if (key_index < 0) return false; IM_ASSERT(key_index >= 0 && key_index < IM_ARRAYSIZE(g.IO.KeysDown)); const float t = g.IO.KeysDownDuration[key_index]; - if (t == 0.0f) - return 1; - if (t > repeat_delay && repeat_rate > 0.0f) - { - int count = (int)((t - repeat_delay) / repeat_rate) - (int)((t - repeat_delay - g.IO.DeltaTime) / repeat_rate); - return (count > 0) ? count : 0; - } - return 0; + return CalcTypematicPressedRepeatAmount(t, t - g.IO.DeltaTime, repeat_delay, repeat_rate); } bool ImGui::IsKeyPressed(int key_index, bool repeat) @@ -4823,9 +4882,13 @@ bool ImGui::Begin(const char* name, bool* p_open, const ImVec2& size_on_first_us ImVec2 nav_resize_delta(0.0f, 0.0f); if (g.NavWindowingTarget == window) { - const float resize_speed = ImFloor(600 * g.IO.DeltaTime * ImMin(g.IO.DisplayFramebufferScale.x, g.IO.DisplayFramebufferScale.y)); - nav_resize_delta = NavGetMovingDir(0) * resize_speed; - held |= (nav_resize_delta.x != 0.0f || nav_resize_delta.y != 0.0f); // For coloring + nav_resize_delta = GetNavInputAmount2d(0, ImGuiNavReadMode_Down); + if (nav_resize_delta.x != 0.0f || nav_resize_delta.y != 0.0f) + { + nav_resize_delta *= ImFloor(600 * g.IO.DeltaTime * ImMin(g.IO.DisplayFramebufferScale.x, g.IO.DisplayFramebufferScale.y)); + g.NavDisableMouseHover = true; + held = true; // For coloring + } } ImVec2 size_target(FLT_MAX,FLT_MAX); @@ -6267,13 +6330,13 @@ bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool { // We report navigated item as hovered but we don't set g.HoveredId to not interfere with mouse hovered = true; - if (!g.NavWindowingTarget && IsKeyDownMap(ImGuiKey_NavActivate)) + if (!g.NavWindowingTarget && IsNavInputDown(ImGuiNavInput_PadActivate)) { // Set active id so it can be queried by user via IsItemActive(), etc. but don't react to it ourselves - g.NavActivateId = g.NavId; - SetActiveID(g.NavId, window); + g.NavActivateId = id; + SetActiveID(id, window); g.ActiveIdAllowNavDirFlags = (1 << ImGuiNavDir_Left) | (1 << ImGuiNavDir_Right) | (1 << ImGuiNavDir_Up) | (1 << ImGuiNavDir_Down); - if (IsKeyPressedMap(ImGuiKey_NavActivate, (flags & ImGuiButtonFlags_Repeat) != 0)) + if (IsNavInputPressed(ImGuiNavInput_PadActivate, (flags & ImGuiButtonFlags_Repeat) ? ImGuiNavReadMode_Repeat : ImGuiNavReadMode_Pressed)) pressed = true; } } @@ -6296,7 +6359,7 @@ bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool g.NavDisableHighlight = true; } if (g.ActiveId == id && g.ActiveIdSource == ImGuiInputSource_Nav) - if (!IsKeyDownMap(ImGuiKey_NavActivate)) + if (!IsNavInputDown(ImGuiNavInput_PadActivate)) SetActiveID(0); // AllowOverlap mode (rarely used) requires previous frame HoveredId to be null or to match. This allows using patterns where a later submitted widget overlaps a previous one. @@ -7136,47 +7199,6 @@ int ImGui::ParseFormatPrecision(const char* fmt, int default_precision) return precision; } -ImVec2 ImGui::NavGetMovingDir(int stick_no, float slow_factor, float fast_factor) -{ - IM_ASSERT(stick_no >= 0 && stick_no < 2); - ImVec2 dir(0.0f, 0.0f); - if (stick_no == 0) - { - if (IsKeyDownMap(ImGuiKey_NavLeft)) dir.x -= 1.0f; - if (IsKeyDownMap(ImGuiKey_NavRight)) dir.x += 1.0f; - if (IsKeyDownMap(ImGuiKey_NavUp)) dir.y -= 1.0f; - if (IsKeyDownMap(ImGuiKey_NavDown)) dir.y += 1.0f; - } - if (stick_no == 1) - { - if (IsKeyDownMap(ImGuiKey_NavScrollLeft)) dir.x -= 1.0f; - if (IsKeyDownMap(ImGuiKey_NavScrollRight)) dir.x += 1.0f; - if (IsKeyDownMap(ImGuiKey_NavScrollUp)) dir.y -= 1.0f; - if (IsKeyDownMap(ImGuiKey_NavScrollDown)) dir.y += 1.0f; - } - if (slow_factor != 0.0f && IsKeyDownMap(ImGuiKey_NavTweakSlower)) - dir *= slow_factor; - if (fast_factor != 0.0f && IsKeyDownMap(ImGuiKey_NavTweakFaster)) - dir *= fast_factor; - return dir; -} - -// Adjustment delta for slider/drag/etc. -// FIXME-NAVIGATION: Accelerate over time? Expose more settings? Handle faster/slower modifiers here instead of widget level? -ImVec2 ImGui::NavGetTweakDelta() -{ - ImGuiContext& g = *GImGui; - float repeat_delay = g.IO.KeyRepeatDelay * 0.80f; - float repeat_rate = g.IO.KeyRepeatRate * 0.30f; - - ImVec2 delta(0.0f, 0.0f); - if (int count = GetKeyPressedAmount(g.IO.KeyMap[ImGuiKey_NavLeft], repeat_delay, repeat_rate)) delta.x = (float)-count; - if (int count = GetKeyPressedAmount(g.IO.KeyMap[ImGuiKey_NavRight], repeat_delay, repeat_rate)) delta.x = (float)+count; - if (int count = GetKeyPressedAmount(g.IO.KeyMap[ImGuiKey_NavUp], repeat_delay, repeat_rate)) delta.y = (float)-count; - if (int count = GetKeyPressedAmount(g.IO.KeyMap[ImGuiKey_NavDown], repeat_delay, repeat_rate)) delta.y = (float)+count; - return delta; -} - static float GetMinimumStepAtDecimalPrecision(int decimal_precision) { static const float min_steps[10] = { 1.0f, 0.1f, 0.01f, 0.001f, 0.0001f, 0.00001f, 0.000001f, 0.0000001f, 0.00000001f, 0.000000001f }; @@ -7275,15 +7297,15 @@ bool ImGui::SliderBehavior(const ImRect& frame_bb, ImGuiID id, float* v, float v normalized_pos = 1.0f - normalized_pos; set_new_value = true; } - else if (g.ActiveIdSource == ImGuiInputSource_Nav && IsKeyDownMap(ImGuiKey_NavActivate)) + else if (g.ActiveIdSource == ImGuiInputSource_Nav && IsNavInputDown(ImGuiNavInput_PadActivate)) { - const ImVec2 delta2 = NavGetTweakDelta(); + const ImVec2 delta2 = GetNavInputAmount2d(0, ImGuiNavReadMode_RepeatFast, 0.0f, 0.0f); if (float delta = is_horizontal ? delta2.x : -delta2.y) { normalized_pos = SliderBehaviorCalcRatioFromValue(*v, v_min, v_max, power, linear_zero_pos); if (decimal_precision == 0 && !is_non_linear) { - if (fabsf(v_max - v_min) <= 100.0f || IsKeyDownMap(ImGuiKey_NavTweakSlower)) + if (fabsf(v_max - v_min) <= 100.0f || IsNavInputDown(ImGuiNavInput_PadTweakSlow)) delta = ((delta < 0.0f) ? -1.0f : +1.0f) / (v_max - v_min); // Gamepad/keyboard tweak speeds in integer steps else delta /= 100.0f; @@ -7291,10 +7313,10 @@ bool ImGui::SliderBehavior(const ImRect& frame_bb, ImGuiID id, float* v, float v else { delta /= 100.0f; // Gamepad/keyboard tweak speeds in % of slider bounds - if (IsKeyDownMap(ImGuiKey_NavTweakSlower)) + if (IsNavInputDown(ImGuiNavInput_PadTweakSlow)) delta /= 10.0f; } - if (IsKeyDownMap(ImGuiKey_NavTweakFaster)) + if (IsNavInputDown(ImGuiNavInput_PadTweakFast)) delta *= 10.0f; normalized_pos = ImSaturate(normalized_pos + delta); // FIXME-NAVIGATION: todo: cancel adjustment if current value already past edge and we are moving in edge direction, to avoid clamping value to edge. set_new_value = true; @@ -7602,7 +7624,7 @@ bool ImGui::DragBehavior(const ImRect& frame_bb, ImGuiID id, float* v, float v_s // Process clicking on the drag if (g.ActiveId == id) { - if (g.IO.MouseDown[0] || IsKeyDownMap(ImGuiKey_NavActivate)) + if (g.IO.MouseDown[0] || IsNavInputDown(ImGuiNavInput_PadActivate)) { if (g.ActiveIdIsJustActivated) { @@ -7627,11 +7649,7 @@ bool ImGui::DragBehavior(const ImRect& frame_bb, ImGuiID id, float* v, float v_s } if (g.ActiveIdSource == ImGuiInputSource_Nav) { - adjust_delta = NavGetTweakDelta().x; - if (IsKeyDownMap(ImGuiKey_NavTweakFaster)) - adjust_delta *= 10.0f; - if (IsKeyDownMap(ImGuiKey_NavTweakSlower)) - adjust_delta /= 10.0f; + adjust_delta = GetNavInputAmount2d(0, ImGuiNavReadMode_RepeatFast, 1.0f/10.0f, 1.0f).x; } adjust_delta *= v_speed; g.DragLastMouseDelta.x = mouse_drag_delta.x; diff --git a/imgui.h b/imgui.h index d43cd8cd2bfb..c34d68c69be9 100644 --- a/imgui.h +++ b/imgui.h @@ -70,6 +70,7 @@ typedef void* ImTextureID; // user data to identify a texture (this is typedef int ImGuiCol; // a color identifier for styling // enum ImGuiCol_ typedef int ImGuiStyleVar; // a variable identifier for styling // enum ImGuiStyleVar_ typedef int ImGuiKey; // a key identifier (ImGui-side enum) // enum ImGuiKey_ +typedef int ImGuiNavInput; // an input identifier for gamepad nav // enum ImGuiNavInput_ typedef int ImGuiAlign; // alignment // enum ImGuiAlign_ typedef int ImGuiColorEditMode; // color edit mode for ColorEdit*() // enum ImGuiColorEditMode_ typedef int ImGuiMouseCursor; // a mouse cursor identifier // enum ImGuiMouseCursor_ @@ -437,7 +438,7 @@ namespace ImGui IMGUI_API bool IsKeyDown(int key_index); // key_index into the keys_down[] array, imgui doesn't know the semantic of each entry, uses your own indices! IMGUI_API bool IsKeyPressed(int key_index, bool repeat = true); // uses user's key indices as stored in the keys_down[] array. if repeat=true. uses io.KeyRepeatDelay / KeyRepeatRate IMGUI_API bool IsKeyReleased(int key_index); // " - IMGUI_API int GetKeyPressedAmount(int key_index, float repeat_delay, float rate); // uses provided repeat rate/delay. return a count, typically 0 or 1 but may be >1 if RepeatRate is small enough that DeltaTime > RepeatRate + IMGUI_API int GetKeyPressedAmount(int key_index, float repeat_delay, float rate); // uses provided repeat rate/delay. return a count, most often 0 or 1 but might be >1 if RepeatRate is small enough that DeltaTime > RepeatRate IMGUI_API bool IsMouseDown(int button); // is mouse button held IMGUI_API bool IsMouseClicked(int button, bool repeat = false); // did mouse button clicked (went from !Down to Down) IMGUI_API bool IsMouseDoubleClicked(int button); // did mouse button double-clicked. a double-click returns false in IsMouseClicked(). uses io.MouseDoubleClickTime. @@ -576,10 +577,10 @@ enum ImGuiSelectableFlags_ enum ImGuiKey_ { ImGuiKey_Tab, // for tabbing through fields - ImGuiKey_LeftArrow, // for text edit - ImGuiKey_RightArrow,// for text edit ImGuiKey_UpArrow, // for text edit ImGuiKey_DownArrow, // for text edit + ImGuiKey_LeftArrow, // for text edit + ImGuiKey_RightArrow,// for text edit ImGuiKey_PageUp, ImGuiKey_PageDown, ImGuiKey_Home, // for text edit @@ -594,27 +595,31 @@ enum ImGuiKey_ ImGuiKey_X, // for text edit CTRL+X: cut ImGuiKey_Y, // for text edit CTRL+Y: redo ImGuiKey_Z, // for text edit CTRL+Z: undo - - // Inputs for Gamepad/Keyboard navigation. Feed those buttons with the input of either or both peripherals involved. - ImGuiKey_NavActivate, // press button, tweak value // e.g. Space key, Circle button - ImGuiKey_NavCancel, // close menu/popup/child, unselect // e.g. Escape key, Cross button - ImGuiKey_NavInput, // text input // e.g. Enter key, Triangle button - ImGuiKey_NavMenu, // access menu, focus, move, resize // e.g. Square button - ImGuiKey_NavLeft, // e.g. Left arrow, D-Pad left - ImGuiKey_NavRight, // e.g. Right arrow, D-Pad right - ImGuiKey_NavUp, // e.g. Up arrow, D-Pad up - ImGuiKey_NavDown, // e.g. Down arrow, D-Pad down - ImGuiKey_NavScrollLeft, // e.g. Analog left - ImGuiKey_NavScrollRight,// e.g. Analog right - ImGuiKey_NavScrollUp, // e.g. Analog up - ImGuiKey_NavScrollDown, // e.g. Analog down - ImGuiKey_NavTweakFaster,// e.g. Shift key, R-trigger - ImGuiKey_NavTweakSlower,// e.g. Alt key, L-trigger - ImGuiKey_NavLast_, - ImGuiKey_COUNT }; +enum ImGuiNavInput_ +{ + ImGuiNavInput_PadActivate, // press button, tweak value // e.g. Circle button + ImGuiNavInput_PadCancel, // close menu/popup/child, lose selection // e.g. Cross button + ImGuiNavInput_PadInput, // text input // e.g. Triangle button + ImGuiNavInput_PadMenu, // access menu, focus, move, resize // e.g. Square button + ImGuiNavInput_PadUp, // move up, resize window (with PadMenu held) // e.g. D-pad up/down/left/right + ImGuiNavInput_PadDown, // move down + ImGuiNavInput_PadLeft, // move left + ImGuiNavInput_PadRight, // move right + ImGuiNavInput_PadScrollUp, // scroll up, move window (with PadMenu held) // e.g. right stick up/down/left/right + ImGuiNavInput_PadScrollDown, // " + ImGuiNavInput_PadScrollLeft, // + ImGuiNavInput_PadScrollRight, // + ImGuiNavInput_PadFocusPrev, // next window (with PadMenu held) // e.g. L-trigger + ImGuiNavInput_PadFocusNext, // prev window (with PadMenu held) // e.g. R-trigger + ImGuiNavInput_PadTweakSlow, // slower tweaks // e.g. L-trigger + ImGuiNavInput_PadTweakFast, // faster tweaks // e.g. R-trigger + + ImGuiNavInput_COUNT, +}; + // Enumeration for PushStyleColor() / PopStyleColor() enum ImGuiCol_ { @@ -824,6 +829,7 @@ struct ImGuiIO bool KeySuper; // Keyboard modifier pressed: Cmd/Super/Windows bool KeysDown[512]; // Keyboard keys that are pressed (in whatever storage order you naturally have access to keyboard data) ImWchar InputCharacters[16+1]; // List of characters input (translated by user from keypress+keyboard state). Fill using AddInputCharacter() helper. + float NavInputs[ImGuiNavInput_COUNT]; // Functions IMGUI_API void AddInputCharacter(ImWchar c); // Helper to add a new character into InputCharacters[] @@ -863,6 +869,8 @@ struct ImGuiIO float MouseDragMaxDistanceSqr[5]; // Squared maximum distance of how much mouse has traveled from the click point float KeysDownDuration[512]; // Duration the keyboard key has been down (0.0f == just pressed) float KeysDownDurationPrev[512]; // Previous duration the key has been down + float NavInputsDownDuration[ImGuiNavInput_COUNT]; + float NavInputsPrev[ImGuiNavInput_COUNT]; IMGUI_API ImGuiIO(); }; diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 3050a2c43b88..6f0f7135a0ec 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -1528,6 +1528,9 @@ void ImGui::ShowTestWindow(bool* p_open) ImGui::Text("Keys mods: %s%s%s%s", io.KeyCtrl ? "CTRL " : "", io.KeyShift ? "SHIFT " : "", io.KeyAlt ? "ALT " : "", io.KeySuper ? "SUPER " : ""); ImGui::Text("NavUsable: %d, NavActive: %d", io.NavUsable, io.NavActive); + ImGui::Text("NavInputs down:"); for (int i = 0; i < IM_ARRAYSIZE(io.NavInputs); i++) if (io.NavInputs[i] > 0.0f) { ImGui::SameLine(); ImGui::Text("[%d] %.2f", i, io.NavInputs[i]); } + ImGui::Text("NavInputs pressed:"); for (int i = 0; i < IM_ARRAYSIZE(io.NavInputs); i++) if (io.NavInputsDownDuration[i] == 0.0f) { ImGui::SameLine(); ImGui::Text("[%d]", i); } + ImGui::Text("NavInputs duration:"); for (int i = 0; i < IM_ARRAYSIZE(io.NavInputs); i++) if (io.NavInputsDownDuration[i] >= 0.0f) { ImGui::SameLine(); ImGui::Text("[%d] %.2f", i, io.NavInputsDownDuration[i]); } ImGui::Button("Hovering me sets the\nkeyboard capture flag"); if (ImGui::IsItemHovered()) diff --git a/imgui_internal.h b/imgui_internal.h index 35a206f1853e..deb4cf37d1f3 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -784,8 +784,7 @@ namespace ImGui IMGUI_API void OpenPopupEx(const char* str_id, bool reopen_existing); - IMGUI_API ImVec2 NavGetTweakDelta(); - IMGUI_API ImVec2 NavGetMovingDir(int stick_no, float slow_factor = 0.0f, float fast_factor = 0.0f); + IMGUI_API int CalcTypematicPressedRepeatAmount(float t, float t_prev, float repeat_delay, float repeat_rate); inline IMGUI_API ImU32 GetColorU32(ImGuiCol idx, float alpha_mul) { ImVec4 c = GImGui->Style.Colors[idx]; c.w *= GImGui->Style.Alpha * alpha_mul; return ImGui::ColorConvertFloat4ToU32(c); } inline IMGUI_API ImU32 GetColorU32(const ImVec4& col) { ImVec4 c = col; c.w *= GImGui->Style.Alpha; return ImGui::ColorConvertFloat4ToU32(c); } From c263961f07fff4615c6390f449e0d4253bee8f89 Mon Sep 17 00:00:00 2001 From: ocornut Date: Thu, 4 Aug 2016 10:41:33 +0200 Subject: [PATCH 075/823] Nav: Menu: Allow PadDown to open a menu from a menu bar, PadRight from a menu (#323, #126) --- imgui.cpp | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 52cab7054f20..07ab3908fe66 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -9754,14 +9754,25 @@ bool ImGui::BeginMenu(const char* label, bool enabled) want_close = menu_is_open; want_open = !menu_is_open; } + if (g.NavId == id && g.NavMoveRequest && g.NavMoveDir == ImGuiNavDir_Right) // Nav-Right to open + { + want_open = true; + g.NavMoveRequest = false; + } } - else if (menu_is_open && pressed && menuset_is_open) // menu-bar: click open menu to close + else if (menu_is_open && pressed && menuset_is_open) // Menu bar: click an open menu again to close it { want_close = true; want_open = menu_is_open = false; } - else if (pressed || (hovered && menuset_is_open && !menu_is_open)) // menu-bar: first click to open, then hover to open others + else if (pressed || (hovered && menuset_is_open && !menu_is_open)) // Menu bar: click to open a first menu, then hover to open others + want_open = true; + else if (g.NavId == id && g.NavMoveRequest && g.NavMoveDir == ImGuiNavDir_Down) // Menu bar: Nav-Down to open + { + g.NavMoveRequest = false; want_open = true; + } + if (!enabled) // explicitly close if an open menu becomes disabled, facilitate users code a lot in pattern such as 'if (BeginMenu("options", has_object)) { ..use object.. }' want_close = true; if (want_close && IsPopupOpen(id)) From d85c1be6b6efbaeedad5736d30c37ac015b5e079 Mon Sep 17 00:00:00 2001 From: ocornut Date: Thu, 4 Aug 2016 12:53:46 +0200 Subject: [PATCH 076/823] Nav: Reordered Cancel handling code so you you can leave a child within a popup without closing the popup (#323) --- imgui.cpp | 37 +++++++++++++++++-------------------- 1 file changed, 17 insertions(+), 20 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 07ab3908fe66..14a10af8cf93 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2591,13 +2591,27 @@ static void NavUpdate() { ImGui::SetActiveID(0); } + else if (g.NavWindow && (g.NavWindow->Flags & ImGuiWindowFlags_ChildWindow) && !(g.NavWindow->Flags & ImGuiWindowFlags_Popup) && g.NavWindow->ParentWindow) + { + // Exit child window + ImGuiWindow* child_window = g.NavWindow; + ImGuiWindow* parent_window = g.NavWindow->ParentWindow; + ImGui::FocusWindow(parent_window); + g.NavId = parent_window->GetChildID(child_window); + if (g.NavLayer == 0) + parent_window->NavLastId = g.NavId; + g.NavIdIsAlive = false; + if (g.NavDisableMouseHover) + g.NavMousePosDirty = true; + } else if (g.OpenPopupStack.Size > 0) { - // Close open popup or move back to parent window + // Close open popup/menu ClosePopupToLevel(g.OpenPopupStack.Size - 1); } else if (g.NavLayer != 0) { + // Leave the "menu" layer g.NavLayer = 0; if (g.NavWindow->NavLastId) SetNavIdMoveMouse(g.NavWindow->NavLastId, ImRect()); @@ -2606,27 +2620,10 @@ static void NavUpdate() } else { - // Clear NavId for popups but keep it for regular child window so we can leave one and come back where we were + // Clear NavLastId for popups but keep it for regular child window so we can leave one and come back where we were if (g.NavWindow && ((g.NavWindow->Flags & ImGuiWindowFlags_Popup) || !(g.NavWindow->Flags & ImGuiWindowFlags_ChildWindow))) g.NavWindow->NavLastId = 0; - - if (g.NavWindow && (g.NavWindow->Flags & ImGuiWindowFlags_ChildWindow) && g.NavWindow->ParentWindow) - { - // Exit child window - ImGuiWindow* child_window = g.NavWindow; - ImGuiWindow* parent_window = g.NavWindow->ParentWindow; - ImGui::FocusWindow(parent_window); - g.NavId = parent_window->GetChildID(child_window); - if (g.NavLayer == 0) - parent_window->NavLastId = g.NavId; - g.NavIdIsAlive = false; - if (g.NavDisableMouseHover) - g.NavMousePosDirty = true; - } - else - { - g.NavId = 0; - } + g.NavId = 0; } } From 5ef84525098079ca676a22bc59111663d8eb6455 Mon Sep 17 00:00:00 2001 From: ocornut Date: Sun, 7 Aug 2016 13:33:15 +0200 Subject: [PATCH 077/823] Nav: Comments (#323) --- imgui.cpp | 13 +++++++------ imgui.h | 14 +++++++++----- 2 files changed, 16 insertions(+), 11 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 0266135b471c..bbc27e86877f 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -150,13 +150,14 @@ USING GAMEPAD/KEYBOARD NAVIGATION [BETA] - - Gamepad/keyboard navigation support is available, it is currently in Beta and has issues. Your feedback and bug reports are welcome. + - Gamepad/keyboard navigation support is available, currently in Beta with some issues. Your feedback and bug reports are welcome. - See https://github.com/ocornut/imgui/issues/323 for discussion thread and ask questions. - The current primary focus is to support game controllers. - Consider emulating a mouse cursor with DualShock4 touch pad or a spare analog stick as a mouse-emulation fallback. - Consider using Synergy host (on your computer) + uSynergy.c (in your console/tablet/phone app) to use PC mouse/keyboard. - - Being able to share and transition inputs between imgui navigation and your own game/application is tricky, and may requires further work on imgui. - For gamepad use, the easiest approach is to go all-or-nothing, with a buttons combo that toggle your inputs between imgui and your game/application. + - Your inputs are passed to imgui by filling the io.NavInputs[] array. See 'enum ImGuiNavInput_' in imgui.h for a description of available inputs. + - For gamepad use, the easiest approach is to go all-or-nothing, with a buttons combo that toggle your inputs between imgui and your game/application. + Sharing inputs in a more advanced or granular way between imgui and your game/application may be tricky and requires further work on imgui. For more advanced uses, you may want to use: - io.NavUsable: true when a window is focused and it doesn't have the ImGuiWindowFlags_NoNavInputs flag set. - io.NavActive: true when the navigation cursor is visible (and usually goes false when mouse is used). @@ -165,7 +166,7 @@ As we head toward more keyboard-oriented development this aspect will need to be improved. - It is recommended that you enable the 'io.NavMovesMouse' option. Enabling it instructs ImGui that it can request moving your move cursor to track navigated items and ease readability. When enabled and using directional navigation (with d-pad or arrow keys), the NewFrame() functions may alter 'io.MousePos' and set 'io.WantMoveMouse' to notify you that it did so. - When that happens your back-end will need to move the OS mouse cursor on the _next_ frame. The examples binding in examples/ do that. + When that happens your back-end will need to move the OS mouse cursor on the next frame. The examples binding in examples/ do that. // Application init io.NavMovesMouse = true; @@ -175,8 +176,8 @@ MyFuncToSetMousePosition(io.MousePos.x, io.MousePos.y); ImGui::NewFrame(); - In a setup when you may not have easy control over the mouse cursor (e.g. uSynergy doesn't expose changing remote mouse cursor), - you might want to set a boolean to request ignoring your other external mouse positions until they move again. + In a setup when you may not have easy control over the mouse cursor (e.g. uSynergy.c doesn't expose moving remote mouse cursor), + you might want to set a boolean to ignore your other external mouse positions until they move again. API BREAKING CHANGES diff --git a/imgui.h b/imgui.h index e9a8d7bb57ce..708a58f8bb01 100644 --- a/imgui.h +++ b/imgui.h @@ -593,25 +593,29 @@ enum ImGuiKey_ ImGuiKey_COUNT }; +// [BETA] Gamepad/Keyboard directional navigation +// Fill ImGuiIO.NavInputs[] float array every frame to feed gamepad/keyboard navigation inputs. +// 0.0f= not held. 1.0f= fully held. Pass intermediate 0.0f..1.0f values for analog triggers/sticks. +// ImGui uses a simple >0.0f for activation testing, and won't attempt to test for a dead-zone. +// Your code passing analog gamepad values is likely to want to transform your raw inputs, using a dead-zone and maybe a power curve. enum ImGuiNavInput_ { ImGuiNavInput_PadActivate, // press button, tweak value // e.g. Circle button ImGuiNavInput_PadCancel, // close menu/popup/child, lose selection // e.g. Cross button ImGuiNavInput_PadInput, // text input // e.g. Triangle button ImGuiNavInput_PadMenu, // access menu, focus, move, resize // e.g. Square button - ImGuiNavInput_PadUp, // move up, resize window (with PadMenu held) // e.g. D-pad up/down/left/right + ImGuiNavInput_PadUp, // move up, resize window (with PadMenu held) // e.g. D-pad up/down/left/right, analog ImGuiNavInput_PadDown, // move down ImGuiNavInput_PadLeft, // move left ImGuiNavInput_PadRight, // move right - ImGuiNavInput_PadScrollUp, // scroll up, move window (with PadMenu held) // e.g. right stick up/down/left/right + ImGuiNavInput_PadScrollUp, // scroll up, move window (with PadMenu held) // e.g. right stick up/down/left/right, analog ImGuiNavInput_PadScrollDown, // " ImGuiNavInput_PadScrollLeft, // ImGuiNavInput_PadScrollRight, // ImGuiNavInput_PadFocusPrev, // next window (with PadMenu held) // e.g. L-trigger ImGuiNavInput_PadFocusNext, // prev window (with PadMenu held) // e.g. R-trigger - ImGuiNavInput_PadTweakSlow, // slower tweaks // e.g. L-trigger - ImGuiNavInput_PadTweakFast, // faster tweaks // e.g. R-trigger - + ImGuiNavInput_PadTweakSlow, // slower tweaks // e.g. L-trigger, analog + ImGuiNavInput_PadTweakFast, // faster tweaks // e.g. R-trigger, analog ImGuiNavInput_COUNT, }; From 8a6d209f68411ebe12c21229494112fbd29ebecf Mon Sep 17 00:00:00 2001 From: ocornut Date: Sun, 7 Aug 2016 13:34:25 +0200 Subject: [PATCH 078/823] Nav: Failed movement request with no current NavId fallback to an InitDefaultRequest so that we always land somewhere on first move (#323) --- imgui.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/imgui.cpp b/imgui.cpp index bbc27e86877f..148e7723b8e9 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2664,6 +2664,14 @@ static void NavUpdate() if (g.NavMoveDir != ImGuiNavDir_None) g.NavMoveRequest = true; + // If we initiate a movement request and have no current NavId, we initiate a InitDefautRequest that will be used as a fallback if the direction fails to find a match + if (g.NavMoveRequest && g.NavId == 0) + { + g.NavInitDefaultRequest = g.NavInitDefaultResultExplicit = true; + g.NavInitDefaultResultId = 0; + g.NavDisableHighlight = false; + } + // Scrolling if (g.NavWindow && !(g.NavWindow->Flags & ImGuiWindowFlags_NoNavInputs) && !g.NavWindowingTarget) { From e55882f74b5608331f355f5240cd56a9e5937910 Mon Sep 17 00:00:00 2001 From: ocornut Date: Sun, 7 Aug 2016 15:18:04 +0200 Subject: [PATCH 079/823] Nav: Allow PadLeft to close a menu (#323) --- imgui.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/imgui.cpp b/imgui.cpp index 221b21472313..c96fdf99a51c 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -9779,6 +9779,11 @@ bool ImGui::BeginMenu(const char* label, bool enabled) want_open = true; g.NavMoveRequest = false; } + if (g.NavWindow && g.NavWindow->ParentWindow == window && g.NavMoveRequest && g.NavMoveDir == ImGuiNavDir_Left) // Nav-Left to close + { + want_close = true; + g.NavMoveRequest = false; + } } else if (menu_is_open && pressed && menuset_is_open) // Menu bar: click an open menu again to close it { From 6aa80197633f23bb0c7d72ac4731d6895766c613 Mon Sep 17 00:00:00 2001 From: ocornut Date: Sun, 7 Aug 2016 15:19:29 +0200 Subject: [PATCH 080/823] Nav: Fixed bug where pressing NavInput(Triangle) to turn slider/drag into text input would then change subsequent NavActivate as well (#323) --- imgui.cpp | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index c96fdf99a51c..d98505a250b0 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2763,6 +2763,8 @@ void ImGui::NewFrame() g.ActiveIdPreviousFrame = g.ActiveId; g.ActiveIdIsAlive = false; g.ActiveIdIsJustActivated = false; + if (g.ScalarAsInputTextId && g.ActiveId != g.ScalarAsInputTextId) + g.ScalarAsInputTextId = 0; // Update keyboard input state memcpy(g.IO.KeysDownDurationPrev, g.IO.KeysDownDuration, sizeof(g.IO.KeysDownDuration)); @@ -7167,6 +7169,7 @@ static bool DataTypeApplyOpFromText(const char* buf, const char* initial_value_b } // Create text input in place of a slider (when CTRL+Clicking on slider) +// FIXME: Logic is messy and confusing. bool ImGui::InputScalarAsWidgetReplacement(const ImRect& aabb, const char* label, ImGuiDataType data_type, void* data_ptr, ImGuiID id, int decimal_precision) { ImGuiContext& g = *GImGui; @@ -7181,18 +7184,12 @@ bool ImGui::InputScalarAsWidgetReplacement(const ImRect& aabb, const char* label char buf[32]; DataTypeFormatString(data_type, data_ptr, decimal_precision, buf, IM_ARRAYSIZE(buf)); bool text_value_changed = InputTextEx(label, buf, IM_ARRAYSIZE(buf), aabb.GetSize(), ImGuiInputTextFlags_CharsDecimal | ImGuiInputTextFlags_AutoSelectAll); - if (g.ScalarAsInputTextId == 0) + if (g.ScalarAsInputTextId == 0) // First frame we started displaying the InputText widget { - // First frame IM_ASSERT(g.ActiveId == id); // InputText ID expected to match the Slider ID (else we'd need to store them both, which is also possible) g.ScalarAsInputTextId = g.ActiveId; SetHoveredID(id); } - else if (g.ActiveId != g.ScalarAsInputTextId) - { - // Release - g.ScalarAsInputTextId = 0; - } if (text_value_changed) return DataTypeApplyOpFromText(buf, GImGui->InputTextState.InitialText.begin(), data_type, data_ptr, NULL); return false; From a68132948b036393bc319db8bcd7192208f052b0 Mon Sep 17 00:00:00 2001 From: ocornut Date: Sun, 7 Aug 2016 15:26:04 +0200 Subject: [PATCH 081/823] Nav: Added ImGuiCol_NavWindowingHighlight into style (#323) --- imgui.cpp | 11 +++++------ imgui.h | 1 + 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index d98505a250b0..42f2a440b800 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -833,6 +833,7 @@ ImGuiStyle::ImGuiStyle() Colors[ImGuiCol_PlotHistogramHovered] = ImVec4(1.00f, 0.60f, 0.00f, 1.00f); Colors[ImGuiCol_TextSelectedBg] = ImVec4(0.00f, 0.00f, 1.00f, 0.35f); Colors[ImGuiCol_ModalWindowDarkening] = ImVec4(0.20f, 0.20f, 0.20f, 0.35f); + Colors[ImGuiCol_NavWindowingHighlight] = ImVec4(1.00f, 1.00f, 1.00f, 0.12f); } ImGuiIO::ImGuiIO() @@ -1961,8 +1962,7 @@ static float NavScoreItemDistInterval(float a0, float a1, float b0, float b1) } // Scoring function for directional navigation. Based on https://gist.github.com/rygorous/6981057 -// FIXME-NAVIGATION: Pretty rough. -// FIXME-NAVIGATION: May want to handle the degenerate case that we have commented out. +// FIXME-NAVIGATION: Pretty rough. Also may want to handle the degenerate case that we have commented out. static bool NavScoreItem(ImRect cand) { ImGuiContext& g = *GImGui; @@ -2540,7 +2540,6 @@ static void NavUpdate() g.NavWindowingToggleLayer &= (g.NavWindowingDisplayAlpha < 1.0f); // Once button is held long enough we don't consider it a tag-to-toggle-layer press anymore. // Select window to focus - // FIXME-NAVIGATION: Need to clarify input semantic, naming is misleading/incorrect here. const int focus_change_dir = (int)IsNavInputPressed(ImGuiNavInput_PadFocusPrev, ImGuiNavReadMode_RepeatSlow) - (int)IsNavInputPressed(ImGuiNavInput_PadFocusNext, ImGuiNavReadMode_RepeatSlow); if (focus_change_dir != 0 && !(g.NavWindowingTarget->Flags & ImGuiWindowFlags_Modal)) { @@ -4868,13 +4867,12 @@ bool ImGui::Begin(const char* name, bool* p_open, const ImVec2& size_on_first_us window->DrawList->AddRectFilled(fullscreen_rect.Min, fullscreen_rect.Max, GetColorU32(ImGuiCol_ModalWindowDarkening, g.ModalWindowDarkeningRatio)); // Navigation windowing (via ImGuiKey_NavWindowing key) shows whole window selected - // FIXME-NAVIGATION: Styling if (g.NavWindowingTarget == window) { ImRect bb = window->Rect(); bb.Expand(g.FontSize); - window->DrawList->AddRectFilled(bb.Min, bb.Max, IM_COL32(255,255,255,(int)(30 * g.NavWindowingDisplayAlpha))/*ImGui::GetColorU32(ImGuiCol_HeaderHovered, 0.15f)*/, g.Style.WindowRounding); - window->DrawList->AddRect(bb.Min, bb.Max, ImGui::GetColorU32(ImGuiCol_HeaderHovered, g.NavWindowingDisplayAlpha), g.Style.WindowRounding); + window->DrawList->AddRectFilled(bb.Min, bb.Max, GetColorU32(ImGuiCol_NavWindowingHighlight, g.NavWindowingDisplayAlpha), g.Style.WindowRounding); + window->DrawList->AddRect(bb.Min, bb.Max, GetColorU32(ImGuiCol_HeaderHovered, g.NavWindowingDisplayAlpha), g.Style.WindowRounding); } // Draw window + handle manual resize @@ -5586,6 +5584,7 @@ const char* ImGui::GetStyleColName(ImGuiCol idx) case ImGuiCol_PlotHistogramHovered: return "PlotHistogramHovered"; case ImGuiCol_TextSelectedBg: return "TextSelectedBg"; case ImGuiCol_ModalWindowDarkening: return "ModalWindowDarkening"; + case ImGuiCol_NavWindowingHighlight: return "NavWindowingHighlight"; } IM_ASSERT(0); return "Unknown"; diff --git a/imgui.h b/imgui.h index 708a58f8bb01..d2cebfebba63 100644 --- a/imgui.h +++ b/imgui.h @@ -665,6 +665,7 @@ enum ImGuiCol_ ImGuiCol_PlotHistogramHovered, ImGuiCol_TextSelectedBg, ImGuiCol_ModalWindowDarkening, // darken entire screen when a modal window is active + ImGuiCol_NavWindowingHighlight, // when holding NavMenu to focus/move/resize windows ImGuiCol_COUNT }; From 525ef5b357b09fe3417c4a191257be62a9710dfc Mon Sep 17 00:00:00 2001 From: ocornut Date: Sun, 7 Aug 2016 15:31:00 +0200 Subject: [PATCH 082/823] Nav: Tweaked default highlight clipping (clipped by scrollbar) and removed subtle background (#323) --- imgui.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 42f2a440b800..7e3d690f348b 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2080,8 +2080,7 @@ static void RenderNavHighlight(ImU32 id, const ImRect& bb) if (id != g.NavId || g.NavDisableHighlight) return; ImGuiWindow* window = ImGui::GetCurrentWindow(); - window->DrawList->PushClipRect(window->WindowRectClipped.Min - ImVec2(2,2), window->WindowRectClipped.Max + ImVec2(2,2)); - window->DrawList->AddRectFilled(bb.Min - ImVec2(2,2), bb.Max + ImVec2(2,2), ImGui::GetColorU32(ImGuiCol_HeaderHovered, 0.15f), g.Style.FrameRounding); + window->DrawList->PushClipRect(window->InnerRect.Min - ImVec2(2,2), window->InnerRect.Max + ImVec2(2,2)); window->DrawList->AddRect(bb.Min - ImVec2(2,2), bb.Max + ImVec2(2,2), ImGui::GetColorU32(ImGuiCol_HeaderHovered), g.Style.FrameRounding); //window->DrawList->AddRect(g.NavRefRectScreen.Min, g.NavRefRectScreen.Max, IM_COL32(255,0,0,255)); window->DrawList->PopClipRect(); From 785f51227a5222b83cb5fd21984fd32d0dc4eb3a Mon Sep 17 00:00:00 2001 From: ocornut Date: Sun, 7 Aug 2016 19:07:24 +0200 Subject: [PATCH 083/823] Demo tweaks --- imgui_demo.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 6f0f7135a0ec..ff946e06116f 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -527,9 +527,10 @@ void ImGui::ShowTestWindow(bool* p_open) ImGui::TreePop(); } - static bool a=false; - if (ImGui::Button("Button")) { printf("Clicked\n"); a ^= 1; } - if (a) + static int clicked = 0; + if (ImGui::Button("Button")) + clicked++; + if (clicked & 1) { ImGui::SameLine(); ImGui::Text("Thanks for clicking me!"); @@ -1833,9 +1834,11 @@ static void ShowExampleMenuFile() ImGui::EndChild(); static float f = 0.5f; static int n = 0; + static bool b = true; ImGui::SliderFloat("Value", &f, 0.0f, 1.0f); ImGui::InputFloat("Input", &f, 0.1f); ImGui::Combo("Combo", &n, "Yes\0No\0Maybe\0\0"); + ImGui::Checkbox("Check", &b); ImGui::EndMenu(); } if (ImGui::BeginMenu("Colors")) From 8828889d5ec1d8fb9ddb72bab16d5e21ba8425c6 Mon Sep 17 00:00:00 2001 From: ocornut Date: Sun, 7 Aug 2016 20:05:24 +0200 Subject: [PATCH 084/823] Refactored rare transient bool stacks into a set of flags, added unexposed ImGuiItemFlags_SelectableDontClosePopup (#323) --- imgui.cpp | 60 +++++++++++++++++++++++++++++------------------- imgui_internal.h | 24 ++++++++++++------- 2 files changed, 52 insertions(+), 32 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 7e3d690f348b..1b5c5f0242b2 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2111,7 +2111,7 @@ bool ImGui::ItemAdd(const ImRect& bb, const ImGuiID* id, const ImRect* nav_bb_ar { const ImRect& nav_bb = nav_bb_arg ? *nav_bb_arg : bb; const ImRect nav_bb_rel(nav_bb.Min - g.NavWindow->Pos, nav_bb.Max - g.NavWindow->Pos); - if (g.NavInitDefaultRequest && g.NavLayer == window->DC.NavLayerCurrent && window->DC.AllowNavDefaultFocus) + if (g.NavInitDefaultRequest && g.NavLayer == window->DC.NavLayerCurrent && (window->DC.ItemFlags & ImGuiItemFlags_AllowNavDefaultFocus)) { g.NavInitDefaultRequest = g.NavInitDefaultResultExplicit = false; // Clear flag immediately, first item gets default, also simplify the if() in ItemAdd() g.NavInitDefaultResultId = *id; @@ -2186,7 +2186,7 @@ bool ImGui::FocusableItemRegister(ImGuiWindow* window, ImGuiID id, bool tab_stop { ImGuiContext& g = *GImGui; - const bool allow_keyboard_focus = window->DC.AllowKeyboardFocus; + const bool allow_keyboard_focus = (window->DC.ItemFlags & ImGuiItemFlags_AllowKeyboardFocus) != 0; window->FocusIdxAllCounter++; if (allow_keyboard_focus) window->FocusIdxTabCounter++; @@ -5027,14 +5027,12 @@ bool ImGui::Begin(const char* name, bool* p_open, const ImVec2& size_on_first_us window->DC.LogLinePosY = window->DC.CursorPos.y - 9999.0f; window->DC.ChildWindows.resize(0); window->DC.LayoutType = ImGuiLayoutType_Vertical; + window->DC.ItemFlags = ImGuiItemFlags_Default_; window->DC.ItemWidth = window->ItemWidthDefault; window->DC.TextWrapPos = -1.0f; // disabled - window->DC.AllowKeyboardFocus = window->DC.AllowNavDefaultFocus = true; - window->DC.ButtonRepeat = false; + window->DC.ItemFlagsStack.resize(0); window->DC.ItemWidthStack.resize(0); window->DC.TextWrapPosStack.resize(0); - window->DC.AllowKeyboardFocusStack.resize(0); - window->DC.ButtonRepeatStack.resize(0); window->DC.ColorEditMode = ImGuiColorEditMode_UserSelect; window->DC.ColumnsCurrent = 0; window->DC.ColumnsCount = 1; @@ -5045,6 +5043,12 @@ bool ImGui::Begin(const char* name, bool* p_open, const ImVec2& size_on_first_us window->DC.GroupStack.resize(0); window->MenuColumns.Update(3, style.ItemSpacing.x, !window_was_active); + if ((flags & ImGuiWindowFlags_ChildWindow) && (window->DC.ItemFlags != parent_window->DC.ItemFlags)) + { + window->DC.ItemFlags = parent_window->DC.ItemFlags; + window->DC.ItemFlagsStack.push_back(window->DC.ItemFlags); + } + if (window->AutoFitFramesX > 0) window->AutoFitFramesX--; if (window->AutoFitFramesY > 0) @@ -5062,9 +5066,9 @@ bool ImGui::Begin(const char* name, bool* p_open, const ImVec2& size_on_first_us if (!(flags & ImGuiWindowFlags_NoTitleBar)) { // Close & collapse button are on layer 1 (same as menus) and don't default focus - const bool backup_allow_nav_default_focus = window->DC.AllowNavDefaultFocus; + const ImGuiItemFlags backup_item_options = window->DC.ItemFlags; if (window->Flags & ImGuiWindowFlags_MenuBar) - window->DC.AllowNavDefaultFocus = false; + window->DC.ItemFlags &= ~ImGuiItemFlags_AllowNavDefaultFocus; window->DC.NavLayerCurrent++; // Close button @@ -5090,7 +5094,7 @@ bool ImGui::Begin(const char* name, bool* p_open, const ImVec2& size_on_first_us } window->DC.NavLayerCurrent--; - window->DC.AllowNavDefaultFocus = backup_allow_nav_default_focus; + window->DC.ItemFlags = backup_item_options; // Title text (FIXME: refactor text alignment facilities along with RenderText helpers) ImVec2 text_min = window->Pos + style.FramePadding; @@ -5402,32 +5406,41 @@ void ImGui::PopFont() SetCurrentFont(g.FontStack.empty() ? g.IO.Fonts->Fonts[0] : g.FontStack.back()); } -void ImGui::PushAllowKeyboardFocus(bool allow_keyboard_focus) +void ImGui::PushItemFlag(ImGuiItemFlags option, bool enabled) { ImGuiWindow* window = GetCurrentWindow(); - window->DC.AllowKeyboardFocus = allow_keyboard_focus; - window->DC.AllowKeyboardFocusStack.push_back(allow_keyboard_focus); + if (enabled) + window->DC.ItemFlags |= option; + else + window->DC.ItemFlags &= ~option; + window->DC.ItemFlagsStack.push_back(window->DC.ItemFlags); } -void ImGui::PopAllowKeyboardFocus() +void ImGui::PopItemFlag() { ImGuiWindow* window = GetCurrentWindow(); - window->DC.AllowKeyboardFocusStack.pop_back(); - window->DC.AllowKeyboardFocus = window->DC.AllowKeyboardFocusStack.empty() ? true : window->DC.AllowKeyboardFocusStack.back(); + window->DC.ItemFlagsStack.pop_back(); + window->DC.ItemFlags = window->DC.ItemFlagsStack.empty() ? ImGuiItemFlags_Default_ : window->DC.ItemFlagsStack.back(); +} + +void ImGui::PushAllowKeyboardFocus(bool allow_keyboard_focus) +{ + PushItemFlag(ImGuiItemFlags_AllowKeyboardFocus, allow_keyboard_focus); +} + +void ImGui::PopAllowKeyboardFocus() +{ + PopItemFlag(); } void ImGui::PushButtonRepeat(bool repeat) { - ImGuiWindow* window = GetCurrentWindow(); - window->DC.ButtonRepeat = repeat; - window->DC.ButtonRepeatStack.push_back(repeat); + PushItemFlag(ImGuiItemFlags_ButtonRepeat, repeat); } void ImGui::PopButtonRepeat() { - ImGuiWindow* window = GetCurrentWindow(); - window->DC.ButtonRepeatStack.pop_back(); - window->DC.ButtonRepeat = window->DC.ButtonRepeatStack.empty() ? false : window->DC.ButtonRepeatStack.back(); + PopItemFlag(); } void ImGui::PushTextWrapPos(float wrap_pos_x) @@ -5507,7 +5520,6 @@ void ImGui::PushStyleVar(ImGuiStyleVar idx, float val) *pvar = val; } - void ImGui::PushStyleVar(ImGuiStyleVar idx, const ImVec2& val) { ImGuiContext& g = *GImGui; @@ -6413,7 +6425,7 @@ bool ImGui::ButtonEx(const char* label, const ImVec2& size_arg, ImGuiButtonFlags if (!ItemAdd(bb, &id)) return false; - if (window->DC.ButtonRepeat) flags |= ImGuiButtonFlags_Repeat; + if (window->DC.ItemFlags & ImGuiItemFlags_ButtonRepeat) flags |= ImGuiButtonFlags_Repeat; bool hovered, held; bool pressed = ButtonBehavior(bb, id, &hovered, &held, flags); @@ -9481,7 +9493,7 @@ bool ImGui::Selectable(const char* label, bool selected, ImGuiSelectableFlags fl if (flags & ImGuiSelectableFlags_Disabled) PopStyleColor(); // Automatically close popups - if (pressed && !(flags & ImGuiSelectableFlags_DontClosePopups) && (window->Flags & ImGuiWindowFlags_Popup)) + if (pressed && (window->Flags & ImGuiWindowFlags_Popup) && !(flags & ImGuiSelectableFlags_DontClosePopups) && !((window->DC.ItemFlags & ImGuiItemFlags_SelectableDontClosePopup))) CloseCurrentPopup(); return pressed; } diff --git a/imgui_internal.h b/imgui_internal.h index 647adde398a0..f726d2a2e513 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -47,6 +47,7 @@ typedef int ImGuiLayoutType; // enum ImGuiLayoutType_ typedef int ImGuiButtonFlags; // enum ImGuiButtonFlags_ typedef int ImGuiTreeNodeFlags; // enum ImGuiTreeNodeFlags_ typedef int ImGuiSliderFlags; // enum ImGuiSliderFlags_ +typedef int ImGuiItemFlags; // enum ImGuiItemFlags_ //------------------------------------------------------------------------- // STB libraries @@ -574,6 +575,16 @@ struct ImGuiContext } }; +// Transient per-window flags, reset at the beginning of the frame. For child window, inherited from parent on first Begin(). +enum ImGuiItemFlags_ +{ + ImGuiItemFlags_AllowKeyboardFocus = 1 << 0, // [true] + ImGuiItemFlags_AllowNavDefaultFocus = 1 << 1, // [true] + ImGuiItemFlags_ButtonRepeat = 1 << 2, // [false] // Button() can be held will a repeat behavior + ImGuiItemFlags_SelectableDontClosePopup = 1 << 3, // [false] // MenuItem/Selectable() automatically closes owner Popup window + ImGuiItemFlags_Default_ = ImGuiItemFlags_AllowKeyboardFocus|ImGuiItemFlags_AllowNavDefaultFocus +}; + // Transient per-window data, reset at the beginning of the frame // FIXME: That's theory, in practice the delimitation between ImGuiWindow and ImGuiDrawContext is quite tenuous and could be reconsidered. struct IMGUI_API ImGuiDrawContext @@ -602,15 +613,12 @@ struct IMGUI_API ImGuiDrawContext ImGuiLayoutType LayoutType; // We store the current settings outside of the vectors to increase memory locality (reduce cache misses). The vectors are rarely modified. Also it allows us to not heap allocate for short-lived windows which are not using those settings. + ImGuiItemFlags ItemFlags; // == ItemFlagsStack.back() [empty == ImGuiItemFlags_Default] float ItemWidth; // == ItemWidthStack.back(). 0.0: default, >0.0: width in pixels, <0.0: align xx pixels to the right of window float TextWrapPos; // == TextWrapPosStack.back() [empty == -1.0f] - bool AllowKeyboardFocus; // == AllowKeyboardFocusStack.back() [empty == true] - bool AllowNavDefaultFocus; // (not exposed via stack) - bool ButtonRepeat; // == ButtonRepeatStack.back() [empty == false] + ImVectorItemFlagsStack; ImVector ItemWidthStack; ImVector TextWrapPosStack; - ImVector AllowKeyboardFocusStack; - ImVector ButtonRepeatStack; ImVectorGroupStack; ImGuiColorEditMode ColorEditMode; int StackSizesBackup[6]; // Store size of various stacks for asserting @@ -647,8 +655,7 @@ struct IMGUI_API ImGuiDrawContext StateStorage = NULL; LayoutType = ImGuiLayoutType_Vertical; ItemWidth = 0.0f; - ButtonRepeat = false; - AllowKeyboardFocus = AllowNavDefaultFocus = true; + ItemFlags = ImGuiItemFlags_Default_; TextWrapPos = -1.0f; ColorEditMode = ImGuiColorEditMode_RGB; memset(StackSizesBackup, 0, sizeof(StackSizesBackup)); @@ -782,8 +789,9 @@ namespace ImGui IMGUI_API ImVec2 CalcItemSize(ImVec2 size, float default_x, float default_y); IMGUI_API float CalcWrapWidthForPos(const ImVec2& pos, float wrap_pos_x); + IMGUI_API void PushItemFlag(ImGuiItemFlags option, bool enabled); + IMGUI_API void PopItemFlag(); IMGUI_API void OpenPopupEx(const char* str_id, bool reopen_existing); - IMGUI_API int CalcTypematicPressedRepeatAmount(float t, float t_prev, float repeat_delay, float repeat_rate); // NB: All position are in absolute pixels coordinates (not window coordinates) From 761a74c62b4d55fb42eae32bfa0b321c3f601ced Mon Sep 17 00:00:00 2001 From: ocornut Date: Sun, 7 Aug 2016 20:21:18 +0200 Subject: [PATCH 085/823] Selectable/MenuItem: Not activated on Click but only on Release is more standard (#126, #245, #323) Apparently menu items started with OnClick (vs OnClickHoldRelease) when doing #126. Hope to not break anything. Also allows using xxx_DontClosePopup flags. --- imgui.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/imgui.cpp b/imgui.cpp index 1b5c5f0242b2..75c45e379da2 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -9467,7 +9467,7 @@ bool ImGui::Selectable(const char* label, bool selected, ImGuiSelectableFlags fl ImGuiButtonFlags button_flags = 0; if (flags & ImGuiSelectableFlags_Menu) button_flags |= ImGuiButtonFlags_PressedOnClick; - if (flags & ImGuiSelectableFlags_MenuItem) button_flags |= ImGuiButtonFlags_PressedOnClick|ImGuiButtonFlags_PressedOnRelease; + if (flags & ImGuiSelectableFlags_MenuItem) button_flags |= ImGuiButtonFlags_PressedOnRelease; if (flags & ImGuiSelectableFlags_Disabled) button_flags |= ImGuiButtonFlags_Disabled; if (flags & ImGuiSelectableFlags_AllowDoubleClick) button_flags |= ImGuiButtonFlags_PressedOnClickRelease | ImGuiButtonFlags_PressedOnDoubleClick; bool hovered, held; From 09cba02d3f0a1e84ed682dae27bfba48b3ecb6e4 Mon Sep 17 00:00:00 2001 From: ocornut Date: Sun, 7 Aug 2016 20:31:51 +0200 Subject: [PATCH 086/823] Nav: DragBehavior: Fix for fast speed (#323 #180) --- imgui.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/imgui.cpp b/imgui.cpp index 75c45e379da2..69c07e206132 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -7676,7 +7676,7 @@ bool ImGui::DragBehavior(const ImRect& frame_bb, ImGuiID id, float* v, float v_s } if (g.ActiveIdSource == ImGuiInputSource_Nav) { - adjust_delta = GetNavInputAmount2d(0, ImGuiNavReadMode_RepeatFast, 1.0f/10.0f, 1.0f).x; + adjust_delta = GetNavInputAmount2d(0, ImGuiNavReadMode_RepeatFast, 1.0f/10.0f, 10.0f).x; } adjust_delta *= v_speed; g.DragLastMouseDelta.x = mouse_drag_delta.x; From df1d1b5b25b8a7d36bfa7d69b0e83b2478acb487 Mon Sep 17 00:00:00 2001 From: ocornut Date: Sun, 7 Aug 2016 20:40:57 +0200 Subject: [PATCH 087/823] Nav: DragBehavior: Adjust minimum step to displayed precision when using navigation (#323, #180) --- imgui.cpp | 2 ++ imgui.h | 1 + 2 files changed, 3 insertions(+) diff --git a/imgui.cpp b/imgui.cpp index 69c07e206132..ebe07cb71c7e 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -7662,6 +7662,8 @@ bool ImGui::DragBehavior(const ImRect& frame_bb, ImGuiID id, float* v, float v_s if (v_speed == 0.0f && (v_max - v_min) != 0.0f && (v_max - v_min) < FLT_MAX) v_speed = (v_max - v_min) * g.DragSpeedDefaultRatio; + if (g.ActiveIdSource == ImGuiInputSource_Nav) + v_speed = ImMax(v_speed, GetMinimumStepAtDecimalPrecision(decimal_precision)); float v_cur = g.DragCurrentValue; const ImVec2 mouse_drag_delta = GetMouseDragDelta(0, 1.0f); diff --git a/imgui.h b/imgui.h index d2cebfebba63..5b0bc55d76a0 100644 --- a/imgui.h +++ b/imgui.h @@ -282,6 +282,7 @@ namespace ImGui // Widgets: Drags (tip: ctrl+click on a drag box to input with keyboard. manually input values aren't clamped, can go off-bounds) // For all the Float2/Float3/Float4/Int2/Int3/Int4 versions of every functions, remember than a 'float v[3]' function argument is the same as 'float* v'. You can pass address of your first element out of a contiguous set, e.g. &myvector.x + // Speed are per-pixel of mouse movement (v_speed=0.2f: mouse needs to move by 5 pixels to increase value by 1). For gamepad/keyboard navigation, minimum speed is Max(v_speed, minimum_step_at_given_precision). IMGUI_API bool DragFloat(const char* label, float* v, float v_speed = 1.0f, float v_min = 0.0f, float v_max = 0.0f, const char* display_format = "%.3f", float power = 1.0f); // If v_min >= v_max we have no bound IMGUI_API bool DragFloat2(const char* label, float v[2], float v_speed = 1.0f, float v_min = 0.0f, float v_max = 0.0f, const char* display_format = "%.3f", float power = 1.0f); IMGUI_API bool DragFloat3(const char* label, float v[3], float v_speed = 1.0f, float v_min = 0.0f, float v_max = 0.0f, const char* display_format = "%.3f", float power = 1.0f); From 9501cd999151822d8d8232cccded8e7280967296 Mon Sep 17 00:00:00 2001 From: ocornut Date: Sat, 13 Aug 2016 14:22:34 +0200 Subject: [PATCH 088/823] InputText: Fixed calling callback on frame of losing active id, fix part of 848e62bfe0fe6083668afebdfaa5ab234a4817d9 (nav branch only) #323 #701 --- imgui.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index bf375ae92aca..e7a2a76ab57e 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -8695,7 +8695,7 @@ bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2 } bool cancel_edit = false; - if (g.ActiveId == id && !g.ActiveIdIsJustActivated) + if (g.ActiveId == id && !g.ActiveIdIsJustActivated && !clear_active_id) { // Handle key-presses const int k_mask = (io.KeyShift ? STB_TEXTEDIT_K_SHIFT : 0); @@ -8806,7 +8806,7 @@ bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2 value_changed = true; } } - else + if (!cancel_edit && !clear_active_id) { // Apply new value immediately - copy modified buffer back // Note that as soon as the input box is active, the in-widget value gets priority over any underlying modification of the input buffer From 6c19d7b13c3765b8df555dced1919f806f843759 Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 15 Aug 2016 11:41:56 +0200 Subject: [PATCH 089/823] Nav: Fixed clipping rect of navigation highlight, notably for collapsing arrow (#323) --- imgui.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index e7a2a76ab57e..252d795e6e36 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2080,10 +2080,14 @@ static void RenderNavHighlight(ImU32 id, const ImRect& bb) if (id != g.NavId || g.NavDisableHighlight) return; ImGuiWindow* window = ImGui::GetCurrentWindow(); - window->DrawList->PushClipRect(window->InnerRect.Min - ImVec2(2,2), window->InnerRect.Max + ImVec2(2,2)); + + ImRect clip_rect(window->InnerRect.Min - ImVec2(2,2), window->InnerRect.Max + ImVec2(2,2)); + if (!window->ClipRect.Contains(clip_rect)) + window->DrawList->PushClipRect(clip_rect.Min, clip_rect.Max); window->DrawList->AddRect(bb.Min - ImVec2(2,2), bb.Max + ImVec2(2,2), ImGui::GetColorU32(ImGuiCol_HeaderHovered), g.Style.FrameRounding); //window->DrawList->AddRect(g.NavRefRectScreen.Min, g.NavRefRectScreen.Max, IM_COL32(255,0,0,255)); - window->DrawList->PopClipRect(); + if (!window->ClipRect.Contains(clip_rect)) + window->DrawList->PopClipRect(); } // Declare item bounding box for clipping and interaction. From cf16ba6572c1bdc00a1eb10d5e0984695d2f33a2 Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 15 Aug 2016 11:52:02 +0200 Subject: [PATCH 090/823] Nav: Exposed RenderNavHighlight() in imgui_internal.h to increase discoverability and reordered arguments to be more consistent (#323) --- imgui.cpp | 24 ++++++++++++------------ imgui_internal.h | 1 + 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 252d795e6e36..a99a1713b83d 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2074,7 +2074,7 @@ static bool NavScoreItem(ImRect cand) return new_best; } -static void RenderNavHighlight(ImU32 id, const ImRect& bb) +void ImGui::RenderNavHighlight(const ImRect& bb, ImGuiID id) { ImGuiContext& g = *GImGui; if (id != g.NavId || g.NavDisableHighlight) @@ -4358,7 +4358,7 @@ void ImGui::EndChild() if (/*!(window->Flags & ImGuiWindowFlags_NavFlattened) &&*/ (window->DC.NavLayerActiveFlags != 0 || window->DC.NavHasScroll)) { ItemAdd(bb, &id); - RenderNavHighlight(id, bb); + RenderNavHighlight(bb, id); } else { @@ -5093,7 +5093,7 @@ bool ImGui::Begin(const char* name, bool* p_open, const ImVec2& size_on_first_us ItemAdd(bb, &id); // To allow navigation if (ButtonBehavior(bb, id, NULL, NULL)) window->CollapseToggleWanted = true; // Defer collapsing to next frame as we are too far in the Begin() function - RenderNavHighlight(id, bb); + RenderNavHighlight(bb, id); RenderCollapseTriangle(window->Pos + style.FramePadding, !window->Collapsed, 1.0f, true); } @@ -6435,7 +6435,7 @@ bool ImGui::ButtonEx(const char* label, const ImVec2& size_arg, ImGuiButtonFlags // Render const ImU32 col = GetColorU32((hovered && held) ? ImGuiCol_ButtonActive : hovered ? ImGuiCol_ButtonHovered : ImGuiCol_Button); - RenderNavHighlight(id, bb); + RenderNavHighlight(bb, id); RenderFrame(bb.Min, bb.Max, col, true, style.FrameRounding); RenderTextClipped(bb.Min, bb.Max, label, NULL, &label_size, ImGuiAlign_Center | ImGuiAlign_VCenter); @@ -6565,7 +6565,7 @@ bool ImGui::ImageButton(ImTextureID user_texture_id, const ImVec2& size, const I // Render const ImU32 col = GetColorU32((hovered && held) ? ImGuiCol_ButtonActive : hovered ? ImGuiCol_ButtonHovered : ImGuiCol_Button); - RenderNavHighlight(id, bb); + RenderNavHighlight(bb, id); RenderFrame(bb.Min, bb.Max, col, true, ImClamp((float)ImMin(padding.x, padding.y), 0.0f, style.FrameRounding)); if (bg_col.w > 0.0f) window->DrawList->AddRectFilled(image_bb.Min, image_bb.Max, GetColorU32(bg_col)); @@ -7282,7 +7282,7 @@ bool ImGui::SliderBehavior(const ImRect& frame_bb, ImGuiID id, float* v, float v // Draw frame const ImU32 frame_col = GetColorU32((g.ActiveId == id && g.ActiveIdSource == ImGuiInputSource_Nav) ? ImGuiCol_FrameBgActive : ImGuiCol_FrameBg); - RenderNavHighlight(id, frame_bb); + RenderNavHighlight(frame_bb, id); RenderFrame(frame_bb.Min, frame_bb.Max, frame_col, true, style.FrameRounding); const bool is_non_linear = (power < 1.0f-0.00001f) && (power > 1.0f-0.00001f); @@ -7647,7 +7647,7 @@ bool ImGui::DragBehavior(const ImRect& frame_bb, ImGuiID id, float* v, float v_s // Draw frame const ImU32 frame_col = GetColorU32(g.ActiveId == id ? ImGuiCol_FrameBgActive : g.HoveredId == id ? ImGuiCol_FrameBgHovered : ImGuiCol_FrameBg); - RenderNavHighlight(id, frame_bb); + RenderNavHighlight(frame_bb, id); RenderFrame(frame_bb.Min, frame_bb.Max, frame_col, true, style.FrameRounding); bool value_changed = false; @@ -8143,7 +8143,7 @@ bool ImGui::Checkbox(const char* label, bool* v) if (pressed) *v = !(*v); - RenderNavHighlight(id, total_bb); + RenderNavHighlight(total_bb, id); RenderFrame(check_bb.Min, check_bb.Max, GetColorU32((held && hovered) ? ImGuiCol_FrameBgActive : hovered ? ImGuiCol_FrameBgHovered : ImGuiCol_FrameBg), true, style.FrameRounding); if (*v) { @@ -8210,7 +8210,7 @@ bool ImGui::RadioButton(const char* label, bool active) bool hovered, held; bool pressed = ButtonBehavior(total_bb, id, &hovered, &held); - RenderNavHighlight(id, total_bb); + RenderNavHighlight(total_bb, id); window->DrawList->AddCircleFilled(center, radius, GetColorU32((held && hovered) ? ImGuiCol_FrameBgActive : hovered ? ImGuiCol_FrameBgHovered : ImGuiCol_FrameBg), 16); if (active) { @@ -8906,7 +8906,7 @@ bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2 // Select which buffer we are going to display. When ImGuiInputTextFlags_NoLiveEdit is set 'buf' might still be the old value. We set buf to NULL to prevent accidental usage from now on. const char* buf_display = (g.ActiveId == id && is_editable) ? edit_state.TempTextBuffer.Data : buf; buf = NULL; - RenderNavHighlight(id, frame_bb); + RenderNavHighlight(frame_bb, id); if (!is_multiline) RenderFrame(frame_bb.Min, frame_bb.Max, GetColorU32(ImGuiCol_FrameBg), true, style.FrameRounding); @@ -9330,7 +9330,7 @@ bool ImGui::Combo(const char* label, int* current_item, bool (*items_getter)(voi bool popup_open = IsPopupOpen(id); const ImRect value_bb(frame_bb.Min, frame_bb.Max - ImVec2(arrow_size, 0.0f)); - RenderNavHighlight(id, frame_bb); + RenderNavHighlight(frame_bb, id); RenderFrame(frame_bb.Min, frame_bb.Max, GetColorU32(ImGuiCol_FrameBg), true, style.FrameRounding); RenderFrame(ImVec2(frame_bb.Max.x-arrow_size, frame_bb.Min.y), frame_bb.Max, GetColorU32(popup_open || hovered || navigated ? ImGuiCol_ButtonHovered : ImGuiCol_Button), true, style.FrameRounding); // FIXME-ROUNDING RenderCollapseTriangle(ImVec2(frame_bb.Max.x-arrow_size, frame_bb.Min.y) + style.FramePadding, true); @@ -9861,7 +9861,7 @@ bool ImGui::ColorButton(const ImVec4& col, bool small_height, bool outline_borde bool hovered, held; bool pressed = ButtonBehavior(bb, id, &hovered, &held); - RenderNavHighlight(id, bb); + RenderNavHighlight(bb, id); RenderFrame(bb.Min, bb.Max, GetColorU32(col), outline_border, style.FrameRounding); if (g.HoveredId == id) diff --git a/imgui_internal.h b/imgui_internal.h index f726d2a2e513..0bbeba417dee 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -804,6 +804,7 @@ namespace ImGui IMGUI_API void RenderCollapseTriangle(ImVec2 pos, bool is_open, float scale = 1.0f, bool shadow = false); IMGUI_API void RenderBullet(ImVec2 pos); IMGUI_API void RenderCheckMark(ImVec2 pos, ImU32 col); + IMGUI_API void RenderNavHighlight(const ImRect& bb, ImGuiID id); // Navigation highlight IMGUI_API const char* FindRenderedTextEnd(const char* text, const char* text_end = NULL); // Find the optional ## from which we stop displaying text. IMGUI_API bool ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool* out_held, ImGuiButtonFlags flags = 0); From 3ab0d5cdfde91c6db6a4f51d3999ba36882bb2dd Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 15 Aug 2016 13:07:39 +0200 Subject: [PATCH 091/823] Nav: NavHighlight gets its own color (default to Header color), made rectangle thicker (#323) --- imgui.cpp | 6 ++++-- imgui.h | 3 ++- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index a99a1713b83d..26ff777b1fbb 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -833,6 +833,7 @@ ImGuiStyle::ImGuiStyle() Colors[ImGuiCol_PlotHistogramHovered] = ImVec4(1.00f, 0.60f, 0.00f, 1.00f); Colors[ImGuiCol_TextSelectedBg] = ImVec4(0.00f, 0.00f, 1.00f, 0.35f); Colors[ImGuiCol_ModalWindowDarkening] = ImVec4(0.20f, 0.20f, 0.20f, 0.35f); + Colors[ImGuiCol_NavHighlight] = Colors[ImGuiCol_HeaderHovered]; Colors[ImGuiCol_NavWindowingHighlight] = ImVec4(1.00f, 1.00f, 1.00f, 0.12f); } @@ -2081,10 +2082,10 @@ void ImGui::RenderNavHighlight(const ImRect& bb, ImGuiID id) return; ImGuiWindow* window = ImGui::GetCurrentWindow(); - ImRect clip_rect(window->InnerRect.Min - ImVec2(2,2), window->InnerRect.Max + ImVec2(2,2)); + ImRect clip_rect(window->InnerRect.Min - ImVec2(4,4), window->InnerRect.Max + ImVec2(4,4)); if (!window->ClipRect.Contains(clip_rect)) window->DrawList->PushClipRect(clip_rect.Min, clip_rect.Max); - window->DrawList->AddRect(bb.Min - ImVec2(2,2), bb.Max + ImVec2(2,2), ImGui::GetColorU32(ImGuiCol_HeaderHovered), g.Style.FrameRounding); + window->DrawList->AddRect(bb.Min - ImVec2(3,3), bb.Max + ImVec2(3,3), GetColorU32(ImGuiCol_NavHighlight), g.Style.FrameRounding, 0x0F, 2.0f); //window->DrawList->AddRect(g.NavRefRectScreen.Min, g.NavRefRectScreen.Max, IM_COL32(255,0,0,255)); if (!window->ClipRect.Contains(clip_rect)) window->DrawList->PopClipRect(); @@ -5599,6 +5600,7 @@ const char* ImGui::GetStyleColName(ImGuiCol idx) case ImGuiCol_PlotHistogramHovered: return "PlotHistogramHovered"; case ImGuiCol_TextSelectedBg: return "TextSelectedBg"; case ImGuiCol_ModalWindowDarkening: return "ModalWindowDarkening"; + case ImGuiCol_NavHighlight: return "NavHighlight"; case ImGuiCol_NavWindowingHighlight: return "NavWindowingHighlight"; } IM_ASSERT(0); diff --git a/imgui.h b/imgui.h index 5b0bc55d76a0..420df52da8af 100644 --- a/imgui.h +++ b/imgui.h @@ -666,7 +666,8 @@ enum ImGuiCol_ ImGuiCol_PlotHistogramHovered, ImGuiCol_TextSelectedBg, ImGuiCol_ModalWindowDarkening, // darken entire screen when a modal window is active - ImGuiCol_NavWindowingHighlight, // when holding NavMenu to focus/move/resize windows + ImGuiCol_NavHighlight, // gamepad/keyboard: current highlighted item + ImGuiCol_NavWindowingHighlight, // gamepad/keyboard: when holding NavMenu to focus/move/resize windows ImGuiCol_COUNT }; From ead79dcdac88ed4d06e2f42b83e0b27599c940b2 Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 15 Aug 2016 17:34:17 +0200 Subject: [PATCH 092/823] Metrics: 64-bit display fix --- imgui.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/imgui.cpp b/imgui.cpp index 26ff777b1fbb..d50b13b72627 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -10611,7 +10611,7 @@ void ImGui::ShowMetricsWindow(bool* p_open) ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate); ImGui::Text("%d vertices, %d indices (%d triangles)", ImGui::GetIO().MetricsRenderVertices, ImGui::GetIO().MetricsRenderIndices, ImGui::GetIO().MetricsRenderIndices / 3); ImGui::Text("%d allocations", ImGui::GetIO().MetricsAllocs); - ImGui::Text("sizeof(ImGuiContext) = %u, sizeof(ImGuiWindow) = %u", sizeof(ImGuiContext), sizeof(ImGuiWindow)); + ImGui::Text("sizeof(ImGuiContext) = %u, sizeof(ImGuiWindow) = %u", (int)sizeof(ImGuiContext), (int)sizeof(ImGuiWindow)); static bool show_clip_rects = true; ImGui::Checkbox("Show clipping rectangles when hovering a ImDrawCmd", &show_clip_rects); ImGui::Separator(); From e3fec8c0aaa00e92c0c22570ff7a7df6b3910074 Mon Sep 17 00:00:00 2001 From: ocornut Date: Sat, 20 Aug 2016 19:19:58 +0200 Subject: [PATCH 093/823] Renamed function (#323) --- imgui.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index d50b13b72627..a26dd9be9e6c 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2363,7 +2363,7 @@ static ImVec2 NavCalcPreferredMousePos() return ImClamp(p, r.Min, r.Max); } -static void SetNavIdMoveMouse(ImGuiID id, const ImRect& rect_rel) +static void SetNavIdAndMoveMouse(ImGuiID id, const ImRect& rect_rel) { ImGuiContext& g = *GImGui; g.NavId = id; @@ -2519,7 +2519,7 @@ static void NavUpdate() // Apply result from previous frame navigation directional move request ImGui::SetActiveID(0); - SetNavIdMoveMouse(g.NavMoveResultId, g.NavMoveResultRectRel); + SetNavIdAndMoveMouse(g.NavMoveResultId, g.NavMoveResultRectRel); g.NavMoveFromClampedRefRect = false; } @@ -2590,7 +2590,7 @@ static void NavUpdate() g.NavDisableHighlight = false; g.NavDisableMouseHover = true; if (g.NavLayer == 0 && g.NavWindow->NavLastId) - SetNavIdMoveMouse(g.NavWindow->NavLastId, ImRect()); + SetNavIdAndMoveMouse(g.NavWindow->NavLastId, ImRect()); else NavInitWindow(g.NavWindow, true); } @@ -2632,7 +2632,7 @@ static void NavUpdate() // Leave the "menu" layer g.NavLayer = 0; if (g.NavWindow->NavLastId) - SetNavIdMoveMouse(g.NavWindow->NavLastId, ImRect()); + SetNavIdAndMoveMouse(g.NavWindow->NavLastId, ImRect()); else NavInitWindow(g.NavWindow, true); } From e4c099d67c653f03138b500554a5fba05abf1bc4 Mon Sep 17 00:00:00 2001 From: ocornut Date: Sat, 20 Aug 2016 22:11:00 +0200 Subject: [PATCH 094/823] Nav: Comments + fixed handling of PadLeft in menus (fix e55882f) (#323) --- imgui.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index a26dd9be9e6c..98398001ce40 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -164,9 +164,10 @@ - query focus information with IsWindowFocused(), IsAnyWindowFocused(), IsAnyItemFocused() functions. The reality is more complex than what those flags can express. Please discuss your issues and usage scenario in the thread above. As we head toward more keyboard-oriented development this aspect will need to be improved. - - It is recommended that you enable the 'io.NavMovesMouse' option. Enabling it instructs ImGui that it can request moving your move cursor to track navigated items and ease readability. + - It is recommended that you enable the 'io.NavMovesMouse' option. Enabling it instructs ImGui that it can move your move cursor to track navigated items and ease readability. When enabled and using directional navigation (with d-pad or arrow keys), the NewFrame() functions may alter 'io.MousePos' and set 'io.WantMoveMouse' to notify you that it did so. - When that happens your back-end will need to move the OS mouse cursor on the next frame. The examples binding in examples/ do that. + When that happens your back-end NEEDS to move the OS or underlying mouse cursor on the next frame. The examples binding in examples/ do that. + (Important: It you set 'io.NavMovesMouse' to true but don't honor 'io.WantMoveMouse' properly, imgui will misbehave as it will think your mouse is moving back and forth.) // Application init io.NavMovesMouse = true; @@ -9794,7 +9795,7 @@ bool ImGui::BeginMenu(const char* label, bool enabled) want_open = true; g.NavMoveRequest = false; } - if (g.NavWindow && g.NavWindow->ParentWindow == window && g.NavMoveRequest && g.NavMoveDir == ImGuiNavDir_Left) // Nav-Left to close + if (g.NavWindow && g.NavWindow->ParentWindow == window && g.NavMoveRequest && g.NavMoveDir == ImGuiNavDir_Left && IsPopupOpen(id)) // Nav-Left to close { want_close = true; g.NavMoveRequest = false; From 4f7c63a7af393db05e7706140ba04f2a8282e521 Mon Sep 17 00:00:00 2001 From: ocornut Date: Sat, 20 Aug 2016 23:25:53 +0200 Subject: [PATCH 095/823] Nav: Fixed a bug where mouse positioning requests would be sent while opening submenus with mouse (#323) --- imgui.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/imgui.cpp b/imgui.cpp index 98398001ce40..9936ba349368 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2463,7 +2463,7 @@ static void NavUpdate() IM_ASSERT(g.NavWindow); g.NavId = g.NavInitDefaultResultId; g.NavRefRectRel = g.NavInitDefaultResultRectRel; - if (!g.NavDisableHighlight) + if (g.NavDisableMouseHover) g.NavMousePosDirty = true; if (g.NavLayer == 0) g.NavWindow->NavLastId = g.NavId; From 695ca7bb45eea9a48b84a8def2d15616aeffdc41 Mon Sep 17 00:00:00 2001 From: ocornut Date: Sat, 20 Aug 2016 23:27:25 +0200 Subject: [PATCH 096/823] Nav: Tidying up. Comments. (#323) --- imgui.cpp | 47 ++++++++++++++++++++++++----------------------- imgui_internal.h | 4 ++-- 2 files changed, 26 insertions(+), 25 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 9936ba349368..9fa3a282b0c0 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2333,6 +2333,24 @@ int ImGui::GetFrameCount() return GImGui->FrameCount; } +static void SetNavId(ImGuiID id) +{ + ImGuiContext& g = *GImGui; + g.NavId = id; + if (g.NavLayer == 0) + g.NavWindow->NavLastId = g.NavId; +} + +static void SetNavIdAndMoveMouse(ImGuiID id, const ImRect& rect_rel) +{ + ImGuiContext& g = *GImGui; + SetNavId(id); + g.NavRefRectRel = rect_rel; + g.NavMousePosDirty = true; + g.NavDisableHighlight = false; + g.NavDisableMouseHover = true; +} + // This needs to be called before we submit any widget (aka in or before Begin) static void NavInitWindow(ImGuiWindow* window, bool force_reinit) { @@ -2340,9 +2358,7 @@ static void NavInitWindow(ImGuiWindow* window, bool force_reinit) IM_ASSERT(window == g.NavWindow); if (!(window->Flags & ImGuiWindowFlags_ChildWindow) || (window->Flags & ImGuiWindowFlags_Popup) || (window->NavLastId == 0) || force_reinit) { - g.NavId = 0; - if (g.NavLayer == 0) - window->NavLastId = 0; + SetNavId(0); g.NavInitDefaultRequest = true; g.NavInitDefaultResultId = 0; g.NavInitDefaultResultExplicit = false; @@ -2364,18 +2380,6 @@ static ImVec2 NavCalcPreferredMousePos() return ImClamp(p, r.Min, r.Max); } -static void SetNavIdAndMoveMouse(ImGuiID id, const ImRect& rect_rel) -{ - ImGuiContext& g = *GImGui; - g.NavId = id; - if (g.NavLayer == 0) - g.NavWindow->NavLastId = g.NavId; - g.NavRefRectRel = rect_rel; - g.NavMousePosDirty = true; - g.NavDisableHighlight = false; - g.NavDisableMouseHover = true; -} - static int FindWindowIndex(ImGuiWindow* window) // FIXME-OPT O(N) { ImGuiContext& g = *GImGui; @@ -2461,12 +2465,10 @@ static void NavUpdate() { // Apply result from previous navigation init request (typically select the first item, unless SetItemDefaultFocus() has been called) IM_ASSERT(g.NavWindow); - g.NavId = g.NavInitDefaultResultId; + SetNavId(g.NavInitDefaultResultId); g.NavRefRectRel = g.NavInitDefaultResultRectRel; if (g.NavDisableMouseHover) g.NavMousePosDirty = true; - if (g.NavLayer == 0) - g.NavWindow->NavLastId = g.NavId; } g.NavInitDefaultRequest = false; g.NavInitDefaultResultExplicit = false; @@ -2616,9 +2618,7 @@ static void NavUpdate() ImGuiWindow* child_window = g.NavWindow; ImGuiWindow* parent_window = g.NavWindow->ParentWindow; ImGui::FocusWindow(parent_window); - g.NavId = parent_window->GetChildID(child_window); - if (g.NavLayer == 0) - parent_window->NavLastId = g.NavId; + SetNavId(parent_window->GetChildID(child_window)); g.NavIdIsAlive = false; if (g.NavDisableMouseHover) g.NavMousePosDirty = true; @@ -9756,7 +9756,8 @@ bool ImGui::BeginMenu(const char* label, bool enabled) if (!enabled) PopStyleColor(); } - bool hovered = enabled && IsHovered(window->DC.LastItemRect, id); + bool hovered = enabled && IsHovered(window->DC.LastItemRect, id); // FIXME: Why not using window->DC.LastItemHoveredAndUsable / IsItemHovered() ? + if (menuset_is_open) g.NavWindow = backed_nav_window; @@ -10724,7 +10725,7 @@ void ImGui::ShowMetricsWindow(bool* p_open) ImGui::Text("HoveredRootWindow: '%s'", g.HoveredRootWindow ? g.HoveredRootWindow->Name : "NULL"); ImGui::Text("HoveredId: 0x%08X/0x%08X", g.HoveredId, g.HoveredIdPreviousFrame); // Data is "in-flight" so depending on when the Metrics window is called we may see current frame information or not ImGui::Text("ActiveId: 0x%08X/0x%08X, ActiveIdWindow: %s", g.ActiveId, g.ActiveIdPreviousFrame, g.ActiveIdWindow ? g.ActiveIdWindow->Name : "NULL"); - ImGui::Text("NavWindow: '%s', NavId: 0x%08X", g.NavWindow ? g.NavWindow->Name : "NULL", g.NavId); + ImGui::Text("NavWindow: '%s', NavId: 0x%08X, NavLayer: %d", g.NavWindow ? g.NavWindow->Name : "NULL", g.NavId, g.NavLayer); ImGui::Text("NavRefRectRel: (%.1f,%.1f)(%.1f,%.1f)", g.NavRefRectRel.Min.x, g.NavRefRectRel.Min.y, g.NavRefRectRel.Max.x, g.NavRefRectRel.Max.y); ImGui::Text("NavUsable: %d, NavActive: %d", g.IO.NavUsable, g.IO.NavActive); ImGui::Text("NavDisableHighlight: %d, NavDisableMouseHover: %d", g.NavDisableHighlight, g.NavDisableMouseHover); diff --git a/imgui_internal.h b/imgui_internal.h index 0bbeba417dee..cabd56018722 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -416,8 +416,8 @@ struct ImGuiContext int NavIdTabCounter; // == NavWindow->DC.FocusIdxTabCounter at time of NavId processing bool NavIdIsAlive; // Nav widget has been seen this frame ~~ NavRefRectRel is valid bool NavMousePosDirty; - bool NavDisableHighlight; // When user starts using mouse, we hide gamepad/keyboard functionalities - bool NavDisableMouseHover; // When user starts using gamepad/keyboard, we disable mouse hovering until mouse is touched again + bool NavDisableHighlight; // When user starts using mouse, we hide gamepad/keyboard highlight (nb: but they are still available, which is why NavDisableHighlight isn't always != NavDisableMouseHover) + bool NavDisableMouseHover; // When user starts using gamepad/keyboard, we hide mouse hovering highlight until mouse is touched again. bool NavInitDefaultRequest; // Init request for appearing window to select first item ImGuiID NavInitDefaultResultId; ImRect NavInitDefaultResultRectRel; From bf4265785095e4e1a41d90a32200974d5538bf2e Mon Sep 17 00:00:00 2001 From: ocornut Date: Sat, 20 Aug 2016 23:59:54 +0200 Subject: [PATCH 097/823] Nav: Clearing mouse hover flag using MouseClicked[] test instead of MouseDown[] so that invalid mouse button won't keep breaking nav (#323) --- imgui.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/imgui.cpp b/imgui.cpp index 9fa3a282b0c0..8d85c29ffaa3 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2817,7 +2817,7 @@ void ImGui::NewFrame() { g.IO.MouseDragMaxDistanceSqr[i] = ImMax(g.IO.MouseDragMaxDistanceSqr[i], ImLengthSqr(g.IO.MousePos - g.IO.MouseClickedPos[i])); } - if (g.IO.MouseDown[i]) // Pressing any mouse button reactivate mouse hovering which may have been deactivated by gamepad/keyboard navigation + if (g.IO.MouseClicked[i]) // Clicking any mouse button reactivate mouse hovering which may have been deactivated by gamepad/keyboard navigation g.NavDisableMouseHover = false; } From 30c04d0dbefb89822840b6dc71d43490fb14150c Mon Sep 17 00:00:00 2001 From: ocornut Date: Sun, 21 Aug 2016 00:10:48 +0200 Subject: [PATCH 098/823] Nav: Mouse pos passed to backend always rounded, so that lossy application of non-integer mouse pos doesn't lead to undesirable movement (#3 --- imgui.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/imgui.cpp b/imgui.cpp index 8d85c29ffaa3..fccc7e2db4c9 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2377,7 +2377,7 @@ static ImVec2 NavCalcPreferredMousePos() return g.IO.MousePos; ImVec2 p = g.NavWindow->Pos + ImVec2(g.NavRefRectRel.Min.x + ImMin(g.Style.FramePadding.x*4, g.NavRefRectRel.GetWidth()), g.NavRefRectRel.Max.y - ImMin(g.Style.FramePadding.y, g.NavRefRectRel.GetHeight())); ImRect r = GetVisibleRect(); - return ImClamp(p, r.Min, r.Max); + return ImFloor(ImClamp(p, r.Min, r.Max)); // ImFloor() is important because non-integer mouse position application in backend might be lossy and result in undesirable non-zero delta. } static int FindWindowIndex(ImGuiWindow* window) // FIXME-OPT O(N) From 43ee5d73e9f524320489720639942ff60bbfaf54 Mon Sep 17 00:00:00 2001 From: ocornut Date: Sun, 21 Aug 2016 11:45:50 +0200 Subject: [PATCH 099/823] Nav: Hovering MenuItem/Selectable with mouse makes NavId, matching what seems to be Windows beahvior at least for menus (#323) --- imgui.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/imgui.cpp b/imgui.cpp index fccc7e2db4c9..f47a4108465e 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -9484,6 +9484,13 @@ bool ImGui::Selectable(const char* label, bool selected, ImGuiSelectableFlags fl if (flags & ImGuiSelectableFlags_Disabled) selected = false; + // Hovering selectable with mouse updates NavId accordingly so navigation can be resumed with gamepad/keyboard (this doesn't happen on most widgets) + if (hovered && !g.NavDisableMouseHover && (g.IO.MouseDelta.x != 0.0f || g.IO.MouseDelta.y != 0.0f)) + { + g.NavDisableHighlight = true; + SetNavId(id); + } + // Render if (hovered || selected) { From ea2425ad9a423425d454991c6446b1f258fa6069 Mon Sep 17 00:00:00 2001 From: ocornut Date: Sun, 21 Aug 2016 12:44:59 +0200 Subject: [PATCH 100/823] Nav: Fixed entering child with PadActivate not setting ActiveIdSource to Nav (#323) --- imgui.cpp | 5 ++++- imgui_internal.h | 1 + 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/imgui.cpp b/imgui.cpp index f47a4108465e..ae8fb2f6d676 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -4321,6 +4321,7 @@ bool ImGui::BeginChild(const char* str_id, const ImVec2& size_arg, bool border, FocusWindow(child_window); NavInitWindow(child_window, false); SetActiveIDNoNav(id+1, child_window); // Steal ActiveId with a dummy id so that key-press won't activate child item + GImGui->ActiveIdSource = ImGuiInputSource_Nav; } return ret; @@ -10728,10 +10729,12 @@ void ImGui::ShowMetricsWindow(bool* p_open) } if (ImGui::TreeNode("Basic state")) { + const char* input_source_names[] = { "None", "Mouse", "Nav" }; IM_ASSERT(IM_ARRAYSIZE(input_source_names) == ImGuiInputSource_Count_); ImGui::Text("HoveredWindow: '%s'", g.HoveredWindow ? g.HoveredWindow->Name : "NULL"); ImGui::Text("HoveredRootWindow: '%s'", g.HoveredRootWindow ? g.HoveredRootWindow->Name : "NULL"); ImGui::Text("HoveredId: 0x%08X/0x%08X", g.HoveredId, g.HoveredIdPreviousFrame); // Data is "in-flight" so depending on when the Metrics window is called we may see current frame information or not - ImGui::Text("ActiveId: 0x%08X/0x%08X, ActiveIdWindow: %s", g.ActiveId, g.ActiveIdPreviousFrame, g.ActiveIdWindow ? g.ActiveIdWindow->Name : "NULL"); + ImGui::Text("ActiveId: 0x%08X/0x%08X, ActiveIdSource: %s", g.ActiveId, g.ActiveIdPreviousFrame, input_source_names[g.ActiveIdSource]); + ImGui::Text("ActiveIdWindow: '%s", g.ActiveIdWindow ? g.ActiveIdWindow->Name : "NULL"); ImGui::Text("NavWindow: '%s', NavId: 0x%08X, NavLayer: %d", g.NavWindow ? g.NavWindow->Name : "NULL", g.NavId, g.NavLayer); ImGui::Text("NavRefRectRel: (%.1f,%.1f)(%.1f,%.1f)", g.NavRefRectRel.Min.x, g.NavRefRectRel.Min.y, g.NavRefRectRel.Max.x, g.NavRefRectRel.Max.y); ImGui::Text("NavUsable: %d, NavActive: %d", g.IO.NavUsable, g.IO.NavActive); diff --git a/imgui_internal.h b/imgui_internal.h index cabd56018722..a4bd7bb0a1fd 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -203,6 +203,7 @@ enum ImGuiInputSource ImGuiInputSource_None = 0, ImGuiInputSource_Mouse, ImGuiInputSource_Nav, + ImGuiInputSource_Count_, }; enum ImGuiNavDir From 87eb749cbccb302e049f77129180528733e948a9 Mon Sep 17 00:00:00 2001 From: ocornut Date: Sun, 21 Aug 2016 13:25:40 +0200 Subject: [PATCH 101/823] Added IsItemHoveredOrFocused() (provisional name), better handling of popup/tooltip positioning when using mouse+nav (#323) --- imgui.cpp | 18 ++++++++++++------ imgui.h | 1 + 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index ae8fb2f6d676..77e1d62665c0 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -3961,6 +3961,12 @@ bool ImGui::IsItemFocused() return g.NavId && !g.NavDisableHighlight && g.NavId == g.CurrentWindow->DC.LastItemId; } +bool ImGui::IsItemHoveredOrFocused() +{ + ImGuiContext& g = *GImGui; + return g.NavDisableMouseHover ? IsItemFocused() : IsItemHovered(); +} + bool ImGui::IsItemClicked(int mouse_button) { return IsMouseClicked(mouse_button) && IsItemHovered(); @@ -4090,7 +4096,7 @@ void ImGui::OpenPopupEx(const char* str_id, bool reopen_existing) ImGuiID id = window->GetID(str_id); int current_stack_size = g.CurrentPopupStack.Size; ImVec2 mouse_pos = g.IO.MousePos; - ImVec2 popup_pos = (g.ActiveIdSource == ImGuiInputSource_Nav) ? NavCalcPreferredMousePos() : mouse_pos; + ImVec2 popup_pos = (!g.NavDisableHighlight && g.NavDisableMouseHover) ? NavCalcPreferredMousePos() : mouse_pos; ImGuiPopupRef popup_ref = ImGuiPopupRef(id, window, window->GetID("##menus"), popup_pos, mouse_pos); // Tagged as new ref because constructor sets Window to NULL (we are passing the ParentWindow info here) if (g.OpenPopupStack.Size < current_stack_size + 1) g.OpenPopupStack.push_back(popup_ref); @@ -4820,7 +4826,7 @@ bool ImGui::Begin(const char* name, bool* p_open, const ImVec2& size_on_first_us // Position tooltip (always follows mouse) if ((flags & ImGuiWindowFlags_Tooltip) != 0 && !window_pos_set_by_api) { - ImVec2 ref_pos = (g.ActiveIdSource == ImGuiInputSource_Nav) ? NavCalcPreferredMousePos() : g.IO.MousePos; + ImVec2 ref_pos = (!g.NavDisableHighlight && g.NavDisableMouseHover) ? NavCalcPreferredMousePos() : g.IO.MousePos; ImRect rect_to_avoid(ref_pos.x - 16, ref_pos.y - 8, ref_pos.x + 24, ref_pos.y + 24); // FIXME: Completely hard-coded. Perhaps center on cursor hit-point instead? window->PosFloat = FindBestPopupWindowPos(ref_pos, window->Size, &window->AutoPosLastDirection, rect_to_avoid); if (window->AutoPosLastDirection == -1) @@ -9876,7 +9882,7 @@ bool ImGui::ColorButton(const ImVec4& col, bool small_height, bool outline_borde RenderNavHighlight(bb, id); RenderFrame(bb.Min, bb.Max, GetColorU32(col), outline_border, style.FrameRounding); - if (g.HoveredId == id) + if (IsItemHoveredOrFocused()) SetTooltip("Color:\n(%.2f,%.2f,%.2f,%.2f)\n#%02X%02X%02X%02X", col.x, col.y, col.z, col.w, IM_F32_TO_INT8_SAT(col.x), IM_F32_TO_INT8_SAT(col.y), IM_F32_TO_INT8_SAT(col.z), IM_F32_TO_INT8_SAT(col.z)); return pressed; @@ -9994,7 +10000,7 @@ bool ImGui::ColorEdit4(const char* label, float col[4], bool alpha) g.ColorEditModeStorage.SetInt(id, (edit_mode + 1) % 3); // Don't set local copy of 'edit_mode' right away! // Recreate our own tooltip over's ColorButton() one because we want to display correct alpha here - if (IsItemHovered()) + if (IsItemHoveredOrFocused()) SetTooltip("Color:\n(%.2f,%.2f,%.2f,%.2f)\n#%02X%02X%02X%02X", col[0], col[1], col[2], col[3], IM_F32_TO_INT8_SAT(col[0]), IM_F32_TO_INT8_SAT(col[1]), IM_F32_TO_INT8_SAT(col[2]), IM_F32_TO_INT8_SAT(col[3])); if (window->DC.ColorEditMode == ImGuiColorEditMode_UserSelectShowButton) @@ -10653,7 +10659,7 @@ void ImGui::ShowMetricsWindow(bool* p_open) } ImDrawIdx* idx_buffer = (draw_list->IdxBuffer.Size > 0) ? draw_list->IdxBuffer.Data : NULL; bool pcmd_node_open = ImGui::TreeNode((void*)(pcmd - draw_list->CmdBuffer.begin()), "Draw %-4d %s vtx, tex = %p, clip_rect = (%.0f,%.0f)..(%.0f,%.0f)", pcmd->ElemCount, draw_list->IdxBuffer.Size > 0 ? "indexed" : "non-indexed", pcmd->TextureId, pcmd->ClipRect.x, pcmd->ClipRect.y, pcmd->ClipRect.z, pcmd->ClipRect.w); - if (show_clip_rects && (ImGui::IsItemHovered() || ImGui::IsItemFocused())) + if (show_clip_rects && ImGui::IsItemHoveredOrFocused()) { ImRect clip_rect = pcmd->ClipRect; ImRect vtxs_rect; @@ -10677,7 +10683,7 @@ void ImGui::ShowMetricsWindow(bool* p_open) buf_p += sprintf(buf_p, "%s %04d { pos = (%8.2f,%8.2f), uv = (%.6f,%.6f), col = %08X }\n", (n == 0) ? "vtx" : " ", vtx_i, v.pos.x, v.pos.y, v.uv.x, v.uv.y, v.col); } ImGui::Selectable(buf, false); - if (ImGui::IsItemHovered() || ImGui::IsItemFocused()) + if (ImGui::IsItemHoveredOrFocused()) overlay_draw_list->AddPolyline(triangles_pos, 3, IM_COL32(255,255,0,255), true, 1.0f, false); // Add triangle without AA, more readable for large-thin triangle } ImGui::TreePop(); diff --git a/imgui.h b/imgui.h index 420df52da8af..02bec5689278 100644 --- a/imgui.h +++ b/imgui.h @@ -399,6 +399,7 @@ namespace ImGui IMGUI_API bool IsItemHoveredRect(); // is the last item hovered by mouse? even if another item is active or window is blocked by popup while we are hovering this IMGUI_API bool IsItemActive(); // is the last item active? (e.g. button being held, text field being edited- items that don't interact will always return false) IMGUI_API bool IsItemFocused(); // is the last item focused for keyboard/gamepad navigation? + IMGUI_API bool IsItemHoveredOrFocused(); // select best suitable between IsItemHovered() when mouse is used and IsItemFocused() when navigation is used. useful for tooltips that needs to work with both controls. IMGUI_API bool IsItemClicked(int mouse_button = 0); // is the last item clicked? (e.g. button/node just clicked on) IMGUI_API bool IsItemVisible(); // is the last item visible? (aka not out of sight due to clipping/scrolling.) IMGUI_API bool IsAnyItemHovered(); From ac7826c8a542b3862661c77935b37dbaf5fe410c Mon Sep 17 00:00:00 2001 From: ocornut Date: Sun, 21 Aug 2016 14:37:48 +0200 Subject: [PATCH 102/823] ImRect: Added Translate() helper, removed redundant and misleading Reduce() --- imgui.cpp | 6 +++--- imgui_internal.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 77e1d62665c0..f150ebc2bcf1 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -4416,7 +4416,7 @@ static ImVec2 FindBestPopupWindowPos(const ImVec2& base_pos, const ImVec2& size, // Clamp into visible area while not overlapping the cursor. Safety padding is optional if our popup size won't fit without it. ImVec2 safe_padding = style.DisplaySafeAreaPadding; ImRect r_outer(GetVisibleRect()); - r_outer.Reduce(ImVec2((size.x - r_outer.GetWidth() > safe_padding.x*2) ? safe_padding.x : 0.0f, (size.y - r_outer.GetHeight() > safe_padding.y*2) ? safe_padding.y : 0.0f)); + r_outer.Expand(ImVec2((size.x - r_outer.GetWidth() > safe_padding.x*2) ? -safe_padding.x : 0.0f, (size.y - r_outer.GetHeight() > safe_padding.y*2) ? -safe_padding.y : 0.0f)); ImVec2 base_pos_clamped = ImClamp(base_pos, r_outer.Min, r_outer.Max - size); for (int n = (*last_dir != -1) ? -1 : 0; n < 4; n++) // Last, Right, down, up, left. (Favor last used direction). @@ -5234,7 +5234,7 @@ static void Scrollbar(ImGuiWindow* window, bool horizontal) else window_rounding_corners = (((window->Flags & ImGuiWindowFlags_NoTitleBar) && !(window->Flags & ImGuiWindowFlags_MenuBar)) ? 2 : 0) | (other_scrollbar ? 0 : 4); window->DrawList->AddRectFilled(bb.Min, bb.Max, ImGui::GetColorU32(ImGuiCol_ScrollbarBg), window_rounding, window_rounding_corners); - bb.Reduce(ImVec2(ImClamp((float)(int)((bb.Max.x - bb.Min.x - 2.0f) * 0.5f), 0.0f, 3.0f), ImClamp((float)(int)((bb.Max.y - bb.Min.y - 2.0f) * 0.5f), 0.0f, 3.0f))); + bb.Expand(ImVec2(-ImClamp((float)(int)((bb.Max.x - bb.Min.x - 2.0f) * 0.5f), 0.0f, 3.0f), -ImClamp((float)(int)((bb.Max.y - bb.Min.y - 2.0f) * 0.5f), 0.0f, 3.0f))); // V denote the main axis of the scrollbar float scrollbar_size_v = horizontal ? bb.GetWidth() : bb.GetHeight(); @@ -8104,7 +8104,7 @@ void ImGui::ProgressBar(float fraction, const ImVec2& size_arg, const char* over // Render fraction = ImSaturate(fraction); RenderFrame(bb.Min, bb.Max, GetColorU32(ImGuiCol_FrameBg), true, style.FrameRounding); - bb.Reduce(ImVec2(window->BorderSize, window->BorderSize)); + bb.Expand(ImVec2(-window->BorderSize, -window->BorderSize)); const ImVec2 fill_br = ImVec2(ImLerp(bb.Min.x, bb.Max.x, fraction), bb.Max.y); RenderFrame(bb.Min, fill_br, GetColorU32(ImGuiCol_PlotHistogram), false, style.FrameRounding); diff --git a/imgui_internal.h b/imgui_internal.h index a4bd7bb0a1fd..210f6b057f23 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -242,7 +242,7 @@ struct IMGUI_API ImRect void Add(const ImRect& rhs) { if (Min.x > rhs.Min.x) Min.x = rhs.Min.x; if (Min.y > rhs.Min.y) Min.y = rhs.Min.y; if (Max.x < rhs.Max.x) Max.x = rhs.Max.x; if (Max.y < rhs.Max.y) Max.y = rhs.Max.y; } void Expand(const float amount) { Min.x -= amount; Min.y -= amount; Max.x += amount; Max.y += amount; } void Expand(const ImVec2& amount) { Min.x -= amount.x; Min.y -= amount.y; Max.x += amount.x; Max.y += amount.y; } - void Reduce(const ImVec2& amount) { Min.x += amount.x; Min.y += amount.y; Max.x -= amount.x; Max.y -= amount.y; } + void Translate(const ImVec2& v) { Min.x += v.x; Min.y += v.y; Max.x += v.x; Max.y += v.y; } void Clip(ImRect& r) const { r.Min.x = ImClamp(r.Min.x, Min.x, Max.x); r.Min.y = ImClamp(r.Min.y, Min.y, Max.y); r.Max.x = ImClamp(r.Max.x, Min.x, Max.x); r.Max.y = ImClamp(r.Max.y, Min.y, Max.y); } void Floor() { Min.x = (float)(int)Min.x; Min.y = (float)(int)Min.y; Max.x = (float)(int)Max.x; Max.y = (float)(int)Max.y; } ImVec2 GetClosestPoint(ImVec2 p, bool on_edge) const From f71cdd13b71895c1d7f10b7eaa9d0fdc2849f626 Mon Sep 17 00:00:00 2001 From: ocornut Date: Sun, 21 Aug 2016 14:39:13 +0200 Subject: [PATCH 103/823] Internal tidying up, moved code to CalcNextScrollFromScrollTargetAndClamp() so it can be reused by upcoming nav code. --- imgui.cpp | 31 ++++++++++++++++--------------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index f150ebc2bcf1..e2718ce5f40f 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -710,6 +710,7 @@ static inline bool IsWindowContentHoverable(ImGuiWindow* window); static void ClearSetNextWindowData(); static void CheckStacksSize(ImGuiWindow* window, bool write); static void Scrollbar(ImGuiWindow* window, bool horizontal); +static ImVec2 CalcNextScrollFromScrollTargetAndClamp(ImGuiWindow* window); static void AddDrawListToRenderList(ImVector& out_render_list, ImDrawList* draw_list); static void AddWindowToRenderList(ImVector& out_render_list, ImGuiWindow* window); @@ -4539,6 +4540,19 @@ static void ApplySizeFullWithConstraint(ImGuiWindow* window, ImVec2 new_size) window->SizeFull = new_size; } +static ImVec2 CalcNextScrollFromScrollTargetAndClamp(ImGuiWindow* window) +{ + ImVec2 scroll = window->Scroll; + if (window->ScrollTarget.x < FLT_MAX) + scroll.x = window->ScrollTarget.x - (window->ScrollTargetCenterRatio.x * window->SizeFull.x); + if (window->ScrollTarget.y < FLT_MAX) + scroll.y = window->ScrollTarget.y - ((1.0f - window->ScrollTargetCenterRatio.y) * (window->TitleBarHeight() + window->MenuBarHeight())) - (window->ScrollTargetCenterRatio.y * window->SizeFull.y); + scroll = ImMax(scroll, ImVec2(0.0f, 0.0f)); + if (!window->Collapsed && !window->SkipItems) + scroll = ImMin(scroll, ImMax(ImVec2(0.0f, 0.0f), window->SizeContents - window->SizeFull + window->ScrollbarSizes)); + return scroll; +} + // Push a new ImGui window to add widgets to. // - A default window called "Debug" is automatically stacked at the beginning of every frame so you can use widgets without explicitly calling a Begin/End pair. // - Begin/End can be called multiple times during the frame with the same window name to append content. @@ -4858,21 +4872,8 @@ bool ImGui::Begin(const char* name, bool* p_open, const ImVec2& size_on_first_us window->FocusIdxAllRequestNext = window->FocusIdxTabRequestNext = INT_MAX; // Apply scrolling - if (window->ScrollTarget.x < FLT_MAX) - { - float center_ratio = window->ScrollTargetCenterRatio.x; - window->Scroll.x = window->ScrollTarget.x - (center_ratio * window->SizeFull.x); - window->ScrollTarget.x = FLT_MAX; - } - if (window->ScrollTarget.y < FLT_MAX) - { - float center_ratio = window->ScrollTargetCenterRatio.y; - window->Scroll.y = window->ScrollTarget.y - ((1.0f - center_ratio) * (window->TitleBarHeight() + window->MenuBarHeight())) - (center_ratio * window->SizeFull.y); - window->ScrollTarget.y = FLT_MAX; - } - window->Scroll = ImMax(window->Scroll, ImVec2(0.0f, 0.0f)); - if (!window->Collapsed && !window->SkipItems) - window->Scroll = ImMin(window->Scroll, ImMax(ImVec2(0.0f, 0.0f), window->SizeContents - window->SizeFull + window->ScrollbarSizes)); + window->Scroll = CalcNextScrollFromScrollTargetAndClamp(window); + window->ScrollTarget = ImVec2(FLT_MAX, FLT_MAX); // Modal window darkens what is behind them if ((flags & ImGuiWindowFlags_Modal) != 0 && window == GetFrontMostModalRootWindow()) From 78b7e2dfb3aaf5cef13da1fbe04de7b81fe9cdf4 Mon Sep 17 00:00:00 2001 From: ocornut Date: Sun, 21 Aug 2016 14:53:26 +0200 Subject: [PATCH 104/823] Nav: Process and apply mouse move request immediately after move request result comes (#323) --- imgui.cpp | 32 ++++++++++++++++++-------------- 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index e2718ce5f40f..5fcb2097180a 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2475,20 +2475,6 @@ static void NavUpdate() g.NavInitDefaultResultExplicit = false; g.NavInitDefaultResultId = 0; - // Apply application mouse position movement - if (g.NavMousePosDirty && g.NavIdIsAlive) - { - // Set mouse position given our knowledge of the nav widget position from last frame - if (g.IO.NavMovesMouse) - { - g.IO.MousePos = g.IO.MousePosPrev = NavCalcPreferredMousePos(); - g.IO.WantMoveMouse = true; - } - g.NavMousePosDirty = false; - } - g.NavIdIsAlive = false; - g.NavTabbedId = 0; - // Process navigation move request if (g.NavMoveRequest && g.NavMoveResultId != 0) { @@ -2519,6 +2505,10 @@ static void NavUpdate() g.NavWindow->ScrollTarget.y = g.NavMoveResultRectRel.Max.y + g.NavWindow->Scroll.y + g.Style.ItemSpacing.y; g.NavWindow->ScrollTargetCenterRatio.y = 1.0f; } + + // Estimate upcoming scroll so we can offset our relative mouse position so mouse position can be applied immediately (under this block) + ImVec2 next_scroll = CalcNextScrollFromScrollTargetAndClamp(g.NavWindow); + g.NavMoveResultRectRel.Translate(g.NavWindow->Scroll - next_scroll); } // Apply result from previous frame navigation directional move request @@ -2527,6 +2517,20 @@ static void NavUpdate() g.NavMoveFromClampedRefRect = false; } + // Apply application mouse position movement, after we had a chance to process move request result. + if (g.NavMousePosDirty && g.NavIdIsAlive) + { + // Set mouse position given our knowledge of the nav widget position from last frame + if (g.IO.NavMovesMouse) + { + g.IO.MousePos = g.IO.MousePosPrev = NavCalcPreferredMousePos(); + g.IO.WantMoveMouse = true; + } + g.NavMousePosDirty = false; + } + g.NavIdIsAlive = false; + g.NavTabbedId = 0; + // Navigation windowing mode (change focus, move/resize window) if (!g.NavWindowingTarget && IsNavInputPressed(ImGuiNavInput_PadMenu, ImGuiNavReadMode_Pressed)) { From fddf9ca10ed63f8d837a3104ac178d1910bdcf93 Mon Sep 17 00:00:00 2001 From: ocornut Date: Sun, 21 Aug 2016 15:25:29 +0200 Subject: [PATCH 105/823] Nav: Fixed nav highlight clipping (affected non non-menu items within menubar) (#323) --- imgui.cpp | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 5fcb2097180a..f2d08b29376e 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2084,12 +2084,14 @@ void ImGui::RenderNavHighlight(const ImRect& bb, ImGuiID id) return; ImGuiWindow* window = ImGui::GetCurrentWindow(); - ImRect clip_rect(window->InnerRect.Min - ImVec2(4,4), window->InnerRect.Max + ImVec2(4,4)); - if (!window->ClipRect.Contains(clip_rect)) - window->DrawList->PushClipRect(clip_rect.Min, clip_rect.Max); - window->DrawList->AddRect(bb.Min - ImVec2(3,3), bb.Max + ImVec2(3,3), GetColorU32(ImGuiCol_NavHighlight), g.Style.FrameRounding, 0x0F, 2.0f); + const float THICKNESS = 2.0f; + const float DISTANCE = 3.0f + THICKNESS * 0.5f; + ImRect display_rect(bb.Min - ImVec2(DISTANCE,DISTANCE), bb.Max + ImVec2(DISTANCE,DISTANCE)); + if (!window->ClipRect.Contains(display_rect)) + window->DrawList->PushClipRect(display_rect.Min, display_rect.Max); + window->DrawList->AddRect(display_rect.Min + ImVec2(THICKNESS*0.5f,THICKNESS*0.5f), display_rect.Max - ImVec2(THICKNESS*0.5f,THICKNESS*0.5f), GetColorU32(ImGuiCol_NavHighlight), g.Style.FrameRounding, 0x0F, THICKNESS); //window->DrawList->AddRect(g.NavRefRectScreen.Min, g.NavRefRectScreen.Max, IM_COL32(255,0,0,255)); - if (!window->ClipRect.Contains(clip_rect)) + if (!window->ClipRect.Contains(display_rect)) window->DrawList->PopClipRect(); } From 252f0941014a53e52eaade05cef3968858914020 Mon Sep 17 00:00:00 2001 From: ocornut Date: Sun, 21 Aug 2016 15:26:40 +0200 Subject: [PATCH 106/823] Nav: Undo 87eb749cbc, agressively including nav focus test in IsItemHovered() (#323) --- imgui.cpp | 17 +++++++---------- imgui.h | 3 +-- imgui_demo.cpp | 2 +- 3 files changed, 9 insertions(+), 13 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index f2d08b29376e..f6a39491ccc2 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -3942,6 +3942,9 @@ void ImGui::CaptureMouseFromApp(bool capture) bool ImGui::IsItemHovered() { ImGuiWindow* window = GetCurrentWindowRead(); + ImGuiContext& g = *GImGui; + if (g.NavDisableMouseHover) + return IsItemFocused(); return window->DC.LastItemHoveredAndUsable; } @@ -3968,12 +3971,6 @@ bool ImGui::IsItemFocused() return g.NavId && !g.NavDisableHighlight && g.NavId == g.CurrentWindow->DC.LastItemId; } -bool ImGui::IsItemHoveredOrFocused() -{ - ImGuiContext& g = *GImGui; - return g.NavDisableMouseHover ? IsItemFocused() : IsItemHovered(); -} - bool ImGui::IsItemClicked(int mouse_button) { return IsMouseClicked(mouse_button) && IsItemHovered(); @@ -9889,7 +9886,7 @@ bool ImGui::ColorButton(const ImVec4& col, bool small_height, bool outline_borde RenderNavHighlight(bb, id); RenderFrame(bb.Min, bb.Max, GetColorU32(col), outline_border, style.FrameRounding); - if (IsItemHoveredOrFocused()) + if (IsItemHovered()) SetTooltip("Color:\n(%.2f,%.2f,%.2f,%.2f)\n#%02X%02X%02X%02X", col.x, col.y, col.z, col.w, IM_F32_TO_INT8_SAT(col.x), IM_F32_TO_INT8_SAT(col.y), IM_F32_TO_INT8_SAT(col.z), IM_F32_TO_INT8_SAT(col.z)); return pressed; @@ -10007,7 +10004,7 @@ bool ImGui::ColorEdit4(const char* label, float col[4], bool alpha) g.ColorEditModeStorage.SetInt(id, (edit_mode + 1) % 3); // Don't set local copy of 'edit_mode' right away! // Recreate our own tooltip over's ColorButton() one because we want to display correct alpha here - if (IsItemHoveredOrFocused()) + if (IsItemHovered()) SetTooltip("Color:\n(%.2f,%.2f,%.2f,%.2f)\n#%02X%02X%02X%02X", col[0], col[1], col[2], col[3], IM_F32_TO_INT8_SAT(col[0]), IM_F32_TO_INT8_SAT(col[1]), IM_F32_TO_INT8_SAT(col[2]), IM_F32_TO_INT8_SAT(col[3])); if (window->DC.ColorEditMode == ImGuiColorEditMode_UserSelectShowButton) @@ -10666,7 +10663,7 @@ void ImGui::ShowMetricsWindow(bool* p_open) } ImDrawIdx* idx_buffer = (draw_list->IdxBuffer.Size > 0) ? draw_list->IdxBuffer.Data : NULL; bool pcmd_node_open = ImGui::TreeNode((void*)(pcmd - draw_list->CmdBuffer.begin()), "Draw %-4d %s vtx, tex = %p, clip_rect = (%.0f,%.0f)..(%.0f,%.0f)", pcmd->ElemCount, draw_list->IdxBuffer.Size > 0 ? "indexed" : "non-indexed", pcmd->TextureId, pcmd->ClipRect.x, pcmd->ClipRect.y, pcmd->ClipRect.z, pcmd->ClipRect.w); - if (show_clip_rects && ImGui::IsItemHoveredOrFocused()) + if (show_clip_rects && ImGui::IsItemHovered()) { ImRect clip_rect = pcmd->ClipRect; ImRect vtxs_rect; @@ -10690,7 +10687,7 @@ void ImGui::ShowMetricsWindow(bool* p_open) buf_p += sprintf(buf_p, "%s %04d { pos = (%8.2f,%8.2f), uv = (%.6f,%.6f), col = %08X }\n", (n == 0) ? "vtx" : " ", vtx_i, v.pos.x, v.pos.y, v.uv.x, v.uv.y, v.col); } ImGui::Selectable(buf, false); - if (ImGui::IsItemHoveredOrFocused()) + if (ImGui::IsItemHovered()) overlay_draw_list->AddPolyline(triangles_pos, 3, IM_COL32(255,255,0,255), true, 1.0f, false); // Add triangle without AA, more readable for large-thin triangle } ImGui::TreePop(); diff --git a/imgui.h b/imgui.h index 02bec5689278..dfb0e5ce7073 100644 --- a/imgui.h +++ b/imgui.h @@ -395,11 +395,10 @@ namespace ImGui IMGUI_API void PopClipRect(); // Utilities - IMGUI_API bool IsItemHovered(); // is the last item hovered by mouse, and usable? + IMGUI_API bool IsItemHovered(); // is the last item hovered by mouse (and usable)? or we are currently using Nav and the item is focused. IMGUI_API bool IsItemHoveredRect(); // is the last item hovered by mouse? even if another item is active or window is blocked by popup while we are hovering this IMGUI_API bool IsItemActive(); // is the last item active? (e.g. button being held, text field being edited- items that don't interact will always return false) IMGUI_API bool IsItemFocused(); // is the last item focused for keyboard/gamepad navigation? - IMGUI_API bool IsItemHoveredOrFocused(); // select best suitable between IsItemHovered() when mouse is used and IsItemFocused() when navigation is used. useful for tooltips that needs to work with both controls. IMGUI_API bool IsItemClicked(int mouse_button = 0); // is the last item clicked? (e.g. button/node just clicked on) IMGUI_API bool IsItemVisible(); // is the last item visible? (aka not out of sight due to clipping/scrolling.) IMGUI_API bool IsAnyItemHovered(); diff --git a/imgui_demo.cpp b/imgui_demo.cpp index ff946e06116f..6dc663b369cb 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -763,7 +763,7 @@ void ImGui::ShowTestWindow(bool* p_open) } } - if (ImGui::CollapsingHeader("Graphs widgets")) + if (ImGui::CollapsingHeader("Plots widgets")) { static bool animate = true; ImGui::Checkbox("Animate", &animate); From 2303b67c40a7ab2a45fc680403d37b1178ed94d3 Mon Sep 17 00:00:00 2001 From: ocornut Date: Sun, 21 Aug 2016 16:05:19 +0200 Subject: [PATCH 107/823] Close button submitted after collapse button. Should have no effect. Consistent with expectation & will be used as fallback for nav (#323) --- imgui.cpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index f6a39491ccc2..4bb89688e32c 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -5088,15 +5088,6 @@ bool ImGui::Begin(const char* name, bool* p_open, const ImVec2& size_on_first_us window->DC.ItemFlags &= ~ImGuiItemFlags_AllowNavDefaultFocus; window->DC.NavLayerCurrent++; - // Close button - if (p_open != NULL) - { - const float PAD = 2.0f; - const float rad = (window->TitleBarHeight() - PAD*2.0f) * 0.5f; - if (CloseButton(window->GetID("#CLOSE"), window->Rect().GetTR() + ImVec2(-PAD - rad, PAD + rad), rad)) - *p_open = false; - } - // Collapse button const ImVec2 text_size = CalcTextSize(name, NULL, true); if (!(flags & ImGuiWindowFlags_NoCollapse)) @@ -5110,6 +5101,15 @@ bool ImGui::Begin(const char* name, bool* p_open, const ImVec2& size_on_first_us RenderCollapseTriangle(window->Pos + style.FramePadding, !window->Collapsed, 1.0f, true); } + // Close button + if (p_open != NULL) + { + const float PAD = 2.0f; + const float rad = (window->TitleBarHeight() - PAD*2.0f) * 0.5f; + if (CloseButton(window->GetID("#CLOSE"), window->Rect().GetTR() + ImVec2(-PAD - rad, PAD + rad), rad)) + *p_open = false; + } + window->DC.NavLayerCurrent--; window->DC.ItemFlags = backup_item_options; From 49ca1c2b885f7c41734bfd51e15981bd02545cae Mon Sep 17 00:00:00 2001 From: ocornut Date: Sun, 21 Aug 2016 16:07:55 +0200 Subject: [PATCH 108/823] Nav: InitDefaultRequest saves a fallback item so PadMenu on a collapsed window gets us to the collapse button (#323) --- imgui.cpp | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 4bb89688e32c..55c994426c95 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2116,15 +2116,20 @@ bool ImGui::ItemAdd(const ImRect& bb, const ImGuiID* id, const ImRect* nav_bb_ar // We could early out with `if (is_clipped && !g.NavInitDefaultRequest) return false;` but when we wouldn't be able to reach unclipped widgets. This would work if user had explicit scrolling control (e.g. mapped on a stick) // A more pragmatic solution for handling last lists is relying on the fact that they are likely evenly spread items (so that clipper can work) and we could nav at higher-level (apply index, etc.) // So eventually we would like to provide the user will the primitives to be able to implement that sort of customized/efficient navigation handling whenever necessary. - if (id != NULL && g.NavWindow == window->RootNavWindow && g.IO.NavUsable) + if (id != NULL && g.IO.NavUsable && g.NavWindow == window->RootNavWindow) { const ImRect& nav_bb = nav_bb_arg ? *nav_bb_arg : bb; const ImRect nav_bb_rel(nav_bb.Min - g.NavWindow->Pos, nav_bb.Max - g.NavWindow->Pos); - if (g.NavInitDefaultRequest && g.NavLayer == window->DC.NavLayerCurrent && (window->DC.ItemFlags & ImGuiItemFlags_AllowNavDefaultFocus)) + if (g.NavInitDefaultRequest && g.NavLayer == window->DC.NavLayerCurrent) { - g.NavInitDefaultRequest = g.NavInitDefaultResultExplicit = false; // Clear flag immediately, first item gets default, also simplify the if() in ItemAdd() - g.NavInitDefaultResultId = *id; - g.NavInitDefaultResultRectRel = nav_bb_rel; + // Even if 'ImGuiItemFlags_AllowNavDefaultFocus' is off (typically collapse/close button) we record the first ResultId so they can be used as fallback + if (window->DC.ItemFlags & ImGuiItemFlags_AllowNavDefaultFocus) + g.NavInitDefaultRequest = g.NavInitDefaultResultExplicit = false; // Found a match, clear request + if (g.NavInitDefaultResultId == 0 || (window->DC.ItemFlags & ImGuiItemFlags_AllowNavDefaultFocus)) + { + g.NavInitDefaultResultId = *id; + g.NavInitDefaultResultRectRel = nav_bb_rel; + } } //const bool DEBUG_NAV = false; // [DEBUG] Enable to test scoring on all items. From c6c7371a4c8a58dcb28f967dc861dec66bb04823 Mon Sep 17 00:00:00 2001 From: ocornut Date: Sun, 21 Aug 2016 16:11:53 +0200 Subject: [PATCH 109/823] Nav: Removed unnecessary test following 49ca1c2b885f7c41734bfd51e15981bd02545cae (#323) --- imgui.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 55c994426c95..f28523b7103e 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -5089,8 +5089,7 @@ bool ImGui::Begin(const char* name, bool* p_open, const ImVec2& size_on_first_us { // Close & collapse button are on layer 1 (same as menus) and don't default focus const ImGuiItemFlags backup_item_options = window->DC.ItemFlags; - if (window->Flags & ImGuiWindowFlags_MenuBar) - window->DC.ItemFlags &= ~ImGuiItemFlags_AllowNavDefaultFocus; + window->DC.ItemFlags &= ~ImGuiItemFlags_AllowNavDefaultFocus; window->DC.NavLayerCurrent++; // Collapse button From df9bdf38f97a2564069881876db88e514cc750c7 Mon Sep 17 00:00:00 2001 From: ocornut Date: Sun, 21 Aug 2016 17:32:15 +0200 Subject: [PATCH 110/823] Nav: NavActivateId, NavInputId are no repeat actions. Repeat buttons handle it themselves already anyway. (#323) --- imgui.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index f28523b7103e..f34e319f281b 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -18,6 +18,9 @@ - MISSION STATEMENT - END-USER GUIDE - PROGRAMMER GUIDE (read me!) + - Read first + - Getting started with integrating imgui in your code/engine + - Using gamepad/keyboard navigation [beta] - API BREAKING CHANGES (read me when you update!) - FREQUENTLY ASKED QUESTIONS (FAQ), TIPS - How can I help? @@ -88,7 +91,7 @@ - Call and read ImGui::ShowTestWindow() for demo code demonstrating most features. - Customization: PushStyleColor()/PushStyleVar() or the style editor to tweak the look of the interface (e.g. if you want a more compact UI or a different color scheme). - GETTING STARTED WITH INTEGRATING IN YOUR ENGINE + GETTING STARTED WITH INTEGRATING IMGUI IN YOUR CODE/ENGINE - See examples/ folder for standalone sample applications. Prefer reading examples/opengl_example/ first as it is the simplest. You may be able to grab and copy a ready made imgui_impl_*** file from the examples/. @@ -2658,8 +2661,8 @@ static void NavUpdate() } } - g.NavActivateId = (g.NavId && !g.NavDisableHighlight && !g.NavWindowingTarget && g.ActiveId == 0 && IsNavInputPressed(ImGuiNavInput_PadActivate, ImGuiNavReadMode_Repeat)) ? g.NavId : 0; - g.NavInputId = (g.NavId && !g.NavDisableHighlight && !g.NavWindowingTarget && g.ActiveId == 0 && IsNavInputPressed(ImGuiNavInput_PadInput, ImGuiNavReadMode_Repeat)) ? g.NavId : 0; + g.NavActivateId = (g.NavId && !g.NavDisableHighlight && !g.NavWindowingTarget && g.ActiveId == 0 && IsNavInputPressed(ImGuiNavInput_PadActivate, ImGuiNavReadMode_Pressed)) ? g.NavId : 0; + g.NavInputId = (g.NavId && !g.NavDisableHighlight && !g.NavWindowingTarget && g.ActiveId == 0 && IsNavInputPressed(ImGuiNavInput_PadInput, ImGuiNavReadMode_Pressed)) ? g.NavId : 0; if (g.NavWindow && (g.NavWindow->Flags & ImGuiWindowFlags_NoNavInputs)) { g.NavActivateId = g.NavInputId = 0; From 3883a2027f77304cb2d72ea7495789420e567b41 Mon Sep 17 00:00:00 2001 From: ocornut Date: Sun, 21 Aug 2016 17:52:42 +0200 Subject: [PATCH 111/823] Nav: Fixed Selectable() crash introduced earlier today in 43ee5d73 + added comments/assert (#323) --- imgui.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index f34e319f281b..f528568f5c56 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2347,6 +2347,7 @@ int ImGui::GetFrameCount() static void SetNavId(ImGuiID id) { ImGuiContext& g = *GImGui; + IM_ASSERT(g.NavWindow); g.NavId = id; if (g.NavLayer == 0) g.NavWindow->NavLastId = g.NavId; @@ -9503,7 +9504,7 @@ bool ImGui::Selectable(const char* label, bool selected, ImGuiSelectableFlags fl selected = false; // Hovering selectable with mouse updates NavId accordingly so navigation can be resumed with gamepad/keyboard (this doesn't happen on most widgets) - if (hovered && !g.NavDisableMouseHover && (g.IO.MouseDelta.x != 0.0f || g.IO.MouseDelta.y != 0.0f)) + if (hovered && !g.NavDisableMouseHover && g.NavWindow == window && (g.IO.MouseDelta.x != 0.0f || g.IO.MouseDelta.y != 0.0f)) { g.NavDisableHighlight = true; SetNavId(id); @@ -9756,7 +9757,7 @@ bool ImGui::BeginMenu(const char* label, bool enabled) bool menuset_is_open = !(window->Flags & ImGuiWindowFlags_Popup) && (g.OpenPopupStack.Size > g.CurrentPopupStack.Size && g.OpenPopupStack[g.CurrentPopupStack.Size].ParentMenuSet == window->GetID("##menus")); ImGuiWindow* backed_nav_window = g.NavWindow; if (menuset_is_open) - g.NavWindow = window; + g.NavWindow = window; // Odd hack to allow hovering across menus of a same menu-set (otherwise we wouldn't be able to hover parent) ImVec2 popup_pos, pos = window->DC.CursorPos; if (window->DC.LayoutType == ImGuiLayoutType_Horizontal) From e8e5c6d788149449c22abe739d35ce311d2a01a0 Mon Sep 17 00:00:00 2001 From: ocornut Date: Tue, 23 Aug 2016 08:58:51 +0200 Subject: [PATCH 112/823] Nav: Comments. Fixed two -Wall warnings. Removed unused function. (#787) --- imgui.cpp | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index f528568f5c56..791c83999498 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -154,7 +154,7 @@ USING GAMEPAD/KEYBOARD NAVIGATION [BETA] - Gamepad/keyboard navigation support is available, currently in Beta with some issues. Your feedback and bug reports are welcome. - - See https://github.com/ocornut/imgui/issues/323 for discussion thread and ask questions. + - See https://github.com/ocornut/imgui/issues/787 discussion thread and ask questions there. - The current primary focus is to support game controllers. - Consider emulating a mouse cursor with DualShock4 touch pad or a spare analog stick as a mouse-emulation fallback. - Consider using Synergy host (on your computer) + uSynergy.c (in your console/tablet/phone app) to use PC mouse/keyboard. @@ -624,7 +624,6 @@ - filters: fuzzy matches (may use code at blog.forrestthewoods.com/4cffeed33fdb) - shortcuts: add a shortcut api, e.g. parse "&Save" and/or "Save (CTRL+S)", pass in to widgets or provide simple ways to use (button=activate, input=focus) !- keyboard: tooltip & combo boxes are messing up / not honoring keyboard tabbing - - keyboard: full keyboard navigation and focus. (#323) - focus: preserve ActiveId/focus stack state, e.g. when opening a menu and close it, previously selected InputText() focus gets restored (#622) - focus: SetKeyboardFocusHere() on with >= 0 offset could be done on same frame (else latch and modulate on beginning of next frame) - input: rework IO system to be able to pass actual ordered/timestamped events. (~#335, #71) @@ -697,7 +696,6 @@ static void LogRenderedText(const ImVec2& ref_pos, const char* text, static void PushMultiItemsWidths(int components, float w_full = 0.0f); static float GetDraggedColumnOffset(int column_index); -static bool IsKeyDownMap(ImGuiKey key); static bool IsKeyPressedMap(ImGuiKey key, bool repeat = true); static void SetCurrentFont(ImFont* font); @@ -2956,10 +2954,12 @@ void ImGui::NewFrame() // Pressing TAB activate widget focus //// NB: Don't discard FocusedWindow if it isn't active, so that a window that go on/off programatically won't lose its keyboard focus. // [2016/07/17] That comment was made invalid by 19d02becef94e8e0f1d432a8bd55cd783876583c if (g.ActiveId == 0 && g.NavWindow != NULL && g.NavWindow->Active && !(g.NavWindow->Flags & ImGuiWindowFlags_NoNavInputs) && !g.IO.KeyCtrl && IsKeyPressedMap(ImGuiKey_Tab, false)) + { if (g.NavId != 0 && g.NavIdTabCounter != INT_MAX) g.NavWindow->FocusIdxTabRequestNext = g.NavIdTabCounter + 1 + (g.IO.KeyShift ? -1 : 1); else g.NavWindow->FocusIdxTabRequestNext = g.IO.KeyShift ? -1 : 0; + } g.NavIdTabCounter = INT_MAX; // Mark all windows as not visible @@ -3781,12 +3781,6 @@ bool ImGui::IsAnyWindowHoveredAtPos(const ImVec2& pos) return FindHoveredWindow(pos, false) != NULL; } -static bool IsKeyDownMap(ImGuiKey key) -{ - const int key_index = GImGui->IO.KeyMap[key]; - return (key_index >= 0) ? ImGui::IsKeyDown(key_index) : false; -} - static bool IsKeyPressedMap(ImGuiKey key, bool repeat) { const int key_index = GImGui->IO.KeyMap[key]; From 67c6d6026a14b70ed619da79b19b3d2565fc0c05 Mon Sep 17 00:00:00 2001 From: ocornut Date: Sun, 27 Nov 2016 18:29:38 +0100 Subject: [PATCH 113/823] Nav: SliderFloat() Fixed non-linear sliders in Nav branch (#787, #323) --- imgui.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 68bd0ad2b30f..fffedf2e4925 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -7339,7 +7339,7 @@ float ImGui::RoundScalar(float value, int decimal_precision) static inline float SliderBehaviorCalcRatioFromValue(float v, float v_min, float v_max, float power, float linear_zero_pos) { - const bool is_non_linear = (power < 1.0f-0.00001f) && (power > 1.0f-0.00001f); + const bool is_non_linear = (power < 1.0f-0.00001f) || (power > 1.0f+0.00001f); const float v_clamped = (v_min < v_max) ? ImClamp(v, v_min, v_max) : ImClamp(v, v_max, v_min); if (is_non_linear) { @@ -7370,7 +7370,7 @@ bool ImGui::SliderBehavior(const ImRect& frame_bb, ImGuiID id, float* v, float v RenderNavHighlight(frame_bb, id); RenderFrame(frame_bb.Min, frame_bb.Max, frame_col, true, style.FrameRounding); - const bool is_non_linear = (power < 1.0f-0.00001f) && (power > 1.0f-0.00001f); + const bool is_non_linear = (power < 1.0f-0.00001f) || (power > 1.0f+0.00001f); const bool is_horizontal = (flags & ImGuiSliderFlags_Vertical) == 0; const float grab_padding = 2.0f; From bb4d19ff7cbd1daf293b07036dff1a049d7e7bee Mon Sep 17 00:00:00 2001 From: ocornut Date: Fri, 23 Dec 2016 12:15:09 +0100 Subject: [PATCH 114/823] Merge branch 'master' - merge fix --- imgui.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/imgui.cpp b/imgui.cpp index f2242252c406..cb5da0cf98ec 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2634,7 +2634,7 @@ static void NavUpdate() const float move_speed = ImFloor(600 * g.IO.DeltaTime * ImMin(g.IO.DisplayFramebufferScale.x, g.IO.DisplayFramebufferScale.y)); g.NavWindowingTarget->PosFloat += move_delta * move_speed; g.NavDisableMouseHover = true; - MarkSettingsDirty(g.NavWindowingTarget); + MarkIniSettingsDirty(g.NavWindowingTarget); } } From 6c82af2b965cb61fb490efe5689d79a4044d9b85 Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 22 Aug 2017 17:44:49 +0800 Subject: [PATCH 115/823] Navigation branch fix (we changed Clip) --- imgui.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/imgui.cpp b/imgui.cpp index f00be193cd57..aaad044b6ec4 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -11066,7 +11066,7 @@ void ImGui::BeginColumns(const char* id, int columns_count, ImGuiColumnsFlags fl float clip_x1 = ImFloor(0.5f + window->Pos.x + GetColumnOffset(column_index) - 1.0f); float clip_x2 = ImFloor(0.5f + window->Pos.x + GetColumnOffset(column_index + 1) - 1.0f); window->DC.ColumnsData[column_index].ClipRect = ImRect(clip_x1, -FLT_MAX, clip_x2, +FLT_MAX); - window->DC.ColumnsData[column_index].ClipRect.Clip(window->ClipRect); + window->ClipRect.Clip(window->DC.ColumnsData[column_index].ClipRect); } window->DrawList->ChannelsSplit(window->DC.ColumnsCount); From 444792f75f0a8a9d77e4bfd55b90c5fd79b652e5 Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 22 Aug 2017 18:27:23 +0800 Subject: [PATCH 116/823] Merge fixes from ,master branch --- imgui_demo.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/imgui_demo.cpp b/imgui_demo.cpp index ef65a2f5f786..b8e612787c9e 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -1000,8 +1000,7 @@ void ImGui::ShowTestWindow(bool* p_open) ImGui::NextColumn(); char buf[32]; sprintf(buf, "%08x", i*5731); - if (ImGui::Button(buf, ImVec2(-1.0f, 0.0f))) - printf("Pressed '%s'\n", buf); + ImGui::Button(buf, ImVec2(-1.0f, 0.0f)); } ImGui::EndChild(); ImGui::PopStyleVar(); @@ -1469,7 +1468,7 @@ void ImGui::ShowTestWindow(bool* p_open) ImGui::OpenPopup("Stacked 2"); if (ImGui::BeginPopupModal("Stacked 2")) { - ImGui::Text("Hello from Stacked The Second!\nWe are piling a modal over another here,\nand also testing if the menu-bar works."); + ImGui::Text("Hello from Stacked The Second!"); if (ImGui::Button("Close")) ImGui::CloseCurrentPopup(); ImGui::EndPopup(); From bea06117bb1c37ce806bfa533a9109c300e10ed4 Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 22 Aug 2017 19:26:21 +0800 Subject: [PATCH 117/823] Nav: Fix navigation inside child windows. Removed GetChildID() and storin/g the info within the window. (#1291) --- imgui.cpp | 19 +++++++------------ imgui_internal.h | 2 +- 2 files changed, 8 insertions(+), 13 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 10503194ecbb..5a6947912388 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1807,6 +1807,7 @@ ImGuiWindow::ImGuiWindow(const char* name) SizeContents = SizeContentsExplicit = ImVec2(0.0f, 0.0f); WindowPadding = ImVec2(0.0f, 0.0f); MoveId = GetID("#MOVE"); + ChildId = 0; Scroll = ImVec2(0.0f, 0.0f); ScrollTarget = ImVec2(FLT_MAX, FLT_MAX); ScrollTargetCenterRatio = ImVec2(0.5f, 0.5f); @@ -1877,13 +1878,6 @@ ImGuiID ImGuiWindow::GetIDNoKeepAlive(const char* str, const char* str_end) return ImHash(str, str_end ? (int)(str_end - str) : 0, seed); } -ImGuiID ImGuiWindow::GetChildID(ImGuiWindow* child_window) -{ - IM_ASSERT(child_window && child_window->ParentWindow == this); - ImGuiID seed = IDStack[0]; - return ImHash(&child_window->ID, sizeof(child_window->ID), seed); -} - //----------------------------------------------------------------------------- // Internal API exposed in imgui_internal.h //----------------------------------------------------------------------------- @@ -2670,7 +2664,8 @@ static void NavUpdate() ImGuiWindow* child_window = g.NavWindow; ImGuiWindow* parent_window = g.NavWindow->ParentWindow; ImGui::FocusWindow(parent_window); - SetNavId(parent_window->GetChildID(child_window)); + IM_ASSERT(child_window->ChildId != 0); + SetNavId(child_window->ChildId); g.NavIdIsAlive = false; if (g.NavDisableMouseHover) g.NavMousePosDirty = true; @@ -4392,12 +4387,12 @@ static bool BeginChildEx(const char* name, ImGuiID id, const ImVec2& size_arg, b bool ret = ImGui::Begin(title, NULL, size, -1.0f, flags); ImGuiWindow* child_window = ImGui::GetCurrentWindow(); + child_window->ChildId = id; child_window->AutoFitChildAxises = auto_fit_axises; if (!(parent_window->Flags & ImGuiWindowFlags_ShowBorders)) child_window->Flags &= ~ImGuiWindowFlags_ShowBorders; // Process navigation-in immediately so NavInit can run on first frame - //const ImGuiID id = parent_window->GetChildID(child_window); if (/*!(flags & ImGuiWindowFlags_NavFlattened) &&*/ (child_window->DC.NavLayerActiveFlags != 0 || child_window->DC.NavHasScroll) && GImGui->NavActivateId == id) { ImGui::FocusWindow(child_window); @@ -4440,13 +4435,12 @@ void ImGui::EndChild() ImGui::End(); ImGuiWindow* parent_window = GetCurrentWindow(); - ImGuiID id = parent_window->GetChildID(window); ImRect bb(parent_window->DC.CursorPos, parent_window->DC.CursorPos + sz); ItemSize(sz); if (/*!(window->Flags & ImGuiWindowFlags_NavFlattened) &&*/ (window->DC.NavLayerActiveFlags != 0 || window->DC.NavHasScroll)) { - ItemAdd(bb, &id); - RenderNavHighlight(bb, id); + ItemAdd(bb, &window->ChildId); + RenderNavHighlight(bb, window->ChildId); } else { @@ -11465,6 +11459,7 @@ void ImGui::ShowMetricsWindow(bool* p_open) ImGui::Text("NavWindow: '%s', NavId: 0x%08X, NavLayer: %d", g.NavWindow ? g.NavWindow->Name : "NULL", g.NavId, g.NavLayer); ImGui::Text("NavRefRectRel: (%.1f,%.1f)(%.1f,%.1f)", g.NavRefRectRel.Min.x, g.NavRefRectRel.Min.y, g.NavRefRectRel.Max.x, g.NavRefRectRel.Max.y); ImGui::Text("NavUsable: %d, NavActive: %d", g.IO.NavUsable, g.IO.NavActive); + ImGui::Text("NavActivateId: 0x%08X, NavInputId: 0x%08X", g.NavActivateId, g.NavInputId); ImGui::Text("NavDisableHighlight: %d, NavDisableMouseHover: %d", g.NavDisableHighlight, g.NavDisableMouseHover); ImGui::TreePop(); } diff --git a/imgui_internal.h b/imgui_internal.h index 5b1b31492d38..f9e388ece622 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -735,6 +735,7 @@ struct IMGUI_API ImGuiWindow ImRect ContentsRegionRect; // Maximum visible content position in window coordinates. ~~ (SizeContentsExplicit ? SizeContentsExplicit : Size - ScrollbarSizes) - CursorStartPos, per axis ImVec2 WindowPadding; // Window padding at the time of begin. We need to lock it, in particular manipulation of the ShowBorder would have an effect ImGuiID MoveId; // == window->GetID("#MOVE") + ImGuiID ChildId; // Id of corresponding item in parent window (for child windows) ImVec2 Scroll; ImVec2 ScrollTarget; // target scroll position. stored as cursor position with scrolling canceled out, so the highest point is always 0.0f. (FLT_MAX for no change) ImVec2 ScrollTargetCenterRatio; // 0.0f = scroll so that target position is at top, 0.5f = scroll so that target position is centered @@ -792,7 +793,6 @@ struct IMGUI_API ImGuiWindow ImGuiID GetID(const char* str, const char* str_end = NULL); ImGuiID GetID(const void* ptr); ImGuiID GetIDNoKeepAlive(const char* str, const char* str_end = NULL); - ImGuiID GetChildID(ImGuiWindow* window); ImRect Rect() const { return ImRect(Pos.x, Pos.y, Pos.x+Size.x, Pos.y+Size.y); } float CalcFontSize() const { return GImGui->FontBaseSize * FontWindowScale; } From f3ab5e6252ec5483fe82c6fd243cbb0caac94ff1 Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 22 Aug 2017 19:43:49 +0800 Subject: [PATCH 118/823] Fixed InputText() bug with ImGuiInputTextFlags_EnterReturnsTrue (in nav branch only) (#787). Thanks @Grouflon --- imgui.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/imgui.cpp b/imgui.cpp index 5a6947912388..acefc4575c01 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -8932,7 +8932,11 @@ bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2 value_changed = true; } } - if (!cancel_edit && !clear_active_id) + + // When using 'ImGuiInputTextFlags_EnterReturnsTrue' as a special case we reapply the live buffer back to the input buffer before clearing ActiveId, even though strictly speaking it wasn't modified on this frame. + // If we didn't do that, code like InputInt() with ImGuiInputTextFlags_EnterReturnsTrue would fail. Also this allows the user to use InputText() with ImGuiInputTextFlags_EnterReturnsTrue without maintaining any user-side storage. + bool apply_edit_back_to_user_buffer = !cancel_edit || (enter_pressed && (flags & ImGuiInputTextFlags_EnterReturnsTrue) != 0); + if (apply_edit_back_to_user_buffer) { // Apply new value immediately - copy modified buffer back // Note that as soon as the input box is active, the in-widget value gets priority over any underlying modification of the input buffer From 2e35957a81d4ff67b30ea80c1592682de796d325 Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 22 Aug 2017 20:02:52 +0800 Subject: [PATCH 119/823] Undo reordering of ImGuiKey in Nav branch --- imgui.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/imgui.h b/imgui.h index d5ed61b55f8e..eae153b9e947 100644 --- a/imgui.h +++ b/imgui.h @@ -587,10 +587,10 @@ enum ImGuiSelectableFlags_ enum ImGuiKey_ { ImGuiKey_Tab, // for tabbing through fields - ImGuiKey_UpArrow, // for text edit - ImGuiKey_DownArrow, // for text edit ImGuiKey_LeftArrow, // for text edit ImGuiKey_RightArrow,// for text edit + ImGuiKey_UpArrow, // for text edit + ImGuiKey_DownArrow, // for text edit ImGuiKey_PageUp, ImGuiKey_PageDown, ImGuiKey_Home, // for text edit From b0fc30bd199636d5f94e59a07c7b0846b964e1f3 Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 22 Aug 2017 20:49:02 +0800 Subject: [PATCH 120/823] Merge branch 'master' into navigation --- imgui.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/imgui.cpp b/imgui.cpp index bb5799c9ed6a..2ef0b6b07d14 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -5725,7 +5725,8 @@ bool ImGui::IsWindowHovered() bool ImGui::IsWindowRectHovered() { - return GImGui->HoveredWindow == GImGui->CurrentWindow; + ImGuiContext& g = *GImGui; + return g.HoveredWindow == g.CurrentWindow; } bool ImGui::IsWindowFocused() @@ -7786,6 +7787,7 @@ bool ImGui::DragBehavior(const ImRect& frame_bb, ImGuiID id, float* v, float v_s if (v_speed == 0.0f && (v_max - v_min) != 0.0f && (v_max - v_min) < FLT_MAX) v_speed = (v_max - v_min) * g.DragSpeedDefaultRatio; + if (g.ActiveIdSource == ImGuiInputSource_Nav) v_speed = ImMax(v_speed, GetMinimumStepAtDecimalPrecision(decimal_precision)); From e6ed2f99397d7906c61410d0819ec5e3a2b192ac Mon Sep 17 00:00:00 2001 From: omar Date: Fri, 25 Aug 2017 00:06:57 +0800 Subject: [PATCH 121/823] Nav: Tooltip do not appear in navigation focus list. (#1294, #787) --- imgui.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/imgui.cpp b/imgui.cpp index 2ef0b6b07d14..89a8c406a607 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -4107,7 +4107,7 @@ static void BeginTooltipEx(bool override_previous_tooltip) window->HiddenFrames = 1; ImFormatString(window_name, IM_ARRAYSIZE(window_name), "##Tooltip%02d", ++g.TooltipOverrideCount); } - ImGui::Begin(window_name, NULL, ImGuiWindowFlags_Tooltip|ImGuiWindowFlags_NoTitleBar|ImGuiWindowFlags_NoMove|ImGuiWindowFlags_NoResize|ImGuiWindowFlags_NoSavedSettings|ImGuiWindowFlags_AlwaysAutoResize); + ImGui::Begin(window_name, NULL, ImGuiWindowFlags_Tooltip|ImGuiWindowFlags_NoTitleBar|ImGuiWindowFlags_NoMove|ImGuiWindowFlags_NoResize|ImGuiWindowFlags_NoSavedSettings|ImGuiWindowFlags_AlwaysAutoResize|ImGuiWindowFlags_NoNavFocus); } void ImGui::SetTooltipV(const char* fmt, va_list args) From 6752cba4bc5662cc0186e54616fcec53340e726c Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 29 Aug 2017 15:39:11 +0800 Subject: [PATCH 122/823] Removed duplicate comments --- imgui.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index fd8bc25e0053..a6c46011b341 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -261,9 +261,6 @@ - 2016/10/15 (1.50) - avoid 'void* user_data' parameter to io.SetClipboardTextFn/io.GetClipboardTextFn pointers. We pass io.ClipboardUserData to it. - 2016/09/25 (1.50) - style.WindowTitleAlign is now a ImVec2 (ImGuiAlign enum was removed). set to (0.5f,0.5f) for horizontal+vertical centering, (0.0f,0.0f) for upper-left, etc. - 2016/07/30 (1.50) - SameLine(x) with x>0.0f is now relative to left of column/group if any, and not always to left of window. This was sort of always the intent and hopefully breakage should be minimal. - - 2016/07/18 (1.50) - renamed IsMouseHoveringAnyWindow() to IsAnyWindowHovered() for consistency. Kept inline redirection function (will obsolete). - - renamed IsPosHoveringAnyWindow() to IsAnyWindowHoveredAtPos() for consistency. Kept inline redirection function (will obsolete). - - renamed IsMouseHoveringWindow() to IsWindowHoveredRect() for consistency. Kept inline redirection function (will obsolete). - 2016/05/12 (1.49) - title bar (using ImGuiCol_TitleBg/ImGuiCol_TitleBgActive colors) isn't rendered over a window background (ImGuiCol_WindowBg color) anymore. If your TitleBg/TitleBgActive alpha was 1.0f or you are using the default theme it will not affect you. However if your TitleBg/TitleBgActive alpha was <1.0f you need to tweak your custom theme to readjust for the fact that we don't draw a WindowBg background behind the title bar. From 97a40e74fb902a27473aa6b033d711ccd247949d Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 29 Aug 2017 18:45:58 +0800 Subject: [PATCH 123/823] Nav: Fixed bad merge of 6def01be5df16e17d71f81a8d4083a0f48d04a8d so the bug fixed in #840 wasn't fully fixed in Nav branch. --- imgui.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 0dcafa2c50d8..c0f0c4b7e6e6 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1919,6 +1919,7 @@ void ImGui::SetActiveID(ImGuiID id, ImGuiWindow* window) g.ActiveIdWindow = window; if (id) { + g.ActiveIdIsAlive = true; g.ActiveIdSource = (g.NavActivateId == id || g.NavInputId == id || g.NavTabbedId == id) ? ImGuiInputSource_Nav : ImGuiInputSource_Mouse; if (g.ActiveIdSource == ImGuiInputSource_Nav) g.NavDisableMouseHover = true; @@ -1939,9 +1940,12 @@ void ImGui::SetActiveIDNoNav(ImGuiID id, ImGuiWindow* window) g.ActiveId = id; g.ActiveIdAllowNavDirFlags = 0; g.ActiveIdAllowOverlap = false; - g.ActiveIdIsAlive |= (id != 0); g.ActiveIdWindow = window; - g.ActiveIdSource = (g.NavActivateId == id || g.NavInputId == id) ? ImGuiInputSource_Nav : ImGuiInputSource_Mouse; + if (id) + { + g.ActiveIdIsAlive = true; + g.ActiveIdSource = (g.NavActivateId == id || g.NavInputId == id) ? ImGuiInputSource_Nav : ImGuiInputSource_Mouse; + } } void ImGui::ClearActiveID() From 6c91a1ef7fabbcb39d2188d57c947e66e9d79de8 Mon Sep 17 00:00:00 2001 From: omar Date: Sun, 17 Sep 2017 23:35:39 +0200 Subject: [PATCH 124/823] Minor comments --- imgui.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 3dd3d3f0e819..425f0d759657 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2034,9 +2034,9 @@ static bool NavScoreItem(ImRect cand) } // Compute distance between boxes - // FIXME-NAVIGATION: Introducing various biases toward typical imgui uses cases, but we don't have any rigorous proof of their effect now. + // FIXME-NAVIGATION: Introducing various biases toward typical imgui uses cases, but we don't have any rigorous proof of their side-effect.. float dbx = NavScoreItemDistInterval(cand.Min.x, cand.Max.x, curr.Min.x, curr.Max.x); - float dby = NavScoreItemDistInterval(ImLerp(cand.Min.y, cand.Max.y, 0.2f), ImLerp(cand.Min.y, cand.Max.y, 0.8f), ImLerp(curr.Min.y, curr.Max.y, 0.2f), ImLerp(curr.Min.y, curr.Max.y, 0.8f)); // Clamp down on Y to keep using box-distance for vertically touching items + float dby = NavScoreItemDistInterval(ImLerp(cand.Min.y, cand.Max.y, 0.2f), ImLerp(cand.Min.y, cand.Max.y, 0.8f), ImLerp(curr.Min.y, curr.Max.y, 0.2f), ImLerp(curr.Min.y, curr.Max.y, 0.8f)); // Scale down on Y to keep using box-distance for vertically touching items if (dby && dbx) dbx = (dbx/1000.0f) + ((dbx > 0.0f) ? +1.0f : -1.0f); float dist_box = fabsf(dbx) + fabsf(dby); @@ -2160,8 +2160,8 @@ bool ImGui::ItemAdd(const ImRect& bb, const ImGuiID* id, const ImRect* nav_bb_ar // (b) So that we can scroll up/down past clipped items. This adds a small O(N) cost to regular navigation requests unfortunately, but it is still limited to one window. // it may not scale very well for windows with ten of thousands of item, but at least the NavRequest is only performed on user interaction, aka maximum once a frame. // We could early out with `if (is_clipped && !g.NavInitDefaultRequest) return false;` but when we wouldn't be able to reach unclipped widgets. This would work if user had explicit scrolling control (e.g. mapped on a stick) - // A more pragmatic solution for handling last lists is relying on the fact that they are likely evenly spread items (so that clipper can work) and we could nav at higher-level (apply index, etc.) - // So eventually we would like to provide the user will the primitives to be able to implement that sort of customized/efficient navigation handling whenever necessary. + // A more pragmatic solution for handling long lists is relying on the fact that they are likely evenly spread items (so that clipper can be used) and we could Nav at higher-level (apply index, etc.) + // So eventually we would like to provide the user will the primitives to be able to implement that customized/efficient navigation handling whenever necessary. if (id != NULL && g.IO.NavUsable && g.NavWindow == window->RootNavWindow) { const ImRect& nav_bb = nav_bb_arg ? *nav_bb_arg : bb; From 113b2467cdb8c8cbf380c4a49e1cd5d747f3fc81 Mon Sep 17 00:00:00 2001 From: omar Date: Wed, 20 Sep 2017 23:02:06 +0200 Subject: [PATCH 125/823] Minor bits. Reduce usage of GImGui multiple times in same function. --- imgui.cpp | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 097b049ee931..cc420b0f3099 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -825,8 +825,8 @@ ImGuiIO::ImGuiIO() ImeWindowHandle = NULL; // Input (NB: we already have memset zero the entire structure) - MousePos = ImVec2(-FLT_MAX,-FLT_MAX); - MousePosPrev = ImVec2(-FLT_MAX,-FLT_MAX); + MousePos = ImVec2(-FLT_MAX, -FLT_MAX); + MousePosPrev = ImVec2(-FLT_MAX, -FLT_MAX); MouseDragThreshold = 6.0f; for (int i = 0; i < IM_ARRAYSIZE(MouseDownDuration); i++) MouseDownDuration[i] = MouseDownDurationPrev[i] = -1.0f; for (int i = 0; i < IM_ARRAYSIZE(KeysDownDuration); i++) KeysDownDuration[i] = KeysDownDurationPrev[i] = -1.0f; @@ -4058,17 +4058,20 @@ bool ImGui::IsItemClicked(int mouse_button) bool ImGui::IsAnyItemHovered() { - return GImGui->HoveredId != 0 || GImGui->HoveredIdPreviousFrame != 0; + ImGuiContext& g = *GImGui; + return g.HoveredId != 0 || g.HoveredIdPreviousFrame != 0; } bool ImGui::IsAnyItemActive() { - return GImGui->ActiveId != 0; + ImGuiContext& g = *GImGui; + return g.ActiveId != 0; } bool ImGui::IsAnyItemFocused() { - return GImGui->NavId != 0 && !GImGui->NavDisableHighlight; + ImGuiContext& g = *GImGui; + return g.NavId != 0 && !g.NavDisableHighlight; } bool ImGui::IsItemVisible() @@ -4406,6 +4409,7 @@ bool ImGui::BeginPopupContextVoid(const char* str_id, int mouse_button) static bool BeginChildEx(const char* name, ImGuiID id, const ImVec2& size_arg, bool border, ImGuiWindowFlags extra_flags) { + ImGuiContext& g = *GImGui; ImGuiWindow* parent_window = ImGui::GetCurrentWindow(); ImGuiWindowFlags flags = ImGuiWindowFlags_NoTitleBar|ImGuiWindowFlags_NoResize|ImGuiWindowFlags_NoSavedSettings|ImGuiWindowFlags_ChildWindow; @@ -4434,12 +4438,12 @@ static bool BeginChildEx(const char* name, ImGuiID id, const ImVec2& size_arg, b child_window->Flags &= ~ImGuiWindowFlags_ShowBorders; // Process navigation-in immediately so NavInit can run on first frame - if (/*!(flags & ImGuiWindowFlags_NavFlattened) &&*/ (child_window->DC.NavLayerActiveFlags != 0 || child_window->DC.NavHasScroll) && GImGui->NavActivateId == id) + if (/*!(flags & ImGuiWindowFlags_NavFlattened) &&*/ (child_window->DC.NavLayerActiveFlags != 0 || child_window->DC.NavHasScroll) && g.NavActivateId == id) { ImGui::FocusWindow(child_window); NavInitWindow(child_window, false); ImGui::SetActiveIDNoNav(id+1, child_window); // Steal ActiveId with a dummy id so that key-press won't activate child item - GImGui->ActiveIdSource = ImGuiInputSource_Nav; + g.ActiveIdSource = ImGuiInputSource_Nav; } return ret; From b9c185402ef6ee8524c9ebd115e45d8967e20c77 Mon Sep 17 00:00:00 2001 From: omar Date: Wed, 20 Sep 2017 23:58:56 +0200 Subject: [PATCH 126/823] Nav: minor tidying up NavUpdate() to use a local variables, easier to test replacing g.NavWindow with g NavMoveResultWindow for navigation accross flattened child windows. --- imgui.cpp | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index cc420b0f3099..ca4bde2cf966 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2545,36 +2545,37 @@ static void NavUpdate() if (g.NavMoveRequest && g.NavMoveResultId != 0) { IM_ASSERT(g.NavWindow); + ImGuiWindow* window = g.NavWindow; // Scroll to keep newly navigated item fully into view - ImRect window_rect_rel(g.NavWindow->InnerRect.Min - g.NavWindow->Pos - ImVec2(1,1), g.NavWindow->InnerRect.Max - g.NavWindow->Pos + ImVec2(1,1)); - //g.OverlayDrawList.AddRect(g.NavWindow->Pos + window_rect_rel.Min, g.NavWindow->Pos + window_rect_rel.Max, IM_COL32_WHITE); // [DEBUG] + ImRect window_rect_rel(window->InnerRect.Min - window->Pos - ImVec2(1,1), window->InnerRect.Max - window->Pos + ImVec2(1,1)); + //g.OverlayDrawList.AddRect(window->Pos + window_rect_rel.Min, window->Pos + window_rect_rel.Max, IM_COL32_WHITE); // [DEBUG] if (g.NavLayer == 0 && !window_rect_rel.Contains(g.NavMoveResultRectRel)) { - if (g.NavWindow->ScrollbarX && g.NavMoveResultRectRel.Min.x < window_rect_rel.Min.x) + if (window->ScrollbarX && g.NavMoveResultRectRel.Min.x < window_rect_rel.Min.x) { - g.NavWindow->ScrollTarget.x = g.NavMoveResultRectRel.Min.x + g.NavWindow->Scroll.x - g.Style.ItemSpacing.x; - g.NavWindow->ScrollTargetCenterRatio.x = 0.0f; + window->ScrollTarget.x = g.NavMoveResultRectRel.Min.x + window->Scroll.x - g.Style.ItemSpacing.x; + window->ScrollTargetCenterRatio.x = 0.0f; } - else if (g.NavWindow->ScrollbarX && g.NavMoveResultRectRel.Max.x >= window_rect_rel.Max.x) + else if (window->ScrollbarX && g.NavMoveResultRectRel.Max.x >= window_rect_rel.Max.x) { - g.NavWindow->ScrollTarget.x = g.NavMoveResultRectRel.Max.x + g.NavWindow->Scroll.x + g.Style.ItemSpacing.x; - g.NavWindow->ScrollTargetCenterRatio.x = 1.0f; + window->ScrollTarget.x = g.NavMoveResultRectRel.Max.x + window->Scroll.x + g.Style.ItemSpacing.x; + window->ScrollTargetCenterRatio.x = 1.0f; } if (g.NavMoveResultRectRel.Min.y < window_rect_rel.Min.y) { - g.NavWindow->ScrollTarget.y = g.NavMoveResultRectRel.Min.y + g.NavWindow->Scroll.y - g.Style.ItemSpacing.y; - g.NavWindow->ScrollTargetCenterRatio.y = 0.0f; + window->ScrollTarget.y = g.NavMoveResultRectRel.Min.y + window->Scroll.y - g.Style.ItemSpacing.y; + window->ScrollTargetCenterRatio.y = 0.0f; } else if (g.NavMoveResultRectRel.Max.y >= window_rect_rel.Max.y) { - g.NavWindow->ScrollTarget.y = g.NavMoveResultRectRel.Max.y + g.NavWindow->Scroll.y + g.Style.ItemSpacing.y; - g.NavWindow->ScrollTargetCenterRatio.y = 1.0f; + window->ScrollTarget.y = g.NavMoveResultRectRel.Max.y + window->Scroll.y + g.Style.ItemSpacing.y; + window->ScrollTargetCenterRatio.y = 1.0f; } // Estimate upcoming scroll so we can offset our relative mouse position so mouse position can be applied immediately (under this block) - ImVec2 next_scroll = CalcNextScrollFromScrollTargetAndClamp(g.NavWindow); - g.NavMoveResultRectRel.Translate(g.NavWindow->Scroll - next_scroll); + ImVec2 next_scroll = CalcNextScrollFromScrollTargetAndClamp(window); + g.NavMoveResultRectRel.Translate(window->Scroll - next_scroll); } // Apply result from previous frame navigation directional move request From f6b6dace9e79c75f8f494f71eb50228062d3e59c Mon Sep 17 00:00:00 2001 From: Jefferson Montgomery Date: Sun, 24 Sep 2017 14:43:37 -0700 Subject: [PATCH 127/823] Pass command list in using ImGui_ImplDX12_NewFrame() instead of ImGui_ImplDX12_Init() --- examples/directx12_example/imgui_impl_dx12.cpp | 7 ++++--- examples/directx12_example/imgui_impl_dx12.h | 4 ++-- examples/directx12_example/main.cpp | 4 ++-- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/examples/directx12_example/imgui_impl_dx12.cpp b/examples/directx12_example/imgui_impl_dx12.cpp index b2d62840794b..8f81b007347c 100644 --- a/examples/directx12_example/imgui_impl_dx12.cpp +++ b/examples/directx12_example/imgui_impl_dx12.cpp @@ -629,13 +629,12 @@ void ImGui_ImplDX12_InvalidateDeviceObjects() } bool ImGui_ImplDX12_Init(void* hwnd, int num_frames_in_flight, - ID3D12Device* device, ID3D12GraphicsCommandList* command_list, + ID3D12Device* device, D3D12_CPU_DESCRIPTOR_HANDLE font_srv_cpu_desc_handle, D3D12_GPU_DESCRIPTOR_HANDLE font_srv_gpu_desc_handle) { g_hWnd = (HWND)hwnd; g_pd3dDevice = device; - g_pd3dCommandList = command_list; g_hFontSrvCpuDescHandle = font_srv_cpu_desc_handle; g_hFontSrvGpuDescHandle = font_srv_gpu_desc_handle; g_pFrameResources = new FrameResources [num_frames_in_flight]; @@ -697,11 +696,13 @@ void ImGui_ImplDX12_Shutdown() g_frameIndex = UINT_MAX; } -void ImGui_ImplDX12_NewFrame() +void ImGui_ImplDX12_NewFrame(ID3D12GraphicsCommandList* command_list) { if (!g_pPipelineState) ImGui_ImplDX12_CreateDeviceObjects(); + g_pd3dCommandList = command_list; + ImGuiIO& io = ImGui::GetIO(); // Setup display size (every frame to accommodate for window resizing) diff --git a/examples/directx12_example/imgui_impl_dx12.h b/examples/directx12_example/imgui_impl_dx12.h index 78cef4ab69f4..7bc828eb0532 100644 --- a/examples/directx12_example/imgui_impl_dx12.h +++ b/examples/directx12_example/imgui_impl_dx12.h @@ -21,11 +21,11 @@ struct D3D12_GPU_DESCRIPTOR_HANDLE; // fontSrvCpuDescHandle and fontSrvGpuDescHandle are handles to a single SRV // descriptor to use for the internal font texture. IMGUI_API bool ImGui_ImplDX12_Init(void* hwnd, int numFramesInFlight, - ID3D12Device* device, ID3D12GraphicsCommandList* cmdList, + ID3D12Device* device, D3D12_CPU_DESCRIPTOR_HANDLE fontSrvCpuDescHandle, D3D12_GPU_DESCRIPTOR_HANDLE fontSrvGpuDescHandle); IMGUI_API void ImGui_ImplDX12_Shutdown(); -IMGUI_API void ImGui_ImplDX12_NewFrame(); +IMGUI_API void ImGui_ImplDX12_NewFrame(ID3D12GraphicsCommandList* cmdList); // Use if you want to reset your rendering device without losing ImGui state. IMGUI_API void ImGui_ImplDX12_InvalidateDeviceObjects(); diff --git a/examples/directx12_example/main.cpp b/examples/directx12_example/main.cpp index 1fc6f37b4ac1..4bca2a29216f 100644 --- a/examples/directx12_example/main.cpp +++ b/examples/directx12_example/main.cpp @@ -300,7 +300,7 @@ int main(int, char**) UpdateWindow(hwnd); // Setup ImGui binding - ImGui_ImplDX12_Init(hwnd, NUM_FRAMES_IN_FLIGHT, g_pd3dDevice, g_pd3dCommandList, + ImGui_ImplDX12_Init(hwnd, NUM_FRAMES_IN_FLIGHT, g_pd3dDevice, g_pd3dSrvDescHeap->GetCPUDescriptorHandleForHeapStart(), g_pd3dSrvDescHeap->GetGPUDescriptorHandleForHeapStart()); @@ -329,7 +329,7 @@ int main(int, char**) DispatchMessage(&msg); continue; } - ImGui_ImplDX12_NewFrame(); + ImGui_ImplDX12_NewFrame(g_pd3dCommandList); // 1. Show a simple window // Tip: if we don't call ImGui::Begin()/ImGui::End() the widgets appears in a window automatically called "Debug" From 3fd5790814aca2e0379cb4188d517640cf070feb Mon Sep 17 00:00:00 2001 From: Jefferson Montgomery Date: Sun, 24 Sep 2017 14:57:38 -0700 Subject: [PATCH 128/823] Pass render target format in ImGui_ImplDX12_Init() instead of hard-coded. --- examples/directx12_example/imgui_impl_dx12.cpp | 5 ++++- examples/directx12_example/imgui_impl_dx12.h | 2 ++ examples/directx12_example/main.cpp | 1 + 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/examples/directx12_example/imgui_impl_dx12.cpp b/examples/directx12_example/imgui_impl_dx12.cpp index 8f81b007347c..b0b65d7d5135 100644 --- a/examples/directx12_example/imgui_impl_dx12.cpp +++ b/examples/directx12_example/imgui_impl_dx12.cpp @@ -32,6 +32,7 @@ static ID3D10Blob* g_pVertexShaderBlob = NULL; static ID3D10Blob* g_pPixelShaderBlob = NULL; static ID3D12RootSignature* g_pRootSignature = NULL; static ID3D12PipelineState* g_pPipelineState = NULL; +static DXGI_FORMAT g_RTVFormat = DXGI_FORMAT_UNKNOWN; static ID3D12Resource* g_pFontTextureResource = NULL; static D3D12_CPU_DESCRIPTOR_HANDLE g_hFontSrvCpuDescHandle = {}; static D3D12_GPU_DESCRIPTOR_HANDLE g_hFontSrvGpuDescHandle = {}; @@ -489,7 +490,7 @@ bool ImGui_ImplDX12_CreateDeviceObjects() psoDesc.pRootSignature = g_pRootSignature; psoDesc.SampleMask = UINT_MAX; psoDesc.NumRenderTargets = 1; - psoDesc.RTVFormats[0] = DXGI_FORMAT_R8G8B8A8_UNORM; + psoDesc.RTVFormats[0] = g_RTVFormat; psoDesc.SampleDesc.Count = 1; psoDesc.Flags = D3D12_PIPELINE_STATE_FLAG_NONE; @@ -630,11 +631,13 @@ void ImGui_ImplDX12_InvalidateDeviceObjects() bool ImGui_ImplDX12_Init(void* hwnd, int num_frames_in_flight, ID3D12Device* device, + DXGI_FORMAT rtv_format, D3D12_CPU_DESCRIPTOR_HANDLE font_srv_cpu_desc_handle, D3D12_GPU_DESCRIPTOR_HANDLE font_srv_gpu_desc_handle) { g_hWnd = (HWND)hwnd; g_pd3dDevice = device; + g_RTVFormat = rtv_format; g_hFontSrvCpuDescHandle = font_srv_cpu_desc_handle; g_hFontSrvGpuDescHandle = font_srv_gpu_desc_handle; g_pFrameResources = new FrameResources [num_frames_in_flight]; diff --git a/examples/directx12_example/imgui_impl_dx12.h b/examples/directx12_example/imgui_impl_dx12.h index 7bc828eb0532..059d73e1f0a7 100644 --- a/examples/directx12_example/imgui_impl_dx12.h +++ b/examples/directx12_example/imgui_impl_dx12.h @@ -6,6 +6,7 @@ // If you are new to ImGui, see examples/README.txt and documentation at the top of imgui.cpp. // https://github.com/ocornut/imgui +enum DXGI_FORMAT; struct ID3D12Device; struct ID3D12GraphicsCommandList; struct D3D12_CPU_DESCRIPTOR_HANDLE; @@ -22,6 +23,7 @@ struct D3D12_GPU_DESCRIPTOR_HANDLE; // descriptor to use for the internal font texture. IMGUI_API bool ImGui_ImplDX12_Init(void* hwnd, int numFramesInFlight, ID3D12Device* device, + DXGI_FORMAT rtv_format, D3D12_CPU_DESCRIPTOR_HANDLE fontSrvCpuDescHandle, D3D12_GPU_DESCRIPTOR_HANDLE fontSrvGpuDescHandle); IMGUI_API void ImGui_ImplDX12_Shutdown(); diff --git a/examples/directx12_example/main.cpp b/examples/directx12_example/main.cpp index 4bca2a29216f..51b9da4e250d 100644 --- a/examples/directx12_example/main.cpp +++ b/examples/directx12_example/main.cpp @@ -301,6 +301,7 @@ int main(int, char**) // Setup ImGui binding ImGui_ImplDX12_Init(hwnd, NUM_FRAMES_IN_FLIGHT, g_pd3dDevice, + DXGI_FORMAT_R8G8B8A8_UNORM, g_pd3dSrvDescHeap->GetCPUDescriptorHandleForHeapStart(), g_pd3dSrvDescHeap->GetGPUDescriptorHandleForHeapStart()); From 869732c456619af9e5eeb883b6f1e692d8b9c44c Mon Sep 17 00:00:00 2001 From: omar Date: Wed, 27 Sep 2017 12:34:18 +0200 Subject: [PATCH 129/823] Nav: Removed unnecessary combo code (that kept the combo arrow highlighted after reverting to mouse controls). (#787) --- imgui.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 6362f62a6b6e..01606b1c1627 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -9538,14 +9538,13 @@ bool ImGui::BeginCombo(const char* label, const char* preview_value, ImVec2 popu bool hovered, held; bool pressed = ButtonBehavior(frame_bb, id, &hovered, &held); - const bool navigated = g.NavId == id; bool popup_open = IsPopupOpen(id); const ImRect value_bb(frame_bb.Min, frame_bb.Max - ImVec2(arrow_size, 0.0f)); RenderNavHighlight(frame_bb, id); RenderFrame(frame_bb.Min, frame_bb.Max, GetColorU32(ImGuiCol_FrameBg), true, style.FrameRounding); - RenderFrame(ImVec2(frame_bb.Max.x-arrow_size, frame_bb.Min.y), frame_bb.Max, GetColorU32(popup_open || hovered || navigated ? ImGuiCol_ButtonHovered : ImGuiCol_Button), true, style.FrameRounding); // FIXME-ROUNDING + RenderFrame(ImVec2(frame_bb.Max.x-arrow_size, frame_bb.Min.y), frame_bb.Max, GetColorU32(popup_open || hovered ? ImGuiCol_ButtonHovered : ImGuiCol_Button), true, style.FrameRounding); // FIXME-ROUNDING RenderCollapseTriangle(ImVec2(frame_bb.Max.x - arrow_size + style.FramePadding.y, frame_bb.Min.y + style.FramePadding.y), true); if (preview_value != NULL) From 79ef64430c1f7089c96a41fe1b2abce0a5836900 Mon Sep 17 00:00:00 2001 From: omar Date: Wed, 27 Sep 2017 17:27:21 +0200 Subject: [PATCH 130/823] Nav: Fixed merge cc26db8ec7f87a21b705fa9821a3c9f76003c7e5 --- imgui.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/imgui.cpp b/imgui.cpp index 0e33fc4d1e17..f6199c7df7a1 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2226,7 +2226,7 @@ bool ImGui::IsItemHovered() if (g.HoveredWindow == window) if (g.ActiveId == 0 || g.ActiveId == window->DC.LastItemId || g.ActiveIdAllowOverlap || g.ActiveId == window->MoveId) if (IsMouseHoveringRect(window->DC.LastItemRect.Min, window->DC.LastItemRect.Max)) - if (IsWindowContentHoverable(window)) + if (!g.NavDisableMouseHover && IsWindowContentHoverable(window)) return true; return false; From 2a8eb618dcc9443a6b741f22b3cf0b0ee038e8b2 Mon Sep 17 00:00:00 2001 From: omar Date: Thu, 28 Sep 2017 00:36:58 +0200 Subject: [PATCH 131/823] Nav: Fixed NavDown to open menu from a menu bar (#787) --- imgui.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/imgui.cpp b/imgui.cpp index 44088aad1cb7..43ffbde9e3b3 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -10039,6 +10039,7 @@ bool ImGui::BeginMenu(const char* label, bool enabled) else if (g.NavId == id && g.NavMoveRequest && g.NavMoveDir == ImGuiDir_Down) // Menu bar: Nav-Down to open { g.NavMoveRequest = false; + want_open = true; } if (!enabled) // explicitly close if an open menu becomes disabled, facilitate users code a lot in pattern such as 'if (BeginMenu("options", has_object)) { ..use object.. }' From af38749ea10b665ee2651f21e7253cf5c9e829df Mon Sep 17 00:00:00 2001 From: omar Date: Thu, 28 Sep 2017 19:07:52 +0200 Subject: [PATCH 132/823] Nav: Fixed ButtonBehavior mistakenly setting active id when the Activate button is held and we have a new NavId, which affected browsing some popups (#787) --- imgui.cpp | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index caf621ff976e..56feaa3a8cc0 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -6575,12 +6575,16 @@ bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool hovered = true; if (!g.NavWindowingTarget && IsNavInputDown(ImGuiNavInput_PadActivate)) { - // Set active id so it can be queried by user via IsItemActive(), etc. but don't react to it ourselves - g.NavActivateId = id; - SetActiveID(id, window); - g.ActiveIdAllowNavDirFlags = (1 << ImGuiDir_Left) | (1 << ImGuiDir_Right) | (1 << ImGuiDir_Up) | (1 << ImGuiDir_Down); - if (IsNavInputPressed(ImGuiNavInput_PadActivate, (flags & ImGuiButtonFlags_Repeat) ? ImGuiNavReadMode_Repeat : ImGuiNavReadMode_Pressed)) + bool nav_pressed = IsNavInputPressed(ImGuiNavInput_PadActivate, (flags & ImGuiButtonFlags_Repeat) ? ImGuiNavReadMode_Repeat : ImGuiNavReadMode_Pressed); + if (nav_pressed) pressed = true; + if (nav_pressed || g.ActiveId == id) + { + // Set active id so it can be queried by user via IsItemActive(), equivalent of holding the mouse button. + g.NavActivateId = id; // This is so SetActiveId assign a Nav source + SetActiveID(id, window); + g.ActiveIdAllowNavDirFlags = (1 << ImGuiDir_Left) | (1 << ImGuiDir_Right) | (1 << ImGuiDir_Up) | (1 << ImGuiDir_Down); + } } } From e0a2a832cd69c2d285333a1e5190f4adc664fffd Mon Sep 17 00:00:00 2001 From: omar Date: Thu, 28 Sep 2017 19:18:41 +0200 Subject: [PATCH 133/823] Nav: Changed internal flag to NoNavDefaultFocus to be false by allow, and more consistent (#787) --- imgui.cpp | 6 +++--- imgui_internal.h | 5 +++-- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 56feaa3a8cc0..750b5e50507d 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2189,9 +2189,9 @@ bool ImGui::ItemAdd(const ImRect& bb, const ImGuiID* id, const ImRect* nav_bb_ar if (g.NavInitDefaultRequest && g.NavLayer == window->DC.NavLayerCurrent) { // Even if 'ImGuiItemFlags_AllowNavDefaultFocus' is off (typically collapse/close button) we record the first ResultId so they can be used as fallback - if (window->DC.ItemFlags & ImGuiItemFlags_AllowNavDefaultFocus) + if (!(window->DC.ItemFlags & ImGuiItemFlags_NoNavDefaultFocus)) g.NavInitDefaultRequest = g.NavInitDefaultResultExplicit = false; // Found a match, clear request - if (g.NavInitDefaultResultId == 0 || (window->DC.ItemFlags & ImGuiItemFlags_AllowNavDefaultFocus)) + if (g.NavInitDefaultResultId == 0 || !(window->DC.ItemFlags & ImGuiItemFlags_NoNavDefaultFocus)) { g.NavInitDefaultResultId = *id; g.NavInitDefaultResultRectRel = nav_bb_rel; @@ -5242,7 +5242,7 @@ bool ImGui::Begin(const char* name, bool* p_open, const ImVec2& size_on_first_us { // Close & collapse button are on layer 1 (same as menus) and don't default focus const ImGuiItemFlags backup_item_options = window->DC.ItemFlags; - window->DC.ItemFlags &= ~ImGuiItemFlags_AllowNavDefaultFocus; + window->DC.ItemFlags |= ImGuiItemFlags_NoNavDefaultFocus; window->DC.NavLayerCurrent++; // Collapse button diff --git a/imgui_internal.h b/imgui_internal.h index b604262c7786..2aa49baa2df6 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -167,6 +167,7 @@ inline void operator delete(void*, ImPlacementNewDummy, void*) {} // Types //----------------------------------------------------------------------------- +// NB: Most of those flags are handled by ButtonBehavior(), but some as for the higher level ButtonEx() function only. enum ImGuiButtonFlags_ { ImGuiButtonFlags_Repeat = 1 << 0, // hold to repeat @@ -637,9 +638,9 @@ enum ImGuiItemFlags_ ImGuiItemFlags_AllowKeyboardFocus = 1 << 0, // true ImGuiItemFlags_ButtonRepeat = 1 << 1, // false // Button() will return true multiple times based on io.KeyRepeatDelay and io.KeyRepeatRate settings. //ImGuiItemFlags_Disabled = 1 << 2, // false // All widgets appears are disabled - ImGuiItemFlags_AllowNavDefaultFocus = 1 << 3, // true + ImGuiItemFlags_NoNavDefaultFocus = 1 << 3, // true ImGuiItemFlags_SelectableDontClosePopup = 1 << 4, // false // MenuItem/Selectable() automatically closes current Popup window - ImGuiItemFlags_Default_ = ImGuiItemFlags_AllowKeyboardFocus|ImGuiItemFlags_AllowNavDefaultFocus + ImGuiItemFlags_Default_ = ImGuiItemFlags_AllowKeyboardFocus }; // Transient per-window data, reset at the beginning of the frame From 50ba5437439395a2c415cbedbc3788f8d2c22dac Mon Sep 17 00:00:00 2001 From: omar Date: Thu, 28 Sep 2017 19:35:10 +0200 Subject: [PATCH 134/823] Comments --- imgui_internal.h | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/imgui_internal.h b/imgui_internal.h index 2aa49baa2df6..bbe98874d473 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -171,13 +171,13 @@ inline void operator delete(void*, ImPlacementNewDummy, void*) {} enum ImGuiButtonFlags_ { ImGuiButtonFlags_Repeat = 1 << 0, // hold to repeat - ImGuiButtonFlags_PressedOnClickRelease = 1 << 1, // (default) return pressed on click+release on same item (default if no PressedOn** flag is set) - ImGuiButtonFlags_PressedOnClick = 1 << 2, // return pressed on click (default requires click+release) - ImGuiButtonFlags_PressedOnRelease = 1 << 3, // return pressed on release (default requires click+release) - ImGuiButtonFlags_PressedOnDoubleClick = 1 << 4, // return pressed on double-click (default requires click+release) - ImGuiButtonFlags_FlattenChilds = 1 << 5, // allow interaction even if a child window is overlapping - ImGuiButtonFlags_DontClosePopups = 1 << 6, // disable automatically closing parent popup on press - ImGuiButtonFlags_Disabled = 1 << 7, // disable interaction + ImGuiButtonFlags_PressedOnClickRelease = 1 << 1, // return true on click + release on same item [DEFAULT if no PressedOn* flag is set] + ImGuiButtonFlags_PressedOnClick = 1 << 2, // return true on click (default requires click+release) + ImGuiButtonFlags_PressedOnRelease = 1 << 3, // return true on release (default requires click+release) + ImGuiButtonFlags_PressedOnDoubleClick = 1 << 4, // return true on double-click (default requires click+release) + ImGuiButtonFlags_FlattenChilds = 1 << 5, // allow interactions even if a child window is overlapping + ImGuiButtonFlags_DontClosePopups = 1 << 6, // disable automatically closing parent popup on press // [UNUSED] + ImGuiButtonFlags_Disabled = 1 << 7, // disable interactions ImGuiButtonFlags_AlignTextBaseLine = 1 << 8, // vertically align button to match text baseline - ButtonEx() only ImGuiButtonFlags_NoKeyModifiers = 1 << 9, // disable interaction if a key modifier is held ImGuiButtonFlags_AllowOverlapMode = 1 << 10, // require previous frame HoveredId to either match id or be null before being usable From 4b4e455c40a340310f06cab45ceddb957d68ace4 Mon Sep 17 00:00:00 2001 From: omar Date: Thu, 28 Sep 2017 19:41:30 +0200 Subject: [PATCH 135/823] Nav: Internal nenaming --- imgui.cpp | 20 ++++++++++---------- imgui_internal.h | 4 ++-- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 750b5e50507d..2a5662844025 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2173,7 +2173,7 @@ bool ImGui::ItemAdd(const ImRect& bb, const ImGuiID* id, const ImRect* nav_bb_ar window->DC.LastItemRect = bb; window->DC.LastItemRectHoveredRect = false; if (id != NULL) - window->DC.NavLayerActiveFlagsNext |= (1 << window->DC.NavLayerCurrent); + window->DC.NavLayerActiveMaskNext |= (1 << window->DC.NavLayerCurrent); // Navigation processing runs prior to clipping early-out // (a) So that NavInitDefaultRequest can be honored, for newly opened windows to select a default widget @@ -2188,8 +2188,8 @@ bool ImGui::ItemAdd(const ImRect& bb, const ImGuiID* id, const ImRect* nav_bb_ar const ImRect nav_bb_rel(nav_bb.Min - g.NavWindow->Pos, nav_bb.Max - g.NavWindow->Pos); if (g.NavInitDefaultRequest && g.NavLayer == window->DC.NavLayerCurrent) { - // Even if 'ImGuiItemFlags_AllowNavDefaultFocus' is off (typically collapse/close button) we record the first ResultId so they can be used as fallback if (!(window->DC.ItemFlags & ImGuiItemFlags_NoNavDefaultFocus)) + // Even if 'ImGuiItemFlags_NoNavDefaultFocus' is on (typically collapse/close button) we record the first ResultId so they can be used as a fallback g.NavInitDefaultRequest = g.NavInitDefaultResultExplicit = false; // Found a match, clear request if (g.NavInitDefaultResultId == 0 || !(window->DC.ItemFlags & ImGuiItemFlags_NoNavDefaultFocus)) { @@ -2695,9 +2695,9 @@ static void NavUpdate() // Single press toggles NavLayer if (g.NavWindowingToggleLayer && g.NavWindow) { - if ((g.NavWindow->DC.NavLayerActiveFlags & (1<<1)) == 0 && (g.NavWindow->RootWindow->DC.NavLayerActiveFlags & (1<<1)) != 0) + if ((g.NavWindow->DC.NavLayerActiveMask & (1<<1)) == 0 && (g.NavWindow->RootWindow->DC.NavLayerActiveMask & (1<<1)) != 0) ImGui::FocusWindow(g.NavWindow->RootWindow); - g.NavLayer = (g.NavWindow->DC.NavLayerActiveFlags & (1<<1)) ? (g.NavLayer ^ 1) : 0; + g.NavLayer = (g.NavWindow->DC.NavLayerActiveMask & (1<<1)) ? (g.NavLayer ^ 1) : 0; g.NavDisableHighlight = false; g.NavDisableMouseHover = true; if (g.NavLayer == 0 && g.NavWindow->NavLastId) @@ -2790,7 +2790,7 @@ static void NavUpdate() { // Fallback manual-scroll with NavUp/NavDown when window has no navigable item const float scroll_speed = ImFloor(g.NavWindow->CalcFontSize() * 100 * g.IO.DeltaTime + 0.5f); // We need round the scrolling speed because sub-pixel scroll isn't reliably supported. - if (!g.NavWindow->DC.NavLayerActiveFlags && g.NavWindow->DC.NavHasScroll && g.NavMoveRequest && (g.NavMoveDir == ImGuiDir_Up || g.NavMoveDir == ImGuiDir_Down)) + if (!g.NavWindow->DC.NavLayerActiveMask && g.NavWindow->DC.NavHasScroll && g.NavMoveRequest && (g.NavMoveDir == ImGuiDir_Up || g.NavMoveDir == ImGuiDir_Down)) SetWindowScrollY(g.NavWindow, ImFloor(g.NavWindow->Scroll.y + ((g.NavMoveDir == ImGuiDir_Up) ? -1.0f : +1.0f) * scroll_speed)); // Manual scroll with NavScrollXXX keys @@ -4462,7 +4462,7 @@ static bool BeginChildEx(const char* name, ImGuiID id, const ImVec2& size_arg, b child_window->Flags &= ~ImGuiWindowFlags_ShowBorders; // Process navigation-in immediately so NavInit can run on first frame - if (/*!(flags & ImGuiWindowFlags_NavFlattened) &&*/ (child_window->DC.NavLayerActiveFlags != 0 || child_window->DC.NavHasScroll) && g.NavActivateId == id) + if (/*!(flags & ImGuiWindowFlags_NavFlattened) &&*/ (child_window->DC.NavLayerActiveMask != 0 || child_window->DC.NavHasScroll) && g.NavActivateId == id) { ImGui::FocusWindow(child_window); NavInitWindow(child_window, false); @@ -4506,7 +4506,7 @@ void ImGui::EndChild() ImGuiWindow* parent_window = GetCurrentWindow(); ImRect bb(parent_window->DC.CursorPos, parent_window->DC.CursorPos + sz); ItemSize(sz); - if (/*!(window->Flags & ImGuiWindowFlags_NavFlattened) &&*/ (window->DC.NavLayerActiveFlags != 0 || window->DC.NavHasScroll)) + if (/*!(window->Flags & ImGuiWindowFlags_NavFlattened) &&*/ (window->DC.NavLayerActiveMask != 0 || window->DC.NavHasScroll)) { ItemAdd(bb, &window->ChildId); RenderNavHighlight(bb, window->ChildId); @@ -5194,8 +5194,8 @@ bool ImGui::Begin(const char* name, bool* p_open, const ImVec2& size_on_first_us window->DC.CursorMaxPos = window->DC.CursorStartPos; window->DC.CurrentLineHeight = window->DC.PrevLineHeight = 0.0f; window->DC.CurrentLineTextBaseOffset = window->DC.PrevLineTextBaseOffset = 0.0f; - window->DC.NavLayerActiveFlags = window->DC.NavLayerActiveFlagsNext; - window->DC.NavLayerActiveFlagsNext = 0x00; + window->DC.NavLayerActiveMask = window->DC.NavLayerActiveMaskNext; + window->DC.NavLayerActiveMaskNext = 0x00; window->DC.NavHasScroll = (GetScrollMaxY() > 0.0f); window->DC.MenuBarAppending = false; window->DC.MenuBarOffsetX = ImMax(window->WindowPadding.x, style.ItemSpacing.x); @@ -11585,7 +11585,7 @@ void ImGui::ShowMetricsWindow(bool* p_open) ImGui::BulletText("Size: (%.1f,%.1f), SizeContents (%.1f,%.1f)", window->Size.x, window->Size.y, window->SizeContents.x, window->SizeContents.y); ImGui::BulletText("Scroll: (%.2f,%.2f)", window->Scroll.x, window->Scroll.y); ImGui::BulletText("Active: %d, Accessed: %d", window->Active, window->Accessed); - ImGui::BulletText("NavLastId: 0x%08x, NavLayerActiveFlags: %02X", window->NavLastId, window->DC.NavLayerActiveFlags); + ImGui::BulletText("NavLastId: 0x%08x, NavLayerActiveMask: %02X", window->NavLastId, window->DC.NavLayerActiveMask); if (window->RootWindow != window) NodeWindow(window->RootWindow, "RootWindow"); if (window->DC.ChildWindows.Size > 0) NodeWindows(window->DC.ChildWindows, "ChildWindows"); ImGui::BulletText("Storage: %d bytes", window->StateStorage.Data.Size * (int)sizeof(ImGuiStorage::Pair)); diff --git a/imgui_internal.h b/imgui_internal.h index bbe98874d473..940c6ff7d314 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -662,7 +662,7 @@ struct IMGUI_API ImGuiDrawContext bool LastItemRectHoveredRect; bool NavHasScroll; // Set when scrolling can be used (ScrollMax > 0.0f) int NavLayerCurrent; // Current layer, 0..31 (we currently only use 0..1) - int NavLayerActiveFlags, NavLayerActiveFlagsNext; // Which layer have been written to. + int NavLayerActiveMask, NavLayerActiveMaskNext; // Which layer have been written to. bool MenuBarAppending; float MenuBarOffsetX; ImVector ChildWindows; @@ -705,7 +705,7 @@ struct IMGUI_API ImGuiDrawContext LastItemRect = ImRect(); LastItemRectHoveredRect = false; NavHasScroll = false; - NavLayerActiveFlags = NavLayerActiveFlagsNext = 0x00; + NavLayerActiveMask = NavLayerActiveMaskNext = 0x00; NavLayerCurrent = 0; MenuBarAppending = false; MenuBarOffsetX = 0.0f; From dd0855de5c26a82407eb0ec3412193fe5ec585ac Mon Sep 17 00:00:00 2001 From: omar Date: Thu, 28 Sep 2017 19:47:45 +0200 Subject: [PATCH 136/823] ButtonBehavior: Tidying up. --- imgui.cpp | 31 ++++++++++++++++++------------- 1 file changed, 18 insertions(+), 13 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 2a5662844025..2dc87ddcfeba 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -6589,25 +6589,30 @@ bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool } bool held = false; - if (g.ActiveId == id && g.ActiveIdSource == ImGuiInputSource_Mouse) + if (g.ActiveId == id) { - if (g.IO.MouseDown[0]) + if (g.ActiveIdSource == ImGuiInputSource_Mouse) { - held = true; + if (g.IO.MouseDown[0]) + { + held = true; + } + else + { + if (hovered && (flags & ImGuiButtonFlags_PressedOnClickRelease)) + if (!((flags & ImGuiButtonFlags_Repeat) && g.IO.MouseDownDurationPrev[0] >= g.IO.KeyRepeatDelay)) // Repeat mode trumps + pressed = true; + ClearActiveID(); + } + if (!(flags & ImGuiButtonFlags_NoNavOverride)) + g.NavDisableHighlight = true; } - else + else if (g.ActiveIdSource == ImGuiInputSource_Nav) { - if (hovered && (flags & ImGuiButtonFlags_PressedOnClickRelease)) - if (!((flags & ImGuiButtonFlags_Repeat) && g.IO.MouseDownDurationPrev[0] >= g.IO.KeyRepeatDelay)) // Repeat mode trumps - pressed = true; - ClearActiveID(); + if (!IsNavInputDown(ImGuiNavInput_PadActivate)) + ClearActiveID(); } - if (!(flags & ImGuiButtonFlags_NoNavOverride)) - g.NavDisableHighlight = true; } - if (g.ActiveId == id && g.ActiveIdSource == ImGuiInputSource_Nav) - if (!IsNavInputDown(ImGuiNavInput_PadActivate)) - ClearActiveID(); // AllowOverlap mode (rarely used) requires previous frame HoveredId to be null or to match. This allows using patterns where a later submitted widget overlaps a previous one. if (hovered && (flags & ImGuiButtonFlags_AllowOverlapMode) && (g.HoveredIdPreviousFrame != id && g.HoveredIdPreviousFrame != 0)) From 878fa96896da94c80dcbf0ce588adfff8cae270f Mon Sep 17 00:00:00 2001 From: omar Date: Thu, 28 Sep 2017 19:57:24 +0200 Subject: [PATCH 137/823] Nav: Re-arranged ItemAdd() to maximize early out (#787) --- imgui.cpp | 67 +++++++++++++++++++++++++++++-------------------------- 1 file changed, 35 insertions(+), 32 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 2dc87ddcfeba..e79a6f46fe91 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2182,41 +2182,44 @@ bool ImGui::ItemAdd(const ImRect& bb, const ImGuiID* id, const ImRect* nav_bb_ar // We could early out with `if (is_clipped && !g.NavInitDefaultRequest) return false;` but when we wouldn't be able to reach unclipped widgets. This would work if user had explicit scrolling control (e.g. mapped on a stick) // A more pragmatic solution for handling long lists is relying on the fact that they are likely evenly spread items (so that clipper can be used) and we could Nav at higher-level (apply index, etc.) // So eventually we would like to provide the user will the primitives to be able to implement that customized/efficient navigation handling whenever necessary. - if (id != NULL && g.IO.NavUsable && g.NavWindow == window->RootNavWindow) - { - const ImRect& nav_bb = nav_bb_arg ? *nav_bb_arg : bb; - const ImRect nav_bb_rel(nav_bb.Min - g.NavWindow->Pos, nav_bb.Max - g.NavWindow->Pos); - if (g.NavInitDefaultRequest && g.NavLayer == window->DC.NavLayerCurrent) - { - if (!(window->DC.ItemFlags & ImGuiItemFlags_NoNavDefaultFocus)) - // Even if 'ImGuiItemFlags_NoNavDefaultFocus' is on (typically collapse/close button) we record the first ResultId so they can be used as a fallback - g.NavInitDefaultRequest = g.NavInitDefaultResultExplicit = false; // Found a match, clear request - if (g.NavInitDefaultResultId == 0 || !(window->DC.ItemFlags & ImGuiItemFlags_NoNavDefaultFocus)) + if (id != NULL && g.NavWindow == window->RootNavWindow) + if (g.NavId == *id || g.NavMoveRequest || g.NavInitDefaultRequest) + if (g.IO.NavUsable) { - g.NavInitDefaultResultId = *id; - g.NavInitDefaultResultRectRel = nav_bb_rel; - } - } + const ImRect& nav_bb = nav_bb_arg ? *nav_bb_arg : bb; + const ImRect nav_bb_rel(nav_bb.Min - g.NavWindow->Pos, nav_bb.Max - g.NavWindow->Pos); + if (g.NavInitDefaultRequest && g.NavLayer == window->DC.NavLayerCurrent) + { + // Even if 'ImGuiItemFlags_NoNavDefaultFocus' is on (typically collapse/close button) we record the first ResultId so they can be used as a fallback + const ImGuiItemFlags item_flags = window->DC.ItemFlags; + if (!(item_flags & ImGuiItemFlags_NoNavDefaultFocus)) + g.NavInitDefaultRequest = g.NavInitDefaultResultExplicit = false; // Found a match, clear request + if (g.NavInitDefaultResultId == 0 || !(item_flags & ImGuiItemFlags_NoNavDefaultFocus)) + { + g.NavInitDefaultResultId = *id; + g.NavInitDefaultResultRectRel = nav_bb_rel; + } + } - //const bool DEBUG_NAV = false; // [DEBUG] Enable to test scoring on all items. - if ((g.NavMoveRequest /*|| DEBUG_NAV*/) && g.NavId != *id) - { - //if (DEBUG_NAV && !g.NavMoveRequest) g.NavMoveDir = ImGuiDir_N; - if (NavScoreItem(nav_bb)) //if (!DEBUG || g.NavMoveRequest) - { - g.NavMoveResultId = *id; - g.NavMoveResultRectRel = nav_bb_rel; - } - } + //const bool DEBUG_NAV = false; // [DEBUG] Enable to test scoring on all items. + if ((g.NavMoveRequest /*|| DEBUG_NAV*/) && g.NavId != *id) + { + //if (DEBUG_NAV && !g.NavMoveRequest) g.NavMoveDir = ImGuiDir_N; + if (NavScoreItem(nav_bb)) //if (!DEBUG || g.NavMoveRequest) + { + g.NavMoveResultId = *id; + g.NavMoveResultRectRel = nav_bb_rel; + } + } - // Update window-relative bounding box of navigated item - if (g.NavId == *id) - { - g.NavRefRectRel = nav_bb_rel; - g.NavIdIsAlive = true; - g.NavIdTabCounter = window->FocusIdxTabCounter; - } - } + // Update window-relative bounding box of navigated item + if (g.NavId == *id) + { + g.NavRefRectRel = nav_bb_rel; + g.NavIdIsAlive = true; + g.NavIdTabCounter = window->FocusIdxTabCounter; + } + } if (is_clipped) return false; From 2d859dee4eb2ee6fff922e63d8dea545ed4e6ebe Mon Sep 17 00:00:00 2001 From: omar Date: Thu, 28 Sep 2017 19:58:01 +0200 Subject: [PATCH 138/823] Nav: Added ImGuiItemFlags_NoNav item flag --- imgui.cpp | 4 ++-- imgui_internal.h | 5 +++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index e79a6f46fe91..2e04738d1b5a 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2182,16 +2182,16 @@ bool ImGui::ItemAdd(const ImRect& bb, const ImGuiID* id, const ImRect* nav_bb_ar // We could early out with `if (is_clipped && !g.NavInitDefaultRequest) return false;` but when we wouldn't be able to reach unclipped widgets. This would work if user had explicit scrolling control (e.g. mapped on a stick) // A more pragmatic solution for handling long lists is relying on the fact that they are likely evenly spread items (so that clipper can be used) and we could Nav at higher-level (apply index, etc.) // So eventually we would like to provide the user will the primitives to be able to implement that customized/efficient navigation handling whenever necessary. + const ImGuiItemFlags item_flags = window->DC.ItemFlags; if (id != NULL && g.NavWindow == window->RootNavWindow) if (g.NavId == *id || g.NavMoveRequest || g.NavInitDefaultRequest) - if (g.IO.NavUsable) + if (g.IO.NavUsable && !(item_flags & ImGuiItemFlags_NoNav)) { const ImRect& nav_bb = nav_bb_arg ? *nav_bb_arg : bb; const ImRect nav_bb_rel(nav_bb.Min - g.NavWindow->Pos, nav_bb.Max - g.NavWindow->Pos); if (g.NavInitDefaultRequest && g.NavLayer == window->DC.NavLayerCurrent) { // Even if 'ImGuiItemFlags_NoNavDefaultFocus' is on (typically collapse/close button) we record the first ResultId so they can be used as a fallback - const ImGuiItemFlags item_flags = window->DC.ItemFlags; if (!(item_flags & ImGuiItemFlags_NoNavDefaultFocus)) g.NavInitDefaultRequest = g.NavInitDefaultResultExplicit = false; // Found a match, clear request if (g.NavInitDefaultResultId == 0 || !(item_flags & ImGuiItemFlags_NoNavDefaultFocus)) diff --git a/imgui_internal.h b/imgui_internal.h index 940c6ff7d314..5b59b68853bd 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -638,8 +638,9 @@ enum ImGuiItemFlags_ ImGuiItemFlags_AllowKeyboardFocus = 1 << 0, // true ImGuiItemFlags_ButtonRepeat = 1 << 1, // false // Button() will return true multiple times based on io.KeyRepeatDelay and io.KeyRepeatRate settings. //ImGuiItemFlags_Disabled = 1 << 2, // false // All widgets appears are disabled - ImGuiItemFlags_NoNavDefaultFocus = 1 << 3, // true - ImGuiItemFlags_SelectableDontClosePopup = 1 << 4, // false // MenuItem/Selectable() automatically closes current Popup window + ImGuiItemFlags_NoNav = 1 << 3, // false + ImGuiItemFlags_NoNavDefaultFocus = 1 << 4, // false + ImGuiItemFlags_SelectableDontClosePopup = 1 << 5, // false // MenuItem/Selectable() automatically closes current Popup window ImGuiItemFlags_Default_ = ImGuiItemFlags_AllowKeyboardFocus }; From 7c2926de17ad16032e5d4ea0f1865305ecccfbdd Mon Sep 17 00:00:00 2001 From: omar Date: Thu, 28 Sep 2017 20:15:32 +0200 Subject: [PATCH 139/823] Demo: Added an extra test related to baseline and fixed an id collision. --- imgui_demo.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 3fbf46245e2a..b7e77a798587 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -811,7 +811,7 @@ void ImGui::ShowTestWindow(bool* p_open) } ImGui::Text("Color button only:"); - ImGui::ColorButton("MyColor##3b", *(ImVec4*)&color, misc_flags, ImVec2(80,80)); + ImGui::ColorButton("MyColor##3c", *(ImVec4*)&color, misc_flags, ImVec2(80,80)); ImGui::Text("Color picker:"); static bool alpha = true; @@ -1186,7 +1186,8 @@ void ImGui::ShowTestWindow(bool* p_open) ImGui::Text("Text aligned to Widget"); ImGui::SameLine(); ImGui::Button("Widget##1"); ImGui::SameLine(); ImGui::Text("Widget"); ImGui::SameLine(); - ImGui::SmallButton("Widget##2"); + ImGui::SmallButton("Widget##2"); ImGui::SameLine(); + ImGui::Button("Widget##3"); // Tree const float spacing = ImGui::GetStyle().ItemInnerSpacing.x; From df366b230e0aecf9bfab1402f5154854d7dd829a Mon Sep 17 00:00:00 2001 From: omar Date: Thu, 28 Sep 2017 20:22:30 +0200 Subject: [PATCH 140/823] ColorPicker4: Use nav flag to provide a slighly better experience when using navigation (#787, #346) --- imgui.cpp | 10 +++++++--- imgui_internal.h | 2 +- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 2e04738d1b5a..5e4945e00c3c 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -6648,7 +6648,8 @@ bool ImGui::ButtonEx(const char* label, const ImVec2& size_arg, ImGuiButtonFlags if (!ItemAdd(bb, &id)) return false; - if (window->DC.ItemFlags & ImGuiItemFlags_ButtonRepeat) flags |= ImGuiButtonFlags_Repeat; + if (window->DC.ItemFlags & ImGuiItemFlags_ButtonRepeat) + flags |= ImGuiButtonFlags_Repeat; bool hovered, held; bool pressed = ButtonBehavior(bb, id, &hovered, &held, flags); @@ -10598,6 +10599,7 @@ bool ImGui::ColorPicker4(const char* label, float col[4], ImGuiColorEditFlags fl bool value_changed = false, value_changed_h = false, value_changed_sv = false; + PushItemFlag(ImGuiItemFlags_NoNav, true); if (flags & ImGuiColorEditFlags_PickerHueWheel) { // Hue wheel + SV triangle logic @@ -10655,10 +10657,9 @@ bool ImGui::ColorPicker4(const char* label, float col[4], ImGuiColorEditFlags fl value_changed = value_changed_h = true; } } - - // Alpha bar logic if (alpha_bar) { + // Alpha bar logic SetCursorScreenPos(ImVec2(bar1_pos_x, picker_pos.y)); InvisibleButton("alpha", ImVec2(bars_width, sv_picker_size)); if (IsItemActive()) @@ -10667,6 +10668,7 @@ bool ImGui::ColorPicker4(const char* label, float col[4], ImGuiColorEditFlags fl value_changed = true; } } + PopItemFlag(); // ImGuiItemFlags_NoNav if (!(flags & ImGuiColorEditFlags_NoSidePreview)) { @@ -10687,6 +10689,7 @@ bool ImGui::ColorPicker4(const char* label, float col[4], ImGuiColorEditFlags fl if (!(flags & ImGuiColorEditFlags_NoSidePreview)) { + PushItemFlag(ImGuiItemFlags_NoNavDefaultFocus, true); ImVec4 col_v4(col[0], col[1], col[2], (flags & ImGuiColorEditFlags_NoAlpha) ? 1.0f : col[3]); if ((flags & ImGuiColorEditFlags_NoLabel)) Text("Current"); @@ -10701,6 +10704,7 @@ bool ImGui::ColorPicker4(const char* label, float col[4], ImGuiColorEditFlags fl value_changed = true; } } + PopItemFlag(); EndGroup(); } diff --git a/imgui_internal.h b/imgui_internal.h index 5b59b68853bd..e2920a4777f9 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -178,7 +178,7 @@ enum ImGuiButtonFlags_ ImGuiButtonFlags_FlattenChilds = 1 << 5, // allow interactions even if a child window is overlapping ImGuiButtonFlags_DontClosePopups = 1 << 6, // disable automatically closing parent popup on press // [UNUSED] ImGuiButtonFlags_Disabled = 1 << 7, // disable interactions - ImGuiButtonFlags_AlignTextBaseLine = 1 << 8, // vertically align button to match text baseline - ButtonEx() only + ImGuiButtonFlags_AlignTextBaseLine = 1 << 8, // vertically align button to match text baseline - ButtonEx() only // FIXME: Should be removed and handled SmallButton(), not possible currently because of DC.CursorPosPrevLine ImGuiButtonFlags_NoKeyModifiers = 1 << 9, // disable interaction if a key modifier is held ImGuiButtonFlags_AllowOverlapMode = 1 << 10, // require previous frame HoveredId to either match id or be null before being usable ImGuiButtonFlags_NoNavOverride = 1 << 11 // don't override navigation id when activated From 1f7f54e196e550d563a0f18e80ac173d3810e8e8 Mon Sep 17 00:00:00 2001 From: omar Date: Thu, 28 Sep 2017 22:00:17 +0200 Subject: [PATCH 141/823] Removed extraneous test. --- imgui.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/imgui.cpp b/imgui.cpp index 5e4945e00c3c..dada4887bd62 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -4987,7 +4987,7 @@ bool ImGui::Begin(const char* name, bool* p_open, const ImVec2& size_on_first_us IM_ASSERT(window_pos_set_by_api); float horizontal_overlap = style.ItemSpacing.x; // We want some overlap to convey the relative depth of each popup (currently the amount of overlap it is hard-coded to style.ItemSpacing.x, may need to introduce another style value). ImRect rect_to_avoid; - if (parent_window && parent_window->DC.MenuBarAppending) + if (parent_window->DC.MenuBarAppending) rect_to_avoid = ImRect(-FLT_MAX, parent_window->Pos.y + parent_window->TitleBarHeight(), FLT_MAX, parent_window->Pos.y + parent_window->TitleBarHeight() + parent_window->MenuBarHeight()); else rect_to_avoid = ImRect(parent_window->Pos.x + horizontal_overlap, -FLT_MAX, parent_window->Pos.x + parent_window->Size.x - horizontal_overlap - parent_window->ScrollbarSizes.x, FLT_MAX); From 30b1d85962814ce3d127e17dcc697dafba45fd10 Mon Sep 17 00:00:00 2001 From: omar Date: Thu, 28 Sep 2017 23:48:30 +0200 Subject: [PATCH 142/823] Nav: Commiting some better organized Debug helper because this going to stay for a bit. --- imgui.cpp | 31 +++++++++++++++++++++---------- imgui_internal.h | 3 ++- 2 files changed, 23 insertions(+), 11 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index dada4887bd62..fa632ee6810d 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -594,6 +594,8 @@ #include // intptr_t #endif +#define IMGUI_DEBUG_NAV 0 + #ifdef _MSC_VER #pragma warning (disable: 4127) // condition expression is constant #pragma warning (disable: 4505) // unreferenced local function has been removed (stb stuff) @@ -2091,7 +2093,7 @@ static bool NavScoreItem(ImRect cand) quadrant = (window->DC.LastItemId < g.NavId) ? ImGuiDir_Left : ImGuiDir_Right; } -#if 0 // [DEBUG] +#if IMGUI_DEBUG_NAV if (ImGui::IsMouseHoveringRect(cand.Min, cand.Max)) { char buf[128]; @@ -2184,7 +2186,7 @@ bool ImGui::ItemAdd(const ImRect& bb, const ImGuiID* id, const ImRect* nav_bb_ar // So eventually we would like to provide the user will the primitives to be able to implement that customized/efficient navigation handling whenever necessary. const ImGuiItemFlags item_flags = window->DC.ItemFlags; if (id != NULL && g.NavWindow == window->RootNavWindow) - if (g.NavId == *id || g.NavMoveRequest || g.NavInitDefaultRequest) + if (g.NavId == *id || g.NavMoveRequest || g.NavInitDefaultRequest || IMGUI_DEBUG_NAV) if (g.IO.NavUsable && !(item_flags & ImGuiItemFlags_NoNav)) { const ImRect& nav_bb = nav_bb_arg ? *nav_bb_arg : bb; @@ -2201,15 +2203,21 @@ bool ImGui::ItemAdd(const ImRect& bb, const ImGuiID* id, const ImRect* nav_bb_ar } } - //const bool DEBUG_NAV = false; // [DEBUG] Enable to test scoring on all items. - if ((g.NavMoveRequest /*|| DEBUG_NAV*/) && g.NavId != *id) + bool new_best = false; +#if IMGUI_DEBUG_NAV + // [DEBUG] Score items at all times + if (!g.NavMoveRequest) + g.NavMoveDir = g.NavMoveDirLast; + if (g.NavId != *id) + new_best = NavScoreItem(nav_bb) && g.NavMoveRequest; +#else + if (g.NavMoveRequest && g.NavId != *id) + new_best = NavScoreItem(nav_bb); +#endif + if (new_best) { - //if (DEBUG_NAV && !g.NavMoveRequest) g.NavMoveDir = ImGuiDir_N; - if (NavScoreItem(nav_bb)) //if (!DEBUG || g.NavMoveRequest) - { - g.NavMoveResultId = *id; - g.NavMoveResultRectRel = nav_bb_rel; - } + g.NavMoveResultId = *id; + g.NavMoveResultRectRel = nav_bb_rel; } // Update window-relative bounding box of navigated item @@ -2778,7 +2786,10 @@ static void NavUpdate() if ((allowed_dir_flags & (1< Date: Fri, 29 Sep 2017 00:01:26 +0200 Subject: [PATCH 143/823] Nav: Support for fallback horizontal scrolling with PadLeft/PadRight (nb: fallback scrolling is only used to navigate windows that have no interactive items). (#787) --- imgui.cpp | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index fa632ee6810d..186f262cb1da 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2802,12 +2802,17 @@ static void NavUpdate() // Scrolling if (g.NavWindow && !(g.NavWindow->Flags & ImGuiWindowFlags_NoNavInputs) && !g.NavWindowingTarget) { - // Fallback manual-scroll with NavUp/NavDown when window has no navigable item + // *Fallback* manual-scroll with NavUp/NavDown when window has no navigable item const float scroll_speed = ImFloor(g.NavWindow->CalcFontSize() * 100 * g.IO.DeltaTime + 0.5f); // We need round the scrolling speed because sub-pixel scroll isn't reliably supported. - if (!g.NavWindow->DC.NavLayerActiveMask && g.NavWindow->DC.NavHasScroll && g.NavMoveRequest && (g.NavMoveDir == ImGuiDir_Up || g.NavMoveDir == ImGuiDir_Down)) - SetWindowScrollY(g.NavWindow, ImFloor(g.NavWindow->Scroll.y + ((g.NavMoveDir == ImGuiDir_Up) ? -1.0f : +1.0f) * scroll_speed)); + if (!g.NavWindow->DC.NavLayerActiveMask && g.NavWindow->DC.NavHasScroll && g.NavMoveRequest) + { + if (g.NavMoveDir == ImGuiDir_Left || g.NavMoveDir == ImGuiDir_Right) + SetWindowScrollX(g.NavWindow, ImFloor(g.NavWindow->Scroll.x + ((g.NavMoveDir == ImGuiDir_Left) ? -1.0f : +1.0f) * scroll_speed)); + if (g.NavMoveDir == ImGuiDir_Up || g.NavMoveDir == ImGuiDir_Down) + SetWindowScrollY(g.NavWindow, ImFloor(g.NavWindow->Scroll.y + ((g.NavMoveDir == ImGuiDir_Up) ? -1.0f : +1.0f) * scroll_speed)); + } - // Manual scroll with NavScrollXXX keys + // *Normal* Manual scroll with NavScrollXXX keys ImVec2 scroll_dir = GetNavInputAmount2d(1, ImGuiNavReadMode_Down, 1.0f/10.0f, 10.0f); if (scroll_dir.x != 0.0f && g.NavWindow->ScrollbarX) { From cf308f403987918f7324047b58bed79eeb57607f Mon Sep 17 00:00:00 2001 From: omar Date: Fri, 29 Sep 2017 00:20:51 +0200 Subject: [PATCH 144/823] Nav: Fixed SetItemDefaultFocus from stealing default focus when we are initializing default focus for a menu bar layer (#787) --- imgui.cpp | 2 +- imgui_demo.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 186f262cb1da..cd6aed41fba1 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -4132,7 +4132,7 @@ void ImGui::SetItemAllowOverlap() void ImGui::SetItemDefaultFocus() { ImGuiContext& g = *GImGui; - if (g.NavWindow == g.CurrentWindow->RootNavWindow && (g.NavInitDefaultRequest || g.NavInitDefaultResultId != 0)) + if (g.NavWindow == g.CurrentWindow->RootNavWindow && (g.NavInitDefaultRequest || g.NavInitDefaultResultId != 0) && g.NavLayer == g.NavWindow->DC.NavLayerCurrent) { g.NavInitDefaultRequest = false; g.NavInitDefaultResultExplicit = true; diff --git a/imgui_demo.cpp b/imgui_demo.cpp index b7e77a798587..637adb8e1fd1 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -2420,7 +2420,7 @@ struct ExampleAppConsole // Demonstrate keeping focus on the input box ImGui::SetItemDefaultFocus(); - if (ImGui::IsItemHovered() || reclaim_focus) + if (reclaim_focus) //|| ImGui::IsItemHovered()) ImGui::SetKeyboardFocusHere(-1); // Auto focus previous widget ImGui::End(); From 9737efb2f17759f1633d0bb5fcda622ae0f0603b Mon Sep 17 00:00:00 2001 From: omar Date: Fri, 29 Sep 2017 17:58:25 +0200 Subject: [PATCH 145/823] Nav: Store per-window last nav id also per-layer so we can easily query them for menu navigation code. (#787) --- imgui.cpp | 35 ++++++++++++++++++----------------- imgui_internal.h | 3 ++- 2 files changed, 20 insertions(+), 18 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 233b3951628d..762cc178bd77 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1839,7 +1839,7 @@ ImGuiWindow::ImGuiWindow(const char* name) Appearing = false; BeginCount = 0; PopupId = 0; - NavLastId = 0; + NavLastIds[0] = NavLastIds[1] = 0; AutoFitFramesX = AutoFitFramesY = -1; AutoFitOnlyGrows = false; AutoFitChildAxises = 0x00; @@ -1934,8 +1934,8 @@ void ImGui::SetActiveID(ImGuiID id, ImGuiWindow* window) g.NavId = id; if (window) g.NavLayer = window->DC.NavLayerCurrent; - if (window && window->DC.NavLayerCurrent == 0) // (Assume that id correspond to the current NavLayer, which should be the case) - window->NavLastId = id; + if (window) // NB: We current assume that SetActiveId() is called in the context where its NavLayer is the current one, which should be the case. + window->NavLastIds[window->DC.NavLayerCurrent] = id; } } @@ -2450,9 +2450,9 @@ static void SetNavId(ImGuiID id) { ImGuiContext& g = *GImGui; IM_ASSERT(g.NavWindow); + IM_ASSERT(g.NavLayer == 0 || g.NavLayer == 1); g.NavId = id; - if (g.NavLayer == 0) - g.NavWindow->NavLastId = g.NavId; + g.NavWindow->NavLastIds[g.NavLayer] = g.NavId; } static void SetNavIdAndMoveMouse(ImGuiID id, const ImRect& rect_rel) @@ -2470,7 +2470,7 @@ static void NavInitWindow(ImGuiWindow* window, bool force_reinit) { ImGuiContext& g = *GImGui; IM_ASSERT(window == g.NavWindow); - if (!(window->Flags & ImGuiWindowFlags_ChildWindow) || (window->Flags & ImGuiWindowFlags_Popup) || (window->NavLastId == 0) || force_reinit) + if (!(window->Flags & ImGuiWindowFlags_ChildWindow) || (window->Flags & ImGuiWindowFlags_Popup) || (window->NavLastIds[0] == 0) || force_reinit) { SetNavId(0); g.NavInitDefaultRequest = true; @@ -2480,7 +2480,7 @@ static void NavInitWindow(ImGuiWindow* window, bool force_reinit) } else { - g.NavId = window->NavLastId; + g.NavId = window->NavLastIds[0]; } } @@ -2699,7 +2699,7 @@ static void NavUpdate() ImGui::FocusWindow(g.NavWindowingTarget); g.NavDisableHighlight = false; g.NavDisableMouseHover = true; - if (g.NavWindowingTarget->NavLastId == 0) + if (g.NavWindowingTarget->NavLastIds[0] == 0) NavInitWindow(g.NavWindowingTarget, false); } @@ -2711,14 +2711,15 @@ static void NavUpdate() g.NavLayer = (g.NavWindow->DC.NavLayerActiveMask & (1<<1)) ? (g.NavLayer ^ 1) : 0; g.NavDisableHighlight = false; g.NavDisableMouseHover = true; - if (g.NavLayer == 0 && g.NavWindow->NavLastId) - SetNavIdAndMoveMouse(g.NavWindow->NavLastId, ImRect()); + if (g.NavLayer == 0 && g.NavWindow->NavLastIds[0] != 0) + SetNavIdAndMoveMouse(g.NavWindow->NavLastIds[0], ImRect()); else NavInitWindow(g.NavWindow, true); } g.NavWindowingTarget = NULL; } } + IM_ASSERT(g.NavLayer == 0 || g.NavLayer == 1); // Set output flags for user application g.IO.NavUsable = g.NavWindow && !(g.NavWindow->Flags & ImGuiWindowFlags_NoNavInputs); @@ -2752,8 +2753,8 @@ static void NavUpdate() { // Leave the "menu" layer g.NavLayer = 0; - if (g.NavWindow->NavLastId) - SetNavIdAndMoveMouse(g.NavWindow->NavLastId, ImRect()); + if (g.NavWindow->NavLastIds[0]) + SetNavIdAndMoveMouse(g.NavWindow->NavLastIds[0], ImRect()); else NavInitWindow(g.NavWindow, true); } @@ -2761,7 +2762,7 @@ static void NavUpdate() { // Clear NavLastId for popups but keep it for regular child window so we can leave one and come back where we were if (g.NavWindow && ((g.NavWindow->Flags & ImGuiWindowFlags_Popup) || !(g.NavWindow->Flags & ImGuiWindowFlags_ChildWindow))) - g.NavWindow->NavLastId = 0; + g.NavWindow->NavLastIds[0] = 0; g.NavId = 0; } } @@ -4807,7 +4808,7 @@ bool ImGui::Begin(const char* name, bool* p_open, const ImVec2& size_on_first_us const bool window_just_appearing_after_hidden_for_resize = (window->HiddenFrames == 1); if (window_just_appearing_after_hidden_for_resize) - window->NavLastId = 0; + window->NavLastIds[0] = 0; window->Appearing = (window_just_activated_by_user || window_just_appearing_after_hidden_for_resize); // Process SetNextWindow***() calls @@ -5500,7 +5501,7 @@ void ImGui::FocusWindow(ImGuiWindow* window) if (g.NavWindow != window) { - g.NavId = window ? window->NavLastId : 0; // Restore NavId + g.NavId = window ? window->NavLastIds[0] : 0; // Restore NavId g.NavIdIsAlive = false; g.NavLayer = 0; if (window && g.NavDisableMouseHover) @@ -9588,7 +9589,7 @@ bool ImGui::BeginCombo(const char* label, const char* preview_value, ImVec2 popu if ((pressed || g.NavActivateId == id) && !popup_open) { if (window->DC.NavLayerCurrent == 0) - window->NavLastId = id; + window->NavLastIds[0] = id; OpenPopupEx(id, false); popup_open = true; } @@ -11617,7 +11618,7 @@ void ImGui::ShowMetricsWindow(bool* p_open) ImGui::BulletText("Size: (%.1f,%.1f), SizeContents (%.1f,%.1f)", window->Size.x, window->Size.y, window->SizeContents.x, window->SizeContents.y); ImGui::BulletText("Scroll: (%.2f,%.2f)", window->Scroll.x, window->Scroll.y); ImGui::BulletText("Active: %d, Accessed: %d", window->Active, window->Accessed); - ImGui::BulletText("NavLastId: 0x%08x, NavLayerActiveMask: %02X", window->NavLastId, window->DC.NavLayerActiveMask); + ImGui::BulletText("NavLastIds: 0x%08X,0x%08X, NavLayerActiveMask: %X", window->NavLastIds[0], window->NavLastIds[1], window->DC.NavLayerActiveMask); if (window->RootWindow != window) NodeWindow(window->RootWindow, "RootWindow"); if (window->DC.ChildWindows.Size > 0) NodeWindows(window->DC.ChildWindows, "ChildWindows"); ImGui::BulletText("Storage: %d bytes", window->StateStorage.Data.Size * (int)sizeof(ImGuiStorage::Pair)); diff --git a/imgui_internal.h b/imgui_internal.h index e8d90a9b0837..f87bd686dae0 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -764,7 +764,6 @@ struct IMGUI_API ImGuiWindow bool Appearing; // Set during the frame where the window is appearing (or re-appearing) int BeginCount; // Number of Begin() during the current frame (generally 0 or 1, 1+ if appending via multiple Begin/End pairs) ImGuiID PopupId; // ID in the popup stack when this window is used as a popup/menu (because we use generic Name/ID for recycling) - ImGuiID NavLastId; // Last known NavId for this window, for nav layer 0 only. int AutoFitFramesX, AutoFitFramesY; bool AutoFitOnlyGrows; int AutoFitChildAxises; @@ -776,6 +775,8 @@ struct IMGUI_API ImGuiWindow ImVec2 SetWindowPosVal; // store window position when using a non-zero Pivot (position set needs to be processed when we know the window size) ImVec2 SetWindowPosPivot; // store window pivot for positioning. ImVec2(0,0) when positioning from top-left corner; ImVec2(0.5f,0.5f) for centering; ImVec2(1,1) for bottom right. + ImGuiID NavLastIds[2]; // Last known NavId for this window, per layer (0/1) + ImGuiDrawContext DC; // Temporary per-window data, reset at the beginning of the frame ImVector IDStack; // ID stack. ID are hashes seeded with the value at the top of the stack ImRect ClipRect; // = DrawList->clip_rect_stack.back(). Scissoring / clipping rectangle. x1, y1, x2, y2. From e3c89aeb10387c17e20a62afaf4d47096087931d Mon Sep 17 00:00:00 2001 From: omar Date: Fri, 29 Sep 2017 18:24:43 +0200 Subject: [PATCH 146/823] Nav: Fixed menuitems/selectable on menu layer (layer 1) from storing themselves in wrong layer of LastNavIds when hovered.causing inconsistencies and bugs when hovering menu with mouse then pressing ALT to return to layer 0). NB: this is not a new bug introduced by the previous commit (which is related to nav layers), bug has been there for a while. (#787) --- imgui.cpp | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 762cc178bd77..62d52fb00b9c 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2446,19 +2446,19 @@ int ImGui::GetFrameCount() return GImGui->FrameCount; } -static void SetNavId(ImGuiID id) +static void SetNavId(ImGuiID id, int nav_layer) { ImGuiContext& g = *GImGui; IM_ASSERT(g.NavWindow); - IM_ASSERT(g.NavLayer == 0 || g.NavLayer == 1); + IM_ASSERT(nav_layer == 0 || nav_layer == 1); g.NavId = id; - g.NavWindow->NavLastIds[g.NavLayer] = g.NavId; + g.NavWindow->NavLastIds[nav_layer] = g.NavId; } -static void SetNavIdAndMoveMouse(ImGuiID id, const ImRect& rect_rel) +static void SetNavIdAndMoveMouse(ImGuiID id, int nav_layer, const ImRect& rect_rel) { ImGuiContext& g = *GImGui; - SetNavId(id); + SetNavId(id, nav_layer); g.NavRefRectRel = rect_rel; g.NavMousePosDirty = true; g.NavDisableHighlight = false; @@ -2472,7 +2472,7 @@ static void NavInitWindow(ImGuiWindow* window, bool force_reinit) IM_ASSERT(window == g.NavWindow); if (!(window->Flags & ImGuiWindowFlags_ChildWindow) || (window->Flags & ImGuiWindowFlags_Popup) || (window->NavLastIds[0] == 0) || force_reinit) { - SetNavId(0); + SetNavId(0, g.NavLayer); g.NavInitDefaultRequest = true; g.NavInitDefaultResultId = 0; g.NavInitDefaultResultExplicit = false; @@ -2579,7 +2579,7 @@ static void NavUpdate() { // Apply result from previous navigation init request (typically select the first item, unless SetItemDefaultFocus() has been called) IM_ASSERT(g.NavWindow); - SetNavId(g.NavInitDefaultResultId); + SetNavId(g.NavInitDefaultResultId, g.NavLayer); g.NavRefRectRel = g.NavInitDefaultResultRectRel; if (g.NavDisableMouseHover) g.NavMousePosDirty = true; @@ -2627,7 +2627,7 @@ static void NavUpdate() // Apply result from previous frame navigation directional move request ImGui::ClearActiveID(); - SetNavIdAndMoveMouse(g.NavMoveResultId, g.NavMoveResultRectRel); + SetNavIdAndMoveMouse(g.NavMoveResultId, g.NavLayer, g.NavMoveResultRectRel); g.NavMoveFromClampedRefRect = false; } @@ -2712,7 +2712,7 @@ static void NavUpdate() g.NavDisableHighlight = false; g.NavDisableMouseHover = true; if (g.NavLayer == 0 && g.NavWindow->NavLastIds[0] != 0) - SetNavIdAndMoveMouse(g.NavWindow->NavLastIds[0], ImRect()); + SetNavIdAndMoveMouse(g.NavWindow->NavLastIds[0], g.NavLayer, ImRect()); else NavInitWindow(g.NavWindow, true); } @@ -2739,7 +2739,7 @@ static void NavUpdate() ImGuiWindow* parent_window = g.NavWindow->ParentWindow; ImGui::FocusWindow(parent_window); IM_ASSERT(child_window->ChildId != 0); - SetNavId(child_window->ChildId); + SetNavId(child_window->ChildId, g.NavLayer); // FIXME-NAV: Layer not necessarily correct g.NavIdIsAlive = false; if (g.NavDisableMouseHover) g.NavMousePosDirty = true; @@ -2754,7 +2754,7 @@ static void NavUpdate() // Leave the "menu" layer g.NavLayer = 0; if (g.NavWindow->NavLastIds[0]) - SetNavIdAndMoveMouse(g.NavWindow->NavLastIds[0], ImRect()); + SetNavIdAndMoveMouse(g.NavWindow->NavLastIds[0], g.NavLayer, ImRect()); else NavInitWindow(g.NavWindow, true); } @@ -9737,7 +9737,7 @@ bool ImGui::Selectable(const char* label, bool selected, ImGuiSelectableFlags fl if (hovered && !g.NavDisableMouseHover && g.NavWindow == window && (g.IO.MouseDelta.x != 0.0f || g.IO.MouseDelta.y != 0.0f)) { g.NavDisableHighlight = true; - SetNavId(id); + SetNavId(id, window->DC.NavLayerCurrent); } // Render From 54eb4c485e898e215669a552dbce10f303bd63c8 Mon Sep 17 00:00:00 2001 From: omar Date: Fri, 29 Sep 2017 19:15:24 +0200 Subject: [PATCH 147/823] Nav: Marked misleading/broken code that will never execute. --- imgui.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/imgui.cpp b/imgui.cpp index 62d52fb00b9c..e3d2b6526765 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -3430,11 +3430,14 @@ void ImGui::EndFrame() if (g.HoveredRootWindow != NULL) { FocusWindow(g.HoveredWindow); + // FIXME-NAV: This never execute because of the FocusWindow call above, however we may might this behavior? + /* if (g.NavWindow != g.HoveredWindow) { g.NavRefRectRel = ImRect(g.IO.MousePos - g.HoveredWindow->Pos, g.IO.MousePos - g.HoveredWindow->Pos); //ImRect(0,0,0,0); g.NavDisableHighlight = true; } + */ if (!(g.HoveredWindow->Flags & ImGuiWindowFlags_NoMove)) { g.MovedWindow = g.HoveredWindow; From 9712a81f85bc22f9c10f7f9492613dc353b4ebd3 Mon Sep 17 00:00:00 2001 From: omar Date: Fri, 29 Sep 2017 19:26:03 +0200 Subject: [PATCH 148/823] Nav: Rectangle rectangle stored per window and per layer as well. Makes things simpler, allows enable us to visualize more data. --- imgui.cpp | 31 ++++++++++++++++++------------- imgui_internal.h | 7 ++++--- 2 files changed, 22 insertions(+), 16 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index e3d2b6526765..6ca7697b005f 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1839,7 +1839,6 @@ ImGuiWindow::ImGuiWindow(const char* name) Appearing = false; BeginCount = 0; PopupId = 0; - NavLastIds[0] = NavLastIds[1] = 0; AutoFitFramesX = AutoFitFramesY = -1; AutoFitOnlyGrows = false; AutoFitChildAxises = 0x00; @@ -1848,6 +1847,9 @@ ImGuiWindow::ImGuiWindow(const char* name) SetWindowPosAllowFlags = SetWindowSizeAllowFlags = SetWindowCollapsedAllowFlags = ImGuiCond_Always | ImGuiCond_Once | ImGuiCond_FirstUseEver | ImGuiCond_Appearing; SetWindowPosVal = SetWindowPosPivot = ImVec2(FLT_MAX, FLT_MAX); + NavLastIds[0] = NavLastIds[1] = 0; + NavRefRectRel[0] = NavRefRectRel[1] = ImRect(); + LastFrameActive = -1; ItemWidthDefault = 0.0f; FontWindowScale = 1.0f; @@ -2223,7 +2225,7 @@ bool ImGui::ItemAdd(const ImRect& bb, const ImGuiID* id, const ImRect* nav_bb_ar // Update window-relative bounding box of navigated item if (g.NavId == *id) { - g.NavRefRectRel = nav_bb_rel; + window->NavRefRectRel[window->DC.NavLayerCurrent] = nav_bb_rel; g.NavIdIsAlive = true; g.NavIdTabCounter = window->FocusIdxTabCounter; } @@ -2459,7 +2461,7 @@ static void SetNavIdAndMoveMouse(ImGuiID id, int nav_layer, const ImRect& rect_r { ImGuiContext& g = *GImGui; SetNavId(id, nav_layer); - g.NavRefRectRel = rect_rel; + g.NavWindow->NavRefRectRel[nav_layer] = rect_rel; g.NavMousePosDirty = true; g.NavDisableHighlight = false; g.NavDisableMouseHover = true; @@ -2487,11 +2489,13 @@ static void NavInitWindow(ImGuiWindow* window, bool force_reinit) static ImVec2 NavCalcPreferredMousePos() { ImGuiContext& g = *GImGui; - if (!g.NavWindow) + ImGuiWindow* window = g.NavWindow; + if (!window) return g.IO.MousePos; - ImVec2 p = g.NavWindow->Pos + ImVec2(g.NavRefRectRel.Min.x + ImMin(g.Style.FramePadding.x*4, g.NavRefRectRel.GetWidth()), g.NavRefRectRel.Max.y - ImMin(g.Style.FramePadding.y, g.NavRefRectRel.GetHeight())); - ImRect r = GetVisibleRect(); - return ImFloor(ImClamp(p, r.Min, r.Max)); // ImFloor() is important because non-integer mouse position application in backend might be lossy and result in undesirable non-zero delta. + const ImRect& ref_rect_rel = window->NavRefRectRel[g.NavLayer]; + ImVec2 pos = g.NavWindow->Pos + ImVec2(ref_rect_rel.Min.x + ImMin(g.Style.FramePadding.x*4, ref_rect_rel.GetWidth()), ref_rect_rel.Max.y - ImMin(g.Style.FramePadding.y, ref_rect_rel.GetHeight())); + ImRect visible_rect = GetVisibleRect(); + return ImFloor(ImClamp(pos, visible_rect.Min, visible_rect.Max)); // ImFloor() is important because non-integer mouse position application in backend might be lossy and result in undesirable non-zero delta. } static int FindWindowIndex(ImGuiWindow* window) // FIXME-OPT O(N) @@ -2580,7 +2584,7 @@ static void NavUpdate() // Apply result from previous navigation init request (typically select the first item, unless SetItemDefaultFocus() has been called) IM_ASSERT(g.NavWindow); SetNavId(g.NavInitDefaultResultId, g.NavLayer); - g.NavRefRectRel = g.NavInitDefaultResultRectRel; + g.NavWindow->NavRefRectRel[g.NavLayer] = g.NavInitDefaultResultRectRel; if (g.NavDisableMouseHover) g.NavMousePosDirty = true; } @@ -2834,21 +2838,22 @@ static void NavUpdate() { // When we have manually scrolled and NavId is out of bounds, we clamp its bounding box (used for search) to the visible area to restart navigation within visible items ImRect window_rect_rel(g.NavWindow->InnerRect.Min - g.NavWindow->Pos - ImVec2(1,1), g.NavWindow->InnerRect.Max - g.NavWindow->Pos + ImVec2(1,1)); - if (!window_rect_rel.Contains(g.NavRefRectRel)) + if (!window_rect_rel.Contains(g.NavWindow->NavRefRectRel[g.NavLayer])) { float pad = g.NavWindow->CalcFontSize() * 0.5f; window_rect_rel.Expand(ImVec2(-ImMin(window_rect_rel.GetWidth(), pad), -ImMin(window_rect_rel.GetHeight(), pad))); // Terrible approximation for the intend of starting navigation from first fully visible item - g.NavRefRectRel.ClipWith(window_rect_rel); + g.NavWindow->NavRefRectRel[g.NavLayer].ClipWith(window_rect_rel); g.NavId = 0; } g.NavMoveFromClampedRefRect = false; } // For scoring we use a single segment on the left side our current item bounding box (not touching the edge to avoid box overlap with zero-spaced items) - g.NavScoringRectScreen = g.NavWindow ? ImRect(g.NavWindow->Pos + g.NavRefRectRel.Min, g.NavWindow->Pos + g.NavRefRectRel.Max) : ImRect(); + g.NavScoringRectScreen = g.NavWindow ? ImRect(g.NavWindow->Pos + g.NavWindow->NavRefRectRel[g.NavLayer].Min, g.NavWindow->Pos + g.NavWindow->NavRefRectRel[g.NavLayer].Max) : ImRect(); g.NavScoringRectScreen.Min.x = ImMin(g.NavScoringRectScreen.Min.x + 1.0f, g.NavScoringRectScreen.Max.x); g.NavScoringRectScreen.Max.x = g.NavScoringRectScreen.Min.x; //g.OverlayDrawList.AddRect(g.NavScoringRectScreen.Min, g.NavScoringRectScreen.Max, IM_COL32(255,200,0,255)); // [DEBUG] + //if (g.NavWindow) for (int layer = 0; layer < 2; layer++) g.OverlayDrawList.AddRect(g.NavWindow->Pos + g.NavWindow->NavRefRectRel[layer].Min, g.NavWindow->Pos + g.NavWindow->NavRefRectRel[layer].Max, IM_COL32(255,200,0,255)); // [DEBUG] } void ImGui::NewFrame() @@ -5509,7 +5514,7 @@ void ImGui::FocusWindow(ImGuiWindow* window) g.NavLayer = 0; if (window && g.NavDisableMouseHover) g.NavMousePosDirty = true; - g.NavRefRectRel.Min = g.NavRefRectRel.Max = window ? (window->DC.CursorStartPos - window->Pos) : ImVec2(0,0); + window->NavRefRectRel[0].Min = window->NavRefRectRel[1].Max = window ? (window->DC.CursorStartPos - window->Pos) : ImVec2(0,0); g.NavWindow = window; } @@ -11622,6 +11627,7 @@ void ImGui::ShowMetricsWindow(bool* p_open) ImGui::BulletText("Scroll: (%.2f,%.2f)", window->Scroll.x, window->Scroll.y); ImGui::BulletText("Active: %d, Accessed: %d", window->Active, window->Accessed); ImGui::BulletText("NavLastIds: 0x%08X,0x%08X, NavLayerActiveMask: %X", window->NavLastIds[0], window->NavLastIds[1], window->DC.NavLayerActiveMask); + ImGui::BulletText("NavRefRectRel[0]: (%.1f,%.1f)(%.1f,%.1f)", window->NavRefRectRel[0].Min.x, window->NavRefRectRel[0].Min.y, window->NavRefRectRel[0].Max.x, window->NavRefRectRel[0].Max.y); if (window->RootWindow != window) NodeWindow(window->RootWindow, "RootWindow"); if (window->DC.ChildWindows.Size > 0) NodeWindows(window->DC.ChildWindows, "ChildWindows"); ImGui::BulletText("Storage: %d bytes", window->StateStorage.Data.Size * (int)sizeof(ImGuiStorage::Pair)); @@ -11655,7 +11661,6 @@ void ImGui::ShowMetricsWindow(bool* p_open) ImGui::Text("ActiveId: 0x%08X/0x%08X, ActiveIdSource: %s", g.ActiveId, g.ActiveIdPreviousFrame, input_source_names[g.ActiveIdSource]); ImGui::Text("ActiveIdWindow: '%s'", g.ActiveIdWindow ? g.ActiveIdWindow->Name : "NULL"); ImGui::Text("NavWindow: '%s', NavId: 0x%08X, NavLayer: %d", g.NavWindow ? g.NavWindow->Name : "NULL", g.NavId, g.NavLayer); - ImGui::Text("NavRefRectRel: (%.1f,%.1f)(%.1f,%.1f)", g.NavRefRectRel.Min.x, g.NavRefRectRel.Min.y, g.NavRefRectRel.Max.x, g.NavRefRectRel.Max.y); ImGui::Text("NavUsable: %d, NavActive: %d", g.IO.NavUsable, g.IO.NavActive); ImGui::Text("NavActivateId: 0x%08X, NavInputId: 0x%08X", g.NavActivateId, g.NavInputId); ImGui::Text("NavDisableHighlight: %d, NavDisableMouseHover: %d", g.NavDisableHighlight, g.NavDisableMouseHover); diff --git a/imgui_internal.h b/imgui_internal.h index f87bd686dae0..44c797350575 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -459,7 +459,7 @@ struct ImGuiContext ImGuiID NavId; // Nav/focused item for navigation ImGuiID NavActivateId, NavInputId; // ~~ IsKeyPressedMap(ImGuiKey_NavActive) ? NavId : 0, etc. (to make widget code terser) ImGuiID NavTabbedId; // - ImRect NavRefRectRel, NavScoringRectScreen;// Reference rectangle, in window space. Modified rectangle for directional navigation scoring, in screen space. + ImRect NavScoringRectScreen; // Rectangle used for scoring, in screen space. Based of window->DC.NavRefRectRel[], modified for directional navigation scoring. ImGuiWindow* NavWindowingTarget; float NavWindowingDisplayAlpha; bool NavWindowingToggleLayer; @@ -571,7 +571,7 @@ struct ImGuiContext NavWindow = NULL; NavId = NavActivateId = NavInputId = NavTabbedId = 0; - NavRefRectRel = NavScoringRectScreen = ImRect(); + NavScoringRectScreen = ImRect(); NavWindowingTarget = NULL; NavWindowingDisplayAlpha = 0.0f; NavWindowingToggleLayer = false; @@ -775,7 +775,8 @@ struct IMGUI_API ImGuiWindow ImVec2 SetWindowPosVal; // store window position when using a non-zero Pivot (position set needs to be processed when we know the window size) ImVec2 SetWindowPosPivot; // store window pivot for positioning. ImVec2(0,0) when positioning from top-left corner; ImVec2(0.5f,0.5f) for centering; ImVec2(1,1) for bottom right. - ImGuiID NavLastIds[2]; // Last known NavId for this window, per layer (0/1) + ImGuiID NavLastIds[2]; // Last known NavId for this window, per layer (0/1) + ImRect NavRefRectRel[2]; // Reference rectangle, in window space ImGuiDrawContext DC; // Temporary per-window data, reset at the beginning of the frame ImVector IDStack; // ID stack. ID are hashes seeded with the value at the top of the stack From 8a5a29f0beff1da7e432cfbe54cc6f78575b5d38 Mon Sep 17 00:00:00 2001 From: omar Date: Fri, 29 Sep 2017 19:28:19 +0200 Subject: [PATCH 149/823] Nav: Renamed internal field. --- imgui.cpp | 22 +++++++++++----------- imgui_internal.h | 2 +- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 6ca7697b005f..f65264ac181e 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1848,7 +1848,7 @@ ImGuiWindow::ImGuiWindow(const char* name) SetWindowPosVal = SetWindowPosPivot = ImVec2(FLT_MAX, FLT_MAX); NavLastIds[0] = NavLastIds[1] = 0; - NavRefRectRel[0] = NavRefRectRel[1] = ImRect(); + NavRectRel[0] = NavRectRel[1] = ImRect(); LastFrameActive = -1; ItemWidthDefault = 0.0f; @@ -2225,7 +2225,7 @@ bool ImGui::ItemAdd(const ImRect& bb, const ImGuiID* id, const ImRect* nav_bb_ar // Update window-relative bounding box of navigated item if (g.NavId == *id) { - window->NavRefRectRel[window->DC.NavLayerCurrent] = nav_bb_rel; + window->NavRectRel[window->DC.NavLayerCurrent] = nav_bb_rel; g.NavIdIsAlive = true; g.NavIdTabCounter = window->FocusIdxTabCounter; } @@ -2461,7 +2461,7 @@ static void SetNavIdAndMoveMouse(ImGuiID id, int nav_layer, const ImRect& rect_r { ImGuiContext& g = *GImGui; SetNavId(id, nav_layer); - g.NavWindow->NavRefRectRel[nav_layer] = rect_rel; + g.NavWindow->NavRectRel[nav_layer] = rect_rel; g.NavMousePosDirty = true; g.NavDisableHighlight = false; g.NavDisableMouseHover = true; @@ -2492,8 +2492,8 @@ static ImVec2 NavCalcPreferredMousePos() ImGuiWindow* window = g.NavWindow; if (!window) return g.IO.MousePos; - const ImRect& ref_rect_rel = window->NavRefRectRel[g.NavLayer]; - ImVec2 pos = g.NavWindow->Pos + ImVec2(ref_rect_rel.Min.x + ImMin(g.Style.FramePadding.x*4, ref_rect_rel.GetWidth()), ref_rect_rel.Max.y - ImMin(g.Style.FramePadding.y, ref_rect_rel.GetHeight())); + const ImRect& rect_rel = window->NavRectRel[g.NavLayer]; + ImVec2 pos = g.NavWindow->Pos + ImVec2(rect_rel.Min.x + ImMin(g.Style.FramePadding.x*4, rect_rel.GetWidth()), rect_rel.Max.y - ImMin(g.Style.FramePadding.y, rect_rel.GetHeight())); ImRect visible_rect = GetVisibleRect(); return ImFloor(ImClamp(pos, visible_rect.Min, visible_rect.Max)); // ImFloor() is important because non-integer mouse position application in backend might be lossy and result in undesirable non-zero delta. } @@ -2584,7 +2584,7 @@ static void NavUpdate() // Apply result from previous navigation init request (typically select the first item, unless SetItemDefaultFocus() has been called) IM_ASSERT(g.NavWindow); SetNavId(g.NavInitDefaultResultId, g.NavLayer); - g.NavWindow->NavRefRectRel[g.NavLayer] = g.NavInitDefaultResultRectRel; + g.NavWindow->NavRectRel[g.NavLayer] = g.NavInitDefaultResultRectRel; if (g.NavDisableMouseHover) g.NavMousePosDirty = true; } @@ -2838,18 +2838,18 @@ static void NavUpdate() { // When we have manually scrolled and NavId is out of bounds, we clamp its bounding box (used for search) to the visible area to restart navigation within visible items ImRect window_rect_rel(g.NavWindow->InnerRect.Min - g.NavWindow->Pos - ImVec2(1,1), g.NavWindow->InnerRect.Max - g.NavWindow->Pos + ImVec2(1,1)); - if (!window_rect_rel.Contains(g.NavWindow->NavRefRectRel[g.NavLayer])) + if (!window_rect_rel.Contains(g.NavWindow->NavRectRel[g.NavLayer])) { float pad = g.NavWindow->CalcFontSize() * 0.5f; window_rect_rel.Expand(ImVec2(-ImMin(window_rect_rel.GetWidth(), pad), -ImMin(window_rect_rel.GetHeight(), pad))); // Terrible approximation for the intend of starting navigation from first fully visible item - g.NavWindow->NavRefRectRel[g.NavLayer].ClipWith(window_rect_rel); + g.NavWindow->NavRectRel[g.NavLayer].ClipWith(window_rect_rel); g.NavId = 0; } g.NavMoveFromClampedRefRect = false; } // For scoring we use a single segment on the left side our current item bounding box (not touching the edge to avoid box overlap with zero-spaced items) - g.NavScoringRectScreen = g.NavWindow ? ImRect(g.NavWindow->Pos + g.NavWindow->NavRefRectRel[g.NavLayer].Min, g.NavWindow->Pos + g.NavWindow->NavRefRectRel[g.NavLayer].Max) : ImRect(); + g.NavScoringRectScreen = g.NavWindow ? ImRect(g.NavWindow->Pos + g.NavWindow->NavRectRel[g.NavLayer].Min, g.NavWindow->Pos + g.NavWindow->NavRectRel[g.NavLayer].Max) : ImRect(); g.NavScoringRectScreen.Min.x = ImMin(g.NavScoringRectScreen.Min.x + 1.0f, g.NavScoringRectScreen.Max.x); g.NavScoringRectScreen.Max.x = g.NavScoringRectScreen.Min.x; //g.OverlayDrawList.AddRect(g.NavScoringRectScreen.Min, g.NavScoringRectScreen.Max, IM_COL32(255,200,0,255)); // [DEBUG] @@ -5514,7 +5514,7 @@ void ImGui::FocusWindow(ImGuiWindow* window) g.NavLayer = 0; if (window && g.NavDisableMouseHover) g.NavMousePosDirty = true; - window->NavRefRectRel[0].Min = window->NavRefRectRel[1].Max = window ? (window->DC.CursorStartPos - window->Pos) : ImVec2(0,0); + window->NavRectRel[0].Min = window->NavRectRel[1].Max = window ? (window->DC.CursorStartPos - window->Pos) : ImVec2(0,0); g.NavWindow = window; } @@ -11627,7 +11627,7 @@ void ImGui::ShowMetricsWindow(bool* p_open) ImGui::BulletText("Scroll: (%.2f,%.2f)", window->Scroll.x, window->Scroll.y); ImGui::BulletText("Active: %d, Accessed: %d", window->Active, window->Accessed); ImGui::BulletText("NavLastIds: 0x%08X,0x%08X, NavLayerActiveMask: %X", window->NavLastIds[0], window->NavLastIds[1], window->DC.NavLayerActiveMask); - ImGui::BulletText("NavRefRectRel[0]: (%.1f,%.1f)(%.1f,%.1f)", window->NavRefRectRel[0].Min.x, window->NavRefRectRel[0].Min.y, window->NavRefRectRel[0].Max.x, window->NavRefRectRel[0].Max.y); + ImGui::BulletText("NavRectRel[0]: (%.1f,%.1f)(%.1f,%.1f)", window->NavRectRel[0].Min.x, window->NavRectRel[0].Min.y, window->NavRectRel[0].Max.x, window->NavRectRel[0].Max.y); if (window->RootWindow != window) NodeWindow(window->RootWindow, "RootWindow"); if (window->DC.ChildWindows.Size > 0) NodeWindows(window->DC.ChildWindows, "ChildWindows"); ImGui::BulletText("Storage: %d bytes", window->StateStorage.Data.Size * (int)sizeof(ImGuiStorage::Pair)); diff --git a/imgui_internal.h b/imgui_internal.h index 44c797350575..836914865135 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -776,7 +776,7 @@ struct IMGUI_API ImGuiWindow ImVec2 SetWindowPosPivot; // store window pivot for positioning. ImVec2(0,0) when positioning from top-left corner; ImVec2(0.5f,0.5f) for centering; ImVec2(1,1) for bottom right. ImGuiID NavLastIds[2]; // Last known NavId for this window, per layer (0/1) - ImRect NavRefRectRel[2]; // Reference rectangle, in window space + ImRect NavRectRel[2]; // Reference rectangle, in window space ImGuiDrawContext DC; // Temporary per-window data, reset at the beginning of the frame ImVector IDStack; // ID stack. ID are hashes seeded with the value at the top of the stack From bfaa426f7fda56295da6de33b9252db8f4aaa01a Mon Sep 17 00:00:00 2001 From: omar Date: Fri, 29 Sep 2017 19:34:11 +0200 Subject: [PATCH 150/823] Nav: Minor tidying up (adding local variables to be a little more sane). --- imgui.cpp | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index f65264ac181e..961fa1486101 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2808,25 +2808,26 @@ static void NavUpdate() if (g.NavWindow && !(g.NavWindow->Flags & ImGuiWindowFlags_NoNavInputs) && !g.NavWindowingTarget) { // *Fallback* manual-scroll with NavUp/NavDown when window has no navigable item - const float scroll_speed = ImFloor(g.NavWindow->CalcFontSize() * 100 * g.IO.DeltaTime + 0.5f); // We need round the scrolling speed because sub-pixel scroll isn't reliably supported. - if (!g.NavWindow->DC.NavLayerActiveMask && g.NavWindow->DC.NavHasScroll && g.NavMoveRequest) + ImGuiWindow* window = g.NavWindow; + const float scroll_speed = ImFloor(window->CalcFontSize() * 100 * g.IO.DeltaTime + 0.5f); // We need round the scrolling speed because sub-pixel scroll isn't reliably supported. + if (!window->DC.NavLayerActiveMask && window->DC.NavHasScroll && g.NavMoveRequest) { if (g.NavMoveDir == ImGuiDir_Left || g.NavMoveDir == ImGuiDir_Right) - SetWindowScrollX(g.NavWindow, ImFloor(g.NavWindow->Scroll.x + ((g.NavMoveDir == ImGuiDir_Left) ? -1.0f : +1.0f) * scroll_speed)); + SetWindowScrollX(window, ImFloor(window->Scroll.x + ((g.NavMoveDir == ImGuiDir_Left) ? -1.0f : +1.0f) * scroll_speed)); if (g.NavMoveDir == ImGuiDir_Up || g.NavMoveDir == ImGuiDir_Down) - SetWindowScrollY(g.NavWindow, ImFloor(g.NavWindow->Scroll.y + ((g.NavMoveDir == ImGuiDir_Up) ? -1.0f : +1.0f) * scroll_speed)); + SetWindowScrollY(window, ImFloor(window->Scroll.y + ((g.NavMoveDir == ImGuiDir_Up) ? -1.0f : +1.0f) * scroll_speed)); } // *Normal* Manual scroll with NavScrollXXX keys ImVec2 scroll_dir = GetNavInputAmount2d(1, ImGuiNavReadMode_Down, 1.0f/10.0f, 10.0f); - if (scroll_dir.x != 0.0f && g.NavWindow->ScrollbarX) + if (scroll_dir.x != 0.0f && window->ScrollbarX) { - SetWindowScrollX(g.NavWindow, ImFloor(g.NavWindow->Scroll.x + scroll_dir.x * scroll_speed)); + SetWindowScrollX(window, ImFloor(window->Scroll.x + scroll_dir.x * scroll_speed)); g.NavMoveFromClampedRefRect = true; } if (scroll_dir.y != 0.0f) { - SetWindowScrollY(g.NavWindow, ImFloor(g.NavWindow->Scroll.y + scroll_dir.y * scroll_speed)); + SetWindowScrollY(window, ImFloor(window->Scroll.y + scroll_dir.y * scroll_speed)); g.NavMoveFromClampedRefRect = true; } } @@ -2837,12 +2838,13 @@ static void NavUpdate() if (g.NavMoveRequest && g.NavMoveFromClampedRefRect && g.NavLayer == 0) { // When we have manually scrolled and NavId is out of bounds, we clamp its bounding box (used for search) to the visible area to restart navigation within visible items - ImRect window_rect_rel(g.NavWindow->InnerRect.Min - g.NavWindow->Pos - ImVec2(1,1), g.NavWindow->InnerRect.Max - g.NavWindow->Pos + ImVec2(1,1)); - if (!window_rect_rel.Contains(g.NavWindow->NavRectRel[g.NavLayer])) + ImGuiWindow* window = g.NavWindow; + ImRect window_rect_rel(window->InnerRect.Min - window->Pos - ImVec2(1,1), window->InnerRect.Max - window->Pos + ImVec2(1,1)); + if (!window_rect_rel.Contains(window->NavRectRel[g.NavLayer])) { - float pad = g.NavWindow->CalcFontSize() * 0.5f; - window_rect_rel.Expand(ImVec2(-ImMin(window_rect_rel.GetWidth(), pad), -ImMin(window_rect_rel.GetHeight(), pad))); // Terrible approximation for the intend of starting navigation from first fully visible item - g.NavWindow->NavRectRel[g.NavLayer].ClipWith(window_rect_rel); + float pad = window->CalcFontSize() * 0.5f; + window_rect_rel.Expand(ImVec2(-ImMin(window_rect_rel.GetWidth(), pad), -ImMin(window_rect_rel.GetHeight(), pad))); // Terrible approximation for the intent of starting navigation from first fully visible item + window->NavRectRel[g.NavLayer].ClipWith(window_rect_rel); g.NavId = 0; } g.NavMoveFromClampedRefRect = false; @@ -2853,7 +2855,7 @@ static void NavUpdate() g.NavScoringRectScreen.Min.x = ImMin(g.NavScoringRectScreen.Min.x + 1.0f, g.NavScoringRectScreen.Max.x); g.NavScoringRectScreen.Max.x = g.NavScoringRectScreen.Min.x; //g.OverlayDrawList.AddRect(g.NavScoringRectScreen.Min, g.NavScoringRectScreen.Max, IM_COL32(255,200,0,255)); // [DEBUG] - //if (g.NavWindow) for (int layer = 0; layer < 2; layer++) g.OverlayDrawList.AddRect(g.NavWindow->Pos + g.NavWindow->NavRefRectRel[layer].Min, g.NavWindow->Pos + g.NavWindow->NavRefRectRel[layer].Max, IM_COL32(255,200,0,255)); // [DEBUG] + //if (g.NavWindow) for (int layer = 0; layer < 2; layer++) g.OverlayDrawList.AddRect(g.NavWindow->Pos + g.NavWindow->NavRectRel[layer].Min, g.NavWindow->Pos + g.NavWindow->NavRectRel[layer].Max, IM_COL32(255,200,0,255)); // [DEBUG] } void ImGui::NewFrame() From 5a9ebeca9e45e10d3e14dad49c33af27eea7ca70 Mon Sep 17 00:00:00 2001 From: omar Date: Fri, 29 Sep 2017 19:49:20 +0200 Subject: [PATCH 151/823] Nav: Fix typo from 9712a81f85bc22f9c10f7f9492613dc353b4ebd3 --- imgui.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/imgui.cpp b/imgui.cpp index 961fa1486101..a09bb8c6d0dc 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -5516,7 +5516,7 @@ void ImGui::FocusWindow(ImGuiWindow* window) g.NavLayer = 0; if (window && g.NavDisableMouseHover) g.NavMousePosDirty = true; - window->NavRectRel[0].Min = window->NavRectRel[1].Max = window ? (window->DC.CursorStartPos - window->Pos) : ImVec2(0,0); + window->NavRectRel[0].Min = window->NavRectRel[0].Max = window ? (window->DC.CursorStartPos - window->Pos) : ImVec2(0,0); g.NavWindow = window; } From cf3b21179b251ce651dcfd9d287cc3049c896c84 Mon Sep 17 00:00:00 2001 From: omar Date: Fri, 29 Sep 2017 20:03:02 +0200 Subject: [PATCH 152/823] Nav: Comments --- imgui.cpp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index a09bb8c6d0dc..eb7e1ea0606e 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2035,7 +2035,6 @@ static float NavScoreItemDistInterval(float a0, float a1, float b0, float b1) } // Scoring function for directional navigation. Based on https://gist.github.com/rygorous/6981057 -// FIXME-NAVIGATION: Pretty rough. Also may want to handle the degenerate case that we have commented out. static bool NavScoreItem(ImRect cand) { ImGuiContext& g = *GImGui; @@ -2043,7 +2042,7 @@ static bool NavScoreItem(ImRect cand) if (g.NavLayer != window->DC.NavLayerCurrent) return false; - const ImRect& curr = g.NavScoringRectScreen; // Current modified source rect (NB: we've applied Max.x = Min.x in NavUpdate() to inhibit the effect of having lots of items with varied width) + const ImRect& curr = g.NavScoringRectScreen; // Current modified source rect (NB: we've applied Max.x = Min.x in NavUpdate() to inhibit the effect of having varied item width) // We perform scoring on items bounding box clipped by their parent window on the other axis (clipping on our movement axis would give us equal scores for all clipped items) if (g.NavMoveDir == ImGuiDir_Left || g.NavMoveDir == ImGuiDir_Right) @@ -2058,7 +2057,7 @@ static bool NavScoreItem(ImRect cand) } // Compute distance between boxes - // FIXME-NAVIGATION: Introducing various biases toward typical imgui uses cases, but we don't have any rigorous proof of their side-effect.. + // FIXME-NAVIGATION: Introducing biases for vertical navigation, needs to be removed. float dbx = NavScoreItemDistInterval(cand.Min.x, cand.Max.x, curr.Min.x, curr.Max.x); float dby = NavScoreItemDistInterval(ImLerp(cand.Min.y, cand.Max.y, 0.2f), ImLerp(cand.Min.y, cand.Max.y, 0.8f), ImLerp(curr.Min.y, curr.Max.y, 0.2f), ImLerp(curr.Min.y, curr.Max.y, 0.8f)); // Scale down on Y to keep using box-distance for vertically touching items if (dby && dbx) @@ -2127,7 +2126,7 @@ static bool NavScoreItem(ImRect cand) } else if (dist_center == g.NavMoveResultDistCenter) { - // Still tied! we need to be extra-careful to make sure everything gets linked properly. We consistently break ties by symbolically moving "later" buttons + // Still tied! we need to be extra-careful to make sure everything gets linked properly. We consistently break ties by symbolically moving "later" items // (with higher index) to the right/downwards by an infinitesimal amount since we the current "best" button already (so it must have a lower index), // this is fairly easy. This rule ensures that all buttons with dx==dy==0 will end up being linked in order of appearance along the x axis. if (((g.NavMoveDir == ImGuiDir_Up || g.NavMoveDir == ImGuiDir_Down) ? dby : dbx) < 0.0f) // moving bj to the right/down decreases distance @@ -2167,7 +2166,7 @@ void ImGui::RenderNavHighlight(const ImRect& bb, ImGuiID id) // Declare item bounding box for clipping and interaction. // Note that the size can be different than the one provided to ItemSize(). Typically, widgets that spread over available surface -// declares their minimum size requirement to ItemSize() and then use a larger region for drawing/interaction, which is passed to ItemAdd(). +// declare their minimum size requirement to ItemSize() and then use a larger region for drawing/interaction, which is passed to ItemAdd(). bool ImGui::ItemAdd(const ImRect& bb, const ImGuiID* id, const ImRect* nav_bb_arg) { ImGuiContext& g = *GImGui; From f4e4c3870559781bb64c3817fe2f78ddf8979468 Mon Sep 17 00:00:00 2001 From: omar Date: Fri, 29 Sep 2017 22:19:53 +0200 Subject: [PATCH 153/823] BeginMenu(): fixed logic to distinguish vertical menu from one layed out in a menu bar. Makes MenuItem() in a regular window behave more consistently, and this will be also needed by upcoming menu-navigation changes in the nav branch. (#126, #787) --- imgui.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/imgui.cpp b/imgui.cpp index eb7e1ea0606e..08e697c40dd5 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -10029,7 +10029,7 @@ bool ImGui::BeginMenu(const char* label, bool enabled) g.NavWindow = backed_nav_window; bool want_open = false, want_close = false; - if (window->Flags & (ImGuiWindowFlags_Popup|ImGuiWindowFlags_ChildMenu)) + if (window->DC.LayoutType != ImGuiLayoutType_Horizontal) // (window->Flags & (ImGuiWindowFlags_Popup|ImGuiWindowFlags_ChildMenu)) { // Implement http://bjk5.com/post/44698559168/breaking-down-amazons-mega-dropdown to avoid using timers, so menus feels more reactive. bool moving_within_opened_triangle = false; From 1eaa9d0621ef6db263290785c698c27df3301243 Mon Sep 17 00:00:00 2001 From: omar Date: Fri, 29 Sep 2017 22:56:51 +0200 Subject: [PATCH 154/823] Nav: Fixed uninitialized variable (that had no side-effects due to the code/data flow involved) --- imgui_internal.h | 1 + 1 file changed, 1 insertion(+) diff --git a/imgui_internal.h b/imgui_internal.h index 836914865135..bf1ff1f85279 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -583,6 +583,7 @@ struct ImGuiContext NavInitDefaultRequest = false; NavInitDefaultResultId = 0; NavInitDefaultResultExplicit = false; + NavMoveFromClampedRefRect = false; NavMoveRequest = false; NavMoveDir = NavMoveDirLast = ImGuiDir_None; NavMoveResultId = 0; From 587e637db0be03fb11754a59c59383912cbdaf73 Mon Sep 17 00:00:00 2001 From: omar Date: Fri, 29 Sep 2017 22:57:44 +0200 Subject: [PATCH 155/823] Nav: Taking note that we should aim to remove MenuBarAppending later. --- imgui_internal.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/imgui_internal.h b/imgui_internal.h index bf1ff1f85279..5b399b52797c 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -665,8 +665,9 @@ struct IMGUI_API ImGuiDrawContext bool LastItemRectHoveredRect; bool NavHasScroll; // Set when scrolling can be used (ScrollMax > 0.0f) int NavLayerCurrent; // Current layer, 0..31 (we currently only use 0..1) - int NavLayerActiveMask, NavLayerActiveMaskNext; // Which layer have been written to. - bool MenuBarAppending; + int NavLayerActiveMask; // Which layer have been written to (result from previous frame) + int NavLayerActiveMaskNext; // Which layer have been written to (buffer for current frame) + bool MenuBarAppending; // FIXME: Remove this float MenuBarOffsetX; ImVector ChildWindows; ImGuiStorage* StateStorage; From 88a354585a87b69ad27b1570736a22860f78ca13 Mon Sep 17 00:00:00 2001 From: omar Date: Fri, 29 Sep 2017 23:36:41 +0200 Subject: [PATCH 156/823] Nav: It's now possible to navigate sibling of a menu-bar while navigating inside one of their child. If a Left<>Right navigation request fails to find a match we forward the request to the root menu. (#787, #126) Currently the sibling menu is isn't automatically opened, that's still left to it (and even that can be anoying in Windows when the first menu-item is a child menu) --- imgui.cpp | 56 ++++++++++++++++++++++++++++++++++++++++++------ imgui_internal.h | 11 ++++++---- 2 files changed, 56 insertions(+), 11 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 08e697c40dd5..deeb7c3470ad 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2634,6 +2634,15 @@ static void NavUpdate() g.NavMoveFromClampedRefRect = false; } + // When a forwarded move request failed, we restore the highlight that we disabled during the forward frame + if (g.NavMoveRequestForwardStep == 2) + { + IM_ASSERT(g.NavMoveRequest); + if (g.NavMoveResultId == 0) + g.NavDisableHighlight = false; + g.NavMoveRequestForwardStep = 0; + } + // Apply application mouse position movement, after we had a chance to process move request result. if (g.NavMousePosDirty && g.NavIdIsAlive) { @@ -2781,14 +2790,24 @@ static void NavUpdate() // Initiate directional inputs request const int allowed_dir_flags = (g.ActiveId == 0) ? ~0 : g.ActiveIdAllowNavDirFlags; - g.NavMoveDir = ImGuiDir_None; - if (g.NavWindow && !g.NavWindowingTarget && allowed_dir_flags && !(g.NavWindow->Flags & ImGuiWindowFlags_NoNavInputs)) + if (g.NavMoveRequestForwardStep == 0) { - if ((allowed_dir_flags & (1<Flags & ImGuiWindowFlags_NoNavInputs)) + { + if ((allowed_dir_flags & (1<InnerRect.Min - window->Pos - ImVec2(1,1), window->InnerRect.Max - window->Pos + ImVec2(1,1)); if (!window_rect_rel.Contains(window->NavRectRel[g.NavLayer])) @@ -5231,6 +5251,7 @@ bool ImGui::Begin(const char* name, bool* p_open, const ImVec2& size_on_first_us window->DC.LogLinePosY = window->DC.CursorPos.y - 9999.0f; window->DC.ChildWindows.resize(0); window->DC.LayoutType = ImGuiLayoutType_Vertical; + window->DC.ParentLayoutType = parent_window ? parent_window->DC.LayoutType : ImGuiLayoutType_Vertical; window->DC.ItemFlags = ImGuiItemFlags_Default_; window->DC.ItemWidth = window->ItemWidthDefault; window->DC.TextWrapPos = -1.0f; // disabled @@ -9966,6 +9987,27 @@ void ImGui::EndMenuBar() ImGuiWindow* window = GetCurrentWindow(); if (window->SkipItems) return; + ImGuiContext& g = *GImGui; + + // When a move request within one of our child menu failed, capture the request to navigate among our siblings. + if (g.NavMoveRequest && g.NavMoveResultId == 0 && (g.NavMoveDir == ImGuiDir_Left || g.NavMoveDir == ImGuiDir_Right)) + { + ImGuiWindow* nav_earliest_child = g.NavWindow; + while (nav_earliest_child->ParentWindow && (nav_earliest_child->ParentWindow->Flags & ImGuiWindowFlags_ChildMenu)) + nav_earliest_child = nav_earliest_child->ParentWindow; + if (nav_earliest_child->ParentWindow == window && nav_earliest_child->DC.ParentLayoutType == ImGuiLayoutType_Horizontal && g.NavMoveRequestForwardStep == 0) + { + // To do so we claim focus back, restore NavId and then process the movement request for yet another frame. + // This involve a one-frame delay which isn't very problematic in this situation. We could remove it by scoring in advance for multiple window (probably not worth the hassle/cost) + IM_ASSERT(window->DC.NavLayerActiveMaskNext & 0x02); // Sanity check + FocusWindow(window); + SetNavIdAndMoveMouse(window->NavLastIds[1], 1, window->NavRectRel[1]); + g.NavLayer = 1; + g.NavDisableHighlight = true; // Hide highlight for the current frame so we don't see the intermediary selection. + g.NavMoveRequest = false; + g.NavMoveRequestForwardStep = 1; + } + } IM_ASSERT(window->Flags & ImGuiWindowFlags_MenuBar); IM_ASSERT(window->DC.MenuBarAppending); diff --git a/imgui_internal.h b/imgui_internal.h index 5b399b52797c..bf0876c308a4 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -473,8 +473,9 @@ struct ImGuiContext ImGuiID NavInitDefaultResultId; ImRect NavInitDefaultResultRectRel; bool NavInitDefaultResultExplicit; // Whether the result was explicitly requested with SetItemDefaultFocus() - bool NavMoveRequest; // Move request for this frame bool NavMoveFromClampedRefRect; // Set by manual scrolling, if we scroll to a point where NavId isn't visible we reset navigation from visible items + bool NavMoveRequest; // Move request for this frame + int NavMoveRequestForwardStep; // 0: no forward, 1: forward request, 2: forward result ImGuiDir NavMoveDir; // West/East/North/South ImGuiDir NavMoveDirLast; // ImGuiID NavMoveResultId; // Best move request candidate @@ -585,6 +586,7 @@ struct ImGuiContext NavInitDefaultResultExplicit = false; NavMoveFromClampedRefRect = false; NavMoveRequest = false; + NavMoveRequestForwardStep = 0; NavMoveDir = NavMoveDirLast = ImGuiDir_None; NavMoveResultId = 0; NavMoveResultDistBox = NavMoveResultDistCenter = NavMoveResultDistAxial = 0.0f; @@ -663,8 +665,8 @@ struct IMGUI_API ImGuiDrawContext ImGuiID LastItemId; ImRect LastItemRect; bool LastItemRectHoveredRect; - bool NavHasScroll; // Set when scrolling can be used (ScrollMax > 0.0f) - int NavLayerCurrent; // Current layer, 0..31 (we currently only use 0..1) + bool NavHasScroll; // Set when scrolling can be used (ScrollMax > 0.0f) + int NavLayerCurrent; // Current layer, 0..31 (we currently only use 0..1) int NavLayerActiveMask; // Which layer have been written to (result from previous frame) int NavLayerActiveMaskNext; // Which layer have been written to (buffer for current frame) bool MenuBarAppending; // FIXME: Remove this @@ -672,6 +674,7 @@ struct IMGUI_API ImGuiDrawContext ImVector ChildWindows; ImGuiStorage* StateStorage; ImGuiLayoutType LayoutType; + ImGuiLayoutType ParentLayoutType; // Layout type of parent window at the time of Begin() // We store the current settings outside of the vectors to increase memory locality (reduce cache misses). The vectors are rarely modified. Also it allows us to not heap allocate for short-lived windows which are not using those settings. ImGuiItemFlags ItemFlags; // == ItemFlagsStack.back() [empty == ImGuiItemFlags_Default] @@ -714,7 +717,7 @@ struct IMGUI_API ImGuiDrawContext MenuBarAppending = false; MenuBarOffsetX = 0.0f; StateStorage = NULL; - LayoutType = ImGuiLayoutType_Vertical; + LayoutType = ParentLayoutType = ImGuiLayoutType_Vertical; ItemWidth = 0.0f; ItemFlags = ImGuiItemFlags_Default_; TextWrapPos = -1.0f; From ecd72cc0c7e85733f68ecec2fb0b472f28524123 Mon Sep 17 00:00:00 2001 From: omar Date: Fri, 29 Sep 2017 22:09:55 +0200 Subject: [PATCH 157/823] Nav: Disabled the final axial check when considering candidates in most situations except menubars. It's definitively undesirable inside Menu as we want to catch nav request failures reliably. I think it may be considered as an option if we find this desirable i some circumstances. Right now ideally I'd remove it totally but with current scoring setup, without it we can't easily reach the Window Close button. (#787) --- imgui.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index deeb7c3470ad..9031b9c67a32 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2098,7 +2098,7 @@ static bool NavScoreItem(ImRect cand) if (ImGui::IsMouseHoveringRect(cand.Min, cand.Max)) { char buf[128]; - ImFormatString(buf, IM_ARRAYSIZE(buf), "db (%.0f,%.0f->%.5f) dc (%.0f,%.0f->%.5f) da (%.0f,%.0f->%.5f) quad %c", dbx, dby, dist_box, dcx, dcy, dist_center, dax, day, dist_axial, "WENS"[quadrant]); + ImFormatString(buf, IM_ARRAYSIZE(buf), "dbox (%.2f,%.2f->%.4f) dcen (%.2f,%.2f->%.4f) d (%.2f,%.2f->%.4f) nav %c, quad %c", dbx, dby, dist_box, dcx, dcy, dist_center, dax, day, dist_axial, "WENS"[g.NavMoveDir], "WENS"[quadrant]); g.OverlayDrawList.AddRect(cand.Min, cand.Max, IM_COL32(255,255,0,200)); g.OverlayDrawList.AddRectFilled(cand.Max-ImVec2(4,4), cand.Max+ImGui::CalcTextSize(buf)+ImVec2(4,4), IM_COL32(40,0,0,150)); g.OverlayDrawList.AddText(cand.Max, ~0U, buf); @@ -2138,8 +2138,10 @@ static bool NavScoreItem(ImRect cand) // Axial check: if 'curr' has no link at all in some direction and 'cand' lies roughly in that direction, add a tentative link. This will only be kept if no "real" matches // are found, so it only augments the graph produced by the above method using extra links. (important, since it doesn't guarantee strong connectedness) // This is just to avoid buttons having no links in a particular direction when there's a suitable neighbor. you get good graphs without this too. - if (g.NavMoveResultDistBox == FLT_MAX) - if (dist_axial < g.NavMoveResultDistAxial) // Check axial match + // 2017/09/29: FIXME: This now currently only enabled inside menubars, ideally we'd disable it everywhere. Menus in particular need to catch failure. For general navigation it feels awkward. + // Disabling it may however lead to disconnected graphs when nodes are very spaced out on different axis. Perhaps consider offering this as an option? + if (g.NavMoveResultDistBox == FLT_MAX && dist_axial < g.NavMoveResultDistAxial) // Check axial match + if (g.NavLayer == 1 && !(g.NavWindow->Flags & ImGuiWindowFlags_ChildMenu)) if ((g.NavMoveDir == ImGuiDir_Left && dax < 0.0f) || (g.NavMoveDir == ImGuiDir_Right && dax > 0.0f) || (g.NavMoveDir == ImGuiDir_Up && day < 0.0f) || (g.NavMoveDir == ImGuiDir_Down && day > 0.0f)) g.NavMoveResultDistAxial = dist_axial, new_best = true; @@ -9990,7 +9992,7 @@ void ImGui::EndMenuBar() ImGuiContext& g = *GImGui; // When a move request within one of our child menu failed, capture the request to navigate among our siblings. - if (g.NavMoveRequest && g.NavMoveResultId == 0 && (g.NavMoveDir == ImGuiDir_Left || g.NavMoveDir == ImGuiDir_Right)) + if (g.NavMoveRequest && g.NavMoveResultId == 0 && (g.NavMoveDir == ImGuiDir_Left || g.NavMoveDir == ImGuiDir_Right) && (g.NavWindow->Flags & ImGuiWindowFlags_ChildMenu)) { ImGuiWindow* nav_earliest_child = g.NavWindow; while (nav_earliest_child->ParentWindow && (nav_earliest_child->ParentWindow->Flags & ImGuiWindowFlags_ChildMenu)) From 0046c618b06db9a794ac2fdca920a55f92969a25 Mon Sep 17 00:00:00 2001 From: omar Date: Sat, 30 Sep 2017 00:47:07 +0200 Subject: [PATCH 158/823] Nav: Allow to collapse tree nodes with NavLeft and open them with NavRight (#787, #1079) --- imgui.cpp | 29 +++++++++++++++++++++++------ imgui_demo.cpp | 2 +- 2 files changed, 24 insertions(+), 7 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 9031b9c67a32..894bab7a6668 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -7044,14 +7044,31 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l ImGuiButtonFlags button_flags = ImGuiButtonFlags_NoKeyModifiers | ((flags & ImGuiTreeNodeFlags_AllowOverlapMode) ? ImGuiButtonFlags_AllowOverlapMode : 0); if (flags & ImGuiTreeNodeFlags_OpenOnDoubleClick) button_flags |= ImGuiButtonFlags_PressedOnDoubleClick | ((flags & ImGuiTreeNodeFlags_OpenOnArrow) ? ImGuiButtonFlags_PressedOnClickRelease : 0); + bool hovered, held, pressed = ButtonBehavior(interact_bb, id, &hovered, &held, button_flags); - if (pressed && !(flags & ImGuiTreeNodeFlags_Leaf)) + if (!(flags & ImGuiTreeNodeFlags_Leaf)) { - bool toggled = !(flags & (ImGuiTreeNodeFlags_OpenOnArrow | ImGuiTreeNodeFlags_OpenOnDoubleClick)) || (g.NavActivateId == id); - if (flags & ImGuiTreeNodeFlags_OpenOnArrow) - toggled |= IsMouseHoveringRect(interact_bb.Min, ImVec2(interact_bb.Min.x + text_offset_x, interact_bb.Max.y)) && (!g.NavDisableMouseHover); - if (flags & ImGuiTreeNodeFlags_OpenOnDoubleClick) - toggled |= g.IO.MouseDoubleClicked[0]; + bool toggled = false; + if (pressed) + { + toggled = !(flags & (ImGuiTreeNodeFlags_OpenOnArrow | ImGuiTreeNodeFlags_OpenOnDoubleClick)) || (g.NavActivateId == id); + if (flags & ImGuiTreeNodeFlags_OpenOnArrow) + toggled |= IsMouseHoveringRect(interact_bb.Min, ImVec2(interact_bb.Min.x + text_offset_x, interact_bb.Max.y)) && (!g.NavDisableMouseHover); + if (flags & ImGuiTreeNodeFlags_OpenOnDoubleClick) + toggled |= g.IO.MouseDoubleClicked[0]; + } + + if (g.NavId == id && g.NavMoveRequest && g.NavMoveDir == ImGuiDir_Left && is_open) + { + toggled = true; + g.NavMoveRequest = false; + } + if (g.NavId == id && g.NavMoveRequest && g.NavMoveDir == ImGuiDir_Right && !is_open) // If there's something upcoming on the line we may want to give it the priority? + { + toggled = true; + g.NavMoveRequest = false; + } + if (toggled) { is_open = !is_open; diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 637adb8e1fd1..879cd9b8b518 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -456,9 +456,9 @@ void ImGui::ShowTestWindow(bool* p_open) if (ImGui::TreeNode("Collapsing Headers")) { static bool closable_group = true; + ImGui::Checkbox("Enable extra group", &closable_group); if (ImGui::CollapsingHeader("Header")) { - ImGui::Checkbox("Enable extra group", &closable_group); for (int i = 0; i < 5; i++) ImGui::Text("Some content %d", i); } From 491edfd8d8ff7c17143b26cd25a4d63ebb1b5a25 Mon Sep 17 00:00:00 2001 From: omar Date: Sat, 30 Sep 2017 23:46:23 +0200 Subject: [PATCH 159/823] Nav: Fixed a crash introduced yesterday. --- imgui.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/imgui.cpp b/imgui.cpp index 894bab7a6668..68f1e76c4a48 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -5538,7 +5538,8 @@ void ImGui::FocusWindow(ImGuiWindow* window) g.NavLayer = 0; if (window && g.NavDisableMouseHover) g.NavMousePosDirty = true; - window->NavRectRel[0].Min = window->NavRectRel[0].Max = window ? (window->DC.CursorStartPos - window->Pos) : ImVec2(0,0); + if (window) + window->NavRectRel[0].Min = window->NavRectRel[0].Max = window->DC.CursorStartPos - window->Pos; g.NavWindow = window; } From 74da533c939cdc367b3af98a7a6594b67fd51451 Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 3 Oct 2017 11:22:38 -0700 Subject: [PATCH 160/823] Nav: Added NavJustNavigatedId internal info to record when we land on a given item after a navigation request, useful for various algorithms (currently looking at range selection stuff) (#787) --- imgui.cpp | 8 +++++--- imgui_internal.h | 5 +++-- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 68f1e76c4a48..711b9ab5929d 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1928,7 +1928,7 @@ void ImGui::SetActiveID(ImGuiID id, ImGuiWindow* window) if (id) { g.ActiveIdIsAlive = true; - g.ActiveIdSource = (g.NavActivateId == id || g.NavInputId == id || g.NavTabbedId == id) ? ImGuiInputSource_Nav : ImGuiInputSource_Mouse; + g.ActiveIdSource = (g.NavActivateId == id || g.NavInputId == id || g.NavJustTabbedId == id || g.NavJustNavigatedId == id) ? ImGuiInputSource_Nav : ImGuiInputSource_Mouse; if (g.ActiveIdSource == ImGuiInputSource_Nav) g.NavDisableMouseHover = true; else @@ -2318,7 +2318,7 @@ bool ImGui::FocusableItemRegister(ImGuiWindow* window, ImGuiID id, bool tab_stop return true; if (allow_keyboard_focus && window->FocusIdxTabCounter == window->FocusIdxTabRequestCurrent) { - g.NavTabbedId = id; + g.NavJustTabbedId = id; return true; } @@ -2592,6 +2592,7 @@ static void NavUpdate() g.NavInitDefaultRequest = false; g.NavInitDefaultResultExplicit = false; g.NavInitDefaultResultId = 0; + g.NavJustNavigatedId = 0; // Process navigation move request if (g.NavMoveRequest && g.NavMoveResultId != 0) @@ -2633,6 +2634,7 @@ static void NavUpdate() // Apply result from previous frame navigation directional move request ImGui::ClearActiveID(); SetNavIdAndMoveMouse(g.NavMoveResultId, g.NavLayer, g.NavMoveResultRectRel); + g.NavJustNavigatedId = g.NavMoveResultId; g.NavMoveFromClampedRefRect = false; } @@ -2657,7 +2659,7 @@ static void NavUpdate() g.NavMousePosDirty = false; } g.NavIdIsAlive = false; - g.NavTabbedId = 0; + g.NavJustTabbedId = 0; // Navigation windowing mode (change focus, move/resize window) if (!g.NavWindowingTarget && IsNavInputPressed(ImGuiNavInput_PadMenu, ImGuiNavReadMode_Pressed)) diff --git a/imgui_internal.h b/imgui_internal.h index bf0876c308a4..8c3a1764e0de 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -458,7 +458,8 @@ struct ImGuiContext ImGuiWindow* NavWindow; // Nav/focused window for navigation ImGuiID NavId; // Nav/focused item for navigation ImGuiID NavActivateId, NavInputId; // ~~ IsKeyPressedMap(ImGuiKey_NavActive) ? NavId : 0, etc. (to make widget code terser) - ImGuiID NavTabbedId; // + ImGuiID NavJustTabbedId; // Just tabbed to this id. + ImGuiID NavJustNavigatedId; // Just navigated to this id (result of a successfully MoveRequest) ImRect NavScoringRectScreen; // Rectangle used for scoring, in screen space. Based of window->DC.NavRefRectRel[], modified for directional navigation scoring. ImGuiWindow* NavWindowingTarget; float NavWindowingDisplayAlpha; @@ -571,7 +572,7 @@ struct ImGuiContext SettingsDirtyTimer = 0.0f; NavWindow = NULL; - NavId = NavActivateId = NavInputId = NavTabbedId = 0; + NavId = NavActivateId = NavInputId = NavJustTabbedId = 0; NavScoringRectScreen = ImRect(); NavWindowingTarget = NULL; NavWindowingDisplayAlpha = 0.0f; From 64a51327d3d87b98644311600cea202df6da9809 Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 3 Oct 2017 13:25:40 -0700 Subject: [PATCH 161/823] Nav: Added NavMoveResultParentId internal info to record when the parent/context of a given NavId. Useful for various algorithms (currently looking at range selection stuff) (#787) --- imgui.cpp | 2 ++ imgui_internal.h | 2 ++ 2 files changed, 4 insertions(+) diff --git a/imgui.cpp b/imgui.cpp index 711b9ab5929d..112ce24ea723 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2220,6 +2220,7 @@ bool ImGui::ItemAdd(const ImRect& bb, const ImGuiID* id, const ImRect* nav_bb_ar if (new_best) { g.NavMoveResultId = *id; + g.NavMoveResultParentId = window->IDStack.back(); g.NavMoveResultRectRel = nav_bb_rel; } @@ -2856,6 +2857,7 @@ static void NavUpdate() // Reset search g.NavMoveResultId = 0; + g.NavMoveResultParentId = 0; g.NavMoveResultDistAxial = g.NavMoveResultDistBox = g.NavMoveResultDistCenter = FLT_MAX; // When we have manually scrolled (without using navigation) and NavId becomes out of bounds, we clamp its bounding box (used for search) to the visible area to restart navigation within visible items diff --git a/imgui_internal.h b/imgui_internal.h index 8c3a1764e0de..3798e7fa23aa 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -480,6 +480,7 @@ struct ImGuiContext ImGuiDir NavMoveDir; // West/East/North/South ImGuiDir NavMoveDirLast; // ImGuiID NavMoveResultId; // Best move request candidate + ImGuiID NavMoveResultParentId; // float NavMoveResultDistBox; // Best move request candidate box distance to current NavId float NavMoveResultDistCenter; // Best move request candidate center distance to current NavId float NavMoveResultDistAxial; @@ -590,6 +591,7 @@ struct ImGuiContext NavMoveRequestForwardStep = 0; NavMoveDir = NavMoveDirLast = ImGuiDir_None; NavMoveResultId = 0; + NavMoveResultParentId = 0; NavMoveResultDistBox = NavMoveResultDistCenter = NavMoveResultDistAxial = 0.0f; SetNextWindowPosVal = ImVec2(0.0f, 0.0f); From cb4e6c8212d736e1ac0ac5a5911239af23660fc8 Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 3 Oct 2017 13:44:48 -0700 Subject: [PATCH 162/823] Nav: Selectable(): activating selectable also sets NavId + removed the MouseDelta test (added in 43ee5d73e9f524320489720639942ff60bbfaf54, #323) as I don't think it is needed. (#787) --- imgui.cpp | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 112ce24ea723..954f6424e250 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -9788,11 +9788,12 @@ bool ImGui::Selectable(const char* label, bool selected, ImGuiSelectableFlags fl selected = false; // Hovering selectable with mouse updates NavId accordingly so navigation can be resumed with gamepad/keyboard (this doesn't happen on most widgets) - if (hovered && !g.NavDisableMouseHover && g.NavWindow == window && (g.IO.MouseDelta.x != 0.0f || g.IO.MouseDelta.y != 0.0f)) - { - g.NavDisableHighlight = true; - SetNavId(id, window->DC.NavLayerCurrent); - } + if (pressed || hovered)// && (g.IO.MouseDelta.x != 0.0f || g.IO.MouseDelta.y != 0.0f)) + if (!g.NavDisableMouseHover && g.NavWindow == window) + { + g.NavDisableHighlight = true; + SetNavId(id, window->DC.NavLayerCurrent); + } // Render if (hovered || selected) From 6ea90af6b76f2b9f7b86c12813bafd6f0408bdc0 Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 3 Oct 2017 13:53:17 -0700 Subject: [PATCH 163/823] Nav: Highlight clipped within host window then extruded out. (#787) --- imgui.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 954f6424e250..805844f2a6cb 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2155,14 +2155,16 @@ void ImGui::RenderNavHighlight(const ImRect& bb, ImGuiID id) return; ImGuiWindow* window = ImGui::GetCurrentWindow(); + ImRect display_rect = bb; + display_rect.ClipWith(window->ClipRect); const float THICKNESS = 2.0f; const float DISTANCE = 3.0f + THICKNESS * 0.5f; - ImRect display_rect(bb.Min - ImVec2(DISTANCE,DISTANCE), bb.Max + ImVec2(DISTANCE,DISTANCE)); - if (!window->ClipRect.Contains(display_rect)) + display_rect.Expand(ImVec2(DISTANCE,DISTANCE)); + bool fully_visible = window->ClipRect.Contains(display_rect); + if (!fully_visible) window->DrawList->PushClipRect(display_rect.Min, display_rect.Max); window->DrawList->AddRect(display_rect.Min + ImVec2(THICKNESS*0.5f,THICKNESS*0.5f), display_rect.Max - ImVec2(THICKNESS*0.5f,THICKNESS*0.5f), GetColorU32(ImGuiCol_NavHighlight), g.Style.FrameRounding, 0x0F, THICKNESS); - //window->DrawList->AddRect(g.NavRefRectScreen.Min, g.NavRefRectScreen.Max, IM_COL32(255,0,0,255)); - if (!window->ClipRect.Contains(display_rect)) + if (!fully_visible) window->DrawList->PopClipRect(); } From a56b71e866ff658be06b7bb2688d75d637372581 Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 3 Oct 2017 13:54:19 -0700 Subject: [PATCH 164/823] Nav: Added code to render thin highlight type. (#787) --- imgui.cpp | 31 ++++++++++++++++++++----------- imgui_internal.h | 10 +++++++++- 2 files changed, 29 insertions(+), 12 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 805844f2a6cb..45d90f702982 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2148,24 +2148,33 @@ static bool NavScoreItem(ImRect cand) return new_best; } -void ImGui::RenderNavHighlight(const ImRect& bb, ImGuiID id) +void ImGui::RenderNavHighlight(const ImRect& bb, ImGuiID id, ImGuiNavHighlightFlags flags) { ImGuiContext& g = *GImGui; - if (id != g.NavId || g.NavDisableHighlight) + if (id != g.NavId) return; + if (g.NavDisableHighlight && !(flags & ImGuiNavHighlightFlags_AlwaysRender)) + return; ImGuiWindow* window = ImGui::GetCurrentWindow(); ImRect display_rect = bb; display_rect.ClipWith(window->ClipRect); - const float THICKNESS = 2.0f; - const float DISTANCE = 3.0f + THICKNESS * 0.5f; - display_rect.Expand(ImVec2(DISTANCE,DISTANCE)); - bool fully_visible = window->ClipRect.Contains(display_rect); - if (!fully_visible) - window->DrawList->PushClipRect(display_rect.Min, display_rect.Max); - window->DrawList->AddRect(display_rect.Min + ImVec2(THICKNESS*0.5f,THICKNESS*0.5f), display_rect.Max - ImVec2(THICKNESS*0.5f,THICKNESS*0.5f), GetColorU32(ImGuiCol_NavHighlight), g.Style.FrameRounding, 0x0F, THICKNESS); - if (!fully_visible) - window->DrawList->PopClipRect(); + if (flags & ImGuiNavHighlightFlags_TypeDefault) + { + const float THICKNESS = 2.0f; + const float DISTANCE = 3.0f + THICKNESS * 0.5f; + display_rect.Expand(ImVec2(DISTANCE,DISTANCE)); + bool fully_visible = window->ClipRect.Contains(display_rect); + if (!fully_visible) + window->DrawList->PushClipRect(display_rect.Min, display_rect.Max); + window->DrawList->AddRect(display_rect.Min + ImVec2(THICKNESS*0.5f,THICKNESS*0.5f), display_rect.Max - ImVec2(THICKNESS*0.5f,THICKNESS*0.5f), GetColorU32(ImGuiCol_NavHighlight), g.Style.FrameRounding, 0x0F, THICKNESS); + if (!fully_visible) + window->DrawList->PopClipRect(); + } + if (flags & ImGuiNavHighlightFlags_TypeThin) + { + window->DrawList->AddRect(display_rect.Min, display_rect.Max, GetColorU32(ImGuiCol_NavHighlight), g.Style.FrameRounding, ~0, 1.0f); + } } // Declare item bounding box for clipping and interaction. diff --git a/imgui_internal.h b/imgui_internal.h index 3798e7fa23aa..9ef0fbb18639 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -51,6 +51,7 @@ typedef int ImGuiTreeNodeFlags; // enum ImGuiTreeNodeFlags_ typedef int ImGuiSliderFlags; // enum ImGuiSliderFlags_ typedef int ImGuiSeparatorFlags; // enum ImGuiSeparatorFlags_ typedef int ImGuiItemFlags; // enum ImGuiItemFlags_ +typedef int ImGuiNavHighlightFlags; //------------------------------------------------------------------------- // STB libraries @@ -250,6 +251,13 @@ enum ImGuiDir ImGuiDir_Down = 3 }; +enum ImGuiNavHighlightFlags_ +{ + ImGuiNavHighlightFlags_TypeDefault = 1 << 0, + ImGuiNavHighlightFlags_TypeThin = 1 << 1, + ImGuiNavHighlightFlags_AlwaysRender = 1 << 2 +}; + enum ImGuiCorner { ImGuiCorner_TopLeft = 1 << 0, // 1 @@ -895,7 +903,7 @@ namespace ImGui IMGUI_API void RenderCollapseTriangle(ImVec2 pos, bool is_open, float scale = 1.0f); IMGUI_API void RenderBullet(ImVec2 pos); IMGUI_API void RenderCheckMark(ImVec2 pos, ImU32 col); - IMGUI_API void RenderNavHighlight(const ImRect& bb, ImGuiID id); // Navigation highlight + IMGUI_API void RenderNavHighlight(const ImRect& bb, ImGuiID id, ImGuiNavHighlightFlags flags = ImGuiNavHighlightFlags_TypeDefault); // Navigation highlight IMGUI_API void RenderRectFilledRangeH(ImDrawList* draw_list, const ImRect& rect, ImU32 col, float x_start_norm, float x_end_norm, float rounding); IMGUI_API const char* FindRenderedTextEnd(const char* text, const char* text_end = NULL); // Find the optional ## from which we stop displaying text. From 42ee537be38ede09fefc9d1b02d85c62359d93ae Mon Sep 17 00:00:00 2001 From: omar Date: Wed, 4 Oct 2017 10:45:35 -0700 Subject: [PATCH 165/823] Comments --- imgui_internal.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/imgui_internal.h b/imgui_internal.h index 9ef0fbb18639..d170f458c9d2 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -202,8 +202,8 @@ enum ImGuiColumnsFlags_ enum ImGuiSelectableFlagsPrivate_ { // NB: need to be in sync with last value of ImGuiSelectableFlags_ - ImGuiSelectableFlags_Menu = 1 << 3, - ImGuiSelectableFlags_MenuItem = 1 << 4, + ImGuiSelectableFlags_Menu = 1 << 3, // -> PressedOnClick + ImGuiSelectableFlags_MenuItem = 1 << 4, // -> PressedOnRelease ImGuiSelectableFlags_Disabled = 1 << 5, ImGuiSelectableFlags_DrawFillAvailWidth = 1 << 6 }; From f326fac64a7d25898fbd3fc7c2f7ac152bd18a3d Mon Sep 17 00:00:00 2001 From: omar Date: Thu, 5 Oct 2017 10:29:17 -0700 Subject: [PATCH 166/823] Nav: Menus and popups now have move request wrap around vertically (using the move request forward thing added recently). (#787) --- imgui.cpp | 19 ++++++++++++++++++- imgui_internal.h | 6 +++--- 2 files changed, 21 insertions(+), 4 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 6502e7878d4b..b2711c4cc928 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -4476,11 +4476,28 @@ bool ImGui::BeginPopupModal(const char* name, bool* p_open, ImGuiWindowFlags ext return is_open; } +static void NavProcessMoveRequestWrapAround(ImGuiWindow* window) +{ + ImGuiContext& g = *GImGui; + if (g.NavMoveRequest && g.NavWindow == window && g.NavMoveResultId == 0) + if ((g.NavMoveDir == ImGuiDir_Up || g.NavMoveDir == ImGuiDir_Down) && g.NavMoveRequestForwardStep == 0 && g.NavLayer == 0) + { + g.NavMoveRequest = false; + g.NavMoveRequestForwardStep = 1; + g.NavWindow->NavRectRel[0].Min.y = g.NavWindow->NavRectRel[0].Max.y = (g.NavMoveDir == ImGuiDir_Up) ? window->SizeFull.y : 0.0f; + } +} + void ImGui::EndPopup() { + ImGuiContext& g = *GImGui; ImGuiWindow* window = GetCurrentWindow(); IM_ASSERT(window->Flags & ImGuiWindowFlags_Popup); // Mismatched BeginPopup()/EndPopup() calls - IM_ASSERT(GImGui->CurrentPopupStack.Size > 0); + IM_ASSERT(g.CurrentPopupStack.Size > 0); + + // Make all menus and popups wrap around for now, may need to expose that policy. + NavProcessMoveRequestWrapAround(window); + End(); if (!(window->Flags & ImGuiWindowFlags_Modal)) PopStyleVar(); diff --git a/imgui_internal.h b/imgui_internal.h index d170f458c9d2..1bb4750533c0 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -484,9 +484,9 @@ struct ImGuiContext bool NavInitDefaultResultExplicit; // Whether the result was explicitly requested with SetItemDefaultFocus() bool NavMoveFromClampedRefRect; // Set by manual scrolling, if we scroll to a point where NavId isn't visible we reset navigation from visible items bool NavMoveRequest; // Move request for this frame - int NavMoveRequestForwardStep; // 0: no forward, 1: forward request, 2: forward result - ImGuiDir NavMoveDir; // West/East/North/South - ImGuiDir NavMoveDirLast; // + int NavMoveRequestForwardStep; // 0: no forward, 1: forward request, 2: forward result (this is used to navigate sibling parent menus from a child menu) + ImGuiDir NavMoveDir; // Direction of the move request (left/right/up/down) + ImGuiDir NavMoveDirLast; // Direction of the previous move request ImGuiID NavMoveResultId; // Best move request candidate ImGuiID NavMoveResultParentId; // float NavMoveResultDistBox; // Best move request candidate box distance to current NavId From f2c9bd8d4f527892502c7032edda347a142bb703 Mon Sep 17 00:00:00 2001 From: omar Date: Thu, 5 Oct 2017 16:39:59 -0700 Subject: [PATCH 167/823] Nav: Fixed uninitialized context variables for sanity. --- imgui_internal.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/imgui_internal.h b/imgui_internal.h index 1bb4750533c0..10efd74c5219 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -573,6 +573,7 @@ struct ImGuiContext ActiveIdIsAlive = false; ActiveIdIsJustActivated = false; ActiveIdAllowOverlap = false; + ActiveIdAllowNavDirFlags = 0; ActiveIdClickOffset = ImVec2(-1,-1); ActiveIdWindow = NULL; ActiveIdSource = ImGuiInputSource_None; @@ -586,6 +587,7 @@ struct ImGuiContext NavWindowingTarget = NULL; NavWindowingDisplayAlpha = 0.0f; NavWindowingToggleLayer = false; + NavLayer = 0; NavIdTabCounter = INT_MAX; NavIdIsAlive = false; NavMousePosDirty = false; From 518f02f4de99cefd78566d78edb59073f7b0b8d5 Mon Sep 17 00:00:00 2001 From: omar Date: Thu, 5 Oct 2017 18:10:59 -0700 Subject: [PATCH 168/823] Demo: better demo for SetKeyboardFocusHere() --- imgui_demo.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 879cd9b8b518..22adf891c0da 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -1753,6 +1753,16 @@ void ImGui::ShowTestWindow(bool* p_open) ImGui::InputText("3 (tab skip)", buf, IM_ARRAYSIZE(buf)); if (ImGui::IsItemActive()) has_focus = 3; ImGui::PopAllowKeyboardFocus(); + + // Use >= 0 parameter to SetKeyboardFocusHere() to focus an upcoming item + static float f3[3] = { 0.0f, 0.0f, 0.0f }; + int focus_ahead = -1; + if (ImGui::Button("Focus on X")) focus_ahead = 0; ImGui::SameLine(); + if (ImGui::Button("Focus on Y")) focus_ahead = 1; ImGui::SameLine(); + if (ImGui::Button("Focus on Z")) focus_ahead = 2; + if (focus_ahead != -1) ImGui::SetKeyboardFocusHere(focus_ahead); + ImGui::SliderFloat3("Float3", &f3[0], 0.0f, 1.0f); + if (has_focus) ImGui::Text("Item with focus: %d", has_focus); else From 2f27b733be7f42835dc67d85cae6024b3559c97b Mon Sep 17 00:00:00 2001 From: omar Date: Thu, 5 Oct 2017 18:33:40 -0700 Subject: [PATCH 169/823] Nav: Fixed uninitialized context variables for sanity. --- imgui_internal.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/imgui_internal.h b/imgui_internal.h index 10efd74c5219..e8873737f0ae 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -582,7 +582,8 @@ struct ImGuiContext SettingsDirtyTimer = 0.0f; NavWindow = NULL; - NavId = NavActivateId = NavInputId = NavJustTabbedId = 0; + NavId = NavActivateId = NavInputId = 0; + NavJustTabbedId = NavJustNavigatedId = 0; NavScoringRectScreen = ImRect(); NavWindowingTarget = NULL; NavWindowingDisplayAlpha = 0.0f; From 80c4e2fe7b8fe5aa194ef3e29137b6f893fa1ff4 Mon Sep 17 00:00:00 2001 From: omar Date: Thu, 5 Oct 2017 20:35:47 -0700 Subject: [PATCH 170/823] Nav: Tidying up activation mechanism so that setting NavActivateId can trigger buttons. --- imgui.cpp | 44 +++++++++++++++++++++++++++----------------- imgui_internal.h | 5 +++-- 2 files changed, 30 insertions(+), 19 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 0016d57c47e3..6a466f5f1527 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2818,13 +2818,23 @@ static void NavUpdate() } } - g.NavActivateId = (g.NavId && !g.NavDisableHighlight && !g.NavWindowingTarget && g.ActiveId == 0 && IsNavInputPressed(ImGuiNavInput_PadActivate, ImGuiNavReadMode_Pressed)) ? g.NavId : 0; - g.NavInputId = (g.NavId && !g.NavDisableHighlight && !g.NavWindowingTarget && g.ActiveId == 0 && IsNavInputPressed(ImGuiNavInput_PadInput, ImGuiNavReadMode_Pressed)) ? g.NavId : 0; + g.NavActivateId = g.NavActivateDownId = g.NavInputId = 0; + if (g.NavId != 0 && !g.NavDisableHighlight && !g.NavWindowingTarget) + { + if (g.ActiveId == 0 && IsNavInputPressed(ImGuiNavInput_PadActivate, ImGuiNavReadMode_Pressed)) + g.NavActivateId = g.NavId; + if ((g.ActiveId == 0 || g.ActiveId == g.NavId) && IsNavInputDown(ImGuiNavInput_PadActivate)) + g.NavActivateDownId = g.NavId; + if (g.ActiveId == 0 && IsNavInputPressed(ImGuiNavInput_PadInput, ImGuiNavReadMode_Pressed)) + g.NavInputId = g.NavId; + } if (g.NavWindow && (g.NavWindow->Flags & ImGuiWindowFlags_NoNavInputs)) { - g.NavActivateId = g.NavInputId = 0; + g.NavActivateId = g.NavActivateDownId = g.NavInputId = 0; g.NavDisableHighlight = true; } + if (g.NavActivateId != 0) + IM_ASSERT(g.NavActivateDownId == g.NavActivateId); g.NavMoveRequest = false; // Initiate directional inputs request @@ -6681,18 +6691,18 @@ bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool { // We report navigated item as hovered but we don't set g.HoveredId to not interfere with mouse hovered = true; - if (!g.NavWindowingTarget && IsNavInputDown(ImGuiNavInput_PadActivate)) + } + if (g.NavActivateDownId == id) + { + bool nav_pressed = (g.NavActivateId == id) || IsNavInputPressed(ImGuiNavInput_PadActivate, (flags & ImGuiButtonFlags_Repeat) ? ImGuiNavReadMode_Repeat : ImGuiNavReadMode_Pressed); + if (nav_pressed) + pressed = true; + if (nav_pressed || g.ActiveId == id) { - bool nav_pressed = IsNavInputPressed(ImGuiNavInput_PadActivate, (flags & ImGuiButtonFlags_Repeat) ? ImGuiNavReadMode_Repeat : ImGuiNavReadMode_Pressed); - if (nav_pressed) - pressed = true; - if (nav_pressed || g.ActiveId == id) - { - // Set active id so it can be queried by user via IsItemActive(), equivalent of holding the mouse button. - g.NavActivateId = id; // This is so SetActiveId assign a Nav source - SetActiveID(id, window); - g.ActiveIdAllowNavDirFlags = (1 << ImGuiDir_Left) | (1 << ImGuiDir_Right) | (1 << ImGuiDir_Up) | (1 << ImGuiDir_Down); - } + // Set active id so it can be queried by user via IsItemActive(), equivalent of holding the mouse button. + g.NavActivateId = id; // This is so SetActiveId assign a Nav source + SetActiveID(id, window); + g.ActiveIdAllowNavDirFlags = (1 << ImGuiDir_Left) | (1 << ImGuiDir_Right) | (1 << ImGuiDir_Up) | (1 << ImGuiDir_Down); } } @@ -6717,7 +6727,7 @@ bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool } else if (g.ActiveIdSource == ImGuiInputSource_Nav) { - if (!IsNavInputDown(ImGuiNavInput_PadActivate)) + if (g.NavActivateDownId != id) ClearActiveID(); } } @@ -7677,7 +7687,7 @@ bool ImGui::SliderBehavior(const ImRect& frame_bb, ImGuiID id, float* v, float v clicked_t = 1.0f - clicked_t; set_new_value = true; } - else if (g.ActiveIdSource == ImGuiInputSource_Nav && IsNavInputDown(ImGuiNavInput_PadActivate)) + else if (g.ActiveIdSource == ImGuiInputSource_Nav && g.NavActivateDownId == id) { const ImVec2 delta2 = GetNavInputAmount2d(0, ImGuiNavReadMode_RepeatFast, 0.0f, 0.0f); if (float delta = is_horizontal ? delta2.x : -delta2.y) @@ -7997,7 +8007,7 @@ bool ImGui::DragBehavior(const ImRect& frame_bb, ImGuiID id, float* v, float v_s // Process clicking on the drag if (g.ActiveId == id) { - if (g.IO.MouseDown[0] || IsNavInputDown(ImGuiNavInput_PadActivate)) + if (g.IO.MouseDown[0] || g.NavActivateDownId == id) { if (g.ActiveIdIsJustActivated) { diff --git a/imgui_internal.h b/imgui_internal.h index e8873737f0ae..318520d8051d 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -465,7 +465,8 @@ struct ImGuiContext // Navigation data (for gamepad/keyboard) ImGuiWindow* NavWindow; // Nav/focused window for navigation ImGuiID NavId; // Nav/focused item for navigation - ImGuiID NavActivateId, NavInputId; // ~~ IsKeyPressedMap(ImGuiKey_NavActive) ? NavId : 0, etc. (to make widget code terser) + ImGuiID NavActivateId, NavActivateDownId; // ~~ IsNavInputPressed(ImGuiNavInput_PadActivate) ? NavId : 0, etc. + ImGuiID NavInputId; // ~~ IsNavInputPressed(ImGuiNavInput_PadInput) ? NavId : 0, etc. ImGuiID NavJustTabbedId; // Just tabbed to this id. ImGuiID NavJustNavigatedId; // Just navigated to this id (result of a successfully MoveRequest) ImRect NavScoringRectScreen; // Rectangle used for scoring, in screen space. Based of window->DC.NavRefRectRel[], modified for directional navigation scoring. @@ -582,7 +583,7 @@ struct ImGuiContext SettingsDirtyTimer = 0.0f; NavWindow = NULL; - NavId = NavActivateId = NavInputId = 0; + NavId = NavActivateId = NavActivateDownId = NavInputId = 0; NavJustTabbedId = NavJustNavigatedId = 0; NavScoringRectScreen = ImRect(); NavWindowingTarget = NULL; From 59c6f35bf6b8919000d7deacc0a7b1c1428a2519 Mon Sep 17 00:00:00 2001 From: omar Date: Thu, 5 Oct 2017 21:25:20 -0700 Subject: [PATCH 171/823] Added ActivateItem(), GetItemID() functions. --- imgui.cpp | 17 +++++++++++++++++ imgui.h | 6 +++++- imgui_demo.cpp | 27 ++++++++++++++++++++++----- imgui_internal.h | 3 ++- 4 files changed, 46 insertions(+), 7 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 6a466f5f1527..7c76018d0af0 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2837,6 +2837,11 @@ static void NavUpdate() IM_ASSERT(g.NavActivateDownId == g.NavActivateId); g.NavMoveRequest = false; + // Process explicit activation request + if (g.NavNextActivateId != 0) + g.NavActivateId = g.NavActivateDownId = g.NavInputId = g.NavNextActivateId; + g.NavNextActivateId = 0; + // Initiate directional inputs request const int allowed_dir_flags = (g.ActiveId == 0) ? ~0 : g.ActiveIdAllowNavDirFlags; if (g.NavMoveRequestForwardStep == 0) @@ -6379,6 +6384,18 @@ void ImGui::SetScrollHere(float center_y_ratio) SetScrollFromPosY(target_y, center_y_ratio); } +void ImGui::ActivateItem(ImGuiID id) +{ + ImGuiContext& g = *GImGui; + g.NavNextActivateId = id; +} + +ImGuiID ImGui::GetItemID() +{ + ImGuiContext& g = *GImGui; + return g.CurrentWindow->DC.LastItemId; +} + void ImGui::SetKeyboardFocusHere(int offset) { IM_ASSERT(offset >= -1); // -1 is allowed but not below diff --git a/imgui.h b/imgui.h index 8e47249ef3fd..c36017514201 100644 --- a/imgui.h +++ b/imgui.h @@ -177,7 +177,6 @@ namespace ImGui IMGUI_API void SetScrollY(float scroll_y); // set scrolling amount [0..GetScrollMaxY()] IMGUI_API void SetScrollHere(float center_y_ratio = 0.5f); // adjust scrolling amount to make current cursor position visible. center_y_ratio=0.0: top, 0.5: center, 1.0: bottom. IMGUI_API void SetScrollFromPosY(float pos_y, float center_y_ratio = 0.5f); // adjust scrolling amount to make given position valid. use GetCursorPos() or GetCursorStartPos()+offset to get valid positions. - IMGUI_API void SetKeyboardFocusHere(int offset = 0); // FIXME-NAVIGATION // focus keyboard on the next widget. Use positive 'offset' to access sub components of a multiple component widget. Use -1 to access previous widget. IMGUI_API void SetStateStorage(ImGuiStorage* tree); // replace tree state storage with our own (if you want to manipulate it yourself, typically clear subsection of it) IMGUI_API ImGuiStorage* GetStateStorage(); @@ -416,6 +415,11 @@ namespace ImGui // Styles IMGUI_API void StyleColorsClassic(ImGuiStyle* dst = NULL); + // Focus, Activation + IMGUI_API void ActivateItem(ImGuiID id); // remotely activate a button, checkbox, tree node etc. given its unique ID. activation is queued and processed on the next frame when the item is encountered again. + IMGUI_API ImGuiID GetItemID(); // get id of previous item, generally ~GetID(label) + IMGUI_API void SetKeyboardFocusHere(int offset = 0); // FIXME-NAVIGATION // focus keyboard on the next widget. Use positive 'offset' to access sub components of a multiple component widget. Use -1 to access previous widget. + // Utilities IMGUI_API bool IsItemHovered(); // is the last item hovered by mouse (and usable)? or we are currently using Nav and the item is focused. IMGUI_API bool IsItemRectHovered(); // is the last item hovered by mouse? even if another item is active or window is blocked by popup while we are hovering this diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 22adf891c0da..c058fa1e99e7 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -1754,6 +1754,11 @@ void ImGui::ShowTestWindow(bool* p_open) if (ImGui::IsItemActive()) has_focus = 3; ImGui::PopAllowKeyboardFocus(); + if (has_focus) + ImGui::Text("Item with focus: %d", has_focus); + else + ImGui::Text("Item with focus: "); + // Use >= 0 parameter to SetKeyboardFocusHere() to focus an upcoming item static float f3[3] = { 0.0f, 0.0f, 0.0f }; int focus_ahead = -1; @@ -1763,14 +1768,26 @@ void ImGui::ShowTestWindow(bool* p_open) if (focus_ahead != -1) ImGui::SetKeyboardFocusHere(focus_ahead); ImGui::SliderFloat3("Float3", &f3[0], 0.0f, 1.0f); - if (has_focus) - ImGui::Text("Item with focus: %d", has_focus); - else - ImGui::Text("Item with focus: "); - ImGui::TextWrapped("Cursor & selection are preserved when refocusing last used item in code."); + ImGui::TextWrapped("NB: Cursor & selection are preserved when refocusing last used item in code."); ImGui::TreePop(); } +#if 0 + if (ImGui::TreeNode("Remote Activation")) + { + static char label[256]; + ImGui::InputText("Label", label, IM_ARRAYSIZE(label)); + ImGui::PopID(); // We don't yet have an easy way compute ID at other levels of the ID stack so we pop it manually for now (e.g. we'd like something like GetID("../label")) + ImGuiID id = ImGui::GetID(label); + ImGui::PushID("Remote Activation"); + if (ImGui::SmallButton("Activate")) + ImGui::ActivateItem(id); + ImGui::SameLine(); + ImGui::Text("ID = 0x%08X", id); + ImGui::TreePop(); + } +#endif + if (ImGui::TreeNode("Dragging")) { ImGui::TextWrapped("You can use ImGui::GetMouseDragDelta(0) to query for the dragged amount on any widget."); diff --git a/imgui_internal.h b/imgui_internal.h index 318520d8051d..e9660a2f8cdc 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -469,6 +469,7 @@ struct ImGuiContext ImGuiID NavInputId; // ~~ IsNavInputPressed(ImGuiNavInput_PadInput) ? NavId : 0, etc. ImGuiID NavJustTabbedId; // Just tabbed to this id. ImGuiID NavJustNavigatedId; // Just navigated to this id (result of a successfully MoveRequest) + ImGuiID NavNextActivateId; // Set by ActivateItem(), queued until next frame ImRect NavScoringRectScreen; // Rectangle used for scoring, in screen space. Based of window->DC.NavRefRectRel[], modified for directional navigation scoring. ImGuiWindow* NavWindowingTarget; float NavWindowingDisplayAlpha; @@ -584,7 +585,7 @@ struct ImGuiContext NavWindow = NULL; NavId = NavActivateId = NavActivateDownId = NavInputId = 0; - NavJustTabbedId = NavJustNavigatedId = 0; + NavJustTabbedId = NavJustNavigatedId = NavNextActivateId = 0; NavScoringRectScreen = ImRect(); NavWindowingTarget = NULL; NavWindowingDisplayAlpha = 0.0f; From f5bd4663ddc4228da8cf94abfda5d8614bdb922e Mon Sep 17 00:00:00 2001 From: omar Date: Thu, 5 Oct 2017 22:02:13 -0700 Subject: [PATCH 172/823] Nav: Moving the big chunk of code from ItemAdd() to NavProcessItem() --- imgui.cpp | 89 ++++++++++++++++++++++++++++--------------------------- 1 file changed, 46 insertions(+), 43 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 7c76018d0af0..96e506b032b5 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2200,6 +2200,50 @@ void ImGui::RenderNavHighlight(const ImRect& bb, ImGuiID id, ImGuiNavHighlightFl } } +static void NavProcessItem(ImGuiWindow* window, const ImRect& nav_bb, const ImGuiID id) +{ + ImGuiContext& g = *GImGui; + const ImGuiItemFlags item_flags = window->DC.ItemFlags; + const ImRect nav_bb_rel(nav_bb.Min - g.NavWindow->Pos, nav_bb.Max - g.NavWindow->Pos); + if (g.NavInitDefaultRequest && g.NavLayer == window->DC.NavLayerCurrent) + { + // Even if 'ImGuiItemFlags_NoNavDefaultFocus' is on (typically collapse/close button) we record the first ResultId so they can be used as a fallback + if (!(item_flags & ImGuiItemFlags_NoNavDefaultFocus)) + g.NavInitDefaultRequest = g.NavInitDefaultResultExplicit = false; // Found a match, clear request + if (g.NavInitDefaultResultId == 0 || !(item_flags & ImGuiItemFlags_NoNavDefaultFocus)) + { + g.NavInitDefaultResultId = id; + g.NavInitDefaultResultRectRel = nav_bb_rel; + } + } + + bool new_best = false; +#if IMGUI_DEBUG_NAV + // [DEBUG] Score items at all times + if (!g.NavMoveRequest) + g.NavMoveDir = g.NavMoveDirLast; + if (g.NavId != id) + new_best = NavScoreItem(nav_bb) && g.NavMoveRequest; +#else + if (g.NavMoveRequest && g.NavId != id) + new_best = NavScoreItem(nav_bb); +#endif + if (new_best) + { + g.NavMoveResultId = id; + g.NavMoveResultParentId = window->IDStack.back(); + g.NavMoveResultRectRel = nav_bb_rel; + } + + // Update window-relative bounding box of navigated item + if (g.NavId == id) + { + window->NavRectRel[window->DC.NavLayerCurrent] = nav_bb_rel; + g.NavIdIsAlive = true; + g.NavIdTabCounter = window->FocusIdxTabCounter; + } +} + // Declare item bounding box for clipping and interaction. // Note that the size can be different than the one provided to ItemSize(). Typically, widgets that spread over available surface // declare their minimum size requirement to ItemSize() and then use a larger region for drawing/interaction, which is passed to ItemAdd(). @@ -2221,51 +2265,10 @@ bool ImGui::ItemAdd(const ImRect& bb, const ImGuiID* id, const ImRect* nav_bb_ar // We could early out with `if (is_clipped && !g.NavInitDefaultRequest) return false;` but when we wouldn't be able to reach unclipped widgets. This would work if user had explicit scrolling control (e.g. mapped on a stick) // A more pragmatic solution for handling long lists is relying on the fact that they are likely evenly spread items (so that clipper can be used) and we could Nav at higher-level (apply index, etc.) // So eventually we would like to provide the user will the primitives to be able to implement that customized/efficient navigation handling whenever necessary. - const ImGuiItemFlags item_flags = window->DC.ItemFlags; if (id != NULL && g.NavWindow == window->RootNavWindow) if (g.NavId == *id || g.NavMoveRequest || g.NavInitDefaultRequest || IMGUI_DEBUG_NAV) - if (g.IO.NavUsable && !(item_flags & ImGuiItemFlags_NoNav)) - { - const ImRect& nav_bb = nav_bb_arg ? *nav_bb_arg : bb; - const ImRect nav_bb_rel(nav_bb.Min - g.NavWindow->Pos, nav_bb.Max - g.NavWindow->Pos); - if (g.NavInitDefaultRequest && g.NavLayer == window->DC.NavLayerCurrent) - { - // Even if 'ImGuiItemFlags_NoNavDefaultFocus' is on (typically collapse/close button) we record the first ResultId so they can be used as a fallback - if (!(item_flags & ImGuiItemFlags_NoNavDefaultFocus)) - g.NavInitDefaultRequest = g.NavInitDefaultResultExplicit = false; // Found a match, clear request - if (g.NavInitDefaultResultId == 0 || !(item_flags & ImGuiItemFlags_NoNavDefaultFocus)) - { - g.NavInitDefaultResultId = *id; - g.NavInitDefaultResultRectRel = nav_bb_rel; - } - } - - bool new_best = false; -#if IMGUI_DEBUG_NAV - // [DEBUG] Score items at all times - if (!g.NavMoveRequest) - g.NavMoveDir = g.NavMoveDirLast; - if (g.NavId != *id) - new_best = NavScoreItem(nav_bb) && g.NavMoveRequest; -#else - if (g.NavMoveRequest && g.NavId != *id) - new_best = NavScoreItem(nav_bb); -#endif - if (new_best) - { - g.NavMoveResultId = *id; - g.NavMoveResultParentId = window->IDStack.back(); - g.NavMoveResultRectRel = nav_bb_rel; - } - - // Update window-relative bounding box of navigated item - if (g.NavId == *id) - { - window->NavRectRel[window->DC.NavLayerCurrent] = nav_bb_rel; - g.NavIdIsAlive = true; - g.NavIdTabCounter = window->FocusIdxTabCounter; - } - } + if (g.IO.NavUsable) + NavProcessItem(window, nav_bb_arg ? *nav_bb_arg : bb, *id); if (is_clipped) return false; From a77dd02e8aa404687e97dd9b0c01509d868ba3dc Mon Sep 17 00:00:00 2001 From: omar Date: Thu, 5 Oct 2017 22:06:46 -0700 Subject: [PATCH 173/823] Nav: Moving code next to its peers --- imgui.cpp | 58 +++++++++++++++++++++++++++---------------------------- 1 file changed, 29 insertions(+), 29 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 96e506b032b5..d593e0ffc446 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2171,35 +2171,6 @@ static bool NavScoreItem(ImRect cand) return new_best; } -void ImGui::RenderNavHighlight(const ImRect& bb, ImGuiID id, ImGuiNavHighlightFlags flags) -{ - ImGuiContext& g = *GImGui; - if (id != g.NavId) - return; - if (g.NavDisableHighlight && !(flags & ImGuiNavHighlightFlags_AlwaysRender)) - return; - ImGuiWindow* window = ImGui::GetCurrentWindow(); - - ImRect display_rect = bb; - display_rect.ClipWith(window->ClipRect); - if (flags & ImGuiNavHighlightFlags_TypeDefault) - { - const float THICKNESS = 2.0f; - const float DISTANCE = 3.0f + THICKNESS * 0.5f; - display_rect.Expand(ImVec2(DISTANCE,DISTANCE)); - bool fully_visible = window->ClipRect.Contains(display_rect); - if (!fully_visible) - window->DrawList->PushClipRect(display_rect.Min, display_rect.Max); - window->DrawList->AddRect(display_rect.Min + ImVec2(THICKNESS*0.5f,THICKNESS*0.5f), display_rect.Max - ImVec2(THICKNESS*0.5f,THICKNESS*0.5f), GetColorU32(ImGuiCol_NavHighlight), g.Style.FrameRounding, 0x0F, THICKNESS); - if (!fully_visible) - window->DrawList->PopClipRect(); - } - if (flags & ImGuiNavHighlightFlags_TypeThin) - { - window->DrawList->AddRect(display_rect.Min, display_rect.Max, GetColorU32(ImGuiCol_NavHighlight), g.Style.FrameRounding, ~0, 1.0f); - } -} - static void NavProcessItem(ImGuiWindow* window, const ImRect& nav_bb, const ImGuiID id) { ImGuiContext& g = *GImGui; @@ -3870,6 +3841,35 @@ void ImGui::RenderCheckMark(ImVec2 pos, ImU32 col) window->DrawList->PathStroke(col, false); } +void ImGui::RenderNavHighlight(const ImRect& bb, ImGuiID id, ImGuiNavHighlightFlags flags) +{ + ImGuiContext& g = *GImGui; + if (id != g.NavId) + return; + if (g.NavDisableHighlight && !(flags & ImGuiNavHighlightFlags_AlwaysRender)) + return; + ImGuiWindow* window = ImGui::GetCurrentWindow(); + + ImRect display_rect = bb; + display_rect.ClipWith(window->ClipRect); + if (flags & ImGuiNavHighlightFlags_TypeDefault) + { + const float THICKNESS = 2.0f; + const float DISTANCE = 3.0f + THICKNESS * 0.5f; + display_rect.Expand(ImVec2(DISTANCE,DISTANCE)); + bool fully_visible = window->ClipRect.Contains(display_rect); + if (!fully_visible) + window->DrawList->PushClipRect(display_rect.Min, display_rect.Max); + window->DrawList->AddRect(display_rect.Min + ImVec2(THICKNESS*0.5f,THICKNESS*0.5f), display_rect.Max - ImVec2(THICKNESS*0.5f,THICKNESS*0.5f), GetColorU32(ImGuiCol_NavHighlight), g.Style.FrameRounding, 0x0F, THICKNESS); + if (!fully_visible) + window->DrawList->PopClipRect(); + } + if (flags & ImGuiNavHighlightFlags_TypeThin) + { + window->DrawList->AddRect(display_rect.Min, display_rect.Max, GetColorU32(ImGuiCol_NavHighlight), g.Style.FrameRounding, ~0, 1.0f); + } +} + // Calculate text size. Text can be multi-line. Optionally ignore text after a ## marker. // CalcTextSize("") should return ImVec2(0.0f, GImGui->FontSize) ImVec2 ImGui::CalcTextSize(const char* text, const char* text_end, bool hide_text_after_double_hash, float wrap_width) From 40df7a51559e24c0c97494353d0232326741d997 Mon Sep 17 00:00:00 2001 From: omar Date: Fri, 6 Oct 2017 09:40:13 -0700 Subject: [PATCH 174/823] Nav: Removed possibly redundant test prior to calling NavProcessItem() from ItemAdd() --- imgui.cpp | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index d593e0ffc446..15007e50f0ab 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2174,6 +2174,8 @@ static bool NavScoreItem(ImRect cand) static void NavProcessItem(ImGuiWindow* window, const ImRect& nav_bb, const ImGuiID id) { ImGuiContext& g = *GImGui; + //if (!g.IO.NavUsable) // [2017/10/06] Removed this possibly redundant test but I am not sure of all the side-effects yet. Some of the feature here will need to work regardless of using a _NoNavInputs flag. + // return; const ImGuiItemFlags item_flags = window->DC.ItemFlags; const ImRect nav_bb_rel(nav_bb.Min - g.NavWindow->Pos, nav_bb.Max - g.NavWindow->Pos); if (g.NavInitDefaultRequest && g.NavLayer == window->DC.NavLayerCurrent) @@ -2238,8 +2240,7 @@ bool ImGui::ItemAdd(const ImRect& bb, const ImGuiID* id, const ImRect* nav_bb_ar // So eventually we would like to provide the user will the primitives to be able to implement that customized/efficient navigation handling whenever necessary. if (id != NULL && g.NavWindow == window->RootNavWindow) if (g.NavId == *id || g.NavMoveRequest || g.NavInitDefaultRequest || IMGUI_DEBUG_NAV) - if (g.IO.NavUsable) - NavProcessItem(window, nav_bb_arg ? *nav_bb_arg : bb, *id); + NavProcessItem(window, nav_bb_arg ? *nav_bb_arg : bb, *id); if (is_clipped) return false; @@ -2482,7 +2483,11 @@ static void NavInitWindow(ImGuiWindow* window, bool force_reinit) { ImGuiContext& g = *GImGui; IM_ASSERT(window == g.NavWindow); - if (!(window->Flags & ImGuiWindowFlags_ChildWindow) || (window->Flags & ImGuiWindowFlags_Popup) || (window->NavLastIds[0] == 0) || force_reinit) + bool init_for_nav = false; + if (!(window->Flags & ImGuiWindowFlags_NoNavInputs)) + if (!(window->Flags & ImGuiWindowFlags_ChildWindow) || (window->Flags & ImGuiWindowFlags_Popup) || (window->NavLastIds[0] == 0) || force_reinit) + init_for_nav = true; + if (init_for_nav) { SetNavId(0, g.NavLayer); g.NavInitDefaultRequest = true; From e12cfa9dfd8ae80f70f8229f6510e225bee1fe68 Mon Sep 17 00:00:00 2001 From: omar Date: Fri, 6 Oct 2017 09:44:50 -0700 Subject: [PATCH 175/823] Nav: Minor midying up and comments, --- imgui.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 15007e50f0ab..bfba93ead0fb 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2228,19 +2228,19 @@ bool ImGui::ItemAdd(const ImRect& bb, const ImGuiID* id, const ImRect* nav_bb_ar window->DC.LastItemId = id ? *id : 0; window->DC.LastItemRect = bb; window->DC.LastItemRectHoveredRect = false; - if (id != NULL) - window->DC.NavLayerActiveMaskNext |= (1 << window->DC.NavLayerCurrent); // Navigation processing runs prior to clipping early-out // (a) So that NavInitDefaultRequest can be honored, for newly opened windows to select a default widget // (b) So that we can scroll up/down past clipped items. This adds a small O(N) cost to regular navigation requests unfortunately, but it is still limited to one window. - // it may not scale very well for windows with ten of thousands of item, but at least the NavRequest is only performed on user interaction, aka maximum once a frame. + // it may not scale very well for windows with ten of thousands of item, but at least NavMoveRequest is only set on user interaction, aka maximum once a frame. // We could early out with `if (is_clipped && !g.NavInitDefaultRequest) return false;` but when we wouldn't be able to reach unclipped widgets. This would work if user had explicit scrolling control (e.g. mapped on a stick) - // A more pragmatic solution for handling long lists is relying on the fact that they are likely evenly spread items (so that clipper can be used) and we could Nav at higher-level (apply index, etc.) - // So eventually we would like to provide the user will the primitives to be able to implement that customized/efficient navigation handling whenever necessary. - if (id != NULL && g.NavWindow == window->RootNavWindow) - if (g.NavId == *id || g.NavMoveRequest || g.NavInitDefaultRequest || IMGUI_DEBUG_NAV) - NavProcessItem(window, nav_bb_arg ? *nav_bb_arg : bb, *id); + if (id != NULL) + { + window->DC.NavLayerActiveMaskNext |= (1 << window->DC.NavLayerCurrent); + if (g.NavWindow == window->RootNavWindow) + if (g.NavId == *id || g.NavMoveRequest || g.NavInitDefaultRequest || IMGUI_DEBUG_NAV) + NavProcessItem(window, nav_bb_arg ? *nav_bb_arg : bb, *id); + } if (is_clipped) return false; From f451785c9efea3f26997aae0169d6db9189f166b Mon Sep 17 00:00:00 2001 From: omar Date: Fri, 6 Oct 2017 10:17:01 -0700 Subject: [PATCH 176/823] Nav: Shuffled code in ItemAdd() so that NavProcessItem() may have access to LastItemId (will be required by tabbing) --- imgui.cpp | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index bfba93ead0fb..56102bbc8783 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2113,7 +2113,7 @@ static bool NavScoreItem(ImRect cand) } else { - // Degenerate case: two overlapping buttons with same center, break ties using order + // Degenerate case: two overlapping buttons with same center, break ties arbitrarily (note that LastItemId here is really the _previous_ item order, but it doesn't matter) quadrant = (window->DC.LastItemId < g.NavId) ? ImGuiDir_Left : ImGuiDir_Right; } @@ -2190,6 +2190,7 @@ static void NavProcessItem(ImGuiWindow* window, const ImRect& nav_bb, const ImGu } } + // Scoring for navigation bool new_best = false; #if IMGUI_DEBUG_NAV // [DEBUG] Score items at all times @@ -2224,10 +2225,6 @@ bool ImGui::ItemAdd(const ImRect& bb, const ImGuiID* id, const ImRect* nav_bb_ar { ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; - const bool is_clipped = IsClippedEx(bb, id, false); - window->DC.LastItemId = id ? *id : 0; - window->DC.LastItemRect = bb; - window->DC.LastItemRectHoveredRect = false; // Navigation processing runs prior to clipping early-out // (a) So that NavInitDefaultRequest can be honored, for newly opened windows to select a default widget @@ -2242,8 +2239,15 @@ bool ImGui::ItemAdd(const ImRect& bb, const ImGuiID* id, const ImRect* nav_bb_ar NavProcessItem(window, nav_bb_arg ? *nav_bb_arg : bb, *id); } + // Clipping test + store basic information about the current item. + const bool is_clipped = IsClippedEx(bb, id, false); + window->DC.LastItemId = id ? *id : 0; + window->DC.LastItemRect = bb; if (is_clipped) + { + window->DC.LastItemRectHoveredRect = false; return false; + } //if (g.IO.KeyAlt) window->DrawList->AddRect(bb.Min, bb.Max, IM_COL32(255,255,0,120)); // [DEBUG] // We need to calculate this now to take account of the current clipping rectangle (as items like Selectable may change them) From d16309ca777414c1ea13dbef3d1051bd98a1223d Mon Sep 17 00:00:00 2001 From: omar Date: Fri, 6 Oct 2017 14:40:53 -0700 Subject: [PATCH 177/823] Internal: ItemAdd() minor shallow tweaks --- imgui.cpp | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 7ecdf92cd8f6..c8ff306fc444 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2226,23 +2226,24 @@ bool ImGui::ItemAdd(const ImRect& bb, ImGuiID id, const ImRect* nav_bb_arg) ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; - // Navigation processing runs prior to clipping early-out - // (a) So that NavInitDefaultRequest can be honored, for newly opened windows to select a default widget - // (b) So that we can scroll up/down past clipped items. This adds a small O(N) cost to regular navigation requests unfortunately, but it is still limited to one window. - // it may not scale very well for windows with ten of thousands of item, but at least NavMoveRequest is only set on user interaction, aka maximum once a frame. - // We could early out with `if (is_clipped && !g.NavInitDefaultRequest) return false;` but when we wouldn't be able to reach unclipped widgets. This would work if user had explicit scrolling control (e.g. mapped on a stick) if (id != 0) { + // Navigation processing runs prior to clipping early-out + // (a) So that NavInitDefaultRequest can be honored, for newly opened windows to select a default widget + // (b) So that we can scroll up/down past clipped items. This adds a small O(N) cost to regular navigation requests unfortunately, but it is still limited to one window. + // it may not scale very well for windows with ten of thousands of item, but at least NavMoveRequest is only set on user interaction, aka maximum once a frame. + // We could early out with `if (is_clipped && !g.NavInitDefaultRequest) return false;` but when we wouldn't be able to reach unclipped widgets. This would work if user had explicit scrolling control (e.g. mapped on a stick) window->DC.NavLayerActiveMaskNext |= (1 << window->DC.NavLayerCurrent); if (g.NavWindow == window->RootNavWindow) if (g.NavId == id || g.NavMoveRequest || g.NavInitDefaultRequest || IMGUI_DEBUG_NAV) NavProcessItem(window, nav_bb_arg ? *nav_bb_arg : bb, id); } - // Clipping test + store basic information about the current item. - const bool is_clipped = IsClippedEx(bb, id, false); window->DC.LastItemId = id; window->DC.LastItemRect = bb; + + // Clipping test + const bool is_clipped = IsClippedEx(bb, id, false); if (is_clipped) { window->DC.LastItemRectHoveredRect = false; From c3105919bacacabe207a7064ba2f636a20f136cf Mon Sep 17 00:00:00 2001 From: omar Date: Fri, 6 Oct 2017 14:51:15 -0700 Subject: [PATCH 178/823] Nav: Minor tweaks also toward removing processing from ItemAdd() --- imgui.cpp | 10 +++++++--- imgui_internal.h | 2 ++ 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index c8ff306fc444..207993c47dd6 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2233,7 +2233,7 @@ bool ImGui::ItemAdd(const ImRect& bb, ImGuiID id, const ImRect* nav_bb_arg) // (b) So that we can scroll up/down past clipped items. This adds a small O(N) cost to regular navigation requests unfortunately, but it is still limited to one window. // it may not scale very well for windows with ten of thousands of item, but at least NavMoveRequest is only set on user interaction, aka maximum once a frame. // We could early out with `if (is_clipped && !g.NavInitDefaultRequest) return false;` but when we wouldn't be able to reach unclipped widgets. This would work if user had explicit scrolling control (e.g. mapped on a stick) - window->DC.NavLayerActiveMaskNext |= (1 << window->DC.NavLayerCurrent); + window->DC.NavLayerActiveMaskNext |= window->DC.NavLayerCurrentMask; if (g.NavWindow == window->RootNavWindow) if (g.NavId == id || g.NavMoveRequest || g.NavInitDefaultRequest || IMGUI_DEBUG_NAV) NavProcessItem(window, nav_bb_arg ? *nav_bb_arg : bb, id); @@ -5377,9 +5377,10 @@ bool ImGui::Begin(const char* name, bool* p_open, const ImVec2& size_on_first_us if (!(flags & ImGuiWindowFlags_NoTitleBar)) { // Close & collapse button are on layer 1 (same as menus) and don't default focus - const ImGuiItemFlags backup_item_options = window->DC.ItemFlags; + const ImGuiItemFlags item_flags_backup = window->DC.ItemFlags; window->DC.ItemFlags |= ImGuiItemFlags_NoNavDefaultFocus; window->DC.NavLayerCurrent++; + window->DC.NavLayerCurrentMask <<= 1; // Collapse button if (!(flags & ImGuiWindowFlags_NoCollapse)) @@ -5403,7 +5404,8 @@ bool ImGui::Begin(const char* name, bool* p_open, const ImVec2& size_on_first_us } window->DC.NavLayerCurrent--; - window->DC.ItemFlags = backup_item_options; + window->DC.NavLayerCurrentMask >>= 1; + window->DC.ItemFlags = item_flags_backup; // Title text (FIXME: refactor text alignment facilities along with RenderText helpers) const ImVec2 text_size = CalcTextSize(name, NULL, true); @@ -10093,6 +10095,7 @@ bool ImGui::BeginMenuBar() window->DC.CursorPos = ImVec2(rect.Min.x + window->DC.MenuBarOffsetX, rect.Min.y);// + g.Style.FramePadding.y); window->DC.LayoutType = ImGuiLayoutType_Horizontal; window->DC.NavLayerCurrent++; + window->DC.NavLayerCurrentMask <<= 1; window->DC.MenuBarAppending = true; AlignFirstTextHeightToWidgets(); return true; @@ -10134,6 +10137,7 @@ void ImGui::EndMenuBar() EndGroup(); window->DC.LayoutType = ImGuiLayoutType_Vertical; window->DC.NavLayerCurrent--; + window->DC.NavLayerCurrentMask >>= 1; window->DC.MenuBarAppending = false; } diff --git a/imgui_internal.h b/imgui_internal.h index c31fc4e643ac..f8519e992ab8 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -683,6 +683,7 @@ struct IMGUI_API ImGuiDrawContext bool LastItemRectHoveredRect; bool NavHasScroll; // Set when scrolling can be used (ScrollMax > 0.0f) int NavLayerCurrent; // Current layer, 0..31 (we currently only use 0..1) + int NavLayerCurrentMask; // = (1 << NavLayerCurrent) used by ItemAdd prior to clipping. int NavLayerActiveMask; // Which layer have been written to (result from previous frame) int NavLayerActiveMaskNext; // Which layer have been written to (buffer for current frame) bool MenuBarAppending; // FIXME: Remove this @@ -730,6 +731,7 @@ struct IMGUI_API ImGuiDrawContext NavHasScroll = false; NavLayerActiveMask = NavLayerActiveMaskNext = 0x00; NavLayerCurrent = 0; + NavLayerCurrentMask = 1 << 0; MenuBarAppending = false; MenuBarOffsetX = 0.0f; StateStorage = NULL; From d91b093be64350c73beb645e97abe57a38725678 Mon Sep 17 00:00:00 2001 From: omar Date: Fri, 6 Oct 2017 14:56:25 -0700 Subject: [PATCH 179/823] Nav: Minor tweaks in NavProcessItem() used by ItemAdd() --- imgui.cpp | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 207993c47dd6..997417465371 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2191,22 +2191,22 @@ static void NavProcessItem(ImGuiWindow* window, const ImRect& nav_bb, const ImGu } // Scoring for navigation - bool new_best = false; -#if IMGUI_DEBUG_NAV - // [DEBUG] Score items at all times - if (!g.NavMoveRequest) - g.NavMoveDir = g.NavMoveDirLast; if (g.NavId != id) - new_best = NavScoreItem(nav_bb) && g.NavMoveRequest; + { +#if IMGUI_DEBUG_NAV + // [DEBUG] Score all items in NavWindow at all times + if (!g.NavMoveRequest) + g.NavMoveDir = g.NavMoveDirLast; + bool new_best = NavScoreItem(nav_bb) && g.NavMoveRequest; #else - if (g.NavMoveRequest && g.NavId != id) - new_best = NavScoreItem(nav_bb); + bool new_best = g.NavMoveRequest && NavScoreItem(nav_bb); #endif - if (new_best) - { - g.NavMoveResultId = id; - g.NavMoveResultParentId = window->IDStack.back(); - g.NavMoveResultRectRel = nav_bb_rel; + if (new_best) + { + g.NavMoveResultId = id; + g.NavMoveResultParentId = window->IDStack.back(); + g.NavMoveResultRectRel = nav_bb_rel; + } } // Update window-relative bounding box of navigated item From d2975115cd43778994b7226d259896b7ae2f0956 Mon Sep 17 00:00:00 2001 From: omar Date: Fri, 6 Oct 2017 15:14:28 -0700 Subject: [PATCH 180/823] Nav: Caching into g.NavAnyRequest to minimize hot path cost (and so we can add many more request sources) --- imgui.cpp | 26 +++++++++++++++++++++++--- imgui_internal.h | 2 ++ 2 files changed, 25 insertions(+), 3 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 997417465371..0289c4a9c632 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2171,6 +2171,19 @@ static bool NavScoreItem(ImRect cand) return new_best; } +static inline void NavUpdateAnyRequestFlag() +{ + ImGuiContext& g = *GImGui; + g.NavAnyRequest = g.NavMoveRequest || g.NavInitDefaultRequest || IMGUI_DEBUG_NAV; +} + +static void NavMoveRequestCancel() +{ + ImGuiContext& g = *GImGui; + g.NavMoveRequest = false; + NavUpdateAnyRequestFlag(); +} + static void NavProcessItem(ImGuiWindow* window, const ImRect& nav_bb, const ImGuiID id) { ImGuiContext& g = *GImGui; @@ -2182,7 +2195,10 @@ static void NavProcessItem(ImGuiWindow* window, const ImRect& nav_bb, const ImGu { // Even if 'ImGuiItemFlags_NoNavDefaultFocus' is on (typically collapse/close button) we record the first ResultId so they can be used as a fallback if (!(item_flags & ImGuiItemFlags_NoNavDefaultFocus)) + { g.NavInitDefaultRequest = g.NavInitDefaultResultExplicit = false; // Found a match, clear request + NavUpdateAnyRequestFlag(); + } if (g.NavInitDefaultResultId == 0 || !(item_flags & ImGuiItemFlags_NoNavDefaultFocus)) { g.NavInitDefaultResultId = id; @@ -2235,7 +2251,7 @@ bool ImGui::ItemAdd(const ImRect& bb, ImGuiID id, const ImRect* nav_bb_arg) // We could early out with `if (is_clipped && !g.NavInitDefaultRequest) return false;` but when we wouldn't be able to reach unclipped widgets. This would work if user had explicit scrolling control (e.g. mapped on a stick) window->DC.NavLayerActiveMaskNext |= window->DC.NavLayerCurrentMask; if (g.NavWindow == window->RootNavWindow) - if (g.NavId == id || g.NavMoveRequest || g.NavInitDefaultRequest || IMGUI_DEBUG_NAV) + if (g.NavId == id || g.NavAnyRequest) NavProcessItem(window, nav_bb_arg ? *nav_bb_arg : bb, id); } @@ -2499,6 +2515,7 @@ static void NavInitWindow(ImGuiWindow* window, bool force_reinit) g.NavInitDefaultResultId = 0; g.NavInitDefaultResultExplicit = false; g.NavInitDefaultResultRectRel = ImRect(); + NavUpdateAnyRequestFlag(); } else { @@ -2860,6 +2877,8 @@ static void NavUpdate() g.NavDisableHighlight = false; } + NavUpdateAnyRequestFlag(); + // Scrolling if (g.NavWindow && !(g.NavWindow->Flags & ImGuiWindowFlags_NoNavInputs) && !g.NavWindowingTarget) { @@ -4237,6 +4256,7 @@ void ImGui::SetItemDefaultFocus() g.NavInitDefaultResultExplicit = true; g.NavInitDefaultResultId = g.NavWindow->DC.LastItemId; g.NavInitDefaultResultRectRel = ImRect(g.NavWindow->DC.LastItemRect.Min - g.NavWindow->Pos, g.NavWindow->DC.LastItemRect.Max - g.NavWindow->Pos); + NavUpdateAnyRequestFlag(); if (!IsItemVisible()) SetScrollHere(); } @@ -4511,8 +4531,8 @@ static void NavProcessMoveRequestWrapAround(ImGuiWindow* window) if (g.NavMoveRequest && g.NavWindow == window && g.NavMoveResultId == 0) if ((g.NavMoveDir == ImGuiDir_Up || g.NavMoveDir == ImGuiDir_Down) && g.NavMoveRequestForwardStep == 0 && g.NavLayer == 0) { - g.NavMoveRequest = false; g.NavMoveRequestForwardStep = 1; + NavMoveRequestCancel(); g.NavWindow->NavRectRel[0].Min.y = g.NavWindow->NavRectRel[0].Max.y = (g.NavMoveDir == ImGuiDir_Up) ? window->SizeFull.y : 0.0f; } } @@ -10123,8 +10143,8 @@ void ImGui::EndMenuBar() SetNavIdAndMoveMouse(window->NavLastIds[1], 1, window->NavRectRel[1]); g.NavLayer = 1; g.NavDisableHighlight = true; // Hide highlight for the current frame so we don't see the intermediary selection. - g.NavMoveRequest = false; g.NavMoveRequestForwardStep = 1; + NavMoveRequestCancel(); } } diff --git a/imgui_internal.h b/imgui_internal.h index f8519e992ab8..670b07d7361b 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -480,6 +480,7 @@ struct ImGuiContext bool NavMousePosDirty; bool NavDisableHighlight; // When user starts using mouse, we hide gamepad/keyboard highlight (nb: but they are still available, which is why NavDisableHighlight isn't always != NavDisableMouseHover) bool NavDisableMouseHover; // When user starts using gamepad/keyboard, we hide mouse hovering highlight until mouse is touched again. + bool NavAnyRequest; // ~~ NavMoveRequest || NavInitDefaultRequest bool NavInitDefaultRequest; // Init request for appearing window to select first item ImGuiID NavInitDefaultResultId; ImRect NavInitDefaultResultRectRel; @@ -596,6 +597,7 @@ struct ImGuiContext NavMousePosDirty = false; NavDisableHighlight = true; NavDisableMouseHover = false; + NavAnyRequest = false; NavInitDefaultRequest = false; NavInitDefaultResultId = 0; NavInitDefaultResultExplicit = false; From 4d83078885e3568c4b32662a87d61518d0696279 Mon Sep 17 00:00:00 2001 From: omar Date: Fri, 6 Oct 2017 15:50:32 -0700 Subject: [PATCH 181/823] Nav: Moving code next to its peers --- imgui.cpp | 30 +++++++++++++++--------------- imgui.h | 2 +- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 0289c4a9c632..ebc415b6fa2e 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -4247,21 +4247,6 @@ void ImGui::SetItemAllowOverlap() g.ActiveIdAllowOverlap = true; } -void ImGui::SetItemDefaultFocus() -{ - ImGuiContext& g = *GImGui; - if (g.NavWindow == g.CurrentWindow->RootNavWindow && (g.NavInitDefaultRequest || g.NavInitDefaultResultId != 0) && g.NavLayer == g.NavWindow->DC.NavLayerCurrent) - { - g.NavInitDefaultRequest = false; - g.NavInitDefaultResultExplicit = true; - g.NavInitDefaultResultId = g.NavWindow->DC.LastItemId; - g.NavInitDefaultResultRectRel = ImRect(g.NavWindow->DC.LastItemRect.Min - g.NavWindow->Pos, g.NavWindow->DC.LastItemRect.Max - g.NavWindow->Pos); - NavUpdateAnyRequestFlag(); - if (!IsItemVisible()) - SetScrollHere(); - } -} - ImVec2 ImGui::GetItemRectMin() { ImGuiWindow* window = GetCurrentWindowRead(); @@ -6441,6 +6426,21 @@ void ImGui::SetKeyboardFocusHere(int offset) window->FocusIdxTabRequestNext = INT_MAX; } +void ImGui::SetItemDefaultFocus() +{ + ImGuiContext& g = *GImGui; + if (g.NavWindow == g.CurrentWindow->RootNavWindow && (g.NavInitDefaultRequest || g.NavInitDefaultResultId != 0) && g.NavLayer == g.NavWindow->DC.NavLayerCurrent) + { + g.NavInitDefaultRequest = false; + g.NavInitDefaultResultExplicit = true; + g.NavInitDefaultResultId = g.NavWindow->DC.LastItemId; + g.NavInitDefaultResultRectRel = ImRect(g.NavWindow->DC.LastItemRect.Min - g.NavWindow->Pos, g.NavWindow->DC.LastItemRect.Max - g.NavWindow->Pos); + NavUpdateAnyRequestFlag(); + if (!IsItemVisible()) + SetScrollHere(); + } +} + void ImGui::SetStateStorage(ImGuiStorage* tree) { ImGuiWindow* window = GetCurrentWindow(); diff --git a/imgui.h b/imgui.h index b49dacb1c1b5..7dda2d3e8f23 100644 --- a/imgui.h +++ b/imgui.h @@ -419,6 +419,7 @@ namespace ImGui IMGUI_API void ActivateItem(ImGuiID id); // remotely activate a button, checkbox, tree node etc. given its unique ID. activation is queued and processed on the next frame when the item is encountered again. IMGUI_API ImGuiID GetItemID(); // get id of previous item, generally ~GetID(label) IMGUI_API void SetKeyboardFocusHere(int offset = 0); // FIXME-NAVIGATION // focus keyboard on the next widget. Use positive 'offset' to access sub components of a multiple component widget. Use -1 to access previous widget. + IMGUI_API void SetItemDefaultFocus(); // FIXME-NAVIGATION // make last item the default focused item of a window // Utilities IMGUI_API bool IsItemHovered(); // is the last item hovered by mouse (and usable)? or we are currently using Nav and the item is focused. @@ -434,7 +435,6 @@ namespace ImGui IMGUI_API ImVec2 GetItemRectMax(); // " IMGUI_API ImVec2 GetItemRectSize(); // " IMGUI_API void SetItemAllowOverlap(); // allow last item to be overlapped by a subsequent item. sometimes useful with invisible buttons, selectables, etc. to catch unused area. - IMGUI_API void SetItemDefaultFocus(); // make last item the default focused item of a window IMGUI_API bool IsWindowFocused(); // is current window focused IMGUI_API bool IsWindowHovered(); // is current window hovered and hoverable (not blocked by a popup) (differentiate child windows from each others) IMGUI_API bool IsWindowRectHovered(); // is current window rectangle hovered, disregarding of any consideration of being blocked by a popup. (unlike IsWindowHovered() this will return true even if the window is blocked because of a popup) From 69dd89535818c4413c9c0b9f13c0e23c6277c03a Mon Sep 17 00:00:00 2001 From: omar Date: Fri, 6 Oct 2017 15:54:29 -0700 Subject: [PATCH 182/823] Nav: Renaming NavInitDefaultRequest -> NavInitRequest --- imgui.cpp | 52 ++++++++++++++++++++++++------------------------ imgui_internal.h | 16 +++++++-------- 2 files changed, 34 insertions(+), 34 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index ebc415b6fa2e..ced2f747d863 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2174,7 +2174,7 @@ static bool NavScoreItem(ImRect cand) static inline void NavUpdateAnyRequestFlag() { ImGuiContext& g = *GImGui; - g.NavAnyRequest = g.NavMoveRequest || g.NavInitDefaultRequest || IMGUI_DEBUG_NAV; + g.NavAnyRequest = g.NavMoveRequest || g.NavInitRequest || IMGUI_DEBUG_NAV; } static void NavMoveRequestCancel() @@ -2191,18 +2191,18 @@ static void NavProcessItem(ImGuiWindow* window, const ImRect& nav_bb, const ImGu // return; const ImGuiItemFlags item_flags = window->DC.ItemFlags; const ImRect nav_bb_rel(nav_bb.Min - g.NavWindow->Pos, nav_bb.Max - g.NavWindow->Pos); - if (g.NavInitDefaultRequest && g.NavLayer == window->DC.NavLayerCurrent) + if (g.NavInitRequest && g.NavLayer == window->DC.NavLayerCurrent) { // Even if 'ImGuiItemFlags_NoNavDefaultFocus' is on (typically collapse/close button) we record the first ResultId so they can be used as a fallback if (!(item_flags & ImGuiItemFlags_NoNavDefaultFocus)) { - g.NavInitDefaultRequest = g.NavInitDefaultResultExplicit = false; // Found a match, clear request + g.NavInitRequest = g.NavInitResultExplicit = false; // Found a match, clear request NavUpdateAnyRequestFlag(); } - if (g.NavInitDefaultResultId == 0 || !(item_flags & ImGuiItemFlags_NoNavDefaultFocus)) + if (g.NavInitResultId == 0 || !(item_flags & ImGuiItemFlags_NoNavDefaultFocus)) { - g.NavInitDefaultResultId = id; - g.NavInitDefaultResultRectRel = nav_bb_rel; + g.NavInitResultId = id; + g.NavInitResultRectRel = nav_bb_rel; } } @@ -2245,10 +2245,10 @@ bool ImGui::ItemAdd(const ImRect& bb, ImGuiID id, const ImRect* nav_bb_arg) if (id != 0) { // Navigation processing runs prior to clipping early-out - // (a) So that NavInitDefaultRequest can be honored, for newly opened windows to select a default widget + // (a) So that NavInitRequest can be honored, for newly opened windows to select a default widget // (b) So that we can scroll up/down past clipped items. This adds a small O(N) cost to regular navigation requests unfortunately, but it is still limited to one window. // it may not scale very well for windows with ten of thousands of item, but at least NavMoveRequest is only set on user interaction, aka maximum once a frame. - // We could early out with `if (is_clipped && !g.NavInitDefaultRequest) return false;` but when we wouldn't be able to reach unclipped widgets. This would work if user had explicit scrolling control (e.g. mapped on a stick) + // We could early out with "if (is_clipped && !g.NavInitRequest) return false;" but when we wouldn't be able to reach unclipped widgets. This would work if user had explicit scrolling control (e.g. mapped on a stick) window->DC.NavLayerActiveMaskNext |= window->DC.NavLayerCurrentMask; if (g.NavWindow == window->RootNavWindow) if (g.NavId == id || g.NavAnyRequest) @@ -2511,10 +2511,10 @@ static void NavInitWindow(ImGuiWindow* window, bool force_reinit) if (init_for_nav) { SetNavId(0, g.NavLayer); - g.NavInitDefaultRequest = true; - g.NavInitDefaultResultId = 0; - g.NavInitDefaultResultExplicit = false; - g.NavInitDefaultResultRectRel = ImRect(); + g.NavInitRequest = true; + g.NavInitResultId = 0; + g.NavInitResultExplicit = false; + g.NavInitResultRectRel = ImRect(); NavUpdateAnyRequestFlag(); } else @@ -2616,18 +2616,18 @@ static void NavUpdate() g.IO.WantMoveMouse = false; // Process navigation init request (select first/default focus) - if (g.NavInitDefaultResultId != 0 && (!g.NavDisableHighlight || g.NavInitDefaultResultExplicit)) + if (g.NavInitResultId != 0 && (!g.NavDisableHighlight || g.NavInitResultExplicit)) { // Apply result from previous navigation init request (typically select the first item, unless SetItemDefaultFocus() has been called) IM_ASSERT(g.NavWindow); - SetNavId(g.NavInitDefaultResultId, g.NavLayer); - g.NavWindow->NavRectRel[g.NavLayer] = g.NavInitDefaultResultRectRel; + SetNavId(g.NavInitResultId, g.NavLayer); + g.NavWindow->NavRectRel[g.NavLayer] = g.NavInitResultRectRel; if (g.NavDisableMouseHover) g.NavMousePosDirty = true; } - g.NavInitDefaultRequest = false; - g.NavInitDefaultResultExplicit = false; - g.NavInitDefaultResultId = 0; + g.NavInitRequest = false; + g.NavInitResultExplicit = false; + g.NavInitResultId = 0; g.NavJustNavigatedId = 0; // Process navigation move request @@ -2775,7 +2775,7 @@ static void NavUpdate() // Set output flags for user application g.IO.NavUsable = g.NavWindow && !(g.NavWindow->Flags & ImGuiWindowFlags_NoNavInputs); - g.IO.NavActive = (g.IO.NavUsable && g.NavId != 0 && !g.NavDisableHighlight) || (g.NavWindowingTarget != NULL) || g.NavInitDefaultRequest; + g.IO.NavActive = (g.IO.NavUsable && g.NavId != 0 && !g.NavDisableHighlight) || (g.NavWindowingTarget != NULL) || g.NavInitRequest; // Process NavCancel input (to close a popup, get back to parent, clear focus) if (IsNavInputPressed(ImGuiNavInput_PadCancel, ImGuiNavReadMode_Pressed)) @@ -2872,8 +2872,8 @@ static void NavUpdate() // If we initiate a movement request and have no current NavId, we initiate a InitDefautRequest that will be used as a fallback if the direction fails to find a match if (g.NavMoveRequest && g.NavId == 0) { - g.NavInitDefaultRequest = g.NavInitDefaultResultExplicit = true; - g.NavInitDefaultResultId = 0; + g.NavInitRequest = g.NavInitResultExplicit = true; + g.NavInitResultId = 0; g.NavDisableHighlight = false; } @@ -6429,12 +6429,12 @@ void ImGui::SetKeyboardFocusHere(int offset) void ImGui::SetItemDefaultFocus() { ImGuiContext& g = *GImGui; - if (g.NavWindow == g.CurrentWindow->RootNavWindow && (g.NavInitDefaultRequest || g.NavInitDefaultResultId != 0) && g.NavLayer == g.NavWindow->DC.NavLayerCurrent) + if (g.NavWindow == g.CurrentWindow->RootNavWindow && (g.NavInitRequest || g.NavInitResultId != 0) && g.NavLayer == g.NavWindow->DC.NavLayerCurrent) { - g.NavInitDefaultRequest = false; - g.NavInitDefaultResultExplicit = true; - g.NavInitDefaultResultId = g.NavWindow->DC.LastItemId; - g.NavInitDefaultResultRectRel = ImRect(g.NavWindow->DC.LastItemRect.Min - g.NavWindow->Pos, g.NavWindow->DC.LastItemRect.Max - g.NavWindow->Pos); + g.NavInitRequest = false; + g.NavInitResultExplicit = true; + g.NavInitResultId = g.NavWindow->DC.LastItemId; + g.NavInitResultRectRel = ImRect(g.NavWindow->DC.LastItemRect.Min - g.NavWindow->Pos, g.NavWindow->DC.LastItemRect.Max - g.NavWindow->Pos); NavUpdateAnyRequestFlag(); if (!IsItemVisible()) SetScrollHere(); diff --git a/imgui_internal.h b/imgui_internal.h index 670b07d7361b..77084dc71bda 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -480,11 +480,11 @@ struct ImGuiContext bool NavMousePosDirty; bool NavDisableHighlight; // When user starts using mouse, we hide gamepad/keyboard highlight (nb: but they are still available, which is why NavDisableHighlight isn't always != NavDisableMouseHover) bool NavDisableMouseHover; // When user starts using gamepad/keyboard, we hide mouse hovering highlight until mouse is touched again. - bool NavAnyRequest; // ~~ NavMoveRequest || NavInitDefaultRequest - bool NavInitDefaultRequest; // Init request for appearing window to select first item - ImGuiID NavInitDefaultResultId; - ImRect NavInitDefaultResultRectRel; - bool NavInitDefaultResultExplicit; // Whether the result was explicitly requested with SetItemDefaultFocus() + bool NavAnyRequest; // ~~ NavMoveRequest || NavInitRequest + bool NavInitRequest; // Init request for appearing window to select first item + ImGuiID NavInitResultId; + ImRect NavInitResultRectRel; + bool NavInitResultExplicit; // Whether the result was explicitly requested with SetItemDefaultFocus() bool NavMoveFromClampedRefRect; // Set by manual scrolling, if we scroll to a point where NavId isn't visible we reset navigation from visible items bool NavMoveRequest; // Move request for this frame int NavMoveRequestForwardStep; // 0: no forward, 1: forward request, 2: forward result (this is used to navigate sibling parent menus from a child menu) @@ -598,9 +598,9 @@ struct ImGuiContext NavDisableHighlight = true; NavDisableMouseHover = false; NavAnyRequest = false; - NavInitDefaultRequest = false; - NavInitDefaultResultId = 0; - NavInitDefaultResultExplicit = false; + NavInitRequest = false; + NavInitResultId = 0; + NavInitResultExplicit = false; NavMoveFromClampedRefRect = false; NavMoveRequest = false; NavMoveRequestForwardStep = 0; From 7a14d7dfdcc045163e3a301b6dcf40df16dfb765 Mon Sep 17 00:00:00 2001 From: omar Date: Wed, 11 Oct 2017 19:05:36 +0200 Subject: [PATCH 183/823] Nav: More consistently drawing a (thin) navigation rectangle hover filled frames such as tree nodes, collapsing header, menus. (#787) --- imgui.cpp | 8 ++++++-- imgui_internal.h | 2 +- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index d431a7ee256b..39c2523388e9 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -3878,7 +3878,7 @@ void ImGui::RenderNavHighlight(const ImRect& bb, ImGuiID id, ImGuiNavHighlightFl ImGuiContext& g = *GImGui; if (id != g.NavId) return; - if (g.NavDisableHighlight && !(flags & ImGuiNavHighlightFlags_AlwaysRender)) + if (g.NavDisableHighlight && !(flags & ImGuiNavHighlightFlags_AlwaysDraw)) return; ImGuiWindow* window = ImGui::GetCurrentWindow(); @@ -7204,6 +7204,7 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l { // Framed type RenderFrame(bb.Min, bb.Max, col, true, style.FrameRounding); + RenderNavHighlight(bb, id, ImGuiNavHighlightFlags_TypeThin); RenderCollapseTriangle(bb.Min + ImVec2(padding.x, text_base_offset_y), is_open, 1.0f); if (g.LogEnabled) { @@ -7223,8 +7224,10 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l { // Unframed typed for tree nodes if (hovered || (flags & ImGuiTreeNodeFlags_Selected)) + { RenderFrame(bb.Min, bb.Max, col, false); - + RenderNavHighlight(bb, id, ImGuiNavHighlightFlags_TypeThin); + } if (flags & ImGuiTreeNodeFlags_Bullet) RenderBullet(bb.Min + ImVec2(text_offset_x * 0.5f, g.FontSize*0.50f + text_base_offset_y)); else if (!(flags & ImGuiTreeNodeFlags_Leaf)) @@ -9914,6 +9917,7 @@ bool ImGui::Selectable(const char* label, bool selected, ImGuiSelectableFlags fl { const ImU32 col = GetColorU32((held && hovered) ? ImGuiCol_HeaderActive : hovered ? ImGuiCol_HeaderHovered : ImGuiCol_Header); RenderFrame(bb_with_spacing.Min, bb_with_spacing.Max, col, false, 0.0f); + RenderNavHighlight(bb_with_spacing, id, ImGuiNavHighlightFlags_TypeThin); } if ((flags & ImGuiSelectableFlags_SpanAllColumns) && window->DC.ColumnsCount > 1) diff --git a/imgui_internal.h b/imgui_internal.h index 77084dc71bda..b8d82eeeeec8 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -255,7 +255,7 @@ enum ImGuiNavHighlightFlags_ { ImGuiNavHighlightFlags_TypeDefault = 1 << 0, ImGuiNavHighlightFlags_TypeThin = 1 << 1, - ImGuiNavHighlightFlags_AlwaysRender = 1 << 2 + ImGuiNavHighlightFlags_AlwaysDraw = 1 << 2 }; enum ImGuiCorner From 2047c58efbc204a8562773286ae2507b4b65b847 Mon Sep 17 00:00:00 2001 From: omar Date: Wed, 11 Oct 2017 20:28:16 +0200 Subject: [PATCH 184/823] Nav: Extract part of NavUpdate() into a saner NavScrollToBringItemIntoView() (#787) --- imgui.cpp | 71 ++++++++++++++++++++++++++++++------------------------- 1 file changed, 39 insertions(+), 32 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 39c2523388e9..d887cdb04537 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2611,6 +2611,42 @@ static ImVec2 GetNavInputAmount2d(int stick_no, ImGuiNavReadMode mode, float slo return delta; } +// NB: We modify rect_rel by the amount we scrolled for, so it is immediately updated. +static void NavScrollToBringItemIntoView(ImGuiWindow* window, ImRect& item_rect_rel) +{ + // Scroll to keep newly navigated item fully into view + ImRect window_rect_rel(window->InnerRect.Min - window->Pos - ImVec2(1, 1), window->InnerRect.Max - window->Pos + ImVec2(1, 1)); + //g.OverlayDrawList.AddRect(window->Pos + window_rect_rel.Min, window->Pos + window_rect_rel.Max, IM_COL32_WHITE); // [DEBUG] + if (window_rect_rel.Contains(item_rect_rel)) + return; + + ImGuiContext& g = *GImGui; + if (window->ScrollbarX && item_rect_rel.Min.x < window_rect_rel.Min.x) + { + window->ScrollTarget.x = item_rect_rel.Min.x + window->Scroll.x - g.Style.ItemSpacing.x; + window->ScrollTargetCenterRatio.x = 0.0f; + } + else if (window->ScrollbarX && item_rect_rel.Max.x >= window_rect_rel.Max.x) + { + window->ScrollTarget.x = item_rect_rel.Max.x + window->Scroll.x + g.Style.ItemSpacing.x; + window->ScrollTargetCenterRatio.x = 1.0f; + } + if (item_rect_rel.Min.y < window_rect_rel.Min.y) + { + window->ScrollTarget.y = item_rect_rel.Min.y + window->Scroll.y - g.Style.ItemSpacing.y; + window->ScrollTargetCenterRatio.y = 0.0f; + } + else if (item_rect_rel.Max.y >= window_rect_rel.Max.y) + { + window->ScrollTarget.y = item_rect_rel.Max.y + window->Scroll.y + g.Style.ItemSpacing.y; + window->ScrollTargetCenterRatio.y = 1.0f; + } + + // Estimate upcoming scroll so we can offset our relative mouse position so mouse position can be applied immediately (under this block) + ImVec2 next_scroll = CalcNextScrollFromScrollTargetAndClamp(window); + item_rect_rel.Translate(window->Scroll - next_scroll); +} + static void NavUpdate() { ImGuiContext& g = *GImGui; @@ -2634,39 +2670,10 @@ static void NavUpdate() // Process navigation move request if (g.NavMoveRequest && g.NavMoveResultId != 0) { - IM_ASSERT(g.NavWindow); - ImGuiWindow* window = g.NavWindow; - // Scroll to keep newly navigated item fully into view - ImRect window_rect_rel(window->InnerRect.Min - window->Pos - ImVec2(1,1), window->InnerRect.Max - window->Pos + ImVec2(1,1)); - //g.OverlayDrawList.AddRect(window->Pos + window_rect_rel.Min, window->Pos + window_rect_rel.Max, IM_COL32_WHITE); // [DEBUG] - if (g.NavLayer == 0 && !window_rect_rel.Contains(g.NavMoveResultRectRel)) - { - if (window->ScrollbarX && g.NavMoveResultRectRel.Min.x < window_rect_rel.Min.x) - { - window->ScrollTarget.x = g.NavMoveResultRectRel.Min.x + window->Scroll.x - g.Style.ItemSpacing.x; - window->ScrollTargetCenterRatio.x = 0.0f; - } - else if (window->ScrollbarX && g.NavMoveResultRectRel.Max.x >= window_rect_rel.Max.x) - { - window->ScrollTarget.x = g.NavMoveResultRectRel.Max.x + window->Scroll.x + g.Style.ItemSpacing.x; - window->ScrollTargetCenterRatio.x = 1.0f; - } - if (g.NavMoveResultRectRel.Min.y < window_rect_rel.Min.y) - { - window->ScrollTarget.y = g.NavMoveResultRectRel.Min.y + window->Scroll.y - g.Style.ItemSpacing.y; - window->ScrollTargetCenterRatio.y = 0.0f; - } - else if (g.NavMoveResultRectRel.Max.y >= window_rect_rel.Max.y) - { - window->ScrollTarget.y = g.NavMoveResultRectRel.Max.y + window->Scroll.y + g.Style.ItemSpacing.y; - window->ScrollTargetCenterRatio.y = 1.0f; - } - - // Estimate upcoming scroll so we can offset our relative mouse position so mouse position can be applied immediately (under this block) - ImVec2 next_scroll = CalcNextScrollFromScrollTargetAndClamp(window); - g.NavMoveResultRectRel.Translate(window->Scroll - next_scroll); - } + IM_ASSERT(g.NavWindow); + if (g.NavLayer == 0) + NavScrollToBringItemIntoView(g.NavWindow, g.NavMoveResultRectRel); // Apply result from previous frame navigation directional move request ImGui::ClearActiveID(); From f0d437dd9c73f62cfaa7a29e48c64181d79735a3 Mon Sep 17 00:00:00 2001 From: omar Date: Wed, 11 Oct 2017 20:29:53 +0200 Subject: [PATCH 185/823] Nav: SetActiveId() uses SetActiveIDNoNav() to avoid duplicating logic. (#787) --- imgui.cpp | 26 ++++++++++---------------- 1 file changed, 10 insertions(+), 16 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index d887cdb04537..8d5de35cb981 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1941,7 +1941,7 @@ ImGuiWindow* ImGui::GetParentWindow() return g.CurrentWindowStack[(unsigned int)g.CurrentWindowStack.Size - 2]; } -void ImGui::SetActiveID(ImGuiID id, ImGuiWindow* window) +void ImGui::SetActiveIDNoNav(ImGuiID id, ImGuiWindow* window) { ImGuiContext& g = *GImGui; g.ActiveIdIsJustActivated = (g.ActiveId != id); @@ -1953,6 +1953,15 @@ void ImGui::SetActiveID(ImGuiID id, ImGuiWindow* window) { g.ActiveIdIsAlive = true; g.ActiveIdSource = (g.NavActivateId == id || g.NavInputId == id || g.NavJustTabbedId == id || g.NavJustNavigatedId == id) ? ImGuiInputSource_Nav : ImGuiInputSource_Mouse; + } +} + +void ImGui::SetActiveID(ImGuiID id, ImGuiWindow* window) +{ + ImGuiContext& g = *GImGui; + SetActiveIDNoNav(id, window); + if (id) + { if (g.ActiveIdSource == ImGuiInputSource_Nav) g.NavDisableMouseHover = true; else @@ -1965,21 +1974,6 @@ void ImGui::SetActiveID(ImGuiID id, ImGuiWindow* window) } } -void ImGui::SetActiveIDNoNav(ImGuiID id, ImGuiWindow* window) -{ - ImGuiContext& g = *GImGui; - g.ActiveIdIsJustActivated = (g.ActiveId != id); - g.ActiveId = id; - g.ActiveIdAllowNavDirFlags = 0; - g.ActiveIdAllowOverlap = false; - g.ActiveIdWindow = window; - if (id) - { - g.ActiveIdIsAlive = true; - g.ActiveIdSource = (g.NavActivateId == id || g.NavInputId == id) ? ImGuiInputSource_Nav : ImGuiInputSource_Mouse; - } -} - void ImGui::ClearActiveID() { SetActiveID(0, NULL); From b05b31e6905384c71dbdb223e1ca080cf42033b9 Mon Sep 17 00:00:00 2001 From: omar Date: Wed, 11 Oct 2017 20:37:45 +0200 Subject: [PATCH 186/823] Nav: Made NavWindow always refresh from NavId so we can lazily retrieve the window for user functions that don't have it. This is not required by current commit but I'd rather test it earlier. Idea: eventually if we switch to 64-bit identifiers we could reserve e.g. 20 bits to store a simplified window identifier so we can always retrieve a window from an id. (#787) --- imgui.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/imgui.cpp b/imgui.cpp index 8d5de35cb981..cb5c8bf31f2f 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2224,6 +2224,7 @@ static void NavProcessItem(ImGuiWindow* window, const ImRect& nav_bb, const ImGu if (g.NavId == id) { window->NavRectRel[window->DC.NavLayerCurrent] = nav_bb_rel; + g.NavWindow = window; // Always refresh g.NavWindow, because some operations such as FocusItem() don't have a window. g.NavIdIsAlive = true; g.NavIdTabCounter = window->FocusIdxTabCounter; } From 17519c313a4f4c01df62a1628f28f0571dec9b1f Mon Sep 17 00:00:00 2001 From: omar Date: Wed, 11 Oct 2017 20:47:41 +0200 Subject: [PATCH 187/823] Nav: Extract part of NavUpdate() into a saner NavUpdateWindowingTarget() (#787) --- imgui.cpp | 156 ++++++++++++++++++++++++++++-------------------------- 1 file changed, 81 insertions(+), 75 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index cb5c8bf31f2f..733c04f236c6 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2606,6 +2606,85 @@ static ImVec2 GetNavInputAmount2d(int stick_no, ImGuiNavReadMode mode, float slo return delta; } +// Window management mode (change focus, move/resize window, jump back and forth to menu layer) +static void NavUpdateWindowingTarget() +{ + ImGuiContext& g = *GImGui; + if (!g.NavWindowingTarget && IsNavInputPressed(ImGuiNavInput_PadMenu, ImGuiNavReadMode_Pressed)) + { + ImGuiWindow* window = g.NavWindow; + if (!window) + window = FindWindowNavigable(g.Windows.Size - 1, -1, -1); + if (window) + { + g.NavWindowingTarget = window->RootNonPopupWindow; + g.NavWindowingDisplayAlpha = 0.0f; + g.NavWindowingToggleLayer = true; + } + } + if (g.NavWindowingTarget) + { + // Visuals only appears after a brief time holding the button, so that a fast tap (to toggle NavLayer) doesn't add visual noise + const float pressed_duration = g.IO.NavInputsDownDuration[ImGuiNavInput_PadMenu]; + g.NavWindowingDisplayAlpha = ImMax(g.NavWindowingDisplayAlpha, ImSaturate((pressed_duration - 0.20f) / 0.05f)); + g.NavWindowingToggleLayer &= (g.NavWindowingDisplayAlpha < 1.0f); // Once button is held long enough we don't consider it a tag-to-toggle-layer press anymore. + + // Select window to focus + const int focus_change_dir = (int)IsNavInputPressed(ImGuiNavInput_PadFocusPrev, ImGuiNavReadMode_RepeatSlow) - (int)IsNavInputPressed(ImGuiNavInput_PadFocusNext, ImGuiNavReadMode_RepeatSlow); + if (focus_change_dir != 0 && !(g.NavWindowingTarget->Flags & ImGuiWindowFlags_Modal)) + { + const int i_current = FindWindowIndex(g.NavWindowingTarget); + ImGuiWindow* window_target = FindWindowNavigable(i_current + focus_change_dir, -1, focus_change_dir); + if (!window_target) + window_target = FindWindowNavigable((focus_change_dir < 0) ? (g.Windows.Size - 1) : 0, i_current, focus_change_dir); + g.NavWindowingTarget = window_target; + g.NavWindowingToggleLayer = false; + g.NavWindowingDisplayAlpha = 1.0f; + } + + // Move window + if (g.NavWindowingTarget && !(g.NavWindowingTarget->Flags & ImGuiWindowFlags_NoMove)) + { + const ImVec2 move_delta = GetNavInputAmount2d(1, ImGuiNavReadMode_Down); + if (move_delta.x != 0.0f || move_delta.y != 0.0f) + { + const float move_speed = ImFloor(600 * g.IO.DeltaTime * ImMin(g.IO.DisplayFramebufferScale.x, g.IO.DisplayFramebufferScale.y)); + g.NavWindowingTarget->PosFloat += move_delta * move_speed; + g.NavDisableMouseHover = true; + MarkIniSettingsDirty(g.NavWindowingTarget); + } + } + + if (!IsNavInputDown(ImGuiNavInput_PadMenu)) + { + // Apply actual focus only when releasing the NavMenu button (until then the window was merely rendered front-most) + if (g.NavWindowingTarget && !g.NavWindowingToggleLayer && (!g.NavWindow || g.NavWindowingTarget != g.NavWindow->RootNonPopupWindow)) + { + ImGui::FocusWindow(g.NavWindowingTarget); + g.NavDisableHighlight = false; + g.NavDisableMouseHover = true; + if (g.NavWindowingTarget->NavLastIds[0] == 0) + NavInitWindow(g.NavWindowingTarget, false); + } + + // Single press toggles NavLayer + if (g.NavWindowingToggleLayer && g.NavWindow) + { + if ((g.NavWindow->DC.NavLayerActiveMask & (1 << 1)) == 0 && (g.NavWindow->RootWindow->DC.NavLayerActiveMask & (1 << 1)) != 0) + ImGui::FocusWindow(g.NavWindow->RootWindow); + g.NavLayer = (g.NavWindow->DC.NavLayerActiveMask & (1 << 1)) ? (g.NavLayer ^ 1) : 0; + g.NavDisableHighlight = false; + g.NavDisableMouseHover = true; + if (g.NavLayer == 0 && g.NavWindow->NavLastIds[0] != 0) + SetNavIdAndMoveMouse(g.NavWindow->NavLastIds[0], g.NavLayer, ImRect()); + else + NavInitWindow(g.NavWindow, true); + } + g.NavWindowingTarget = NULL; + } + } +} + // NB: We modify rect_rel by the amount we scrolled for, so it is immediately updated. static void NavScrollToBringItemIntoView(ImGuiWindow* window, ImRect& item_rect_rel) { @@ -2699,83 +2778,10 @@ static void NavUpdate() } g.NavIdIsAlive = false; g.NavJustTabbedId = 0; - - // Navigation windowing mode (change focus, move/resize window) - if (!g.NavWindowingTarget && IsNavInputPressed(ImGuiNavInput_PadMenu, ImGuiNavReadMode_Pressed)) - { - ImGuiWindow* window = g.NavWindow; - if (!window) - window = FindWindowNavigable(g.Windows.Size-1, -1, -1); - if (window) - { - g.NavWindowingTarget = window->RootNonPopupWindow; - g.NavWindowingDisplayAlpha = 0.0f; - g.NavWindowingToggleLayer = true; - } - } - if (g.NavWindowingTarget) - { - // Visuals only appears after a brief time holding the button, so that a fast tap (to toggle NavLayer) doesn't add visual noise - const float pressed_duration = g.IO.NavInputsDownDuration[ImGuiNavInput_PadMenu]; - g.NavWindowingDisplayAlpha = ImMax(g.NavWindowingDisplayAlpha, ImSaturate((pressed_duration - 0.20f) / 0.05f)); - g.NavWindowingToggleLayer &= (g.NavWindowingDisplayAlpha < 1.0f); // Once button is held long enough we don't consider it a tag-to-toggle-layer press anymore. - - // Select window to focus - const int focus_change_dir = (int)IsNavInputPressed(ImGuiNavInput_PadFocusPrev, ImGuiNavReadMode_RepeatSlow) - (int)IsNavInputPressed(ImGuiNavInput_PadFocusNext, ImGuiNavReadMode_RepeatSlow); - if (focus_change_dir != 0 && !(g.NavWindowingTarget->Flags & ImGuiWindowFlags_Modal)) - { - const int i_current = FindWindowIndex(g.NavWindowingTarget); - ImGuiWindow* window_target = FindWindowNavigable(i_current + focus_change_dir, -1, focus_change_dir); - if (!window_target) - window_target = FindWindowNavigable((focus_change_dir < 0) ? (g.Windows.Size-1) : 0, i_current, focus_change_dir); - g.NavWindowingTarget = window_target; - g.NavWindowingToggleLayer = false; - g.NavWindowingDisplayAlpha = 1.0f; - } - - // Move window - if (g.NavWindowingTarget && !(g.NavWindowingTarget->Flags & ImGuiWindowFlags_NoMove)) - { - const ImVec2 move_delta = GetNavInputAmount2d(1, ImGuiNavReadMode_Down); - if (move_delta.x != 0.0f || move_delta.y != 0.0f) - { - const float move_speed = ImFloor(600 * g.IO.DeltaTime * ImMin(g.IO.DisplayFramebufferScale.x, g.IO.DisplayFramebufferScale.y)); - g.NavWindowingTarget->PosFloat += move_delta * move_speed; - g.NavDisableMouseHover = true; - MarkIniSettingsDirty(g.NavWindowingTarget); - } - } - - if (!IsNavInputDown(ImGuiNavInput_PadMenu)) - { - // Apply actual focus only when releasing the NavMenu button (until then the window was merely rendered front-most) - if (g.NavWindowingTarget && !g.NavWindowingToggleLayer && (!g.NavWindow || g.NavWindowingTarget != g.NavWindow->RootNonPopupWindow)) - { - ImGui::FocusWindow(g.NavWindowingTarget); - g.NavDisableHighlight = false; - g.NavDisableMouseHover = true; - if (g.NavWindowingTarget->NavLastIds[0] == 0) - NavInitWindow(g.NavWindowingTarget, false); - } - - // Single press toggles NavLayer - if (g.NavWindowingToggleLayer && g.NavWindow) - { - if ((g.NavWindow->DC.NavLayerActiveMask & (1<<1)) == 0 && (g.NavWindow->RootWindow->DC.NavLayerActiveMask & (1<<1)) != 0) - ImGui::FocusWindow(g.NavWindow->RootWindow); - g.NavLayer = (g.NavWindow->DC.NavLayerActiveMask & (1<<1)) ? (g.NavLayer ^ 1) : 0; - g.NavDisableHighlight = false; - g.NavDisableMouseHover = true; - if (g.NavLayer == 0 && g.NavWindow->NavLastIds[0] != 0) - SetNavIdAndMoveMouse(g.NavWindow->NavLastIds[0], g.NavLayer, ImRect()); - else - NavInitWindow(g.NavWindow, true); - } - g.NavWindowingTarget = NULL; - } - } IM_ASSERT(g.NavLayer == 0 || g.NavLayer == 1); + NavUpdateWindowingTarget(); + // Set output flags for user application g.IO.NavUsable = g.NavWindow && !(g.NavWindow->Flags & ImGuiWindowFlags_NoNavInputs); g.IO.NavActive = (g.IO.NavUsable && g.NavId != 0 && !g.NavDisableHighlight) || (g.NavWindowingTarget != NULL) || g.NavInitRequest; From 4548bcb5c92ea88fd7c77e14cbc9ebde6b81bd14 Mon Sep 17 00:00:00 2001 From: omar Date: Thu, 12 Oct 2017 02:09:13 +0200 Subject: [PATCH 188/823] Nav: commiting shallow bits to reduce noise from working copy/upcoming commit. --- imgui.cpp | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 733c04f236c6..c79284f891f6 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1962,15 +1962,15 @@ void ImGui::SetActiveID(ImGuiID id, ImGuiWindow* window) SetActiveIDNoNav(id, window); if (id) { - if (g.ActiveIdSource == ImGuiInputSource_Nav) - g.NavDisableMouseHover = true; - else - g.NavDisableHighlight = true; g.NavId = id; if (window) g.NavLayer = window->DC.NavLayerCurrent; if (window) // NB: We current assume that SetActiveId() is called in the context where its NavLayer is the current one, which should be the case. window->NavLastIds[window->DC.NavLayerCurrent] = id; + if (g.ActiveIdSource == ImGuiInputSource_Nav) + g.NavDisableMouseHover = true; + else + g.NavDisableHighlight = true; } } @@ -2184,6 +2184,7 @@ static void NavProcessItem(ImGuiWindow* window, const ImRect& nav_bb, const ImGu ImGuiContext& g = *GImGui; //if (!g.IO.NavUsable) // [2017/10/06] Removed this possibly redundant test but I am not sure of all the side-effects yet. Some of the feature here will need to work regardless of using a _NoNavInputs flag. // return; + const ImGuiItemFlags item_flags = window->DC.ItemFlags; const ImRect nav_bb_rel(nav_bb.Min - g.NavWindow->Pos, nav_bb.Max - g.NavWindow->Pos); if (g.NavInitRequest && g.NavLayer == window->DC.NavLayerCurrent) @@ -2223,10 +2224,10 @@ static void NavProcessItem(ImGuiWindow* window, const ImRect& nav_bb, const ImGu // Update window-relative bounding box of navigated item if (g.NavId == id) { - window->NavRectRel[window->DC.NavLayerCurrent] = nav_bb_rel; - g.NavWindow = window; // Always refresh g.NavWindow, because some operations such as FocusItem() don't have a window. + g.NavWindow = window; // Always refresh g.NavWindow, because some operations such as FocusItem() don't have a window. g.NavIdIsAlive = true; g.NavIdTabCounter = window->FocusIdxTabCounter; + window->NavRectRel[window->DC.NavLayerCurrent] = nav_bb_rel; // Store item bounding box (relative to window position) } } @@ -2921,7 +2922,7 @@ static void NavUpdate() g.NavMoveResultParentId = 0; g.NavMoveResultDistAxial = g.NavMoveResultDistBox = g.NavMoveResultDistCenter = FLT_MAX; - // When we have manually scrolled (without using navigation) and NavId becomes out of bounds, we clamp its bounding box (used for search) to the visible area to restart navigation within visible items + // When we have manually scrolled (without using navigation) and NavId becomes out of bounds, we project its bounding box to the visible area to restart navigation within visible items if (g.NavMoveRequest && g.NavMoveFromClampedRefRect && g.NavLayer == 0) { ImGuiWindow* window = g.NavWindow; @@ -9031,9 +9032,9 @@ bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2 select_all = true; } SetActiveID(id, window); + FocusWindow(window); if (!is_multiline) g.ActiveIdAllowNavDirFlags = ((1 << ImGuiDir_Up) | (1 << ImGuiDir_Down)); - FocusWindow(window); } else if (io.MouseClicked[0]) { From 48498b337de330fe91d1faa6b7fbcd154ea28b2f Mon Sep 17 00:00:00 2001 From: omar Date: Fri, 13 Oct 2017 13:07:07 +0200 Subject: [PATCH 189/823] Internals: SetActiveID window cannot be NULL --- imgui.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index c79284f891f6..340da83d6ec6 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1963,10 +1963,10 @@ void ImGui::SetActiveID(ImGuiID id, ImGuiWindow* window) if (id) { g.NavId = id; - if (window) - g.NavLayer = window->DC.NavLayerCurrent; - if (window) // NB: We current assume that SetActiveId() is called in the context where its NavLayer is the current one, which should be the case. - window->NavLastIds[window->DC.NavLayerCurrent] = id; + + // Assume that SetActiveID() is called in the context where its NavLayer is the current layer, which is the case everywhere we call it. + g.NavLayer = window->DC.NavLayerCurrent; + window->NavLastIds[window->DC.NavLayerCurrent] = id; if (g.ActiveIdSource == ImGuiInputSource_Nav) g.NavDisableMouseHover = true; else From 8b095e483b093732b8a46c7b7d97feb3ca665fd2 Mon Sep 17 00:00:00 2001 From: omar Date: Fri, 13 Oct 2017 13:07:45 +0200 Subject: [PATCH 190/823] Internals: Moved SetNavID() and renamed casing to be consistent with stuff exposed in imgui_internal.h --- imgui.cpp | 54 +++++++++++++++++++++++++++--------------------------- 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 340da83d6ec6..ba882a01485b 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1941,6 +1941,25 @@ ImGuiWindow* ImGui::GetParentWindow() return g.CurrentWindowStack[(unsigned int)g.CurrentWindowStack.Size - 2]; } +static void SetNavID(ImGuiID id, int nav_layer) +{ + ImGuiContext& g = *GImGui; + IM_ASSERT(g.NavWindow); + IM_ASSERT(nav_layer == 0 || nav_layer == 1); + g.NavId = id; + g.NavWindow->NavLastIds[nav_layer] = g.NavId; +} + +static void SetNavIDAndMoveMouse(ImGuiID id, int nav_layer, const ImRect& rect_rel) +{ + ImGuiContext& g = *GImGui; + SetNavID(id, nav_layer); + g.NavWindow->NavRectRel[nav_layer] = rect_rel; + g.NavMousePosDirty = true; + g.NavDisableHighlight = false; + g.NavDisableMouseHover = true; +} + void ImGui::SetActiveIDNoNav(ImGuiID id, ImGuiWindow* window) { ImGuiContext& g = *GImGui; @@ -2477,25 +2496,6 @@ int ImGui::GetFrameCount() return GImGui->FrameCount; } -static void SetNavId(ImGuiID id, int nav_layer) -{ - ImGuiContext& g = *GImGui; - IM_ASSERT(g.NavWindow); - IM_ASSERT(nav_layer == 0 || nav_layer == 1); - g.NavId = id; - g.NavWindow->NavLastIds[nav_layer] = g.NavId; -} - -static void SetNavIdAndMoveMouse(ImGuiID id, int nav_layer, const ImRect& rect_rel) -{ - ImGuiContext& g = *GImGui; - SetNavId(id, nav_layer); - g.NavWindow->NavRectRel[nav_layer] = rect_rel; - g.NavMousePosDirty = true; - g.NavDisableHighlight = false; - g.NavDisableMouseHover = true; -} - // This needs to be called before we submit any widget (aka in or before Begin) static void NavInitWindow(ImGuiWindow* window, bool force_reinit) { @@ -2507,7 +2507,7 @@ static void NavInitWindow(ImGuiWindow* window, bool force_reinit) init_for_nav = true; if (init_for_nav) { - SetNavId(0, g.NavLayer); + SetNavID(0, g.NavLayer); g.NavInitRequest = true; g.NavInitResultId = 0; g.NavInitResultExplicit = false; @@ -2677,7 +2677,7 @@ static void NavUpdateWindowingTarget() g.NavDisableHighlight = false; g.NavDisableMouseHover = true; if (g.NavLayer == 0 && g.NavWindow->NavLastIds[0] != 0) - SetNavIdAndMoveMouse(g.NavWindow->NavLastIds[0], g.NavLayer, ImRect()); + SetNavIDAndMoveMouse(g.NavWindow->NavLastIds[0], g.NavLayer, ImRect()); else NavInitWindow(g.NavWindow, true); } @@ -2732,7 +2732,7 @@ static void NavUpdate() { // Apply result from previous navigation init request (typically select the first item, unless SetItemDefaultFocus() has been called) IM_ASSERT(g.NavWindow); - SetNavId(g.NavInitResultId, g.NavLayer); + SetNavID(g.NavInitResultId, g.NavLayer); g.NavWindow->NavRectRel[g.NavLayer] = g.NavInitResultRectRel; if (g.NavDisableMouseHover) g.NavMousePosDirty = true; @@ -2752,7 +2752,7 @@ static void NavUpdate() // Apply result from previous frame navigation directional move request ImGui::ClearActiveID(); - SetNavIdAndMoveMouse(g.NavMoveResultId, g.NavLayer, g.NavMoveResultRectRel); + SetNavIDAndMoveMouse(g.NavMoveResultId, g.NavLayer, g.NavMoveResultRectRel); g.NavJustNavigatedId = g.NavMoveResultId; g.NavMoveFromClampedRefRect = false; } @@ -2801,7 +2801,7 @@ static void NavUpdate() ImGuiWindow* parent_window = g.NavWindow->ParentWindow; ImGui::FocusWindow(parent_window); IM_ASSERT(child_window->ChildId != 0); - SetNavId(child_window->ChildId, g.NavLayer); // FIXME-NAV: Layer not necessarily correct + SetNavID(child_window->ChildId, g.NavLayer); // FIXME-NAV: Layer not necessarily correct g.NavIdIsAlive = false; if (g.NavDisableMouseHover) g.NavMousePosDirty = true; @@ -2816,7 +2816,7 @@ static void NavUpdate() // Leave the "menu" layer g.NavLayer = 0; if (g.NavWindow->NavLastIds[0]) - SetNavIdAndMoveMouse(g.NavWindow->NavLastIds[0], g.NavLayer, ImRect()); + SetNavIDAndMoveMouse(g.NavWindow->NavLastIds[0], g.NavLayer, ImRect()); else NavInitWindow(g.NavWindow, true); } @@ -9918,7 +9918,7 @@ bool ImGui::Selectable(const char* label, bool selected, ImGuiSelectableFlags fl if (!g.NavDisableMouseHover && g.NavWindow == window) { g.NavDisableHighlight = true; - SetNavId(id, window->DC.NavLayerCurrent); + SetNavID(id, window->DC.NavLayerCurrent); } // Render @@ -10154,7 +10154,7 @@ void ImGui::EndMenuBar() // This involve a one-frame delay which isn't very problematic in this situation. We could remove it by scoring in advance for multiple window (probably not worth the hassle/cost) IM_ASSERT(window->DC.NavLayerActiveMaskNext & 0x02); // Sanity check FocusWindow(window); - SetNavIdAndMoveMouse(window->NavLastIds[1], 1, window->NavRectRel[1]); + SetNavIDAndMoveMouse(window->NavLastIds[1], 1, window->NavRectRel[1]); g.NavLayer = 1; g.NavDisableHighlight = true; // Hide highlight for the current frame so we don't see the intermediary selection. g.NavMoveRequestForwardStep = 1; From 03712192223b80bd86950738948157dc60531971 Mon Sep 17 00:00:00 2001 From: omar Date: Fri, 13 Oct 2017 13:23:21 +0200 Subject: [PATCH 191/823] Nav: Internals: Renamed SetActiveIDNoNav -> SetActiveID() and old SetActiveID() -> SetFocusID(), both functions needs to be called when both are desirabled. (#787) May break code relying on imgui_internal.h, relying on nav and not calling ButtonBehavior(). --- imgui.cpp | 44 ++++++++++++++++++++++---------------------- imgui_internal.h | 2 +- 2 files changed, 23 insertions(+), 23 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index ba882a01485b..66f736f7adad 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1960,7 +1960,7 @@ static void SetNavIDAndMoveMouse(ImGuiID id, int nav_layer, const ImRect& rect_r g.NavDisableMouseHover = true; } -void ImGui::SetActiveIDNoNav(ImGuiID id, ImGuiWindow* window) +void ImGui::SetActiveID(ImGuiID id, ImGuiWindow* window) { ImGuiContext& g = *GImGui; g.ActiveIdIsJustActivated = (g.ActiveId != id); @@ -1975,22 +1975,18 @@ void ImGui::SetActiveIDNoNav(ImGuiID id, ImGuiWindow* window) } } -void ImGui::SetActiveID(ImGuiID id, ImGuiWindow* window) +// Assume that SetFocusID() is called in the context where its NavLayer is the current window nav layer. +void ImGui::SetFocusID(ImGuiID id, ImGuiWindow* window) { + IM_ASSERT(id != 0); ImGuiContext& g = *GImGui; - SetActiveIDNoNav(id, window); - if (id) - { - g.NavId = id; - - // Assume that SetActiveID() is called in the context where its NavLayer is the current layer, which is the case everywhere we call it. - g.NavLayer = window->DC.NavLayerCurrent; - window->NavLastIds[window->DC.NavLayerCurrent] = id; - if (g.ActiveIdSource == ImGuiInputSource_Nav) - g.NavDisableMouseHover = true; - else - g.NavDisableHighlight = true; - } + g.NavId = id; + g.NavLayer = window->DC.NavLayerCurrent; + window->NavLastIds[window->DC.NavLayerCurrent] = id; + if (g.ActiveIdSource == ImGuiInputSource_Nav) + g.NavDisableMouseHover = true; + else + g.NavDisableHighlight = true; } void ImGui::ClearActiveID() @@ -3535,7 +3531,7 @@ void ImGui::EndFrame() { g.MovedWindow = g.HoveredWindow; g.MovedWindowMoveId = g.HoveredWindow->MoveId; - SetActiveIDNoNav(g.MovedWindowMoveId, g.HoveredRootWindow); + SetActiveID(g.MovedWindowMoveId, g.HoveredRootWindow); } } else if (g.NavWindow != NULL && GetFrontMostModalRootWindow() == NULL) @@ -4616,7 +4612,7 @@ static bool BeginChildEx(const char* name, ImGuiID id, const ImVec2& size_arg, b { ImGui::FocusWindow(child_window); NavInitWindow(child_window, false); - ImGui::SetActiveIDNoNav(id+1, child_window); // Steal ActiveId with a dummy id so that key-press won't activate child item + ImGui::SetActiveID(id+1, child_window); // Steal ActiveId with a dummy id so that key-press won't activate child item g.ActiveIdSource = ImGuiInputSource_Nav; } @@ -6718,10 +6714,9 @@ bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool // FIXME-NAVIGATION: We don't honor those different behaviors. if ((flags & ImGuiButtonFlags_PressedOnClickRelease) && g.IO.MouseClicked[0]) { - if (flags & ImGuiButtonFlags_NoNavOverride) - SetActiveIDNoNav(id, window); - else - SetActiveID(id, window); // Hold on ID + SetActiveID(id, window); + if (!(flags & ImGuiButtonFlags_NoNavOverride)) + SetFocusID(id, window); FocusWindow(window); g.ActiveIdClickOffset = g.IO.MousePos - bb.Min; } @@ -6764,6 +6759,7 @@ bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool // Set active id so it can be queried by user via IsItemActive(), equivalent of holding the mouse button. g.NavActivateId = id; // This is so SetActiveId assign a Nav source SetActiveID(id, window); + SetFocusID(id, window); g.ActiveIdAllowNavDirFlags = (1 << ImGuiDir_Left) | (1 << ImGuiDir_Right) | (1 << ImGuiDir_Up) | (1 << ImGuiDir_Down); } } @@ -7607,7 +7603,7 @@ bool ImGui::InputScalarAsWidgetReplacement(const ImRect& aabb, const char* label // Our replacement widget will override the focus ID (registered previously to allow for a TAB focus to happen) // On the first frame, g.ScalarAsInputTextId == 0, then on subsequent frames it becomes == id - SetActiveIDNoNav(g.ScalarAsInputTextId, window); + SetActiveID(g.ScalarAsInputTextId, window); g.ActiveIdAllowNavDirFlags = (1 << ImGuiDir_Up) | (1 << ImGuiDir_Down); SetHoveredID(0); FocusableItemUnregister(window); @@ -7876,6 +7872,7 @@ bool ImGui::SliderFloat(const char* label, float* v, float v_min, float v_max, c if (tab_focus_requested || (hovered && g.IO.MouseClicked[0]) || g.NavActivateId == id || g.NavInputId == id) { SetActiveID(id, window); + SetFocusID(id, window); FocusWindow(window); if (tab_focus_requested || g.IO.KeyCtrl || g.NavInputId == id) { @@ -7927,6 +7924,7 @@ bool ImGui::VSliderFloat(const char* label, const ImVec2& size, float* v, float if ((hovered && g.IO.MouseClicked[0]) || g.NavActivateId == id || g.NavInputId == id) { SetActiveID(id, window); + SetFocusID(id, window); FocusWindow(window); } @@ -8177,6 +8175,7 @@ bool ImGui::DragFloat(const char* label, float* v, float v_speed, float v_min, f if (tab_focus_requested || (hovered && (g.IO.MouseClicked[0] || g.IO.MouseDoubleClicked[0])) || g.NavActivateId == id || g.NavInputId == id) { SetActiveID(id, window); + SetFocusID(id, window); FocusWindow(window); if (tab_focus_requested || g.IO.KeyCtrl || g.IO.MouseDoubleClicked[0] || g.NavInputId == id) { @@ -9032,6 +9031,7 @@ bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2 select_all = true; } SetActiveID(id, window); + SetFocusID(id, window); FocusWindow(window); if (!is_multiline) g.ActiveIdAllowNavDirFlags = ((1 << ImGuiDir_Up) | (1 << ImGuiDir_Down)); diff --git a/imgui_internal.h b/imgui_internal.h index b8d82eeeeec8..f7994ae1439e 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -865,7 +865,7 @@ namespace ImGui IMGUI_API void EndFrame(); // Ends the ImGui frame. Automatically called by Render()! you most likely don't need to ever call that yourself directly. If you don't need to render you can call EndFrame() but you'll have wasted CPU already. If you don't need to render, don't create any windows instead! IMGUI_API void SetActiveID(ImGuiID id, ImGuiWindow* window); - IMGUI_API void SetActiveIDNoNav(ImGuiID id, ImGuiWindow* window); + IMGUI_API void SetFocusID(ImGuiID id, ImGuiWindow* window); IMGUI_API void ClearActiveID(); IMGUI_API void SetHoveredID(ImGuiID id); IMGUI_API void KeepAliveID(ImGuiID id); From b667d5a9e745bd79ac723da157602b51b9e2dee4 Mon Sep 17 00:00:00 2001 From: omar Date: Fri, 13 Oct 2017 13:26:02 +0200 Subject: [PATCH 192/823] Nav: Internals: Renamed ImGuiButtonFlags_NoNavOverride to ImGuiButtonFlags_NoNavFocus + fixed a theorically missing test in ButtonBehavior() (#787) --- imgui.cpp | 11 ++++++----- imgui_internal.h | 2 +- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 66f736f7adad..92cce91539a4 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -5214,7 +5214,7 @@ bool ImGui::Begin(const char* name, bool* p_open, const ImVec2& size_on_first_us const ImRect resize_rect(br - ImVec2(resize_corner_size * 0.75f, resize_corner_size * 0.75f), br); const ImGuiID resize_id = window->GetID("#RESIZE"); bool hovered, held; - ButtonBehavior(resize_rect, resize_id, &hovered, &held, ImGuiButtonFlags_FlattenChilds | ImGuiButtonFlags_NoNavOverride); + ButtonBehavior(resize_rect, resize_id, &hovered, &held, ImGuiButtonFlags_FlattenChilds | ImGuiButtonFlags_NoNavFocus); if (hovered || held) g.MouseCursor = ImGuiMouseCursor_ResizeNWSE; @@ -5567,7 +5567,7 @@ static void Scrollbar(ImGuiWindow* window, bool horizontal) bool held = false; bool hovered = false; const bool previously_held = (g.ActiveId == id); - ImGui::ButtonBehavior(bb, id, &hovered, &held, ImGuiButtonFlags_NoNavOverride); + ImGui::ButtonBehavior(bb, id, &hovered, &held, ImGuiButtonFlags_NoNavFocus); float scroll_max = ImMax(1.0f, win_size_contents_v - win_size_avail_v); float scroll_ratio = ImSaturate(scroll_v / scroll_max); @@ -6715,7 +6715,7 @@ bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool if ((flags & ImGuiButtonFlags_PressedOnClickRelease) && g.IO.MouseClicked[0]) { SetActiveID(id, window); - if (!(flags & ImGuiButtonFlags_NoNavOverride)) + if (!(flags & ImGuiButtonFlags_NoNavFocus)) SetFocusID(id, window); FocusWindow(window); g.ActiveIdClickOffset = g.IO.MousePos - bb.Min; @@ -6759,7 +6759,8 @@ bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool // Set active id so it can be queried by user via IsItemActive(), equivalent of holding the mouse button. g.NavActivateId = id; // This is so SetActiveId assign a Nav source SetActiveID(id, window); - SetFocusID(id, window); + if (!(flags & ImGuiButtonFlags_NoNavFocus)) + SetFocusID(id, window); g.ActiveIdAllowNavDirFlags = (1 << ImGuiDir_Left) | (1 << ImGuiDir_Right) | (1 << ImGuiDir_Up) | (1 << ImGuiDir_Down); } } @@ -6780,7 +6781,7 @@ bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool pressed = true; ClearActiveID(); } - if (!(flags & ImGuiButtonFlags_NoNavOverride)) + if (!(flags & ImGuiButtonFlags_NoNavFocus)) g.NavDisableHighlight = true; } else if (g.ActiveIdSource == ImGuiInputSource_Nav) diff --git a/imgui_internal.h b/imgui_internal.h index f7994ae1439e..967b441678f8 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -182,7 +182,7 @@ enum ImGuiButtonFlags_ ImGuiButtonFlags_AlignTextBaseLine = 1 << 8, // vertically align button to match text baseline - ButtonEx() only // FIXME: Should be removed and handled by SmallButton(), not possible currently because of DC.CursorPosPrevLine ImGuiButtonFlags_NoKeyModifiers = 1 << 9, // disable interaction if a key modifier is held ImGuiButtonFlags_AllowOverlapMode = 1 << 10, // require previous frame HoveredId to either match id or be null before being usable - ImGuiButtonFlags_NoNavOverride = 1 << 11 // don't override navigation id when activated + ImGuiButtonFlags_NoNavFocus = 1 << 11 // don't override navigation focus when activated }; enum ImGuiSliderFlags_ From f852b9a52aeff7978bc3d2c5b76d5ffeb57b0f4d Mon Sep 17 00:00:00 2001 From: omar Date: Fri, 13 Oct 2017 13:29:42 +0200 Subject: [PATCH 193/823] Exposed Scrollbar() in imgui_internal.h and removed a bool arg --- imgui.cpp | 18 ++++++++++-------- imgui_internal.h | 1 + 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 92cce91539a4..9556a8bff706 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -644,7 +644,6 @@ static ImGuiWindow* FindHoveredWindow(ImVec2 pos, bool excluding_childs); static ImGuiWindow* CreateNewWindow(const char* name, ImVec2 size, ImGuiWindowFlags flags); static void ClearSetNextWindowData(); static void CheckStacksSize(ImGuiWindow* window, bool write); -static void Scrollbar(ImGuiWindow* window, bool horizontal); static ImVec2 CalcNextScrollFromScrollTargetAndClamp(ImGuiWindow* window); static void AddDrawListToRenderList(ImVector& out_render_list, ImDrawList* draw_list); @@ -5299,9 +5298,9 @@ bool ImGui::Begin(const char* name, bool* p_open, const ImVec2& size_on_first_us // Scrollbars if (window->ScrollbarX) - Scrollbar(window, true); + Scrollbar(ImGuiLayoutType_Horizontal); if (window->ScrollbarY) - Scrollbar(window, false); + Scrollbar(ImGuiLayoutType_Vertical); // Render resize grip // (after the input handling so we don't have a frame of latency) @@ -5522,9 +5521,12 @@ void ImGui::End() // - We handle absolute seeking (when first clicking outside the grab) and relative manipulation (afterward or when clicking inside the grab) // - We store values as normalized ratio and in a form that allows the window content to change while we are holding on a scrollbar // - We handle both horizontal and vertical scrollbars, which makes the terminology not ideal. -static void Scrollbar(ImGuiWindow* window, bool horizontal) +void ImGui::Scrollbar(ImGuiLayoutType direction) { ImGuiContext& g = *GImGui; + ImGuiWindow* window = g.CurrentWindow; + + const bool horizontal = (direction == ImGuiLayoutType_Horizontal); const ImGuiStyle& style = g.Style; const ImGuiID id = window->GetID(horizontal ? "#SCROLLX" : "#SCROLLY"); @@ -5547,7 +5549,7 @@ static void Scrollbar(ImGuiWindow* window, bool horizontal) window_rounding_corners = ImGuiCorner_BotLeft | (other_scrollbar ? 0 : ImGuiCorner_BotRight); else window_rounding_corners = (((window->Flags & ImGuiWindowFlags_NoTitleBar) && !(window->Flags & ImGuiWindowFlags_MenuBar)) ? ImGuiCorner_TopRight : 0) | (other_scrollbar ? 0 : ImGuiCorner_BotRight); - window->DrawList->AddRectFilled(bb.Min, bb.Max, ImGui::GetColorU32(ImGuiCol_ScrollbarBg), window_rounding, window_rounding_corners); + window->DrawList->AddRectFilled(bb.Min, bb.Max, GetColorU32(ImGuiCol_ScrollbarBg), window_rounding, window_rounding_corners); bb.Expand(ImVec2(-ImClamp((float)(int)((bb.Max.x - bb.Min.x - 2.0f) * 0.5f), 0.0f, 3.0f), -ImClamp((float)(int)((bb.Max.y - bb.Min.y - 2.0f) * 0.5f), 0.0f, 3.0f))); // V denote the main, longer axis of the scrollbar (= height for a vertical scrollbar) @@ -5567,7 +5569,7 @@ static void Scrollbar(ImGuiWindow* window, bool horizontal) bool held = false; bool hovered = false; const bool previously_held = (g.ActiveId == id); - ImGui::ButtonBehavior(bb, id, &hovered, &held, ImGuiButtonFlags_NoNavFocus); + ButtonBehavior(bb, id, &hovered, &held, ImGuiButtonFlags_NoNavFocus); float scroll_max = ImMax(1.0f, win_size_contents_v - win_size_avail_v); float scroll_ratio = ImSaturate(scroll_v / scroll_max); @@ -5580,7 +5582,7 @@ static void Scrollbar(ImGuiWindow* window, bool horizontal) // Click position in scrollbar normalized space (0.0f->1.0f) const float clicked_v_norm = ImSaturate((mouse_pos_v - scrollbar_pos_v) / scrollbar_size_v); - ImGui::SetHoveredID(id); + SetHoveredID(id); bool seek_absolute = false; if (!previously_held) @@ -5616,7 +5618,7 @@ static void Scrollbar(ImGuiWindow* window, bool horizontal) } // Render - const ImU32 grab_col = ImGui::GetColorU32(held ? ImGuiCol_ScrollbarGrabActive : hovered ? ImGuiCol_ScrollbarGrabHovered : ImGuiCol_ScrollbarGrab); + const ImU32 grab_col = GetColorU32(held ? ImGuiCol_ScrollbarGrabActive : hovered ? ImGuiCol_ScrollbarGrabHovered : ImGuiCol_ScrollbarGrab); if (horizontal) window->DrawList->AddRectFilled(ImVec2(ImLerp(bb.Min.x, bb.Max.x, grab_v_norm), bb.Min.y), ImVec2(ImLerp(bb.Min.x, bb.Max.x, grab_v_norm) + grab_h_pixels, bb.Max.y), grab_col, style.ScrollbarRounding); else diff --git a/imgui_internal.h b/imgui_internal.h index 967b441678f8..2528b2ec938d 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -890,6 +890,7 @@ namespace ImGui IMGUI_API int CalcTypematicPressedRepeatAmount(float t, float t_prev, float repeat_delay, float repeat_rate); + IMGUI_API void Scrollbar(ImGuiLayoutType direction); IMGUI_API void VerticalSeparator(); // Vertical separator, for menu bars (use current line height). not exposed because it is misleading what it doesn't have an effect on regular layout. // FIXME-WIP: New Columns API From 53780a4fcc5344d0007eb49e9f231dc8954ec0c2 Mon Sep 17 00:00:00 2001 From: omar Date: Fri, 13 Oct 2017 16:23:44 +0200 Subject: [PATCH 194/823] Nav: Shallow tweaks. --- imgui.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 9556a8bff706..20610e6ac66b 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2890,7 +2890,7 @@ static void NavUpdate() // *Fallback* manual-scroll with NavUp/NavDown when window has no navigable item ImGuiWindow* window = g.NavWindow; const float scroll_speed = ImFloor(window->CalcFontSize() * 100 * g.IO.DeltaTime + 0.5f); // We need round the scrolling speed because sub-pixel scroll isn't reliably supported. - if (!window->DC.NavLayerActiveMask && window->DC.NavHasScroll && g.NavMoveRequest) + if (window->DC.NavLayerActiveMask == 0x00 && window->DC.NavHasScroll && g.NavMoveRequest) { if (g.NavMoveDir == ImGuiDir_Left || g.NavMoveDir == ImGuiDir_Right) SetWindowScrollX(window, ImFloor(window->Scroll.x + ((g.NavMoveDir == ImGuiDir_Left) ? -1.0f : +1.0f) * scroll_speed)); @@ -6753,10 +6753,11 @@ bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool } if (g.NavActivateDownId == id) { - bool nav_pressed = (g.NavActivateId == id) || IsNavInputPressed(ImGuiNavInput_PadActivate, (flags & ImGuiButtonFlags_Repeat) ? ImGuiNavReadMode_Repeat : ImGuiNavReadMode_Pressed); - if (nav_pressed) + bool nav_activated_by_code = (g.NavActivateId == id); + bool nav_activated_by_inputs = IsNavInputPressed(ImGuiNavInput_PadActivate, (flags & ImGuiButtonFlags_Repeat) ? ImGuiNavReadMode_Repeat : ImGuiNavReadMode_Pressed); + if (nav_activated_by_code || nav_activated_by_inputs) pressed = true; - if (nav_pressed || g.ActiveId == id) + if (nav_activated_by_code || nav_activated_by_inputs || g.ActiveId == id) { // Set active id so it can be queried by user via IsItemActive(), equivalent of holding the mouse button. g.NavActivateId = id; // This is so SetActiveId assign a Nav source From c42baf392a37e7621f473a16a60031b4a3a62022 Mon Sep 17 00:00:00 2001 From: omar Date: Fri, 13 Oct 2017 16:48:14 +0200 Subject: [PATCH 195/823] Reluctantly exposed GetActiveID(), GetHoveredID() in imgui_internal because the demo code will need it. --- imgui.cpp | 12 ++++++++++++ imgui_internal.h | 2 ++ 2 files changed, 14 insertions(+) diff --git a/imgui.cpp b/imgui.cpp index 20610e6ac66b..e856846ad25c 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1974,6 +1974,12 @@ void ImGui::SetActiveID(ImGuiID id, ImGuiWindow* window) } } +ImGuiID ImGui::GetActiveID() +{ + ImGuiContext& g = *GImGui; + return g.ActiveId; +} + // Assume that SetFocusID() is called in the context where its NavLayer is the current window nav layer. void ImGui::SetFocusID(ImGuiID id, ImGuiWindow* window) { @@ -2000,6 +2006,12 @@ void ImGui::SetHoveredID(ImGuiID id) g.HoveredIdAllowOverlap = false; } +ImGuiID ImGui::GetHoveredID() +{ + ImGuiContext& g = *GImGui; + return g.HoveredId ? g.HoveredId : g.HoveredIdPreviousFrame; +} + void ImGui::KeepAliveID(ImGuiID id) { ImGuiContext& g = *GImGui; diff --git a/imgui_internal.h b/imgui_internal.h index 2528b2ec938d..7f9ee7a1dd00 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -865,9 +865,11 @@ namespace ImGui IMGUI_API void EndFrame(); // Ends the ImGui frame. Automatically called by Render()! you most likely don't need to ever call that yourself directly. If you don't need to render you can call EndFrame() but you'll have wasted CPU already. If you don't need to render, don't create any windows instead! IMGUI_API void SetActiveID(ImGuiID id, ImGuiWindow* window); + IMGUI_API ImGuiID GetActiveID(); IMGUI_API void SetFocusID(ImGuiID id, ImGuiWindow* window); IMGUI_API void ClearActiveID(); IMGUI_API void SetHoveredID(ImGuiID id); + IMGUI_API ImGuiID GetHoveredID(); IMGUI_API void KeepAliveID(ImGuiID id); IMGUI_API void ItemSize(const ImVec2& size, float text_offset_y = 0.0f); From db5f1b79cdb31d50d302f7052a8f25102ecfef57 Mon Sep 17 00:00:00 2001 From: omar Date: Fri, 13 Oct 2017 19:18:59 +0200 Subject: [PATCH 196/823] Nav: ButtonBehavior() keep _displaying_ NavId item as howered when refocusing or moving window, which is consistent with IsItemHovered() and reduce noise/flicker (#787) --- imgui.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index e856846ad25c..fd16860cccb5 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2205,6 +2205,7 @@ static void NavMoveRequestCancel() NavUpdateAnyRequestFlag(); } +// We get there when either NavId == id, or when g.NavAnyRequest is set (which is updated by NavUpdateAnyRequestFlag above) static void NavProcessItem(ImGuiWindow* window, const ImRect& nav_bb, const ImGuiID id) { ImGuiContext& g = *GImGui; @@ -6758,11 +6759,10 @@ bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool } // Gamepad/Keyboard navigation - if (g.NavId == id && !g.NavDisableHighlight && (g.ActiveId == 0 || g.ActiveId == id)) - { - // We report navigated item as hovered but we don't set g.HoveredId to not interfere with mouse + // We report navigated item as hovered but we don't set g.HoveredId to not interfere with mouse. + if (g.NavId == id && !g.NavDisableHighlight && (g.ActiveId == 0 || g.ActiveId == id || g.ActiveId == window->MoveId)) hovered = true; - } + if (g.NavActivateDownId == id) { bool nav_activated_by_code = (g.NavActivateId == id); From d761825cfb92ed4d5ce8fa5abfc59f6c20d77023 Mon Sep 17 00:00:00 2001 From: omar Date: Fri, 13 Oct 2017 22:33:06 +0200 Subject: [PATCH 197/823] Nav: Renaming a field + Comments. --- imgui.cpp | 6 +++--- imgui.h | 4 ++-- imgui_internal.h | 13 +++++++------ 3 files changed, 12 insertions(+), 11 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index fd16860cccb5..454457f9cdc1 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1970,7 +1970,7 @@ void ImGui::SetActiveID(ImGuiID id, ImGuiWindow* window) if (id) { g.ActiveIdIsAlive = true; - g.ActiveIdSource = (g.NavActivateId == id || g.NavInputId == id || g.NavJustTabbedId == id || g.NavJustNavigatedId == id) ? ImGuiInputSource_Nav : ImGuiInputSource_Mouse; + g.ActiveIdSource = (g.NavActivateId == id || g.NavInputId == id || g.NavJustTabbedId == id || g.NavJustMovedToId == id) ? ImGuiInputSource_Nav : ImGuiInputSource_Mouse; } } @@ -2748,7 +2748,7 @@ static void NavUpdate() g.NavInitRequest = false; g.NavInitResultExplicit = false; g.NavInitResultId = 0; - g.NavJustNavigatedId = 0; + g.NavJustMovedToId = 0; // Process navigation move request if (g.NavMoveRequest && g.NavMoveResultId != 0) @@ -2761,7 +2761,7 @@ static void NavUpdate() // Apply result from previous frame navigation directional move request ImGui::ClearActiveID(); SetNavIDAndMoveMouse(g.NavMoveResultId, g.NavLayer, g.NavMoveResultRectRel); - g.NavJustNavigatedId = g.NavMoveResultId; + g.NavJustMovedToId = g.NavMoveResultId; g.NavMoveFromClampedRefRect = false; } diff --git a/imgui.h b/imgui.h index 8c6b8f442785..0a69e9244b56 100644 --- a/imgui.h +++ b/imgui.h @@ -902,8 +902,8 @@ struct ImGuiIO bool WantCaptureKeyboard; // Widget is active (= ImGui will use your keyboard input). Use to hide keyboard from the rest of your application bool WantTextInput; // Some text input widget is active, which will read input characters from the InputCharacters array. Use to activate on screen keyboard if your system needs one bool WantMoveMouse; // MousePos has been altered. back-end should reposition mouse on next frame. used only if 'NavMovesMouse=true'. - bool NavUsable; // Directional navigation is currently allowed (ImGuiKey_NavXXX events). - bool NavActive; // Directional navigation is active/visible and currently allowed (ImGuiKey_NavXXX events). + bool NavUsable; // Directional navigation is currently allowed (will handle ImGuiKey_NavXXX events). + bool NavActive; // Directional navigation is active/visible and currently allowed (will handle ImGuiKey_NavXXX events). float Framerate; // Application framerate estimation, in frame per second. Solely for convenience. Rolling average estimation based on IO.DeltaTime over 120 frames int MetricsAllocs; // Number of active memory allocations int MetricsRenderVertices; // Vertices output during last call to Render() diff --git a/imgui_internal.h b/imgui_internal.h index 7f9ee7a1dd00..fd646eff28c7 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -463,13 +463,14 @@ struct ImGuiContext ImVector CurrentPopupStack; // Which level of BeginPopup() we are in (reset every frame) // Navigation data (for gamepad/keyboard) - ImGuiWindow* NavWindow; // Nav/focused window for navigation - ImGuiID NavId; // Nav/focused item for navigation - ImGuiID NavActivateId, NavActivateDownId; // ~~ IsNavInputPressed(ImGuiNavInput_PadActivate) ? NavId : 0, etc. - ImGuiID NavInputId; // ~~ IsNavInputPressed(ImGuiNavInput_PadInput) ? NavId : 0, etc. + ImGuiWindow* NavWindow; // Focused window for navigation + ImGuiID NavId; // Focused item for navigation + ImGuiID NavActivateId; // ~~ IsNavInputPressed(ImGuiNavInput_PadActivate) ? NavId : 0, also set when calling ActivateItem() + ImGuiID NavActivateDownId; // ~~ IsNavInputPressed(ImGuiNavInput_PadActivate) ? NavId : 0 + ImGuiID NavInputId; // ~~ IsNavInputPressed(ImGuiNavInput_PadInput) ? NavId : 0 ImGuiID NavJustTabbedId; // Just tabbed to this id. - ImGuiID NavJustNavigatedId; // Just navigated to this id (result of a successfully MoveRequest) ImGuiID NavNextActivateId; // Set by ActivateItem(), queued until next frame + ImGuiID NavJustMovedToId; // Just navigated to this id (result of a successfully MoveRequest) ImRect NavScoringRectScreen; // Rectangle used for scoring, in screen space. Based of window->DC.NavRefRectRel[], modified for directional navigation scoring. ImGuiWindow* NavWindowingTarget; float NavWindowingDisplayAlpha; @@ -586,7 +587,7 @@ struct ImGuiContext NavWindow = NULL; NavId = NavActivateId = NavActivateDownId = NavInputId = 0; - NavJustTabbedId = NavJustNavigatedId = NavNextActivateId = 0; + NavJustTabbedId = NavJustMovedToId = NavNextActivateId = 0; NavScoringRectScreen = ImRect(); NavWindowingTarget = NULL; NavWindowingDisplayAlpha = 0.0f; From 7d142622028108314d174af8025dacb368ef5605 Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 16 Oct 2017 00:33:30 +0200 Subject: [PATCH 198/823] Nav: SetFocusID() update NavWindow and NavRectRel just as we get them. Needed by upcoming commit, committing separately as I'm curious if it has any side-effect. (#787) --- imgui.cpp | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 4a1bf07d6608..39e55a57634f 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1980,14 +1980,20 @@ ImGuiID ImGui::GetActiveID() return g.ActiveId; } -// Assume that SetFocusID() is called in the context where its NavLayer is the current window nav layer. void ImGui::SetFocusID(ImGuiID id, ImGuiWindow* window) { IM_ASSERT(id != 0); ImGuiContext& g = *GImGui; + + // Assume that SetActiveID() is called in the context where its NavLayer is the current layer, which is the case everywhere we call it. + const int nav_layer = window->DC.NavLayerCurrent; g.NavId = id; - g.NavLayer = window->DC.NavLayerCurrent; - window->NavLastIds[window->DC.NavLayerCurrent] = id; + g.NavWindow = window; + g.NavLayer = nav_layer; + window->NavLastIds[nav_layer] = id; + if (window->DC.LastItemId == id) + window->NavRectRel[nav_layer] = ImRect(window->DC.LastItemRect.Min - window->Pos, window->DC.LastItemRect.Max - window->Pos); + if (g.ActiveIdSource == ImGuiInputSource_Nav) g.NavDisableMouseHover = true; else From 97851f73764c1b0f77764ff850e59a31e025b722 Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 16 Oct 2017 00:36:31 +0200 Subject: [PATCH 199/823] Nav: NavProcessItem() computes window-relative rectangle using own Window rather than NavWindow. Not sure what it may mean for child-flattened-nav (disabled). (#787) --- imgui.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/imgui.cpp b/imgui.cpp index 39e55a57634f..825db0d50353 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2219,7 +2219,7 @@ static void NavProcessItem(ImGuiWindow* window, const ImRect& nav_bb, const ImGu // return; const ImGuiItemFlags item_flags = window->DC.ItemFlags; - const ImRect nav_bb_rel(nav_bb.Min - g.NavWindow->Pos, nav_bb.Max - g.NavWindow->Pos); + const ImRect nav_bb_rel(nav_bb.Min - window->Pos, nav_bb.Max - window->Pos); if (g.NavInitRequest && g.NavLayer == window->DC.NavLayerCurrent) { // Even if 'ImGuiItemFlags_NoNavDefaultFocus' is on (typically collapse/close button) we record the first ResultId so they can be used as a fallback From ae1866c4241eed391445d51cf5a993197665860c Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 16 Oct 2017 00:38:42 +0200 Subject: [PATCH 200/823] Nav: NavProcessItem() updates current NavLayer. Basically we're hearing toward rebuilidng nav info from an id. (#787). --- imgui.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/imgui.cpp b/imgui.cpp index 825db0d50353..4a4c22d13851 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2258,6 +2258,7 @@ static void NavProcessItem(ImGuiWindow* window, const ImRect& nav_bb, const ImGu if (g.NavId == id) { g.NavWindow = window; // Always refresh g.NavWindow, because some operations such as FocusItem() don't have a window. + g.NavLayer = window->DC.NavLayerCurrent; g.NavIdIsAlive = true; g.NavIdTabCounter = window->FocusIdxTabCounter; window->NavRectRel[window->DC.NavLayerCurrent] = nav_bb_rel; // Store item bounding box (relative to window position) From b70c2fa8879bf24b6bdd7c87a87eca1ff1fdd389 Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 16 Oct 2017 00:46:23 +0200 Subject: [PATCH 201/823] Nav: Internals: Moved some internal code to namespace, comments --- imgui.cpp | 34 +++++++++++++++++++++------------- 1 file changed, 21 insertions(+), 13 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 4a4c22d13851..abcbd54aec88 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -672,6 +672,13 @@ static inline void DataTypeFormatString(ImGuiDataType data_type, void* data static void DataTypeApplyOp(ImGuiDataType data_type, int op, void* value1, const void* value2); static bool DataTypeApplyOpFromText(const char* buf, const char* initial_value_buf, ImGuiDataType data_type, void* data_ptr, const char* scalar_format); +namespace ImGui +{ +static void NavUpdate(); +static void NavUpdateWindowing(); +static void NavProcessItem(ImGuiWindow* window, const ImRect& nav_bb, const ImGuiID id); +} + //----------------------------------------------------------------------------- // Platform dependent default implementations //----------------------------------------------------------------------------- @@ -2212,7 +2219,7 @@ static void NavMoveRequestCancel() } // We get there when either NavId == id, or when g.NavAnyRequest is set (which is updated by NavUpdateAnyRequestFlag above) -static void NavProcessItem(ImGuiWindow* window, const ImRect& nav_bb, const ImGuiID id) +static void ImGui::NavProcessItem(ImGuiWindow* window, const ImRect& nav_bb, const ImGuiID id) { ImGuiContext& g = *GImGui; //if (!g.IO.NavUsable) // [2017/10/06] Removed this possibly redundant test but I am not sure of all the side-effects yet. Some of the feature here will need to work regardless of using a _NoNavInputs flag. @@ -2623,7 +2630,7 @@ static ImVec2 GetNavInputAmount2d(int stick_no, ImGuiNavReadMode mode, float slo } // Window management mode (change focus, move/resize window, jump back and forth to menu layer) -static void NavUpdateWindowingTarget() +static void ImGui::NavUpdateWindowing() { ImGuiContext& g = *GImGui; if (!g.NavWindowingTarget && IsNavInputPressed(ImGuiNavInput_PadMenu, ImGuiNavReadMode_Pressed)) @@ -2676,7 +2683,7 @@ static void NavUpdateWindowingTarget() // Apply actual focus only when releasing the NavMenu button (until then the window was merely rendered front-most) if (g.NavWindowingTarget && !g.NavWindowingToggleLayer && (!g.NavWindow || g.NavWindowingTarget != g.NavWindow->RootNonPopupWindow)) { - ImGui::FocusWindow(g.NavWindowingTarget); + FocusWindow(g.NavWindowingTarget); g.NavDisableHighlight = false; g.NavDisableMouseHover = true; if (g.NavWindowingTarget->NavLastIds[0] == 0) @@ -2687,7 +2694,7 @@ static void NavUpdateWindowingTarget() if (g.NavWindowingToggleLayer && g.NavWindow) { if ((g.NavWindow->DC.NavLayerActiveMask & (1 << 1)) == 0 && (g.NavWindow->RootWindow->DC.NavLayerActiveMask & (1 << 1)) != 0) - ImGui::FocusWindow(g.NavWindow->RootWindow); + FocusWindow(g.NavWindow->RootWindow); g.NavLayer = (g.NavWindow->DC.NavLayerActiveMask & (1 << 1)) ? (g.NavLayer ^ 1) : 0; g.NavDisableHighlight = false; g.NavDisableMouseHover = true; @@ -2737,7 +2744,7 @@ static void NavScrollToBringItemIntoView(ImGuiWindow* window, ImRect& item_rect_ item_rect_rel.Translate(window->Scroll - next_scroll); } -static void NavUpdate() +static void ImGui::NavUpdate() { ImGuiContext& g = *GImGui; g.IO.WantMoveMouse = false; @@ -2745,7 +2752,7 @@ static void NavUpdate() // Process navigation init request (select first/default focus) if (g.NavInitResultId != 0 && (!g.NavDisableHighlight || g.NavInitResultExplicit)) { - // Apply result from previous navigation init request (typically select the first item, unless SetItemDefaultFocus() has been called) + // Apply result from previous navigation init request (will typically select the first item, unless SetItemDefaultFocus() has been called) IM_ASSERT(g.NavWindow); SetNavID(g.NavInitResultId, g.NavLayer); g.NavWindow->NavRectRel[g.NavLayer] = g.NavInitResultRectRel; @@ -2766,7 +2773,7 @@ static void NavUpdate() NavScrollToBringItemIntoView(g.NavWindow, g.NavMoveResultRectRel); // Apply result from previous frame navigation directional move request - ImGui::ClearActiveID(); + ClearActiveID(); SetNavIDAndMoveMouse(g.NavMoveResultId, g.NavLayer, g.NavMoveResultRectRel); g.NavJustMovedToId = g.NavMoveResultId; g.NavMoveFromClampedRefRect = false; @@ -2796,7 +2803,7 @@ static void NavUpdate() g.NavJustTabbedId = 0; IM_ASSERT(g.NavLayer == 0 || g.NavLayer == 1); - NavUpdateWindowingTarget(); + NavUpdateWindowing(); // Set output flags for user application g.IO.NavUsable = g.NavWindow && !(g.NavWindow->Flags & ImGuiWindowFlags_NoNavInputs); @@ -2807,14 +2814,14 @@ static void NavUpdate() { if (g.ActiveId != 0) { - ImGui::ClearActiveID(); + ClearActiveID(); } else if (g.NavWindow && (g.NavWindow->Flags & ImGuiWindowFlags_ChildWindow) && !(g.NavWindow->Flags & ImGuiWindowFlags_Popup) && g.NavWindow->ParentWindow) { // Exit child window ImGuiWindow* child_window = g.NavWindow; ImGuiWindow* parent_window = g.NavWindow->ParentWindow; - ImGui::FocusWindow(parent_window); + FocusWindow(parent_window); IM_ASSERT(child_window->ChildId != 0); SetNavID(child_window->ChildId, g.NavLayer); // FIXME-NAV: Layer not necessarily correct g.NavIdIsAlive = false; @@ -2919,6 +2926,7 @@ static void NavUpdate() } // *Normal* Manual scroll with NavScrollXXX keys + // Next movement request will clamp the NavId reference rectangle to the visible area, so navigation will resume within those bounds. ImVec2 scroll_dir = GetNavInputAmount2d(1, ImGuiNavReadMode_Down, 1.0f/10.0f, 10.0f); if (scroll_dir.x != 0.0f && window->ScrollbarX) { @@ -2974,7 +2982,7 @@ void ImGui::NewFrame() // Initialize on first frame if (!g.Initialized) - ImGui::Initialize(); + Initialize(); SetCurrentFont(GetDefaultFont()); IM_ASSERT(g.Font->IsLoaded()); @@ -3204,8 +3212,8 @@ void ImGui::NewFrame() // Create implicit window - we will only render it if the user has added something to it. // We don't use "Debug" to avoid colliding with user trying to create a "Debug" window with custom flags. - ImGui::SetNextWindowSize(ImVec2(400,400), ImGuiCond_FirstUseEver); - ImGui::Begin("Debug##Default"); + SetNextWindowSize(ImVec2(400,400), ImGuiCond_FirstUseEver); + Begin("Debug##Default"); } void ImGui::Initialize() From 82a27fd3aaf78cafc4bec2ef18729f225ad8fefb Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 16 Oct 2017 02:06:42 +0200 Subject: [PATCH 202/823] Nav: InputText: Fixed using Up/Down history callback feature when Nav is enabled (#787) --- imgui.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/imgui.cpp b/imgui.cpp index abcbd54aec88..2d78969576db 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -9094,6 +9094,8 @@ bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2 // Down the line we should have a cleaner library-wide concept of Selected vs Active. g.ActiveIdAllowOverlap = !io.MouseDown[0]; g.WantTextInputNextFrame = 1; + if (flags & ImGuiInputTextFlags_CallbackHistory) + g.ActiveIdAllowNavDirFlags &= ~((1 << ImGuiDir_Up) | (1 << ImGuiDir_Down)); // Edit in progress const float mouse_x = (io.MousePos.x - frame_bb.Min.x - style.FramePadding.x) + edit_state.ScrollX; From 7ea52ac1e41996f48bcd3de74bf32e6603c0242e Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 16 Oct 2017 02:30:59 +0200 Subject: [PATCH 203/823] Nav: InputTextMultiline: Fixed navigation/selection. Disabled selecting all when activating a multi-line text editor. (#787) --- imgui.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/imgui.cpp b/imgui.cpp index 2d78969576db..ffa2b100ca9f 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -4686,6 +4686,7 @@ void ImGui::EndChild() } else { + // Not navigable into ItemAdd(bb, 0); } } @@ -8974,6 +8975,7 @@ bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2 ImGuiWindow* draw_window = window; if (is_multiline) { + ItemAdd(total_bb, id, &frame_bb); if (!BeginChildFrame(id, frame_bb.GetSize())) { EndChildFrame(); @@ -9022,7 +9024,7 @@ bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2 bool clear_active_id = false; - bool select_all = (g.ActiveId != id) && (((flags & ImGuiInputTextFlags_AutoSelectAll) != 0) || (g.NavInputId == id)); + bool select_all = (g.ActiveId != id) && (((flags & ImGuiInputTextFlags_AutoSelectAll) != 0) || (g.NavInputId == id)) && (!is_multiline); if (focus_requested || user_clicked || user_scrolled || g.NavInputId == id) { if (g.ActiveId != id) From af565ea82810b89c2e1c317be8a7c91bd8014d5e Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 16 Oct 2017 02:41:28 +0200 Subject: [PATCH 204/823] Nav: InputTextMultiline: Fixed navigation/selection. Disabled selecting all when activating a multi-line text editor. (#787) --- imgui.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index ffa2b100ca9f..94e49b7253df 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -9066,8 +9066,8 @@ bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2 SetActiveID(id, window); SetFocusID(id, window); FocusWindow(window); - if (!is_multiline) - g.ActiveIdAllowNavDirFlags = ((1 << ImGuiDir_Up) | (1 << ImGuiDir_Down)); + if (!is_multiline && !(flags & ImGuiInputTextFlags_CallbackHistory)) + g.ActiveIdAllowNavDirFlags |= ((1 << ImGuiDir_Up) | (1 << ImGuiDir_Down)); } else if (io.MouseClicked[0]) { @@ -9096,8 +9096,6 @@ bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2 // Down the line we should have a cleaner library-wide concept of Selected vs Active. g.ActiveIdAllowOverlap = !io.MouseDown[0]; g.WantTextInputNextFrame = 1; - if (flags & ImGuiInputTextFlags_CallbackHistory) - g.ActiveIdAllowNavDirFlags &= ~((1 << ImGuiDir_Up) | (1 << ImGuiDir_Down)); // Edit in progress const float mouse_x = (io.MousePos.x - frame_bb.Min.x - style.FramePadding.x) + edit_state.ScrollX; From 29a652adeec8e9e0dafb5f79f06769ad3442ea3a Mon Sep 17 00:00:00 2001 From: omar Date: Wed, 18 Oct 2017 19:51:32 +0200 Subject: [PATCH 205/823] CollapsingHeader(bool*) variant: fixed for IsItemHovered() to work properly in the nav branch.Basically the close button now has to use ItemAdd() to be navable into, which overwrite the IsItemHovered data. (#600, #787) --- imgui.cpp | 3 +++ imgui_demo.cpp | 2 ++ imgui_internal.h | 11 +++++++++++ 3 files changed, 16 insertions(+) diff --git a/imgui.cpp b/imgui.cpp index acd202c23f97..1114c79cd283 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -7346,8 +7346,11 @@ bool ImGui::CollapsingHeader(const char* label, bool* p_open, ImGuiTreeNodeFlags // Create a small overlapping close button // FIXME: We can evolve this into user accessible helpers to add extra buttons on title bars, headers, etc. ImGuiContext& g = *GImGui; float button_sz = g.FontSize * 0.5f; + ImGuiItemHoveredDataBackup last_item_backup; + last_item_backup.Backup(); if (CloseButton(window->GetID((void*)(intptr_t)(id+1)), ImVec2(ImMin(window->DC.LastItemRect.Max.x, window->ClipRect.Max.x) - g.Style.FramePadding.x - button_sz, window->DC.LastItemRect.Min.y + g.Style.FramePadding.y + button_sz), button_sz)) *p_open = false; + last_item_backup.Restore(); } return is_open; diff --git a/imgui_demo.cpp b/imgui_demo.cpp index ac6ff98ec8dc..c3402c2fd541 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -460,11 +460,13 @@ void ImGui::ShowTestWindow(bool* p_open) ImGui::Checkbox("Enable extra group", &closable_group); if (ImGui::CollapsingHeader("Header")) { + ImGui::Text("IsItemHovered: %d", IsItemHovered()); for (int i = 0; i < 5; i++) ImGui::Text("Some content %d", i); } if (ImGui::CollapsingHeader("Header with a close button", &closable_group)) { + ImGui::Text("IsItemHovered: %d", IsItemHovered()); for (int i = 0; i < 5; i++) ImGui::Text("More content %d", i); } diff --git a/imgui_internal.h b/imgui_internal.h index caca4d6c9a15..6bec13d574d3 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -848,6 +848,17 @@ struct IMGUI_API ImGuiWindow ImRect MenuBarRect() const { float y1 = Pos.y + TitleBarHeight(); return ImRect(Pos.x, y1, Pos.x + SizeFull.x, y1 + MenuBarHeight()); } }; +// Backup and restore just enough data to be able to use IsItemHovered() on item A after another B in the same window has overwritten the data. +struct ImGuiItemHoveredDataBackup +{ + ImGuiID LastItemId; + ImRect LastItemRect; + bool LastItemRectHoveredRect; + + void Backup() { ImGuiWindow* window = GImGui->CurrentWindow; LastItemId = window->DC.LastItemId; LastItemRect = window->DC.LastItemRect; LastItemRectHoveredRect = window->DC.LastItemRectHoveredRect; } + void Restore() { ImGuiWindow* window = GImGui->CurrentWindow; window->DC.LastItemId = LastItemId; window->DC.LastItemRect = LastItemRect; window->DC.LastItemRectHoveredRect = LastItemRectHoveredRect; } +}; + //----------------------------------------------------------------------------- // Internal API // No guarantee of forward compatibility here. From 0ea66dc260522b4b4c3cecc508242a7555cdc8fc Mon Sep 17 00:00:00 2001 From: omar Date: Fri, 20 Oct 2017 18:16:53 +0200 Subject: [PATCH 206/823] Fixed bad merge from Master --- imgui.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/imgui.cpp b/imgui.cpp index dd26f13a5ba4..b7c7ac54f4b9 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2383,7 +2383,7 @@ bool ImGui::ItemHoverable(const ImRect& bb, ImGuiID id) return false; if (!IsMouseHoveringRect(bb.Min, bb.Max)) return false; - if (!g.NavDisableMouseHover || !IsWindowContentHoverable(window, ImGuiHoveredFlags_Default)) + if (g.NavDisableMouseHover || !IsWindowContentHoverable(window, ImGuiHoveredFlags_Default)) return false; SetHoveredID(id); From 23b9060468731259f449f3efb0d1d6c531c02b59 Mon Sep 17 00:00:00 2001 From: omar Date: Fri, 20 Oct 2017 20:35:39 +0200 Subject: [PATCH 207/823] Nav: Honoring ImGuiItemFlags_NoNav which is used by color picker (#787) --- imgui.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/imgui.cpp b/imgui.cpp index 54097f5fa5b9..446fa59e3d25 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2275,7 +2275,7 @@ static void ImGui::NavProcessItem(ImGuiWindow* window, const ImRect& nav_bb, con } // Scoring for navigation - if (g.NavId != id) + if (g.NavId != id && !(item_flags & ImGuiItemFlags_NoNav)) { #if IMGUI_DEBUG_NAV // [DEBUG] Score all items in NavWindow at all times From 5fa81f2a26636d5fb238aa0bd57c2d7ea9d205bf Mon Sep 17 00:00:00 2001 From: omar Date: Fri, 20 Oct 2017 22:12:10 +0200 Subject: [PATCH 208/823] Nav: Added ImGuiNavInput_KeyMenu aside from ImGuiNavInput_PadMenu as it is one differenciator between pad and keyboard that's very annoying with the keyboard. Remove the move/resize behavior that appears than holding the button for a while. (#787) --- imgui.cpp | 4 ++-- imgui.h | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 8cc1eca62676..62d4e8f9e62d 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2665,7 +2665,7 @@ static ImVec2 GetNavInputAmount2d(int stick_no, ImGuiNavReadMode mode, float slo static void ImGui::NavUpdateWindowing() { ImGuiContext& g = *GImGui; - if (!g.NavWindowingTarget && IsNavInputPressed(ImGuiNavInput_PadMenu, ImGuiNavReadMode_Pressed)) + if (!g.NavWindowingTarget && (IsNavInputPressed(ImGuiNavInput_PadMenu, ImGuiNavReadMode_Pressed) || IsNavInputPressed(ImGuiNavInput_KeyMenu, ImGuiNavReadMode_Pressed))) { ImGuiWindow* window = g.NavWindow; if (!window) @@ -2710,7 +2710,7 @@ static void ImGui::NavUpdateWindowing() } } - if (!IsNavInputDown(ImGuiNavInput_PadMenu)) + if (!IsNavInputDown(ImGuiNavInput_PadMenu) && !IsNavInputDown(ImGuiNavInput_KeyMenu)) { // Apply actual focus only when releasing the NavMenu button (until then the window was merely rendered front-most) if (g.NavWindowingTarget && !g.NavWindowingToggleLayer && (!g.NavWindow || g.NavWindowingTarget != g.NavWindow->RootNonPopupWindow)) diff --git a/imgui.h b/imgui.h index bbcac19d2a44..3e2ab628bb0b 100644 --- a/imgui.h +++ b/imgui.h @@ -640,6 +640,7 @@ enum ImGuiNavInput_ ImGuiNavInput_PadFocusNext, // prev window (with PadMenu held) // e.g. R-trigger ImGuiNavInput_PadTweakSlow, // slower tweaks // e.g. L-trigger, analog ImGuiNavInput_PadTweakFast, // faster tweaks // e.g. R-trigger, analog + ImGuiNavInput_KeyMenu, // access menu // e.g. ALT ImGuiNavInput_COUNT, }; From 6f0aa766e12160d5ae3ad2238a4c4f8cc37c0823 Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 23 Oct 2017 11:26:30 +0200 Subject: [PATCH 209/823] Nav: Added internal ImGuiNavReadMode_Released test for key releases. --- imgui.cpp | 5 ++++- imgui.h | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 8edb6915896e..92926ef56436 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2611,6 +2611,7 @@ enum ImGuiNavReadMode { ImGuiNavReadMode_Down, ImGuiNavReadMode_Pressed, + ImGuiNavReadMode_Released, ImGuiNavReadMode_Repeat, ImGuiNavReadMode_RepeatSlow, ImGuiNavReadMode_RepeatFast @@ -2625,6 +2626,8 @@ static float GetNavInputAmount(ImGuiNavInput n, ImGuiNavReadMode mode) const float t = g.IO.NavInputsDownDuration[n]; // Duration pressed if (mode == ImGuiNavReadMode_Pressed) // Return 1.0f when just pressed, no repeat, ignore analog input (we don't need it for Pressed logic) return (t == 0.0f) ? 1.0f : 0.0f; + if (mode == ImGuiNavReadMode_Released) // Return 1.0f when just release, no repeat, ignore analog input (we don't need it for Pressed logic) + return (t < 0.0f && g.IO.NavInputsDownDurationPrev[n] >= 0.0f) ? 1.0f : 0.0f; if (mode == ImGuiNavReadMode_Repeat) return (float)ImGui::CalcTypematicPressedRepeatAmount(t, t - g.IO.DeltaTime, g.IO.KeyRepeatDelay * 0.80f, g.IO.KeyRepeatRate * 0.80f); if (mode == ImGuiNavReadMode_RepeatSlow) @@ -3047,7 +3050,7 @@ void ImGui::NewFrame() memcpy(g.IO.KeysDownDurationPrev, g.IO.KeysDownDuration, sizeof(g.IO.KeysDownDuration)); for (int i = 0; i < IM_ARRAYSIZE(g.IO.KeysDown); i++) g.IO.KeysDownDuration[i] = g.IO.KeysDown[i] ? (g.IO.KeysDownDuration[i] < 0.0f ? 0.0f : g.IO.KeysDownDuration[i] + g.IO.DeltaTime) : -1.0f; - memcpy(g.IO.NavInputsPrev, g.IO.NavInputs, sizeof(g.IO.NavInputs)); + memcpy(g.IO.NavInputsDownDurationPrev, g.IO.NavInputsDownDuration, sizeof(g.IO.NavInputsDownDuration)); for (int i = 0; i < IM_ARRAYSIZE(g.IO.NavInputs); i++) g.IO.NavInputsDownDuration[i] = (g.IO.NavInputs[i] > 0.0f) ? (g.IO.NavInputsDownDuration[i] < 0.0f ? 0.0f : g.IO.NavInputsDownDuration[i] + g.IO.DeltaTime) : -1.0f; diff --git a/imgui.h b/imgui.h index 76d90e70d44d..c31fd1fffe25 100644 --- a/imgui.h +++ b/imgui.h @@ -924,7 +924,7 @@ struct ImGuiIO float KeysDownDuration[512]; // Duration the keyboard key has been down (0.0f == just pressed) float KeysDownDurationPrev[512]; // Previous duration the key has been down float NavInputsDownDuration[ImGuiNavInput_COUNT]; - float NavInputsPrev[ImGuiNavInput_COUNT]; + float NavInputsDownDurationPrev[ImGuiNavInput_COUNT]; IMGUI_API ImGuiIO(); }; From be12f8c55d1e83c8ae2cf8cb69dda750503abbc2 Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 23 Oct 2017 11:26:52 +0200 Subject: [PATCH 210/823] Nav: Fixed handling of ImGuiNavInput_KeyMenu so it doesn't set g.NavWindowingTarget at all, reducing size effects + handling menu layer toggle on Alt Release (#787) --- imgui.cpp | 37 +++++++++++++++++++++++-------------- 1 file changed, 23 insertions(+), 14 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 92926ef56436..2a7ce38c4f52 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2664,11 +2664,13 @@ static ImVec2 GetNavInputAmount2d(int stick_no, ImGuiNavReadMode mode, float slo return delta; } -// Window management mode (change focus, move/resize window, jump back and forth to menu layer) +// Window management mode (change focus, move/resize window, toggle menu layer) static void ImGui::NavUpdateWindowing() { ImGuiContext& g = *GImGui; - if (!g.NavWindowingTarget && (IsNavInputPressed(ImGuiNavInput_PadMenu, ImGuiNavReadMode_Pressed) || IsNavInputPressed(ImGuiNavInput_KeyMenu, ImGuiNavReadMode_Pressed))) + bool toggle_layer = false; + + if (!g.NavWindowingTarget && IsNavInputPressed(ImGuiNavInput_PadMenu, ImGuiNavReadMode_Pressed)) { ImGuiWindow* window = g.NavWindow; if (!window) @@ -2713,7 +2715,7 @@ static void ImGui::NavUpdateWindowing() } } - if (!IsNavInputDown(ImGuiNavInput_PadMenu) && !IsNavInputDown(ImGuiNavInput_KeyMenu)) + if (!IsNavInputDown(ImGuiNavInput_PadMenu)) { // Apply actual focus only when releasing the NavMenu button (until then the window was merely rendered front-most) if (g.NavWindowingTarget && !g.NavWindowingToggleLayer && (!g.NavWindow || g.NavWindowingTarget != g.NavWindow->RootNonPopupWindow)) @@ -2727,20 +2729,27 @@ static void ImGui::NavUpdateWindowing() // Single press toggles NavLayer if (g.NavWindowingToggleLayer && g.NavWindow) - { - if ((g.NavWindow->DC.NavLayerActiveMask & (1 << 1)) == 0 && (g.NavWindow->RootWindow->DC.NavLayerActiveMask & (1 << 1)) != 0) - FocusWindow(g.NavWindow->RootWindow); - g.NavLayer = (g.NavWindow->DC.NavLayerActiveMask & (1 << 1)) ? (g.NavLayer ^ 1) : 0; - g.NavDisableHighlight = false; - g.NavDisableMouseHover = true; - if (g.NavLayer == 0 && g.NavWindow->NavLastIds[0] != 0) - SetNavIDAndMoveMouse(g.NavWindow->NavLastIds[0], g.NavLayer, ImRect()); - else - NavInitWindow(g.NavWindow, true); - } + toggle_layer = true; g.NavWindowingTarget = NULL; } } + + // Keyboard: Press and release ALT to toggle menu + if ((g.ActiveId == 0 || g.ActiveIdAllowOverlap) && IsNavInputPressed(ImGuiNavInput_KeyMenu, ImGuiNavReadMode_Released)) + toggle_layer = true; + + if (toggle_layer && g.NavWindow) + { + if ((g.NavWindow->DC.NavLayerActiveMask & (1 << 1)) == 0 && (g.NavWindow->RootWindow->DC.NavLayerActiveMask & (1 << 1)) != 0) + FocusWindow(g.NavWindow->RootWindow); + g.NavLayer = (g.NavWindow->DC.NavLayerActiveMask & (1 << 1)) ? (g.NavLayer ^ 1) : 0; + g.NavDisableHighlight = false; + g.NavDisableMouseHover = true; + if (g.NavLayer == 0 && g.NavWindow->NavLastIds[0] != 0) + SetNavIDAndMoveMouse(g.NavWindow->NavLastIds[0], g.NavLayer, ImRect()); + else + NavInitWindow(g.NavWindow, true); + } } // NB: We modify rect_rel by the amount we scrolled for, so it is immediately updated. From 2ef2c104a166f12d1a666d8f52b202d126ffdcf7 Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 23 Oct 2017 11:36:43 +0200 Subject: [PATCH 211/823] Begin: Minor tweaks --- imgui.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 2a7ce38c4f52..4a3cb4ff8fc0 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -5332,11 +5332,11 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) // Draw window + handle manual resize ImRect title_bar_rect = window->TitleBarRect(); const float window_rounding = (flags & ImGuiWindowFlags_ChildWindow) ? style.ChildWindowRounding : style.WindowRounding; + const bool window_is_focused = g.NavWindow && window->RootNonPopupWindow == g.NavWindow->RootNonPopupWindow; if (window->Collapsed) { // Title bar only - const bool is_focused = g.NavWindow && window->RootNonPopupWindow == g.NavWindow->RootNonPopupWindow && !g.NavDisableHighlight; - RenderFrame(title_bar_rect.Min, title_bar_rect.Max, GetColorU32(is_focused ? ImGuiCol_TitleBgActive : ImGuiCol_TitleBgCollapsed), true, window_rounding); + RenderFrame(title_bar_rect.Min, title_bar_rect.Max, GetColorU32((window_is_focused && !g.NavDisableHighlight) ? ImGuiCol_TitleBgActive : ImGuiCol_TitleBgCollapsed), true, window_rounding); } else { @@ -5409,9 +5409,8 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) window->DrawList->AddRectFilled(window->Pos+ImVec2(0,window->TitleBarHeight()), window->Pos+window->Size, bg_col, window_rounding, (flags & ImGuiWindowFlags_NoTitleBar) ? ImGuiCorner_All : ImGuiCorner_BotLeft|ImGuiCorner_BotRight); // Title bar - const bool is_focused = g.NavWindow && window->RootNonPopupWindow == g.NavWindow->RootNonPopupWindow; if (!(flags & ImGuiWindowFlags_NoTitleBar)) - window->DrawList->AddRectFilled(title_bar_rect.GetTL(), title_bar_rect.GetBR(), GetColorU32(is_focused ? ImGuiCol_TitleBgActive : ImGuiCol_TitleBg), window_rounding, ImGuiCorner_TopLeft|ImGuiCorner_TopRight); + window->DrawList->AddRectFilled(title_bar_rect.GetTL(), title_bar_rect.GetBR(), GetColorU32(window_is_focused ? ImGuiCol_TitleBgActive : ImGuiCol_TitleBg), window_rounding, ImGuiCorner_TopLeft|ImGuiCorner_TopRight); // Menu bar if (flags & ImGuiWindowFlags_MenuBar) From 20983773f1f3b71ece6b04890ad2ec7f803668e0 Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 23 Oct 2017 12:38:39 +0200 Subject: [PATCH 212/823] Nav: MainMenuBar now releases focus when user gets out of the menu layer. WindowingTarget when applying focus to a window with only menus automatically sets the layer. (#787) This is enough for basic mouse/gamepad usage, but 1- previous window gets an unfocused title bar color temporarily, 2- generaly for gamepad and especially keyboard we need much more to get this done right --- imgui.cpp | 14 ++++++++++++-- imgui_internal.h | 2 +- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index d8d0ae4c8526..fd7d9447e4e7 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2726,6 +2726,10 @@ static void ImGui::NavUpdateWindowing() g.NavDisableMouseHover = true; if (g.NavWindowingTarget->NavLastIds[0] == 0) NavInitWindow(g.NavWindowingTarget, false); + + // If the window only has a menu layer, select it directly + if (g.NavWindowingTarget->DC.NavLayerActiveMask == 0x02) + g.NavLayer = 1; } // Single press toggles NavLayer @@ -4077,7 +4081,7 @@ void ImGui::CalcListClipping(int items_count, float items_height, int* out_items static ImGuiWindow* FindHoveredWindow(ImVec2 pos, bool excluding_childs) { ImGuiContext& g = *GImGui; - for (int i = g.Windows.Size-1; i >= 0; i--) + for (int i = g.Windows.Size - 1; i >= 0; i--) { ImGuiWindow* window = g.Windows[i]; if (!window->Active) @@ -5818,7 +5822,7 @@ void ImGui::FocusPreviousWindow() { ImGuiContext& g = *GImGui; for (int i = g.Windows.Size - 1; i >= 0; i--) - if (g.Windows[i]->WasActive && !(g.Windows[i]->Flags & ImGuiWindowFlags_ChildWindow)) + if (g.Windows[i] != g.NavWindow && g.Windows[i]->WasActive && !(g.Windows[i]->Flags & ImGuiWindowFlags_ChildWindow)) { FocusWindow(g.Windows[i]); return; @@ -10293,6 +10297,12 @@ bool ImGui::BeginMainMenuBar() void ImGui::EndMainMenuBar() { EndMenuBar(); + + // When the user has left the menu layer (typically: closed menus through activation of an item), we restore focus to the previous window + ImGuiContext& g = *GImGui; + if (g.CurrentWindow == g.NavWindow && g.NavLayer == 0) + FocusPreviousWindow(); + End(); PopStyleVar(2); } diff --git a/imgui_internal.h b/imgui_internal.h index 25fb04a6f298..70c2a19c03b4 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -467,7 +467,7 @@ struct ImGuiContext ImVector CurrentPopupStack; // Which level of BeginPopup() we are in (reset every frame) // Navigation data (for gamepad/keyboard) - ImGuiWindow* NavWindow; // Focused window for navigation + ImGuiWindow* NavWindow; // Focused window for navigation. Could be called 'FocusWindow' ImGuiID NavId; // Focused item for navigation ImGuiID NavActivateId; // ~~ IsNavInputPressed(ImGuiNavInput_PadActivate) ? NavId : 0, also set when calling ActivateItem() ImGuiID NavActivateDownId; // ~~ IsNavInputPressed(ImGuiNavInput_PadActivate) ? NavId : 0 From f6ff373b221b4bff34d03905d1aaca67dfa05a22 Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 23 Oct 2017 14:54:23 +0200 Subject: [PATCH 213/823] Nav: #define IMGUI_HAS_NAV to ease sharing code across branches of imgui --- imgui.h | 1 + 1 file changed, 1 insertion(+) diff --git a/imgui.h b/imgui.h index c31fd1fffe25..245a06364fc8 100644 --- a/imgui.h +++ b/imgui.h @@ -17,6 +17,7 @@ #include // memset, memmove, memcpy, strlen, strchr, strcpy, strcmp #define IMGUI_VERSION "1.52 WIP" +#define IMGUI_HAS_NAV // navigation branch // Define attributes of all API symbols declarations, e.g. for DLL under Windows. #ifndef IMGUI_API From d55b69ad6efdfebd627b4daaffe15335c4570380 Mon Sep 17 00:00:00 2001 From: omar Date: Fri, 27 Oct 2017 20:06:45 +0200 Subject: [PATCH 214/823] Styles: Nav tweaks. --- imgui_draw.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/imgui_draw.cpp b/imgui_draw.cpp index aeb7a28405bf..48319ea39671 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -220,6 +220,8 @@ void ImGui::StyleColorsDark(ImGuiStyle* dst) colors[ImGuiCol_PlotHistogramHovered] = ImVec4(1.00f, 0.60f, 0.00f, 1.00f); colors[ImGuiCol_TextSelectedBg] = ImVec4(0.26f, 0.59f, 0.98f, 0.35f); colors[ImGuiCol_ModalWindowDarkening] = ImVec4(0.80f, 0.80f, 0.80f, 0.35f); + colors[ImGuiCol_NavHighlight] = ImVec4(0.26f, 0.59f, 0.98f, 1.00f); + colors[ImGuiCol_NavWindowingHighlight] = ImVec4(1.00f, 1.00f, 1.00f, 0.12f); } //----------------------------------------------------------------------------- From b9ebb34a047c6bdfe8ccd65f764f25fc874f9cbe Mon Sep 17 00:00:00 2001 From: omar Date: Fri, 27 Oct 2017 20:54:48 +0200 Subject: [PATCH 215/823] Nav: ColorButton: Fixed a case of not using local 'hovered' flag directly, messes with some of my drag and drop work, and I can't find/understand the reason why this was left as is (there _was_ a reason at the time but it appears to be obsolete now?) --- imgui.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/imgui.cpp b/imgui.cpp index 2caee52757be..15db9ba680c3 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -10613,7 +10613,7 @@ bool ImGui::ColorButton(const char* desc_id, const ImVec4& col, ImGuiColorEditFl else window->DrawList->AddRect(bb.Min, bb.Max, GetColorU32(ImGuiCol_FrameBg), rounding); // Color button are often in need of some sort of border - if (!(flags & ImGuiColorEditFlags_NoTooltip) && IsItemHovered()) // FIXME-NAVIGATION: 'hovered' ? + if (!(flags & ImGuiColorEditFlags_NoTooltip) && hovered) ColorTooltip(desc_id, &col.x, flags & (ImGuiColorEditFlags_NoAlpha | ImGuiColorEditFlags_AlphaPreview | ImGuiColorEditFlags_AlphaPreviewHalf)); return pressed; From c5536e49efb61d786ea7f5a07031eeca34e00ec1 Mon Sep 17 00:00:00 2001 From: omar Date: Sun, 29 Oct 2017 21:15:02 +0100 Subject: [PATCH 216/823] Drag and drop API experiment --- imgui.cpp | 172 ++++++++++++++++++++++++++++++++++++++++++++++- imgui_internal.h | 53 +++++++++++++++ 2 files changed, 223 insertions(+), 2 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 0c2e72a59aad..ad4a1895fbbe 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2231,6 +2231,15 @@ void ImGui::NewFrame() if (g.ScalarAsInputTextId && g.ActiveId != g.ScalarAsInputTextId) g.ScalarAsInputTextId = 0; + // Elapse drag & drop payload + if (g.DragDropActive && g.DragDropPayload.DataFrameCount + 1 < g.FrameCount) + { + g.DragDropActive = false; + g.DragDropPayload.Clear(); + g.DragDropPayloadBufHeap.clear(); + memset(&g.DragDropPayloadBufLocal, 0, sizeof(g.DragDropPayloadBufLocal)); + } + // Update keyboard input state memcpy(g.IO.KeysDownDurationPrev, g.IO.KeysDownDuration, sizeof(g.IO.KeysDownDuration)); for (int i = 0; i < IM_ARRAYSIZE(g.IO.KeysDown); i++) @@ -5868,7 +5877,8 @@ bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool { if (hovered && (flags & ImGuiButtonFlags_PressedOnClickRelease)) if (!((flags & ImGuiButtonFlags_Repeat) && g.IO.MouseDownDurationPrev[0] >= g.IO.KeyRepeatDelay)) // Repeat mode trumps - pressed = true; + if (!g.DragDropActive) + pressed = true; ClearActiveID(); } } @@ -9426,7 +9436,7 @@ bool ImGui::ColorButton(const char* desc_id, const ImVec4& col, ImGuiColorEditFl else window->DrawList->AddRect(bb.Min, bb.Max, GetColorU32(ImGuiCol_FrameBg), rounding); // Color button are often in need of some sort of border - if (hovered && !(flags & ImGuiColorEditFlags_NoTooltip)) + if (!(flags & ImGuiColorEditFlags_NoTooltip) && hovered) ColorTooltip(desc_id, &col.x, flags & (ImGuiColorEditFlags_NoAlpha | ImGuiColorEditFlags_AlphaPreview | ImGuiColorEditFlags_AlphaPreviewHalf)); return pressed; @@ -10584,6 +10594,164 @@ void ImGui::Value(const char* prefix, float v, const char* float_format) } } +//----------------------------------------------------------------------------- +// DRAG AND DROP +//----------------------------------------------------------------------------- + +// Call when current ID is active. +// When this returns true you need to: a) call SetDragDropPayload() exactly once, b) you may render the payload visual/description, c) call EndDragDropSource() +bool ImGui::BeginDragDropSource(ImGuiDragDropFlags flags, int mouse_button) +{ + ImGuiContext& g = *GImGui; + ImGuiWindow* window = g.CurrentWindow; + if (g.IO.MouseDown[mouse_button] == false) + return false; + if (g.ActiveId != window->DC.LastItemId) + return false; + + if (IsMouseDragging(mouse_button)) + { + if (!g.DragDropActive) + { + ImGuiPayload& payload = g.DragDropPayload; + payload.Clear(); + payload.SourceId = g.ActiveId; + payload.SourceParentId = window->IDStack.back(); + g.DragDropActive = true; + g.DragDropSourceFlags = flags; + g.DragDropMouseButton = mouse_button; + } + + if (!(flags & ImGuiDragDropFlags_SourceNoAutoTooltip)) + { + // FIXME-DRAG + //SetNextWindowPos(g.IO.MousePos - g.ActiveIdClickOffset - g.Style.WindowPadding); + //PushStyleVar(ImGuiStyleVar_Alpha, g.Style.Alpha * 0.60f); // This is better but e.g ColorButton with checkboard has issue with transparent colors :( + SetNextWindowPos(g.IO.MousePos); + PushStyleColor(ImGuiCol_PopupBg, GetStyleColorVec4(ImGuiCol_PopupBg) * ImVec4(1.0f, 1.0f, 1.0f, 0.6f)); + BeginTooltipEx(ImGuiWindowFlags_NoInputs | ImGuiWindowFlags_ShowBorders); + } + return true; + } + return false; +} + +void ImGui::EndDragDropSource() +{ + ImGuiContext& g = *GImGui; + IM_ASSERT(g.DragDropActive); + IM_ASSERT(g.DragDropPayload.DataFrameCount != -1); // Forgot to call SetDragDropSourcePayload(), at least once on the first frame of a successful BeginDragDropSource() + + if (!(g.DragDropSourceFlags & ImGuiDragDropFlags_SourceNoAutoTooltip)) + { + EndTooltip(); + PopStyleColor(); + //PopStyleVar(); + } +} + +// Use 'cond' to choose to submit paypload on drag start or every frame +bool ImGui::SetDragDropPayload(const char* type, const void* data, size_t data_size, ImGuiCond cond) +{ + ImGuiContext& g = *GImGui; + ImGuiPayload& payload = g.DragDropPayload; + if (cond == 0) + cond = ImGuiCond_Always; + + IM_ASSERT(type != NULL); + IM_ASSERT(strlen(type) < IM_ARRAYSIZE(payload.DataType)); // Payload type can be at most 8 characters longs + IM_ASSERT(data != NULL && data_size > 0); + IM_ASSERT(cond == ImGuiCond_Always || cond == ImGuiCond_Once); + IM_ASSERT(payload.SourceId != 0); // Not called between BeginDragDropSource() and EndDragDropSource() + + if (cond == ImGuiCond_Always || payload.DataFrameCount == -1) + { + // Copy payload + ImStrncpy(payload.DataType, type, IM_ARRAYSIZE(payload.DataType)); + g.DragDropPayloadBufHeap.resize(0); + if (data_size > sizeof(g.DragDropPayloadBufLocal)) + { + // Store in heap + g.DragDropPayloadBufHeap.resize((int)data_size); + payload.Data = g.DragDropPayloadBufHeap.Data; + memcpy((void*)payload.Data, data, data_size); + } + else if (data_size > 0) + { + // Store locally + memset(&g.DragDropPayloadBufLocal, 0, sizeof(g.DragDropPayloadBufLocal)); + payload.Data = g.DragDropPayloadBufLocal; + memcpy((void*)payload.Data, data, data_size); + } + else + { + payload.Data = NULL; + } + payload.DataSize = (int)data_size; + } + payload.DataFrameCount = g.FrameCount; + + return (payload.AcceptFrameCount == g.FrameCount) || (payload.AcceptFrameCount == g.FrameCount - 1); +} + +bool ImGui::BeginDragDropTarget() +{ + ImGuiContext& g = *GImGui; + if (!g.DragDropActive) + return false; + + ImGuiWindow* window = g.CurrentWindow; + //if (!window->DC.LastItemRectHoveredRect || (g.ActiveId == g.DragDropPayload.SourceId || g.ActiveIdPreviousFrame == g.DragDropPayload.SourceId)) + if (!window->DC.LastItemRectHoveredRect || (window->DC.LastItemId && window->DC.LastItemId == g.DragDropPayload.SourceId)) + return false; + if (window->RootWindow != g.HoveredWindow->RootWindow) + return false; + + return true; +} + +const ImGuiPayload* ImGui::AcceptDragDropPayload(const char* type, ImGuiDragDropFlags flags) +{ + ImGuiContext& g = *GImGui; + ImGuiWindow* window = g.CurrentWindow; + ImGuiPayload& payload = g.DragDropPayload; + IM_ASSERT(g.DragDropActive); // Not called between BeginDragDropTarget() and EndDragDropTarget() ? + IM_ASSERT(window->DC.LastItemRectHoveredRect); // Not called between BeginDragDropTarget() and EndDragDropTarget() ? + IM_ASSERT(payload.DataFrameCount != -1); // Internal/usage error, please report! + if (type != NULL && !payload.IsDataType(type)) + return NULL; + + if (payload.AcceptId == 0) + payload.AcceptId = window->DC.LastItemId; + + bool was_accepted_previously = (payload.AcceptFrameCount == g.FrameCount - 1); + if (payload.AcceptFrameCount != g.FrameCount) + { + // Render drop visuals + if (!(flags & ImGuiDragDropFlags_AcceptNoDrawDefaultRect) && was_accepted_previously) + { + ImRect r = window->DC.LastItemRect; + r.Expand(4.0f); + window->DrawList->AddRectFilled(r.Min, r.Max, IM_COL32(255, 255, 0, 20), 0.0f); // FIXME-DRAG FIXME-STYLE + window->DrawList->AddRect(r.Min, r.Max, IM_COL32(255, 255, 0, 255), 0.0f, ~0, 2.0f); // FIXME-DRAG FIXME-STYLE + } + payload.AcceptFrameCount = g.FrameCount; + } + + payload.Delivery = was_accepted_previously && IsMouseReleased(g.DragDropMouseButton); + if (!payload.Delivery && !(flags & ImGuiDragDropFlags_AcceptBeforeDelivery)) + return NULL; + + return &payload; +} + +// We don't really use/need this now, but added it for the sake of consistency and because we might need it later. +void ImGui::EndDragDropTarget() +{ + ImGuiContext& g = *GImGui; + IM_ASSERT(g.DragDropActive); +} + //----------------------------------------------------------------------------- // PLATFORM DEPENDENT HELPERS //----------------------------------------------------------------------------- diff --git a/imgui_internal.h b/imgui_internal.h index 1cb723ca7f7d..5c82ea1d8ad2 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -43,9 +43,11 @@ struct ImGuiIniData; struct ImGuiMouseCursorData; struct ImGuiPopupRef; struct ImGuiWindow; +struct ImGuiPayload; // User data payload for drag and drop operations typedef int ImGuiLayoutType; // enum: horizontal or vertical // enum ImGuiLayoutType_ typedef int ImGuiButtonFlags; // flags: for ButtonEx(), ButtonBehavior() // enum ImGuiButtonFlags_ +typedef int ImGuiDragDropFlags; // flags: for *DragDrop*() // enum ImGuiDragDropFlags_ typedef int ImGuiItemFlags; // flags: for PushItemFlag() // enum ImGuiItemFlags_ typedef int ImGuiSeparatorFlags; // flags: for Separator() - internal // enum ImGuiSeparatorFlags_ typedef int ImGuiSliderFlags; // flags: for SliderBehavior() // enum ImGuiSliderFlags_ @@ -215,6 +217,15 @@ enum ImGuiSeparatorFlags_ ImGuiSeparatorFlags_Vertical = 1 << 1 }; +// Flags for ImGui::BeginDragDropSource(), ImGui::AcceptDragDropPayload() +enum ImGuiDragDropFlags_ +{ + ImGuiDragDropFlags_SourceNoAutoTooltip = 1 << 0, + ImGuiDragDropFlags_AcceptBeforeDelivery = 1 << 1, // AcceptDragDropPayload() returns true even before the mouse button is released. You can then call IsDelivery() to test if the payload needs to be delivered. + ImGuiDragDropFlags_AcceptNoDrawDefaultRect = 1 << 2, // Do not draw the default highlight rectangle when hovering over target. + ImGuiDragDropFlags_AcceptPeekOnly = ImGuiDragDropFlags_AcceptBeforeDelivery | ImGuiDragDropFlags_AcceptNoDrawDefaultRect // For peeking ahead and inspecting the payload before delivery. +}; + // FIXME: this is in development, not exposed/functional as a generic feature yet. enum ImGuiLayoutType_ { @@ -404,6 +415,28 @@ struct ImGuiPopupRef ImGuiPopupRef(ImGuiID id, ImGuiWindow* parent_window, ImGuiID parent_menu_set, const ImVec2& mouse_pos) { PopupId = id; Window = NULL; ParentWindow = parent_window; ParentMenuSet = parent_menu_set; MousePosOnOpen = mouse_pos; } }; +// Data payload for Drag and Drop operations +struct ImGuiPayload +{ + // Members + const void* Data; // Data (copied and owned by dear imgui) + int DataSize; // Data size + + // [Internal] + ImGuiID SourceId; // Source item id + ImGuiID SourceParentId; // Source parent id (if available) + ImGuiID AcceptId; // Target item id (set at the time of accepting the payload) + int AcceptFrameCount; // Last time a target expressed a desire to accept the source + int DataFrameCount; // Data timestamp + char DataType[8 + 1]; // Data type tag (short user-supplied string) + bool Delivery; // Set when AcceptDragDropPayload() was called and the mouse button is released over the target item + + ImGuiPayload() { Clear(); } + void Clear() { SourceId = SourceParentId = AcceptId = 0; AcceptFrameCount = -1; Data = NULL; DataSize = 0; memset(DataType, 0, sizeof(DataType)); DataFrameCount = -1; Delivery = false; } + bool IsDataType(const char* type) const { return DataFrameCount != -1 && strcmp(type, DataType) == 0; } + bool IsDelivery() const { return Delivery; } +}; + // Main state for ImGui struct ImGuiContext { @@ -472,6 +505,14 @@ struct ImGuiContext ImGuiMouseCursor MouseCursor; ImGuiMouseCursorData MouseCursorData[ImGuiMouseCursor_Count_]; + // Drag and Drop + bool DragDropActive; + ImGuiDragDropFlags DragDropSourceFlags; + int DragDropMouseButton; + ImGuiPayload DragDropPayload; + ImVector DragDropPayloadBufHeap; // We don't expose the ImVector<> directly + unsigned char DragDropPayloadBufLocal[8]; + // Widget state ImGuiTextEditState InputTextState; ImFont InputTextPasswordFont; @@ -547,6 +588,10 @@ struct ImGuiContext SetNextTreeNodeOpenVal = false; SetNextTreeNodeOpenCond = 0; + DragDropActive = false; + DragDropSourceFlags = 0; + DragDropMouseButton = -1; + ScalarAsInputTextId = 0; ColorEditOptions = ImGuiColorEditFlags__OptionsDefault; DragCurrentValue = 0.0f; @@ -810,6 +855,14 @@ namespace ImGui IMGUI_API void Scrollbar(ImGuiLayoutType direction); IMGUI_API void VerticalSeparator(); // Vertical separator, for menu bars (use current line height). not exposed because it is misleading what it doesn't have an effect on regular layout. + // FIXME-WIP: New Drag and Drop API + IMGUI_API bool BeginDragDropSource(ImGuiDragDropFlags flags = 0, int mouse_button = 0); // Call when the current item is active. If this return true, you can call SetDragDropPayload() + EndDragDropSource() + IMGUI_API bool SetDragDropPayload(const char* type, const void* data, size_t data_size, ImGuiCond cond = 0); // Type is a user defined string of maximum 8 characters. Strings starting with '_' are reserved for dear imgui internal types. Data is copied and held by imgui. + IMGUI_API void EndDragDropSource(); + IMGUI_API bool BeginDragDropTarget(); // Call after submitting an item that may receive an item. If this returns true, you can call AcceptDragDropPayload() + EndDragDropTarget() + IMGUI_API const ImGuiPayload* AcceptDragDropPayload(const char* type, ImGuiDragDropFlags flags = 0); // Accept contents of a given type. If ImGuiDragDropFlags_AcceptBeforeDelivery is set you can peek into the payload before the mouse button is released. + IMGUI_API void EndDragDropTarget(); + // FIXME-WIP: New Columns API IMGUI_API void BeginColumns(const char* id, int count, ImGuiColumnsFlags flags = 0); // setup number of columns. use an identifier to distinguish multiple column sets. close with EndColumns(). IMGUI_API void EndColumns(); // close columns From b5f714e9f9d222f8e10ef641b2dabbcbf76fcfed Mon Sep 17 00:00:00 2001 From: omar Date: Sun, 29 Oct 2017 21:31:49 +0100 Subject: [PATCH 217/823] Drag and Drop: made BeginDragDropSource() clear the IsItemHovered() by default, added a flag to keep it. --- imgui.cpp | 4 ++++ imgui_internal.h | 7 +++++-- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index ad4a1895fbbe..b11a28d73981 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -10631,6 +10631,10 @@ bool ImGui::BeginDragDropSource(ImGuiDragDropFlags flags, int mouse_button) PushStyleColor(ImGuiCol_PopupBg, GetStyleColorVec4(ImGuiCol_PopupBg) * ImVec4(1.0f, 1.0f, 1.0f, 0.6f)); BeginTooltipEx(ImGuiWindowFlags_NoInputs | ImGuiWindowFlags_ShowBorders); } + + if (!(flags & ImGuiDragDropFlags_SourceNoDisableHover)) + window->DC.LastItemRectHoveredRect = false; + return true; } return false; diff --git a/imgui_internal.h b/imgui_internal.h index 5c82ea1d8ad2..d8dfca1cc2a8 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -220,9 +220,12 @@ enum ImGuiSeparatorFlags_ // Flags for ImGui::BeginDragDropSource(), ImGui::AcceptDragDropPayload() enum ImGuiDragDropFlags_ { + // BeginDragDropSource() flags ImGuiDragDropFlags_SourceNoAutoTooltip = 1 << 0, - ImGuiDragDropFlags_AcceptBeforeDelivery = 1 << 1, // AcceptDragDropPayload() returns true even before the mouse button is released. You can then call IsDelivery() to test if the payload needs to be delivered. - ImGuiDragDropFlags_AcceptNoDrawDefaultRect = 1 << 2, // Do not draw the default highlight rectangle when hovering over target. + ImGuiDragDropFlags_SourceNoDisableHover = 1 << 1, // By default, when dragging we clear data so that IsItemHovered() will return true, to avoid subsequent user code submitting tooltips. + // BeginDragDropTarget() flags + ImGuiDragDropFlags_AcceptBeforeDelivery = 1 << 10, // AcceptDragDropPayload() returns true even before the mouse button is released. You can then call IsDelivery() to test if the payload needs to be delivered. + ImGuiDragDropFlags_AcceptNoDrawDefaultRect = 1 << 11, // Do not draw the default highlight rectangle when hovering over target. ImGuiDragDropFlags_AcceptPeekOnly = ImGuiDragDropFlags_AcceptBeforeDelivery | ImGuiDragDropFlags_AcceptNoDrawDefaultRect // For peeking ahead and inspecting the payload before delivery. }; From acf78da74288ba03875d387f502f8faf05ec6b76 Mon Sep 17 00:00:00 2001 From: omar Date: Sun, 29 Oct 2017 21:37:14 +0100 Subject: [PATCH 218/823] Drag and drop: moved to imgui.h --- imgui.h | 44 ++++++++++++++++++++++++++++++++++++++++++++ imgui_internal.h | 45 +-------------------------------------------- 2 files changed, 45 insertions(+), 44 deletions(-) diff --git a/imgui.h b/imgui.h index 995b39801ddf..7f1baa9c8b84 100644 --- a/imgui.h +++ b/imgui.h @@ -64,6 +64,7 @@ struct ImGuiTextBuffer; // Text buffer for logging/accumulating text struct ImGuiTextEditCallbackData; // Shared state of ImGui::InputText() when using custom ImGuiTextEditCallback (rare/advanced use) struct ImGuiSizeConstraintCallbackData;// Structure used to constraint window size in custom ways when using custom ImGuiSizeConstraintCallback (rare/advanced use) struct ImGuiListClipper; // Helper to manually clip large list of items +struct ImGuiPayload; // User data payload for drag and drop operations struct ImGuiContext; // ImGui context (opaque) // Typedefs and Enumerations (declared as int for compatibility and to not pollute the top of this file) @@ -77,6 +78,7 @@ typedef int ImGuiKey; // enum: a key identifier (ImGui-side enum) typedef int ImGuiMouseCursor; // enum: a mouse cursor identifier // enum ImGuiMouseCursor_ typedef int ImGuiCond; // enum: a condition for Set*() // enum ImGuiCond_ typedef int ImGuiColorEditFlags; // flags: color edit flags for Color*() // enum ImGuiColorEditFlags_ +typedef int ImGuiDragDropFlags; // flags: for *DragDrop*() // enum ImGuiDragDropFlags_ typedef int ImGuiWindowFlags; // flags: window flags for Begin*() // enum ImGuiWindowFlags_ typedef int ImGuiColumnsFlags; // flags: for *Columns*() // enum ImGuiColumnsFlags_ typedef int ImGuiInputTextFlags; // flags: for InputText*() // enum ImGuiInputTextFlags_ @@ -410,6 +412,14 @@ namespace ImGui IMGUI_API void LogButtons(); // helper to display buttons for logging to tty/file/clipboard IMGUI_API void LogText(const char* fmt, ...) IM_FMTARGS(1); // pass text data straight to log (without being displayed) + // Drag and Drop + IMGUI_API bool BeginDragDropSource(ImGuiDragDropFlags flags = 0, int mouse_button = 0); // Call when the current item is active. If this return true, you can call SetDragDropPayload() + EndDragDropSource() + IMGUI_API bool SetDragDropPayload(const char* type, const void* data, size_t data_size, ImGuiCond cond = 0); // Type is a user defined string of maximum 8 characters. Strings starting with '_' are reserved for dear imgui internal types. Data is copied and held by imgui. + IMGUI_API void EndDragDropSource(); + IMGUI_API bool BeginDragDropTarget(); // Call after submitting an item that may receive an item. If this returns true, you can call AcceptDragDropPayload() + EndDragDropTarget() + IMGUI_API const ImGuiPayload* AcceptDragDropPayload(const char* type, ImGuiDragDropFlags flags = 0); // Accept contents of a given type. If ImGuiDragDropFlags_AcceptBeforeDelivery is set you can peek into the payload before the mouse button is released. + IMGUI_API void EndDragDropTarget(); + // Clipping IMGUI_API void PushClipRect(const ImVec2& clip_rect_min, const ImVec2& clip_rect_max, bool intersect_with_current_clip_rect); IMGUI_API void PopClipRect(); @@ -583,6 +593,18 @@ enum ImGuiHoveredFlags_ ImGuiHoveredFlags_RectOnly = ImGuiHoveredFlags_AllowWhenBlockedByPopup | ImGuiHoveredFlags_AllowWhenBlockedByActiveItem | ImGuiHoveredFlags_AllowWhenOverlapped }; +// Flags for ImGui::BeginDragDropSource(), ImGui::AcceptDragDropPayload() +enum ImGuiDragDropFlags_ +{ + // BeginDragDropSource() flags + ImGuiDragDropFlags_SourceNoAutoTooltip = 1 << 0, + ImGuiDragDropFlags_SourceNoDisableHover = 1 << 1, // By default, when dragging we clear data so that IsItemHovered() will return true, to avoid subsequent user code submitting tooltips. + // BeginDragDropTarget() flags + ImGuiDragDropFlags_AcceptBeforeDelivery = 1 << 10, // AcceptDragDropPayload() returns true even before the mouse button is released. You can then call IsDelivery() to test if the payload needs to be delivered. + ImGuiDragDropFlags_AcceptNoDrawDefaultRect = 1 << 11, // Do not draw the default highlight rectangle when hovering over target. + ImGuiDragDropFlags_AcceptPeekOnly = ImGuiDragDropFlags_AcceptBeforeDelivery | ImGuiDragDropFlags_AcceptNoDrawDefaultRect // For peeking ahead and inspecting the payload before delivery. +}; + // User fill ImGuiIO.KeyMap[] array with indices into the ImGuiIO.KeysDown[512] array enum ImGuiKey_ { @@ -1118,6 +1140,28 @@ struct ImGuiSizeConstraintCallbackData ImVec2 DesiredSize; // Read-write. Desired size, based on user's mouse position. Write to this field to restrain resizing. }; +// Data payload for Drag and Drop operations +struct ImGuiPayload +{ + // Members + const void* Data; // Data (copied and owned by dear imgui) + int DataSize; // Data size + + // [Internal] + ImGuiID SourceId; // Source item id + ImGuiID SourceParentId; // Source parent id (if available) + ImGuiID AcceptId; // Target item id (set at the time of accepting the payload) + int AcceptFrameCount; // Last time a target expressed a desire to accept the source + int DataFrameCount; // Data timestamp + char DataType[8 + 1]; // Data type tag (short user-supplied string) + bool Delivery; // Set when AcceptDragDropPayload() was called and the mouse button is released over the target item + + ImGuiPayload() { Clear(); } + void Clear() { SourceId = SourceParentId = AcceptId = 0; AcceptFrameCount = -1; Data = NULL; DataSize = 0; memset(DataType, 0, sizeof(DataType)); DataFrameCount = -1; Delivery = false; } + bool IsDataType(const char* type) const { return DataFrameCount != -1 && strcmp(type, DataType) == 0; } + bool IsDelivery() const { return Delivery; } +}; + // Helpers macros to generate 32-bits encoded colors #ifdef IMGUI_USE_BGRA_PACKED_COLOR #define IM_COL32_R_SHIFT 16 diff --git a/imgui_internal.h b/imgui_internal.h index d8dfca1cc2a8..666b4491ab2e 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -43,11 +43,9 @@ struct ImGuiIniData; struct ImGuiMouseCursorData; struct ImGuiPopupRef; struct ImGuiWindow; -struct ImGuiPayload; // User data payload for drag and drop operations typedef int ImGuiLayoutType; // enum: horizontal or vertical // enum ImGuiLayoutType_ typedef int ImGuiButtonFlags; // flags: for ButtonEx(), ButtonBehavior() // enum ImGuiButtonFlags_ -typedef int ImGuiDragDropFlags; // flags: for *DragDrop*() // enum ImGuiDragDropFlags_ typedef int ImGuiItemFlags; // flags: for PushItemFlag() // enum ImGuiItemFlags_ typedef int ImGuiSeparatorFlags; // flags: for Separator() - internal // enum ImGuiSeparatorFlags_ typedef int ImGuiSliderFlags; // flags: for SliderBehavior() // enum ImGuiSliderFlags_ @@ -217,18 +215,6 @@ enum ImGuiSeparatorFlags_ ImGuiSeparatorFlags_Vertical = 1 << 1 }; -// Flags for ImGui::BeginDragDropSource(), ImGui::AcceptDragDropPayload() -enum ImGuiDragDropFlags_ -{ - // BeginDragDropSource() flags - ImGuiDragDropFlags_SourceNoAutoTooltip = 1 << 0, - ImGuiDragDropFlags_SourceNoDisableHover = 1 << 1, // By default, when dragging we clear data so that IsItemHovered() will return true, to avoid subsequent user code submitting tooltips. - // BeginDragDropTarget() flags - ImGuiDragDropFlags_AcceptBeforeDelivery = 1 << 10, // AcceptDragDropPayload() returns true even before the mouse button is released. You can then call IsDelivery() to test if the payload needs to be delivered. - ImGuiDragDropFlags_AcceptNoDrawDefaultRect = 1 << 11, // Do not draw the default highlight rectangle when hovering over target. - ImGuiDragDropFlags_AcceptPeekOnly = ImGuiDragDropFlags_AcceptBeforeDelivery | ImGuiDragDropFlags_AcceptNoDrawDefaultRect // For peeking ahead and inspecting the payload before delivery. -}; - // FIXME: this is in development, not exposed/functional as a generic feature yet. enum ImGuiLayoutType_ { @@ -418,28 +404,6 @@ struct ImGuiPopupRef ImGuiPopupRef(ImGuiID id, ImGuiWindow* parent_window, ImGuiID parent_menu_set, const ImVec2& mouse_pos) { PopupId = id; Window = NULL; ParentWindow = parent_window; ParentMenuSet = parent_menu_set; MousePosOnOpen = mouse_pos; } }; -// Data payload for Drag and Drop operations -struct ImGuiPayload -{ - // Members - const void* Data; // Data (copied and owned by dear imgui) - int DataSize; // Data size - - // [Internal] - ImGuiID SourceId; // Source item id - ImGuiID SourceParentId; // Source parent id (if available) - ImGuiID AcceptId; // Target item id (set at the time of accepting the payload) - int AcceptFrameCount; // Last time a target expressed a desire to accept the source - int DataFrameCount; // Data timestamp - char DataType[8 + 1]; // Data type tag (short user-supplied string) - bool Delivery; // Set when AcceptDragDropPayload() was called and the mouse button is released over the target item - - ImGuiPayload() { Clear(); } - void Clear() { SourceId = SourceParentId = AcceptId = 0; AcceptFrameCount = -1; Data = NULL; DataSize = 0; memset(DataType, 0, sizeof(DataType)); DataFrameCount = -1; Delivery = false; } - bool IsDataType(const char* type) const { return DataFrameCount != -1 && strcmp(type, DataType) == 0; } - bool IsDelivery() const { return Delivery; } -}; - // Main state for ImGui struct ImGuiContext { @@ -594,6 +558,7 @@ struct ImGuiContext DragDropActive = false; DragDropSourceFlags = 0; DragDropMouseButton = -1; + memset(DragDropPayloadBufLocal, 0, sizeof(DragDropPayloadBufLocal)); ScalarAsInputTextId = 0; ColorEditOptions = ImGuiColorEditFlags__OptionsDefault; @@ -858,14 +823,6 @@ namespace ImGui IMGUI_API void Scrollbar(ImGuiLayoutType direction); IMGUI_API void VerticalSeparator(); // Vertical separator, for menu bars (use current line height). not exposed because it is misleading what it doesn't have an effect on regular layout. - // FIXME-WIP: New Drag and Drop API - IMGUI_API bool BeginDragDropSource(ImGuiDragDropFlags flags = 0, int mouse_button = 0); // Call when the current item is active. If this return true, you can call SetDragDropPayload() + EndDragDropSource() - IMGUI_API bool SetDragDropPayload(const char* type, const void* data, size_t data_size, ImGuiCond cond = 0); // Type is a user defined string of maximum 8 characters. Strings starting with '_' are reserved for dear imgui internal types. Data is copied and held by imgui. - IMGUI_API void EndDragDropSource(); - IMGUI_API bool BeginDragDropTarget(); // Call after submitting an item that may receive an item. If this returns true, you can call AcceptDragDropPayload() + EndDragDropTarget() - IMGUI_API const ImGuiPayload* AcceptDragDropPayload(const char* type, ImGuiDragDropFlags flags = 0); // Accept contents of a given type. If ImGuiDragDropFlags_AcceptBeforeDelivery is set you can peek into the payload before the mouse button is released. - IMGUI_API void EndDragDropTarget(); - // FIXME-WIP: New Columns API IMGUI_API void BeginColumns(const char* id, int count, ImGuiColumnsFlags flags = 0); // setup number of columns. use an identifier to distinguish multiple column sets. close with EndColumns(). IMGUI_API void EndColumns(); // close columns From 0e775807b4be21405817df60c53889ab0a1ce230 Mon Sep 17 00:00:00 2001 From: omar Date: Sun, 29 Oct 2017 23:10:44 +0100 Subject: [PATCH 219/823] Drag and Drop: Added a mechanism to allow widgets with no identifiers (such as Text/Image) to be used with BeginDragDropSource() given the explicit ImGuiDragDropFlags_SourceAllowNullID flag. --- imgui.cpp | 46 ++++++++++++++++++++++++++++++++++++++++++++-- imgui.h | 1 + imgui_internal.h | 1 + 3 files changed, 46 insertions(+), 2 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index b11a28d73981..de89f4f69894 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1860,6 +1860,16 @@ ImGuiID ImGuiWindow::GetIDNoKeepAlive(const char* str, const char* str_end) return ImHash(str, str_end ? (int)(str_end - str) : 0, seed); } +// This is particularly dodgy and used in extremely rare situation. +ImGuiID ImGuiWindow::GetIDFromRectangle(const ImRect& r_abs) +{ + ImGuiID seed = IDStack.back(); + const int r_rel[4] = { (int)(r_abs.Min.x - Pos.x), (int)(r_abs.Min.y - Pos.y), (int)(r_abs.Max.x - Pos.x), (int)(r_abs.Max.y - Pos.y) }; + ImGuiID id = ImHash(&r_rel, sizeof(r_rel), seed); + ImGui::KeepAliveID(id); + return id; +} + //----------------------------------------------------------------------------- // Internal API exposed in imgui_internal.h //----------------------------------------------------------------------------- @@ -10606,16 +10616,48 @@ bool ImGui::BeginDragDropSource(ImGuiDragDropFlags flags, int mouse_button) ImGuiWindow* window = g.CurrentWindow; if (g.IO.MouseDown[mouse_button] == false) return false; - if (g.ActiveId != window->DC.LastItemId) + + ImGuiID id = window->DC.LastItemId; + if (id == 0) + { + // If you want to use BeginDragDropSource() on an item with no unique identifier for interaction, such as Text() or Image(), you need to: + // A) Read the explanation below, B) Use the ImGuiDragDropFlags_SourceAllowNullID flag, C) Swallow your programmer pride. + if (!(flags & ImGuiDragDropFlags_SourceAllowNullID)) + { + IM_ASSERT(0); + return false; + } + + // Magic fallback (=somehow reprehensible) to handle items with no assigned ID, e.g. Text(), Image(). + // We build a throwaway ID based on current ID stack + relative AABB of items in window. + // THE IDENTIFIER WON'T SURVIVE ANY REPOSITIONING OF THE WIDGET, so if your widget moves your dragging operation will be canceled. + // If you want fail-proof dragging, + // We don't need to maintain/call ClearActiveID() as releasing the button will early out this function and trigger !ActiveIdIsAlive. + bool is_hovered = window->DC.LastItemRectHoveredRect; + if (!is_hovered && (g.ActiveId == 0 || g.ActiveIdWindow != window)) + return false; + id = window->DC.LastItemId = window->GetIDFromRectangle(window->DC.LastItemRect); + if (is_hovered) + SetHoveredID(id); + if (is_hovered && g.IO.MouseClicked[mouse_button]) + { + SetActiveID(id, window); + FocusWindow(window); + } + if (g.ActiveId == id) // Allow the underlying widget to display/return hovered during the mouse release frame, else we would get a flicker. + g.ActiveIdAllowOverlap = is_hovered; + } + if (g.ActiveId != id) return false; if (IsMouseDragging(mouse_button)) { if (!g.DragDropActive) { + IM_ASSERT(id != 0); ImGuiPayload& payload = g.DragDropPayload; payload.Clear(); - payload.SourceId = g.ActiveId; + payload.SourceId = id; payload.SourceParentId = window->IDStack.back(); g.DragDropActive = true; g.DragDropSourceFlags = flags; diff --git a/imgui.h b/imgui.h index 7f1baa9c8b84..25a9c5a6c87b 100644 --- a/imgui.h +++ b/imgui.h @@ -599,6 +599,7 @@ enum ImGuiDragDropFlags_ // BeginDragDropSource() flags ImGuiDragDropFlags_SourceNoAutoTooltip = 1 << 0, ImGuiDragDropFlags_SourceNoDisableHover = 1 << 1, // By default, when dragging we clear data so that IsItemHovered() will return true, to avoid subsequent user code submitting tooltips. + ImGuiDragDropFlags_SourceAllowNullID = 1 << 2, // Allow items such as Text(), Image() that have no unique identifier to be used as drag source, by manufacturing a temporary identifier based on their window-relative position. This is extremely unusual within the dear imgui ecosystem and so we made it explicit. // BeginDragDropTarget() flags ImGuiDragDropFlags_AcceptBeforeDelivery = 1 << 10, // AcceptDragDropPayload() returns true even before the mouse button is released. You can then call IsDelivery() to test if the payload needs to be delivered. ImGuiDragDropFlags_AcceptNoDrawDefaultRect = 1 << 11, // Do not draw the default highlight rectangle when hovering over target. diff --git a/imgui_internal.h b/imgui_internal.h index 666b4491ab2e..dafb3aef8014 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -754,6 +754,7 @@ struct IMGUI_API ImGuiWindow ImGuiID GetID(const char* str, const char* str_end = NULL); ImGuiID GetID(const void* ptr); ImGuiID GetIDNoKeepAlive(const char* str, const char* str_end = NULL); + ImGuiID GetIDFromRectangle(const ImRect& r_abs); ImRect Rect() const { return ImRect(Pos.x, Pos.y, Pos.x+Size.x, Pos.y+Size.y); } float CalcFontSize() const { return GImGui->FontBaseSize * FontWindowScale; } From d46772b429df1a157b4c2d4ebc11509d3d726cac Mon Sep 17 00:00:00 2001 From: omar Date: Sun, 29 Oct 2017 23:14:17 +0100 Subject: [PATCH 220/823] Comments --- imgui.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index de89f4f69894..709ebdff16ab 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1860,7 +1860,7 @@ ImGuiID ImGuiWindow::GetIDNoKeepAlive(const char* str, const char* str_end) return ImHash(str, str_end ? (int)(str_end - str) : 0, seed); } -// This is particularly dodgy and used in extremely rare situation. +// This is only used in rare/specific situations to manufacture an ID out of nowhere. ImGuiID ImGuiWindow::GetIDFromRectangle(const ImRect& r_abs) { ImGuiID seed = IDStack.back(); @@ -10628,10 +10628,9 @@ bool ImGui::BeginDragDropSource(ImGuiDragDropFlags flags, int mouse_button) return false; } - // Magic fallback (=somehow reprehensible) to handle items with no assigned ID, e.g. Text(), Image(). + // Magic fallback (=somehow reprehensible) to handle items with no assigned ID, e.g. Text(), Image() // We build a throwaway ID based on current ID stack + relative AABB of items in window. // THE IDENTIFIER WON'T SURVIVE ANY REPOSITIONING OF THE WIDGET, so if your widget moves your dragging operation will be canceled. - // If you want fail-proof dragging, // We don't need to maintain/call ClearActiveID() as releasing the button will early out this function and trigger !ActiveIdIsAlive. bool is_hovered = window->DC.LastItemRectHoveredRect; if (!is_hovered && (g.ActiveId == 0 || g.ActiveIdWindow != window)) From a81061955568973e72ebea5d7a3f7035368bd50c Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 30 Oct 2017 00:03:04 +0100 Subject: [PATCH 221/823] Drag and Drop: Added support for drag and drop hold-long-to-open for CollapsingHeader() and TreeNode(). Open only! --- imgui.cpp | 13 +++++++++++++ imgui_internal.h | 3 ++- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/imgui.cpp b/imgui.cpp index 8e7225fc8758..383b012eb5b3 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -5841,6 +5841,16 @@ bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool bool pressed = false; bool hovered = ItemHoverable(bb, id); + // Special mode for Drag and Drop where holding button pressed for a long time while dragging another item triggers the button + if ((flags & ImGuiButtonFlags_PressedOnDragDropHold) && g.DragDropActive && !hovered) + if (IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByActiveItem)) + { + hovered = true; + SetHoveredID(id); + if (CalcTypematicPressedRepeatAmount(g.HoveredIdTimer + 0.0001f, g.HoveredIdTimer + 0.0001f - g.IO.DeltaTime, 0.01f, 0.70f)) // FIXME: Our formula for CalcTypematicPressedRepeatAmount() is fishy + pressed = true; + } + if ((flags & ImGuiButtonFlags_FlattenChilds) && g.HoveredRootWindow == window) g.HoveredWindow = backup_hovered_window; @@ -6271,6 +6281,7 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l // - OpenOnArrow .................... single-click on arrow to open // - OpenOnDoubleClick|OpenOnArrow .. single-click on arrow or double-click anywhere to open ImGuiButtonFlags button_flags = ImGuiButtonFlags_NoKeyModifiers | ((flags & ImGuiTreeNodeFlags_AllowOverlapMode) ? ImGuiButtonFlags_AllowOverlapMode : 0); + button_flags |= ImGuiButtonFlags_PressedOnDragDropHold; if (flags & ImGuiTreeNodeFlags_OpenOnDoubleClick) button_flags |= ImGuiButtonFlags_PressedOnDoubleClick | ((flags & ImGuiTreeNodeFlags_OpenOnArrow) ? ImGuiButtonFlags_PressedOnClickRelease : 0); bool hovered, held, pressed = ButtonBehavior(interact_bb, id, &hovered, &held, button_flags); @@ -6281,6 +6292,8 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l toggled |= IsMouseHoveringRect(interact_bb.Min, ImVec2(interact_bb.Min.x + text_offset_x, interact_bb.Max.y)); if (flags & ImGuiTreeNodeFlags_OpenOnDoubleClick) toggled |= g.IO.MouseDoubleClicked[0]; + if (g.DragDropActive && is_open) // We don't nodes to be highlighted when holding ever after the node has been opened, but don't close them! + toggled = false; if (toggled) { is_open = !is_open; diff --git a/imgui_internal.h b/imgui_internal.h index 6e69c67683d4..53af4b3777a8 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -183,7 +183,8 @@ enum ImGuiButtonFlags_ ImGuiButtonFlags_AlignTextBaseLine = 1 << 8, // vertically align button to match text baseline (ButtonEx() only) ImGuiButtonFlags_NoKeyModifiers = 1 << 9, // disable interaction if a key modifier is held ImGuiButtonFlags_AllowOverlapMode = 1 << 10, // require previous frame HoveredId to either match id or be null before being usable - ImGuiButtonFlags_NoHoldingActiveID = 1 << 11 // don't set ActiveId while holding the mouse (ImGuiButtonFlags_PressedOnClick only) + ImGuiButtonFlags_NoHoldingActiveID = 1 << 11, // don't set ActiveId while holding the mouse (ImGuiButtonFlags_PressedOnClick only) + ImGuiButtonFlags_PressedOnDragDropHold = 1 << 12 // press when held into while we are drag and dropping another item }; enum ImGuiSliderFlags_ From 5956fff7e2959574e4273ca1b5cc540fd0dff0d5 Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 30 Oct 2017 00:10:05 +0100 Subject: [PATCH 222/823] Drag and Drop: ImGuiButtonFlags_PressedOnDragDropHold focuses the target window. --- imgui.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/imgui.cpp b/imgui.cpp index 383b012eb5b3..6603d3f9719d 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -5848,7 +5848,10 @@ bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool hovered = true; SetHoveredID(id); if (CalcTypematicPressedRepeatAmount(g.HoveredIdTimer + 0.0001f, g.HoveredIdTimer + 0.0001f - g.IO.DeltaTime, 0.01f, 0.70f)) // FIXME: Our formula for CalcTypematicPressedRepeatAmount() is fishy + { pressed = true; + FocusWindow(window); + } } if ((flags & ImGuiButtonFlags_FlattenChilds) && g.HoveredRootWindow == window) From 66f42324ad6203560de5631753644ce4d8e81bc8 Mon Sep 17 00:00:00 2001 From: omar Date: Wed, 1 Nov 2017 17:24:17 +0100 Subject: [PATCH 223/823] Drag and Drop: Added ImGuiDragDropFlags_SourceNoHoldToOpenOthers flag. --- imgui.cpp | 2 +- imgui.h | 15 ++++++++------- imgui_internal.h | 2 +- 3 files changed, 10 insertions(+), 9 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 6603d3f9719d..192238658535 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -5842,7 +5842,7 @@ bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool bool hovered = ItemHoverable(bb, id); // Special mode for Drag and Drop where holding button pressed for a long time while dragging another item triggers the button - if ((flags & ImGuiButtonFlags_PressedOnDragDropHold) && g.DragDropActive && !hovered) + if ((flags & ImGuiButtonFlags_PressedOnDragDropHold) && g.DragDropActive && !(g.DragDropSourceFlags & ImGuiDragDropFlags_SourceNoHoldToOpenOthers)) if (IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByActiveItem)) { hovered = true; diff --git a/imgui.h b/imgui.h index 25a9c5a6c87b..12ea6e2a1655 100644 --- a/imgui.h +++ b/imgui.h @@ -597,13 +597,14 @@ enum ImGuiHoveredFlags_ enum ImGuiDragDropFlags_ { // BeginDragDropSource() flags - ImGuiDragDropFlags_SourceNoAutoTooltip = 1 << 0, - ImGuiDragDropFlags_SourceNoDisableHover = 1 << 1, // By default, when dragging we clear data so that IsItemHovered() will return true, to avoid subsequent user code submitting tooltips. - ImGuiDragDropFlags_SourceAllowNullID = 1 << 2, // Allow items such as Text(), Image() that have no unique identifier to be used as drag source, by manufacturing a temporary identifier based on their window-relative position. This is extremely unusual within the dear imgui ecosystem and so we made it explicit. - // BeginDragDropTarget() flags - ImGuiDragDropFlags_AcceptBeforeDelivery = 1 << 10, // AcceptDragDropPayload() returns true even before the mouse button is released. You can then call IsDelivery() to test if the payload needs to be delivered. - ImGuiDragDropFlags_AcceptNoDrawDefaultRect = 1 << 11, // Do not draw the default highlight rectangle when hovering over target. - ImGuiDragDropFlags_AcceptPeekOnly = ImGuiDragDropFlags_AcceptBeforeDelivery | ImGuiDragDropFlags_AcceptNoDrawDefaultRect // For peeking ahead and inspecting the payload before delivery. + ImGuiDragDropFlags_SourceNoAutoTooltip = 1 << 0, // By default, a successful call to BeginDragDropSource opens a tooltip so you can display a preview or description of the dragged contents. This flag disable this behavior. + ImGuiDragDropFlags_SourceNoDisableHover = 1 << 1, // By default, when dragging we clear data so that IsItemHovered() will return true, to avoid subsequent user code submitting tooltips. This flag disable this behavior so you can still call IsItemHovered() on the source item. + ImGuiDragDropFlags_SourceNoHoldToOpenOthers = 1 << 2, // Disable the behavior that allows to open tree nodes and collapsing header by holding over them while dragging a source item. + ImGuiDragDropFlags_SourceAllowNullID = 1 << 3, // Allow items such as Text(), Image() that have no unique identifier to be used as drag source, by manufacturing a temporary identifier based on their window-relative position. This is extremely unusual within the dear imgui ecosystem and so we made it explicit. + // AcceptDragDropPayload() flags + ImGuiDragDropFlags_AcceptBeforeDelivery = 1 << 10, // AcceptDragDropPayload() will returns true even before the mouse button is released. You can then call IsDelivery() to test if the payload needs to be delivered. + ImGuiDragDropFlags_AcceptNoDrawDefaultRect = 1 << 11, // Do not draw the default highlight rectangle when hovering over target. + ImGuiDragDropFlags_AcceptPeekOnly = ImGuiDragDropFlags_AcceptBeforeDelivery | ImGuiDragDropFlags_AcceptNoDrawDefaultRect // For peeking ahead and inspecting the payload before delivery. }; // User fill ImGuiIO.KeyMap[] array with indices into the ImGuiIO.KeysDown[512] array diff --git a/imgui_internal.h b/imgui_internal.h index 53af4b3777a8..5e80c6eef34a 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -184,7 +184,7 @@ enum ImGuiButtonFlags_ ImGuiButtonFlags_NoKeyModifiers = 1 << 9, // disable interaction if a key modifier is held ImGuiButtonFlags_AllowOverlapMode = 1 << 10, // require previous frame HoveredId to either match id or be null before being usable ImGuiButtonFlags_NoHoldingActiveID = 1 << 11, // don't set ActiveId while holding the mouse (ImGuiButtonFlags_PressedOnClick only) - ImGuiButtonFlags_PressedOnDragDropHold = 1 << 12 // press when held into while we are drag and dropping another item + ImGuiButtonFlags_PressedOnDragDropHold = 1 << 12 // press when held into while we are drag and dropping another item (used by e.g. tree nodes, collapsing headers) }; enum ImGuiSliderFlags_ From 553bdeedf78126b9b91289a64dce6efe2e8b741e Mon Sep 17 00:00:00 2001 From: omar Date: Thu, 2 Nov 2017 18:30:46 +0100 Subject: [PATCH 224/823] Drag and Drop: Made it legal to not call SetDragDropPayload() between BeginDragDropSource() and EndDragDropSource(). (#143) --- imgui.cpp | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index e3481db80e73..73456b358758 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -10706,7 +10706,6 @@ void ImGui::EndDragDropSource() { ImGuiContext& g = *GImGui; IM_ASSERT(g.DragDropActive); - IM_ASSERT(g.DragDropPayload.DataFrameCount != -1); // Forgot to call SetDragDropSourcePayload(), at least once on the first frame of a successful BeginDragDropSource() if (!(g.DragDropSourceFlags & ImGuiDragDropFlags_SourceNoAutoTooltip)) { @@ -10714,9 +10713,16 @@ void ImGui::EndDragDropSource() PopStyleColor(); //PopStyleVar(); } + + // Discard the drag if have not called SetDragDropPayload() + if (g.DragDropPayload.DataFrameCount == -1) + { + g.DragDropActive = false; + g.DragDropPayload.Clear(); + } } -// Use 'cond' to choose to submit paypload on drag start or every frame +// Use 'cond' to choose to submit payload on drag start or every frame bool ImGui::SetDragDropPayload(const char* type, const void* data, size_t data_size, ImGuiCond cond) { ImGuiContext& g = *GImGui; @@ -10783,7 +10789,7 @@ const ImGuiPayload* ImGui::AcceptDragDropPayload(const char* type, ImGuiDragDrop ImGuiPayload& payload = g.DragDropPayload; IM_ASSERT(g.DragDropActive); // Not called between BeginDragDropTarget() and EndDragDropTarget() ? IM_ASSERT(window->DC.LastItemRectHoveredRect); // Not called between BeginDragDropTarget() and EndDragDropTarget() ? - IM_ASSERT(payload.DataFrameCount != -1); // Internal/usage error, please report! + IM_ASSERT(payload.DataFrameCount != -1); // Forgot to call EndDragDropTarget() ? if (type != NULL && !payload.IsDataType(type)) return NULL; From 8b725c94cbab321d7bc1b4ee7d1efbf131c4f41d Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 6 Nov 2017 19:39:23 +0100 Subject: [PATCH 225/823] Drag and Drop: Rework internal to allow overlapping targets (#143) --- imgui.cpp | 30 ++++++++++++++---------------- imgui.h | 7 ++++--- 2 files changed, 18 insertions(+), 19 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 73456b358758..8c52e4695ee1 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2250,6 +2250,8 @@ void ImGui::NewFrame() g.ScalarAsInputTextId = 0; // Elapse drag & drop payload + g.DragDropPayload.AcceptIdPrev = g.DragDropPayload.AcceptIdCurr; + g.DragDropPayload.AcceptIdCurr = 0; if (g.DragDropActive && g.DragDropPayload.DataFrameCount + 1 < g.FrameCount) { g.DragDropActive = false; @@ -10773,7 +10775,6 @@ bool ImGui::BeginDragDropTarget() return false; ImGuiWindow* window = g.CurrentWindow; - //if (!window->DC.LastItemRectHoveredRect || (g.ActiveId == g.DragDropPayload.SourceId || g.ActiveIdPreviousFrame == g.DragDropPayload.SourceId)) if (!window->DC.LastItemRectHoveredRect || (window->DC.LastItemId && window->DC.LastItemId == g.DragDropPayload.SourceId)) return false; if (window->RootWindow != g.HoveredWindow->RootWindow) @@ -10793,23 +10794,20 @@ const ImGuiPayload* ImGui::AcceptDragDropPayload(const char* type, ImGuiDragDrop if (type != NULL && !payload.IsDataType(type)) return NULL; - if (payload.AcceptId == 0) - payload.AcceptId = window->DC.LastItemId; - - bool was_accepted_previously = (payload.AcceptFrameCount == g.FrameCount - 1); - if (payload.AcceptFrameCount != g.FrameCount) + // NB: We currently accept NULL id however, overlapping targets required unique ID to function + const bool was_accepted_previously = (payload.AcceptIdPrev == window->DC.LastItemId); + //if (window->DC.LastItemId) + payload.AcceptIdCurr = window->DC.LastItemId; + + // Render drop visuals + if (!(flags & ImGuiDragDropFlags_AcceptNoDrawDefaultRect) && was_accepted_previously) { - // Render drop visuals - if (!(flags & ImGuiDragDropFlags_AcceptNoDrawDefaultRect) && was_accepted_previously) - { - ImRect r = window->DC.LastItemRect; - r.Expand(4.0f); - window->DrawList->AddRectFilled(r.Min, r.Max, IM_COL32(255, 255, 0, 20), 0.0f); // FIXME-DRAG FIXME-STYLE - window->DrawList->AddRect(r.Min, r.Max, IM_COL32(255, 255, 0, 255), 0.0f, ~0, 2.0f); // FIXME-DRAG FIXME-STYLE - } - payload.AcceptFrameCount = g.FrameCount; + ImRect r = window->DC.LastItemRect; + r.Expand(4.0f); + window->DrawList->AddRectFilled(r.Min, r.Max, IM_COL32(255, 255, 0, 20), 0.0f); // FIXME-DRAG FIXME-STYLE + window->DrawList->AddRect(r.Min, r.Max, IM_COL32(255, 255, 0, 255), 0.0f, ~0, 2.0f); // FIXME-DRAG FIXME-STYLE } - + payload.AcceptFrameCount = g.FrameCount; payload.Delivery = was_accepted_previously && IsMouseReleased(g.DragDropMouseButton); if (!payload.Delivery && !(flags & ImGuiDragDropFlags_AcceptBeforeDelivery)) return NULL; diff --git a/imgui.h b/imgui.h index 6191f099171d..849d78648f04 100644 --- a/imgui.h +++ b/imgui.h @@ -587,7 +587,7 @@ enum ImGuiHoveredFlags_ ImGuiHoveredFlags_Default = 0, // Return true if directly over the item/window, not obstructed by another window, not obstructed by an active popup or modal blocking inputs under them. ImGuiHoveredFlags_AllowWhenBlockedByPopup = 1 << 0, // Return true even if a popup window is normally blocking access to this item/window //ImGuiHoveredFlags_AllowWhenBlockedByModal = 1 << 1, // Return true even if a modal popup window is normally blocking access to this item/window. FIXME-TODO: Unavailable yet. - ImGuiHoveredFlags_AllowWhenBlockedByActiveItem = 1 << 2, // Return true even if an active item is blocking access to this item/window + ImGuiHoveredFlags_AllowWhenBlockedByActiveItem = 1 << 2, // Return true even if an active item is blocking access to this item/window. Useful for Drag and Drop patterns. ImGuiHoveredFlags_AllowWhenOverlapped = 1 << 3, // Return true even if the position is overlapped by another window ImGuiHoveredFlags_FlattenChilds = 1 << 4, // Treat all child windows as the same window (for IsWindowHovered()) ImGuiHoveredFlags_RectOnly = ImGuiHoveredFlags_AllowWhenBlockedByPopup | ImGuiHoveredFlags_AllowWhenBlockedByActiveItem | ImGuiHoveredFlags_AllowWhenOverlapped @@ -1153,14 +1153,15 @@ struct ImGuiPayload // [Internal] ImGuiID SourceId; // Source item id ImGuiID SourceParentId; // Source parent id (if available) - ImGuiID AcceptId; // Target item id (set at the time of accepting the payload) + ImGuiID AcceptIdCurr; // Target item id (set at the time of accepting the payload) + ImGuiID AcceptIdPrev; // Target item id from previous frame (we need to store this to allow for overlapping drag and drop targets) int AcceptFrameCount; // Last time a target expressed a desire to accept the source int DataFrameCount; // Data timestamp char DataType[8 + 1]; // Data type tag (short user-supplied string) bool Delivery; // Set when AcceptDragDropPayload() was called and the mouse button is released over the target item ImGuiPayload() { Clear(); } - void Clear() { SourceId = SourceParentId = AcceptId = 0; AcceptFrameCount = -1; Data = NULL; DataSize = 0; memset(DataType, 0, sizeof(DataType)); DataFrameCount = -1; Delivery = false; } + void Clear() { SourceId = SourceParentId = AcceptIdCurr = AcceptIdPrev = 0; AcceptFrameCount = -1; Data = NULL; DataSize = 0; memset(DataType, 0, sizeof(DataType)); DataFrameCount = -1; Delivery = false; } bool IsDataType(const char* type) const { return DataFrameCount != -1 && strcmp(type, DataType) == 0; } bool IsDelivery() const { return Delivery; } }; From de1e7dc088952f484cd905e815449519641d0e81 Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 6 Nov 2017 20:02:56 +0100 Subject: [PATCH 226/823] Drag and Drop: Moved internal fields out of public sight. (#143) --- imgui.cpp | 33 +++++++++++++++++++-------------- imgui.h | 5 +---- imgui_internal.h | 5 +++++ 3 files changed, 25 insertions(+), 18 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 8c52e4695ee1..999b373f301a 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -662,6 +662,7 @@ static bool DataTypeApplyOpFromText(const char* buf, const char* ini namespace ImGui { +static void ClearDragDrop(); static void FocusPreviousWindow(); } @@ -2250,15 +2251,14 @@ void ImGui::NewFrame() g.ScalarAsInputTextId = 0; // Elapse drag & drop payload - g.DragDropPayload.AcceptIdPrev = g.DragDropPayload.AcceptIdCurr; - g.DragDropPayload.AcceptIdCurr = 0; if (g.DragDropActive && g.DragDropPayload.DataFrameCount + 1 < g.FrameCount) { - g.DragDropActive = false; - g.DragDropPayload.Clear(); + ClearDragDrop(); g.DragDropPayloadBufHeap.clear(); memset(&g.DragDropPayloadBufLocal, 0, sizeof(g.DragDropPayloadBufLocal)); } + g.DragDropAcceptIdPrev = g.DragDropAcceptIdCurr; + g.DragDropAcceptIdCurr = 0; // Update keyboard input state memcpy(g.IO.KeysDownDurationPrev, g.IO.KeysDownDuration, sizeof(g.IO.KeysDownDuration)); @@ -10631,6 +10631,15 @@ void ImGui::Value(const char* prefix, float v, const char* float_format) // DRAG AND DROP //----------------------------------------------------------------------------- +static void ImGui::ClearDragDrop() +{ + ImGuiContext& g = *GImGui; + g.DragDropActive = false; + g.DragDropPayload.Clear(); + g.DragDropAcceptIdCurr = g.DragDropAcceptIdPrev = 0; + g.DragDropAcceptFrameCount = -1; +} + // Call when current ID is active. // When this returns true you need to: a) call SetDragDropPayload() exactly once, b) you may render the payload visual/description, c) call EndDragDropSource() bool ImGui::BeginDragDropSource(ImGuiDragDropFlags flags, int mouse_button) @@ -10677,8 +10686,8 @@ bool ImGui::BeginDragDropSource(ImGuiDragDropFlags flags, int mouse_button) if (!g.DragDropActive) { IM_ASSERT(id != 0); + ClearDragDrop(); ImGuiPayload& payload = g.DragDropPayload; - payload.Clear(); payload.SourceId = id; payload.SourceParentId = window->IDStack.back(); g.DragDropActive = true; @@ -10718,10 +10727,7 @@ void ImGui::EndDragDropSource() // Discard the drag if have not called SetDragDropPayload() if (g.DragDropPayload.DataFrameCount == -1) - { - g.DragDropActive = false; - g.DragDropPayload.Clear(); - } + ClearDragDrop(); } // Use 'cond' to choose to submit payload on drag start or every frame @@ -10765,7 +10771,7 @@ bool ImGui::SetDragDropPayload(const char* type, const void* data, size_t data_s } payload.DataFrameCount = g.FrameCount; - return (payload.AcceptFrameCount == g.FrameCount) || (payload.AcceptFrameCount == g.FrameCount - 1); + return (g.DragDropAcceptFrameCount == g.FrameCount) || (g.DragDropAcceptFrameCount == g.FrameCount - 1); } bool ImGui::BeginDragDropTarget() @@ -10795,9 +10801,8 @@ const ImGuiPayload* ImGui::AcceptDragDropPayload(const char* type, ImGuiDragDrop return NULL; // NB: We currently accept NULL id however, overlapping targets required unique ID to function - const bool was_accepted_previously = (payload.AcceptIdPrev == window->DC.LastItemId); - //if (window->DC.LastItemId) - payload.AcceptIdCurr = window->DC.LastItemId; + const bool was_accepted_previously = (g.DragDropAcceptIdPrev == window->DC.LastItemId); + g.DragDropAcceptIdCurr = window->DC.LastItemId; // Render drop visuals if (!(flags & ImGuiDragDropFlags_AcceptNoDrawDefaultRect) && was_accepted_previously) @@ -10807,7 +10812,7 @@ const ImGuiPayload* ImGui::AcceptDragDropPayload(const char* type, ImGuiDragDrop window->DrawList->AddRectFilled(r.Min, r.Max, IM_COL32(255, 255, 0, 20), 0.0f); // FIXME-DRAG FIXME-STYLE window->DrawList->AddRect(r.Min, r.Max, IM_COL32(255, 255, 0, 255), 0.0f, ~0, 2.0f); // FIXME-DRAG FIXME-STYLE } - payload.AcceptFrameCount = g.FrameCount; + g.DragDropAcceptFrameCount = g.FrameCount; payload.Delivery = was_accepted_previously && IsMouseReleased(g.DragDropMouseButton); if (!payload.Delivery && !(flags & ImGuiDragDropFlags_AcceptBeforeDelivery)) return NULL; diff --git a/imgui.h b/imgui.h index 849d78648f04..1624e3173603 100644 --- a/imgui.h +++ b/imgui.h @@ -1153,15 +1153,12 @@ struct ImGuiPayload // [Internal] ImGuiID SourceId; // Source item id ImGuiID SourceParentId; // Source parent id (if available) - ImGuiID AcceptIdCurr; // Target item id (set at the time of accepting the payload) - ImGuiID AcceptIdPrev; // Target item id from previous frame (we need to store this to allow for overlapping drag and drop targets) - int AcceptFrameCount; // Last time a target expressed a desire to accept the source int DataFrameCount; // Data timestamp char DataType[8 + 1]; // Data type tag (short user-supplied string) bool Delivery; // Set when AcceptDragDropPayload() was called and the mouse button is released over the target item ImGuiPayload() { Clear(); } - void Clear() { SourceId = SourceParentId = AcceptIdCurr = AcceptIdPrev = 0; AcceptFrameCount = -1; Data = NULL; DataSize = 0; memset(DataType, 0, sizeof(DataType)); DataFrameCount = -1; Delivery = false; } + void Clear() { SourceId = SourceParentId = 0; Data = NULL; DataSize = 0; memset(DataType, 0, sizeof(DataType)); DataFrameCount = -1; Delivery = false; } bool IsDataType(const char* type) const { return DataFrameCount != -1 && strcmp(type, DataType) == 0; } bool IsDelivery() const { return Delivery; } }; diff --git a/imgui_internal.h b/imgui_internal.h index 5e80c6eef34a..5c3b24c8a099 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -480,6 +480,9 @@ struct ImGuiContext ImGuiDragDropFlags DragDropSourceFlags; int DragDropMouseButton; ImGuiPayload DragDropPayload; + ImGuiID DragDropAcceptIdCurr; // Target item id (set at the time of accepting the payload) + ImGuiID DragDropAcceptIdPrev; // Target item id from previous frame (we need to store this to allow for overlapping drag and drop targets) + int DragDropAcceptFrameCount; // Last time a target expressed a desire to accept the source ImVector DragDropPayloadBufHeap; // We don't expose the ImVector<> directly unsigned char DragDropPayloadBufLocal[8]; @@ -563,6 +566,8 @@ struct ImGuiContext DragDropActive = false; DragDropSourceFlags = 0; DragDropMouseButton = -1; + DragDropAcceptIdPrev = DragDropAcceptIdCurr = 0; + DragDropAcceptFrameCount = -1; memset(DragDropPayloadBufLocal, 0, sizeof(DragDropPayloadBufLocal)); ScalarAsInputTextId = 0; From b6504b8eee930cca4a98d36603273c407a69c135 Mon Sep 17 00:00:00 2001 From: omar Date: Wed, 8 Nov 2017 15:47:52 +0100 Subject: [PATCH 227/823] Drag and drop: Handle overlapping drag target priorities given their surface, which appears to make most sense for drag and drop operations. --- imgui.cpp | 14 ++++++++++++-- imgui_internal.h | 1 + 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 999b373f301a..a5e9d37acd14 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2259,6 +2259,7 @@ void ImGui::NewFrame() } g.DragDropAcceptIdPrev = g.DragDropAcceptIdCurr; g.DragDropAcceptIdCurr = 0; + g.DragDropAcceptIdCurrRectSurface = FLT_MAX; // Update keyboard input state memcpy(g.IO.KeysDownDurationPrev, g.IO.KeysDownDuration, sizeof(g.IO.KeysDownDuration)); @@ -10637,6 +10638,7 @@ static void ImGui::ClearDragDrop() g.DragDropActive = false; g.DragDropPayload.Clear(); g.DragDropAcceptIdCurr = g.DragDropAcceptIdPrev = 0; + g.DragDropAcceptIdCurrRectSurface = FLT_MAX; g.DragDropAcceptFrameCount = -1; } @@ -10800,14 +10802,22 @@ const ImGuiPayload* ImGui::AcceptDragDropPayload(const char* type, ImGuiDragDrop if (type != NULL && !payload.IsDataType(type)) return NULL; - // NB: We currently accept NULL id however, overlapping targets required unique ID to function + // NB: We currently accept NULL id as target. However, overlapping targets requires a unique ID to function! const bool was_accepted_previously = (g.DragDropAcceptIdPrev == window->DC.LastItemId); g.DragDropAcceptIdCurr = window->DC.LastItemId; + // Accept smallest drag target bounding box, this allows us to nest drag targets conveniently without ordering constraints. + ImRect r = window->DC.LastItemRect; + float r_surface = r.GetWidth() * r.GetHeight(); + if (r_surface < g.DragDropAcceptIdCurrRectSurface) + { + g.DragDropAcceptIdCurr = window->DC.LastItemId; + g.DragDropAcceptIdCurrRectSurface = r_surface; + } + // Render drop visuals if (!(flags & ImGuiDragDropFlags_AcceptNoDrawDefaultRect) && was_accepted_previously) { - ImRect r = window->DC.LastItemRect; r.Expand(4.0f); window->DrawList->AddRectFilled(r.Min, r.Max, IM_COL32(255, 255, 0, 20), 0.0f); // FIXME-DRAG FIXME-STYLE window->DrawList->AddRect(r.Min, r.Max, IM_COL32(255, 255, 0, 255), 0.0f, ~0, 2.0f); // FIXME-DRAG FIXME-STYLE diff --git a/imgui_internal.h b/imgui_internal.h index 5c3b24c8a099..c93faf7f6413 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -480,6 +480,7 @@ struct ImGuiContext ImGuiDragDropFlags DragDropSourceFlags; int DragDropMouseButton; ImGuiPayload DragDropPayload; + float DragDropAcceptIdCurrRectSurface; ImGuiID DragDropAcceptIdCurr; // Target item id (set at the time of accepting the payload) ImGuiID DragDropAcceptIdPrev; // Target item id from previous frame (we need to store this to allow for overlapping drag and drop targets) int DragDropAcceptFrameCount; // Last time a target expressed a desire to accept the source From b1653cd361aa2acd632877829c6d55a859e39d20 Mon Sep 17 00:00:00 2001 From: omar Date: Thu, 9 Nov 2017 20:09:09 +0100 Subject: [PATCH 228/823] Drag and Drop: Allow NULL payload (since type only can be useful). (#143) --- imgui.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/imgui.cpp b/imgui.cpp index a5e9d37acd14..2ead2edf28d7 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -10742,7 +10742,7 @@ bool ImGui::SetDragDropPayload(const char* type, const void* data, size_t data_s IM_ASSERT(type != NULL); IM_ASSERT(strlen(type) < IM_ARRAYSIZE(payload.DataType)); // Payload type can be at most 8 characters longs - IM_ASSERT(data != NULL && data_size > 0); + IM_ASSERT((data != NULL && data_size > 0) || (data == NULL && data_size == 0)); IM_ASSERT(cond == ImGuiCond_Always || cond == ImGuiCond_Once); IM_ASSERT(payload.SourceId != 0); // Not called between BeginDragDropSource() and EndDragDropSource() From 4b94738c7e64a7a912a72b373063b42a407ec1bd Mon Sep 17 00:00:00 2001 From: omar Date: Thu, 9 Nov 2017 20:17:10 +0100 Subject: [PATCH 229/823] Drag and Drop: Drop target rectangle goes out of clipping range (#143) --- imgui.cpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 2ead2edf28d7..cdb0254215fe 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -10818,9 +10818,13 @@ const ImGuiPayload* ImGui::AcceptDragDropPayload(const char* type, ImGuiDragDrop // Render drop visuals if (!(flags & ImGuiDragDropFlags_AcceptNoDrawDefaultRect) && was_accepted_previously) { - r.Expand(4.0f); - window->DrawList->AddRectFilled(r.Min, r.Max, IM_COL32(255, 255, 0, 20), 0.0f); // FIXME-DRAG FIXME-STYLE - window->DrawList->AddRect(r.Min, r.Max, IM_COL32(255, 255, 0, 255), 0.0f, ~0, 2.0f); // FIXME-DRAG FIXME-STYLE + // FIXME-DRAG FIXME-STYLE: Settle on a proper default visuals for drop target, w/ ImGuiCol enum value probably. + r.Expand(5.0f); + bool push_clip_rect = !window->ClipRect.Contains(r); + if (push_clip_rect) window->DrawList->PushClipRectFullScreen(); + window->DrawList->AddRectFilled(r.Min, r.Max, IM_COL32(255, 255, 0, 20), 0.0f); + window->DrawList->AddRect(r.Min + ImVec2(1.5f,1.5f), r.Max - ImVec2(1.5f,1.5f), IM_COL32(255, 255, 0, 255), 0.0f, ~0, 2.0f); + if (push_clip_rect) window->DrawList->PopClipRect(); } g.DragDropAcceptFrameCount = g.FrameCount; payload.Delivery = was_accepted_previously && IsMouseReleased(g.DragDropMouseButton); From 7908cce25f01c2e2dffe01732a7efc8a01055140 Mon Sep 17 00:00:00 2001 From: omar Date: Fri, 10 Nov 2017 13:13:28 +0100 Subject: [PATCH 230/823] Drag and Drop: Added internal BeginDragDropTargetCustom() convenient to avoid submitting dummy ItemAdd. (#143) --- imgui.cpp | 39 ++++++++++++++++++++++++++++++--------- imgui_internal.h | 5 +++++ 2 files changed, 35 insertions(+), 9 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index cdb0254215fe..b43295e8f1e2 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -10776,6 +10776,27 @@ bool ImGui::SetDragDropPayload(const char* type, const void* data, size_t data_s return (g.DragDropAcceptFrameCount == g.FrameCount) || (g.DragDropAcceptFrameCount == g.FrameCount - 1); } +bool ImGui::BeginDragDropTargetCustom(const ImRect& bb, ImGuiID id) +{ + ImGuiContext& g = *GImGui; + if (!g.DragDropActive) + return false; + + ImGuiWindow* window = g.CurrentWindow; + if (g.HoveredWindow == NULL || window->RootWindow != g.HoveredWindow->RootWindow) + return false; + if (!IsMouseHoveringRect(bb.Min, bb.Max) || (id && id == g.DragDropPayload.SourceId)) + return false; + + g.DragDropTargetRect = bb; + g.DragDropTargetId = id; + return true; +} + +// We don't use BeginDragDropTargetCustom() and duplicate its code because: +// 1) LastItemRectHoveredRect which handles items that pushes a temporarily clip rectangle in their code. Calling BeginDragDropTargetCustom(LastItemRect) would not handle it. +// 2) and it's faster. as this code may be very frequently called, we want to early out as fast as we can. +// Also note how the HoveredWindow test is positioned differently in both functions (in both functions we optimize for the cheapest early out case) bool ImGui::BeginDragDropTarget() { ImGuiContext& g = *GImGui; @@ -10785,9 +10806,11 @@ bool ImGui::BeginDragDropTarget() ImGuiWindow* window = g.CurrentWindow; if (!window->DC.LastItemRectHoveredRect || (window->DC.LastItemId && window->DC.LastItemId == g.DragDropPayload.SourceId)) return false; - if (window->RootWindow != g.HoveredWindow->RootWindow) + if (g.HoveredWindow == NULL || window->RootWindow != g.HoveredWindow->RootWindow) return false; + g.DragDropTargetRect = window->DC.LastItemRect; + g.DragDropTargetId = window->DC.LastItemId; return true; } @@ -10797,25 +10820,22 @@ const ImGuiPayload* ImGui::AcceptDragDropPayload(const char* type, ImGuiDragDrop ImGuiWindow* window = g.CurrentWindow; ImGuiPayload& payload = g.DragDropPayload; IM_ASSERT(g.DragDropActive); // Not called between BeginDragDropTarget() and EndDragDropTarget() ? - IM_ASSERT(window->DC.LastItemRectHoveredRect); // Not called between BeginDragDropTarget() and EndDragDropTarget() ? IM_ASSERT(payload.DataFrameCount != -1); // Forgot to call EndDragDropTarget() ? if (type != NULL && !payload.IsDataType(type)) return NULL; - // NB: We currently accept NULL id as target. However, overlapping targets requires a unique ID to function! - const bool was_accepted_previously = (g.DragDropAcceptIdPrev == window->DC.LastItemId); - g.DragDropAcceptIdCurr = window->DC.LastItemId; - // Accept smallest drag target bounding box, this allows us to nest drag targets conveniently without ordering constraints. - ImRect r = window->DC.LastItemRect; + // NB: We currently accept NULL id as target. However, overlapping targets requires a unique ID to function! + const bool was_accepted_previously = (g.DragDropAcceptIdPrev == g.DragDropTargetId); + ImRect r = g.DragDropTargetRect; float r_surface = r.GetWidth() * r.GetHeight(); if (r_surface < g.DragDropAcceptIdCurrRectSurface) { - g.DragDropAcceptIdCurr = window->DC.LastItemId; + g.DragDropAcceptIdCurr = g.DragDropTargetId; g.DragDropAcceptIdCurrRectSurface = r_surface; } - // Render drop visuals + // Render default drop visuals if (!(flags & ImGuiDragDropFlags_AcceptNoDrawDefaultRect) && was_accepted_previously) { // FIXME-DRAG FIXME-STYLE: Settle on a proper default visuals for drop target, w/ ImGuiCol enum value probably. @@ -10826,6 +10846,7 @@ const ImGuiPayload* ImGui::AcceptDragDropPayload(const char* type, ImGuiDragDrop window->DrawList->AddRect(r.Min + ImVec2(1.5f,1.5f), r.Max - ImVec2(1.5f,1.5f), IM_COL32(255, 255, 0, 255), 0.0f, ~0, 2.0f); if (push_clip_rect) window->DrawList->PopClipRect(); } + g.DragDropAcceptFrameCount = g.FrameCount; payload.Delivery = was_accepted_previously && IsMouseReleased(g.DragDropMouseButton); if (!payload.Delivery && !(flags & ImGuiDragDropFlags_AcceptBeforeDelivery)) diff --git a/imgui_internal.h b/imgui_internal.h index c93faf7f6413..849ab612d4a3 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -480,6 +480,8 @@ struct ImGuiContext ImGuiDragDropFlags DragDropSourceFlags; int DragDropMouseButton; ImGuiPayload DragDropPayload; + ImRect DragDropTargetRect; + ImGuiID DragDropTargetId; float DragDropAcceptIdCurrRectSurface; ImGuiID DragDropAcceptIdCurr; // Target item id (set at the time of accepting the payload) ImGuiID DragDropAcceptIdPrev; // Target item id from previous frame (we need to store this to allow for overlapping drag and drop targets) @@ -567,6 +569,7 @@ struct ImGuiContext DragDropActive = false; DragDropSourceFlags = 0; DragDropMouseButton = -1; + DragDropTargetId = 0; DragDropAcceptIdPrev = DragDropAcceptIdCurr = 0; DragDropAcceptFrameCount = -1; memset(DragDropPayloadBufLocal, 0, sizeof(DragDropPayloadBufLocal)); @@ -835,6 +838,8 @@ namespace ImGui IMGUI_API void Scrollbar(ImGuiLayoutType direction); IMGUI_API void VerticalSeparator(); // Vertical separator, for menu bars (use current line height). not exposed because it is misleading what it doesn't have an effect on regular layout. + IMGUI_API bool BeginDragDropTargetCustom(const ImRect& bb, ImGuiID id); + // FIXME-WIP: New Columns API IMGUI_API void BeginColumns(const char* id, int count, ImGuiColumnsFlags flags = 0); // setup number of columns. use an identifier to distinguish multiple column sets. close with EndColumns(). IMGUI_API void EndColumns(); // close columns From ffad688fc8d5b957716cb873c1bfbd5c12839bbf Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 14 Nov 2017 22:11:43 +0100 Subject: [PATCH 231/823] Drag and Drop: Added payload->IsPreview() to user can render their custom preview while handling overlapping drop targets. (#143) --- imgui.cpp | 3 ++- imgui.h | 6 ++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index b43295e8f1e2..3eecc73ab3d0 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -10836,7 +10836,8 @@ const ImGuiPayload* ImGui::AcceptDragDropPayload(const char* type, ImGuiDragDrop } // Render default drop visuals - if (!(flags & ImGuiDragDropFlags_AcceptNoDrawDefaultRect) && was_accepted_previously) + payload.Preview = was_accepted_previously; + if (!(flags & ImGuiDragDropFlags_AcceptNoDrawDefaultRect) && payload.Preview) { // FIXME-DRAG FIXME-STYLE: Settle on a proper default visuals for drop target, w/ ImGuiCol enum value probably. r.Expand(5.0f); diff --git a/imgui.h b/imgui.h index 1624e3173603..7959d0e76cdb 100644 --- a/imgui.h +++ b/imgui.h @@ -1155,11 +1155,13 @@ struct ImGuiPayload ImGuiID SourceParentId; // Source parent id (if available) int DataFrameCount; // Data timestamp char DataType[8 + 1]; // Data type tag (short user-supplied string) - bool Delivery; // Set when AcceptDragDropPayload() was called and the mouse button is released over the target item + bool Preview; // Set when AcceptDragDropPayload() was called and mouse has been hovering the target item (nb: handle overlapping drag targets) + bool Delivery; // Set when AcceptDragDropPayload() was called and mouse button is released over the target item. ImGuiPayload() { Clear(); } - void Clear() { SourceId = SourceParentId = 0; Data = NULL; DataSize = 0; memset(DataType, 0, sizeof(DataType)); DataFrameCount = -1; Delivery = false; } + void Clear() { SourceId = SourceParentId = 0; Data = NULL; DataSize = 0; memset(DataType, 0, sizeof(DataType)); DataFrameCount = -1; Preview = Delivery = false; } bool IsDataType(const char* type) const { return DataFrameCount != -1 && strcmp(type, DataType) == 0; } + bool IsPreview() const { return Preview; } bool IsDelivery() const { return Delivery; } }; From 5027311e7fc8f7e1d5d00ed68449d2010d351628 Mon Sep 17 00:00:00 2001 From: omar Date: Wed, 15 Nov 2017 17:59:12 +0100 Subject: [PATCH 232/823] Drag and drop: Standardizing payload types as defines. (#143) --- imgui_internal.h | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/imgui_internal.h b/imgui_internal.h index 1980e45bdc28..45bbedeb7316 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -167,6 +167,10 @@ inline void operator delete(void*, ImPlacementNewDummy, void*) {} // Types //----------------------------------------------------------------------------- +// Drag and Drop payload types. String starting with '_' are managed by Dear ImGui. +#define IMGUI_PAYLOAD_TYPE_COLOR_4F "_COL4F" // float[4] // Standard type for colors. User code may use this type. Build a float[4] out of a float[3] if you don't have alpha. +#define IMGUI_PAYLOAD_TYPE_DOCKABLE "_IMDOCK" // ImGuiWindow* // [Internal] Docking/tabs + enum ImGuiButtonFlags_ { ImGuiButtonFlags_Repeat = 1 << 0, // hold to repeat @@ -239,7 +243,8 @@ enum ImGuiDir ImGuiDir_Left = 0, ImGuiDir_Right = 1, ImGuiDir_Up = 2, - ImGuiDir_Down = 3 + ImGuiDir_Down = 3, + ImGuiDir_Count_ }; enum ImGuiCorner From d323e8cca235ff0c04aa47662d6fa8fa9e69b890 Mon Sep 17 00:00:00 2001 From: omar Date: Sun, 19 Nov 2017 00:47:00 +0100 Subject: [PATCH 233/823] Fixed Style merge for nav branch (#707, #787) --- imgui_draw.cpp | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/imgui_draw.cpp b/imgui_draw.cpp index ccd2ad7a88ff..87e2b39fe386 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -133,19 +133,11 @@ void ImGui::StyleColorsClassic(ImGuiStyle* dst) colors[ImGuiCol_PopupBg] = ImVec4(0.11f, 0.11f, 0.14f, 0.92f); colors[ImGuiCol_Border] = ImVec4(0.70f, 0.70f, 0.70f, 0.27f); colors[ImGuiCol_BorderShadow] = ImVec4(0.00f, 0.00f, 0.00f, 0.00f); -#if 1 - colors[ImGuiCol_FrameBg] = ImVec4(0.80f, 0.80f, 0.80f, 0.30f); // Background of checkbox, radio button, plot, slider, text input - colors[ImGuiCol_FrameBgHovered] = ImVec4(0.90f, 0.80f, 0.80f, 0.40f); - colors[ImGuiCol_FrameBgActive] = ImVec4(0.90f, 0.65f, 0.65f, 0.45f); - colors[ImGuiCol_TitleBg] = ImVec4(0.24f, 0.24f, 0.50f, 0.83f); - colors[ImGuiCol_TitleBgActive] = ImVec4(0.33f, 0.33f, 0.65f, 0.87f); -#else colors[ImGuiCol_FrameBg] = ImVec4(0.43f, 0.43f, 0.43f, 0.39f); colors[ImGuiCol_FrameBgHovered] = ImVec4(0.47f, 0.47f, 0.69f, 0.40f); colors[ImGuiCol_FrameBgActive] = ImVec4(0.42f, 0.41f, 0.64f, 0.69f); colors[ImGuiCol_TitleBg] = ImVec4(0.27f, 0.27f, 0.54f, 0.83f); colors[ImGuiCol_TitleBgActive] = ImVec4(0.32f, 0.32f, 0.63f, 0.87f); -#endif colors[ImGuiCol_TitleBgCollapsed] = ImVec4(0.40f, 0.40f, 0.80f, 0.20f); colors[ImGuiCol_MenuBarBg] = ImVec4(0.40f, 0.40f, 0.55f, 0.80f); colors[ImGuiCol_ScrollbarBg] = ImVec4(0.20f, 0.25f, 0.30f, 0.60f); @@ -280,6 +272,8 @@ void ImGui::StyleColorsLight(ImGuiStyle* dst) colors[ImGuiCol_PlotHistogramHovered] = ImVec4(1.00f, 0.45f, 0.00f, 1.00f); colors[ImGuiCol_TextSelectedBg] = ImVec4(0.26f, 0.59f, 0.98f, 0.35f); colors[ImGuiCol_ModalWindowDarkening] = ImVec4(0.20f, 0.20f, 0.20f, 0.35f); + colors[ImGuiCol_NavHighlight] = colors[ImGuiCol_HeaderHovered]; + colors[ImGuiCol_NavWindowingHighlight] = ImVec4(0.40f, 0.40f, 0.40f, 0.12f); } From dc2768503f91b5d11e6cbb76fde873a53e3ccf7f Mon Sep 17 00:00:00 2001 From: omar Date: Sun, 19 Nov 2017 16:24:17 +0100 Subject: [PATCH 234/823] Fix for drag and drop branch. --- imgui.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/imgui.cpp b/imgui.cpp index 2510fb70d7e9..978277d64f3c 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -10796,7 +10796,7 @@ bool ImGui::BeginDragDropSource(ImGuiDragDropFlags flags, int mouse_button) //PushStyleVar(ImGuiStyleVar_Alpha, g.Style.Alpha * 0.60f); // This is better but e.g ColorButton with checkboard has issue with transparent colors :( SetNextWindowPos(g.IO.MousePos); PushStyleColor(ImGuiCol_PopupBg, GetStyleColorVec4(ImGuiCol_PopupBg) * ImVec4(1.0f, 1.0f, 1.0f, 0.6f)); - BeginTooltipEx(ImGuiWindowFlags_NoInputs | ImGuiWindowFlags_ShowBorders); + BeginTooltipEx(ImGuiWindowFlags_NoInputs); } if (!(flags & ImGuiDragDropFlags_SourceNoDisableHover)) From 7d09a0ae9948f99504ec12d0e297d08cffec0d85 Mon Sep 17 00:00:00 2001 From: omar Date: Wed, 22 Nov 2017 12:26:50 +0100 Subject: [PATCH 235/823] Menu bar: better software clipping to handle small windows, in particular child window don't have the minimum constraint added in e9a7e73bbaacec886f9b39130428b81b7f95bf16 so we need to render clipped menus better. --- imgui.cpp | 23 ++++++++++++++--------- imgui_internal.h | 1 + 2 files changed, 15 insertions(+), 9 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 2323dce02452..c1361f735bfd 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -4460,16 +4460,17 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) window->DrawList->AddRectFilled(window->Pos+ImVec2(0,window->TitleBarHeight()), window->Pos+window->Size, bg_col, window_rounding, (flags & ImGuiWindowFlags_NoTitleBar) ? ImDrawCornerFlags_All : ImDrawCornerFlags_Bot); // Title bar - const bool is_focused = g.NavWindow && window->RootNonPopupWindow == g.NavWindow->RootNonPopupWindow; + const bool window_is_focused = g.NavWindow && window->RootNonPopupWindow == g.NavWindow->RootNonPopupWindow; if (!(flags & ImGuiWindowFlags_NoTitleBar)) - window->DrawList->AddRectFilled(title_bar_rect.GetTL(), title_bar_rect.GetBR(), GetColorU32(is_focused ? ImGuiCol_TitleBgActive : ImGuiCol_TitleBg), window_rounding, ImDrawCornerFlags_Top); + window->DrawList->AddRectFilled(title_bar_rect.Min, title_bar_rect.Max, GetColorU32(window_is_focused ? ImGuiCol_TitleBgActive : ImGuiCol_TitleBg), window_rounding, ImDrawCornerFlags_Top); // Menu bar if (flags & ImGuiWindowFlags_MenuBar) { ImRect menu_bar_rect = window->MenuBarRect(); - window->DrawList->AddRectFilled(menu_bar_rect.GetTL(), menu_bar_rect.GetBR(), GetColorU32(ImGuiCol_MenuBarBg), (flags & ImGuiWindowFlags_NoTitleBar) ? window_rounding : 0.0f, ImDrawCornerFlags_Top); - if (style.FrameBorderSize > 0.0f) + menu_bar_rect.ClipWith(window->Rect()); // Soft clipping, in particular child window don't have minimum size covering the menu bar so this is useful for them. + window->DrawList->AddRectFilled(menu_bar_rect.Min, menu_bar_rect.Max, GetColorU32(ImGuiCol_MenuBarBg), (flags & ImGuiWindowFlags_NoTitleBar) ? window_rounding : 0.0f, ImDrawCornerFlags_Top); + if (style.FrameBorderSize > 0.0f && menu_bar_rect.Max.y < window->Pos.y + window->Size.y) window->DrawList->AddLine(menu_bar_rect.GetBL(), menu_bar_rect.GetBR(), GetColorU32(ImGuiCol_Border), style.FrameBorderSize); } @@ -9231,14 +9232,18 @@ bool ImGui::BeginMenuBar() if (!(window->Flags & ImGuiWindowFlags_MenuBar)) return false; - ImGuiContext& g = *GImGui; IM_ASSERT(!window->DC.MenuBarAppending); BeginGroup(); // Save position PushID("##menubar"); - ImRect rect = window->MenuBarRect(); - rect.Max.x = ImMax(rect.Min.x, rect.Max.x - g.Style.WindowRounding); - PushClipRect(ImVec2(ImFloor(rect.Min.x+0.5f), ImFloor(rect.Min.y + window->WindowBorderSize + 0.5f)), ImVec2(ImFloor(rect.Max.x+0.5f), ImFloor(rect.Max.y+0.5f)), false); - window->DC.CursorPos = ImVec2(rect.Min.x + window->DC.MenuBarOffsetX, rect.Min.y);// + g.Style.FramePadding.y); + + // We don't clip with regular window clipping rectangle as it is already set to the area below. However we clip with window full rect. + // We remove 1 worth of rounding to Max.x to that text in long menus don't tend to display over the lower-right rounded area, which looks particularly glitchy. + ImRect bar_rect = window->MenuBarRect(); + ImRect clip_rect(ImFloor(bar_rect.Min.x + 0.5f), ImFloor(bar_rect.Min.y + window->WindowBorderSize + 0.5f), ImFloor(ImMax(bar_rect.Min.x, bar_rect.Max.x - window->WindowRounding) + 0.5f), ImFloor(bar_rect.Max.y + 0.5f)); + clip_rect.ClipWith(window->Rect()); + PushClipRect(clip_rect.Min, clip_rect.Max, false); + + window->DC.CursorPos = ImVec2(bar_rect.Min.x + window->DC.MenuBarOffsetX, bar_rect.Min.y);// + g.Style.FramePadding.y); window->DC.LayoutType = ImGuiLayoutType_Horizontal; window->DC.MenuBarAppending = true; AlignTextToFramePadding(); diff --git a/imgui_internal.h b/imgui_internal.h index e54936a5b643..f155abf74c3f 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -746,6 +746,7 @@ struct IMGUI_API ImGuiWindow ImGuiID GetID(const void* ptr); ImGuiID GetIDNoKeepAlive(const char* str, const char* str_end = NULL); + // We don't use g.FontSize because the window may be != g.CurrentWidow. ImRect Rect() const { return ImRect(Pos.x, Pos.y, Pos.x+Size.x, Pos.y+Size.y); } float CalcFontSize() const { return GImGui->FontBaseSize * FontWindowScale; } float TitleBarHeight() const { return (Flags & ImGuiWindowFlags_NoTitleBar) ? 0.0f : CalcFontSize() + GImGui->Style.FramePadding.y * 2.0f; } From 6d3cfba8342c32c8f4739eb818779a9d5b05e260 Mon Sep 17 00:00:00 2001 From: stfx Date: Thu, 23 Nov 2017 12:37:11 +0100 Subject: [PATCH 236/823] Add Slider hover color just like Drag I feel like there should be hover color options for each different control instead of the grouped frame color to make it usable for everyone. This also would not reduce performance as all controls already check for hover state as required by the ImGUI::IsHoveredItem() API. --- imgui.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/imgui.cpp b/imgui.cpp index c1361f735bfd..9149eabe850a 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -6856,7 +6856,8 @@ bool ImGui::SliderBehavior(const ImRect& frame_bb, ImGuiID id, float* v, float v const ImGuiStyle& style = g.Style; // Draw frame - RenderFrame(frame_bb.Min, frame_bb.Max, GetColorU32(ImGuiCol_FrameBg), true, style.FrameRounding); + const ImU32 frame_col = GetColorU32(g.ActiveId == id ? ImGuiCol_FrameBgActive : g.HoveredId == id ? ImGuiCol_FrameBgHovered : ImGuiCol_FrameBg); + RenderFrame(frame_bb.Min, frame_bb.Max, frame_col, true, style.FrameRounding); const bool is_non_linear = (power < 1.0f-0.00001f) || (power > 1.0f+0.00001f); const bool is_horizontal = (flags & ImGuiSliderFlags_Vertical) == 0; From 4e3c7f1557af3627f3882ab27bbaecd7cc559427 Mon Sep 17 00:00:00 2001 From: omar Date: Fri, 24 Nov 2017 16:50:11 +0100 Subject: [PATCH 237/823] Nav: Exposed NavInitWindow() in imgui_internal (#787) --- imgui.cpp | 4 ++-- imgui_internal.h | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 815858f28d76..535824504787 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2528,7 +2528,7 @@ int ImGui::GetFrameCount() } // This needs to be called before we submit any widget (aka in or before Begin) -static void NavInitWindow(ImGuiWindow* window, bool force_reinit) +void ImGui::NavInitWindow(ImGuiWindow* window, bool force_reinit) { ImGuiContext& g = *GImGui; IM_ASSERT(window == g.NavWindow); @@ -4724,7 +4724,7 @@ static bool BeginChildEx(const char* name, ImGuiID id, const ImVec2& size_arg, b if (/*!(flags & ImGuiWindowFlags_NavFlattened) &&*/ (child_window->DC.NavLayerActiveMask != 0 || child_window->DC.NavHasScroll) && g.NavActivateId == id) { ImGui::FocusWindow(child_window); - NavInitWindow(child_window, false); + ImGui::NavInitWindow(child_window, false); ImGui::SetActiveID(id+1, child_window); // Steal ActiveId with a dummy id so that key-press won't activate child item g.ActiveIdSource = ImGuiInputSource_Nav; } diff --git a/imgui_internal.h b/imgui_internal.h index 5b238a35c266..0bae4d9bd0a7 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -914,6 +914,8 @@ namespace ImGui IMGUI_API bool BeginPopupEx(ImGuiID id, ImGuiWindowFlags extra_flags); IMGUI_API void BeginTooltipEx(ImGuiWindowFlags extra_flags, bool override_previous_tooltip = true); + IMGUI_API void NavInitWindow(ImGuiWindow* window, bool force_reinit); + IMGUI_API int CalcTypematicPressedRepeatAmount(float t, float t_prev, float repeat_delay, float repeat_rate); IMGUI_API void Scrollbar(ImGuiLayoutType direction); From 46e994de4e9b334e5bf56a9f6f33bf618c72cb9a Mon Sep 17 00:00:00 2001 From: omar Date: Fri, 24 Nov 2017 16:54:03 +0100 Subject: [PATCH 238/823] Nav: Do not clear last navigation id stored in a hidden child window. (#787) --- imgui.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/imgui.cpp b/imgui.cpp index 535824504787..c5a804d8333f 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -5054,7 +5054,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) } const bool window_just_appearing_after_hidden_for_resize = (window->HiddenFrames == 1); - if (window_just_appearing_after_hidden_for_resize) + if (window_just_appearing_after_hidden_for_resize && !(flags & ImGuiWindowFlags_ChildWindow)) window->NavLastIds[0] = 0; window->Appearing = (window_just_activated_by_user || window_just_appearing_after_hidden_for_resize); window->CloseButton = (p_open != NULL); From 77a310736dfbd79c9d0cf8f52835ed5f4d859441 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emmanuel=20Beno=C3=AEt?= Date: Mon, 27 Nov 2017 20:36:23 +0100 Subject: [PATCH 239/823] Horizontal mouse wheel support This patch adds support for the horizontal mouse wheel in ImGui. It affects windows that can be scrolled, as long as the Ctrl key is not being pressed. The scrolling speed has been set empirically so that it matches the scrolling speed on the Firefox browser when the horizontal wheel is used. Internally, it adds a MouseHorizWheel to ImGuiIO, which is then used in NewFrame to scroll the current window. The SDL/GL2, SDL/GL3, GLFW/GL2 and GLFW/GL3 examples has been modified to use it. --- examples/opengl2_example/imgui_impl_glfw.cpp | 9 ++++++--- .../opengl3_example/imgui_impl_glfw_gl3.cpp | 9 ++++++--- .../sdl_opengl2_example/imgui_impl_sdl.cpp | 8 +++++++- .../sdl_opengl3_example/imgui_impl_sdl_gl3.cpp | 8 +++++++- imgui.cpp | 18 ++++++++++++++++++ imgui.h | 1 + 6 files changed, 45 insertions(+), 8 deletions(-) diff --git a/examples/opengl2_example/imgui_impl_glfw.cpp b/examples/opengl2_example/imgui_impl_glfw.cpp index 364d92889576..8aa6395ac26f 100644 --- a/examples/opengl2_example/imgui_impl_glfw.cpp +++ b/examples/opengl2_example/imgui_impl_glfw.cpp @@ -31,6 +31,7 @@ static GLFWwindow* g_Window = NULL; static double g_Time = 0.0f; static bool g_MouseJustPressed[3] = { false, false, false }; +static float g_MouseHorizWheel = 0.0f; static float g_MouseWheel = 0.0f; static GLuint g_FontTexture = 0; @@ -136,9 +137,10 @@ void ImGui_ImplGlfwGL2_MouseButtonCallback(GLFWwindow*, int button, int action, g_MouseJustPressed[button] = true; } -void ImGui_ImplGlfwGL2_ScrollCallback(GLFWwindow*, double /*xoffset*/, double yoffset) +void ImGui_ImplGlfwGL2_ScrollCallback(GLFWwindow*, double xoffset, double yoffset) { - g_MouseWheel += (float)yoffset; // Use fractional mouse wheel. + g_MouseHorizWheel += (float)xoffset; // Use fractional mouse wheel. + g_MouseWheel += (float)yoffset; } void ImGui_ImplGlfwGL2_KeyCallback(GLFWwindow*, int key, int, int action, int mods) @@ -296,8 +298,9 @@ void ImGui_ImplGlfwGL2_NewFrame() g_MouseJustPressed[i] = false; } + io.MouseHorizWheel = g_MouseHorizWheel; io.MouseWheel = g_MouseWheel; - g_MouseWheel = 0.0f; + g_MouseHorizWheel = g_MouseWheel = 0.0f; // Hide OS mouse cursor if ImGui is drawing it glfwSetInputMode(g_Window, GLFW_CURSOR, io.MouseDrawCursor ? GLFW_CURSOR_HIDDEN : GLFW_CURSOR_NORMAL); diff --git a/examples/opengl3_example/imgui_impl_glfw_gl3.cpp b/examples/opengl3_example/imgui_impl_glfw_gl3.cpp index 7d924fcf1887..01accf0c2110 100644 --- a/examples/opengl3_example/imgui_impl_glfw_gl3.cpp +++ b/examples/opengl3_example/imgui_impl_glfw_gl3.cpp @@ -25,6 +25,7 @@ static GLFWwindow* g_Window = NULL; static double g_Time = 0.0f; static bool g_MouseJustPressed[3] = { false, false, false }; +static float g_MouseHorizWheel = 0.0f; static float g_MouseWheel = 0.0f; static GLuint g_FontTexture = 0; static int g_ShaderHandle = 0, g_VertHandle = 0, g_FragHandle = 0; @@ -155,9 +156,10 @@ void ImGui_ImplGlfwGL3_MouseButtonCallback(GLFWwindow*, int button, int action, g_MouseJustPressed[button] = true; } -void ImGui_ImplGlfwGL3_ScrollCallback(GLFWwindow*, double /*xoffset*/, double yoffset) +void ImGui_ImplGlfwGL3_ScrollCallback(GLFWwindow*, double xoffset, double yoffset) { - g_MouseWheel += (float)yoffset; // Use fractional mouse wheel. + g_MouseHorizWheel += (float)xoffset; // Use fractional mouse wheel. + g_MouseWheel += (float)yoffset; } void ImGui_ImplGlfwGL3_KeyCallback(GLFWwindow*, int key, int, int action, int mods) @@ -408,8 +410,9 @@ void ImGui_ImplGlfwGL3_NewFrame() g_MouseJustPressed[i] = false; } + io.MouseHorizWheel = g_MouseHorizWheel; io.MouseWheel = g_MouseWheel; - g_MouseWheel = 0.0f; + g_MouseHorizWheel = g_MouseWheel = 0.0f; // Hide OS mouse cursor if ImGui is drawing it glfwSetInputMode(g_Window, GLFW_CURSOR, io.MouseDrawCursor ? GLFW_CURSOR_HIDDEN : GLFW_CURSOR_NORMAL); diff --git a/examples/sdl_opengl2_example/imgui_impl_sdl.cpp b/examples/sdl_opengl2_example/imgui_impl_sdl.cpp index 66f3ed5a8472..b0a2553dc159 100644 --- a/examples/sdl_opengl2_example/imgui_impl_sdl.cpp +++ b/examples/sdl_opengl2_example/imgui_impl_sdl.cpp @@ -24,6 +24,7 @@ // Data static double g_Time = 0.0f; static bool g_MousePressed[3] = { false, false, false }; +static float g_MouseHorizWheel = 0.0f; static float g_MouseWheel = 0.0f; static GLuint g_FontTexture = 0; @@ -134,6 +135,10 @@ bool ImGui_ImplSdlGL2_ProcessEvent(SDL_Event* event) { case SDL_MOUSEWHEEL: { + if (event->wheel.x > 0) + g_MouseHorizWheel = 1; + if (event->wheel.x < 0) + g_MouseHorizWheel = -1; if (event->wheel.y > 0) g_MouseWheel = 1; if (event->wheel.y < 0) @@ -285,8 +290,9 @@ void ImGui_ImplSdlGL2_NewFrame(SDL_Window *window) io.MouseDown[2] = g_MousePressed[2] || (mouseMask & SDL_BUTTON(SDL_BUTTON_MIDDLE)) != 0; g_MousePressed[0] = g_MousePressed[1] = g_MousePressed[2] = false; + io.MouseHorizWheel = g_MouseHorizWheel; io.MouseWheel = g_MouseWheel; - g_MouseWheel = 0.0f; + g_MouseWheel = g_MouseHorizWheel = 0.0f; // Hide OS mouse cursor if ImGui is drawing it SDL_ShowCursor(io.MouseDrawCursor ? 0 : 1); diff --git a/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.cpp b/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.cpp index 68e27a68c645..933669cf407d 100644 --- a/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.cpp +++ b/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.cpp @@ -19,6 +19,7 @@ // Data static double g_Time = 0.0f; static bool g_MousePressed[3] = { false, false, false }; +static float g_MouseHorizWheel = 0.0f; static float g_MouseWheel = 0.0f; static GLuint g_FontTexture = 0; static int g_ShaderHandle = 0, g_VertHandle = 0, g_FragHandle = 0; @@ -154,6 +155,10 @@ bool ImGui_ImplSdlGL3_ProcessEvent(SDL_Event* event) { case SDL_MOUSEWHEEL: { + if (event->wheel.x > 0) + g_MouseHorizWheel = 1; + if (event->wheel.x < 0) + g_MouseHorizWheel = -1; if (event->wheel.y > 0) g_MouseWheel = 1; if (event->wheel.y < 0) @@ -396,8 +401,9 @@ void ImGui_ImplSdlGL3_NewFrame(SDL_Window* window) io.MouseDown[2] = g_MousePressed[2] || (mouseMask & SDL_BUTTON(SDL_BUTTON_MIDDLE)) != 0; g_MousePressed[0] = g_MousePressed[1] = g_MousePressed[2] = false; + io.MouseHorizWheel = g_MouseHorizWheel; io.MouseWheel = g_MouseWheel; - g_MouseWheel = 0.0f; + g_MouseHorizWheel = g_MouseWheel = 0.0f; // Hide OS mouse cursor if ImGui is drawing it SDL_ShowCursor(io.MouseDrawCursor ? 0 : 1); diff --git a/imgui.cpp b/imgui.cpp index 211bd299da01..f13cfb4d6e82 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -628,6 +628,7 @@ static bool IsKeyPressedMap(ImGuiKey key, bool repeat = true); static ImFont* GetDefaultFont(); static void SetCurrentFont(ImFont* font); static void SetCurrentWindow(ImGuiWindow* window); +static void SetWindowScrollX(ImGuiWindow* window, float new_scroll_x); static void SetWindowScrollY(ImGuiWindow* window, float new_scroll_y); static void SetWindowPos(ImGuiWindow* window, const ImVec2& pos, ImGuiCond cond); static void SetWindowSize(ImGuiWindow* window, const ImVec2& size, ImGuiCond cond); @@ -2430,6 +2431,16 @@ void ImGui::NewFrame() } } + // Horizontal wheel scrolling; for consistency, only allowed if Ctrl is not pressed. + if (g.HoveredWindow && g.IO.MouseHorizWheel != 0.0f && !g.HoveredWindow->Collapsed) + { + ImGuiWindow* window = g.HoveredWindow; + if (!g.IO.KeyCtrl && !(window->Flags & ImGuiWindowFlags_NoScrollWithMouse)) + { + SetWindowScrollX(window, window->Scroll.x - g.IO.MouseHorizWheel * 10.f); + } + } + // Pressing TAB activate widget focus if (g.ActiveId == 0 && g.NavWindow != NULL && g.NavWindow->Active && IsKeyPressedMap(ImGuiKey_Tab, false)) g.NavWindow->FocusIdxTabRequestNext = 0; @@ -5244,6 +5255,13 @@ ImVec2 ImGui::GetWindowPos() return window->Pos; } +static void SetWindowScrollX(ImGuiWindow* window, float new_scroll_x) +{ + window->DC.CursorMaxPos.x += window->Scroll.x; // SizeContents is generally computed based on CursorMaxPos which is affected by scroll position, so we need to apply our change to it. + window->Scroll.x = new_scroll_x; + window->DC.CursorMaxPos.x -= window->Scroll.x; +} + static void SetWindowScrollY(ImGuiWindow* window, float new_scroll_y) { window->DC.CursorMaxPos.y += window->Scroll.y; // SizeContents is generally computed based on CursorMaxPos which is affected by scroll position, so we need to apply our change to it. diff --git a/imgui.h b/imgui.h index 4599d705fd2f..d45b5e865086 100644 --- a/imgui.h +++ b/imgui.h @@ -856,6 +856,7 @@ struct ImGuiIO ImVec2 MousePos; // Mouse position, in pixels. Set to ImVec2(-FLT_MAX,-FLT_MAX) if mouse is unavailable (on another screen, etc.) bool MouseDown[5]; // Mouse buttons: left, right, middle + extras. ImGui itself mostly only uses left button (BeginPopupContext** are using right button). Others buttons allows us to track if the mouse is being used by your application + available to user as a convenience via IsMouse** API. float MouseWheel; // Mouse wheel: 1 unit scrolls about 5 lines text. + float MouseHorizWheel; // Horizontal mouse wheel bool MouseDrawCursor; // Request ImGui to draw a mouse cursor for you (if you are on a platform without a mouse cursor). bool KeyCtrl; // Keyboard modifier pressed: Control bool KeyShift; // Keyboard modifier pressed: Shift From 6ea744d8f42cd8b5bd89562126712ddd79700721 Mon Sep 17 00:00:00 2001 From: omar Date: Thu, 30 Nov 2017 16:54:39 +0100 Subject: [PATCH 240/823] Drag and Drop: Added DragSource from color square. Added DragTarget on ColorEdit4 widget. (#143) --- imgui.cpp | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/imgui.cpp b/imgui.cpp index a21cba8bccef..280a2438a45a 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -9671,6 +9671,16 @@ bool ImGui::ColorButton(const char* desc_id, const ImVec4& col, ImGuiColorEditFl else window->DrawList->AddRect(bb.Min, bb.Max, GetColorU32(ImGuiCol_FrameBg), rounding); // Color button are often in need of some sort of border + if (g.ActiveId == id && BeginDragDropSource()) // NB: The ActiveId test is merely an optional micro-optimization + { + SetDragDropPayload(IMGUI_PAYLOAD_TYPE_COLOR_4F, &col, sizeof(col), ImGuiCond_Once); + ColorButton(desc_id, col, flags); + SameLine(); + TextUnformatted("Color"); + EndDragDropSource(); + hovered = false; + } + if (!(flags & ImGuiColorEditFlags_NoTooltip) && hovered) ColorTooltip(desc_id, &col.x, flags & (ImGuiColorEditFlags_NoAlpha | ImGuiColorEditFlags_AlphaPreview | ImGuiColorEditFlags_AlphaPreviewHalf)); @@ -9947,6 +9957,17 @@ bool ImGui::ColorEdit4(const char* label, float col[4], ImGuiColorEditFlags flag PopID(); EndGroup(); + if (window->DC.LastItemRectHoveredRect && BeginDragDropTarget()) // NB: The LastItemRectHoveredRect test is merely an optional micro-optimization + { + if (const ImGuiPayload* payload = AcceptDragDropPayload(IMGUI_PAYLOAD_TYPE_COLOR_4F)) + { + IM_ASSERT(payload->DataSize == sizeof(ImVec4)); + memcpy((float*)col, payload->Data, sizeof(ImVec4)); + value_changed = true; + } + EndDragDropTarget(); + } + return value_changed; } From 2ca4f9e862fcd4076fb5693b9cc343c92e2564ea Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 5 Dec 2017 20:36:35 +0100 Subject: [PATCH 241/823] Added ImGuiWindowFlags_ResizeFromAnySide flag and code to resize from any of the 4 corners (only 2 corners enabled). (#822) --- imgui.cpp | 113 +++++++++++++++++++++++++++++++++++++++--------------- imgui.h | 2 + 2 files changed, 85 insertions(+), 30 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index e6a91bc676f6..1eaf0efac732 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -4198,6 +4198,37 @@ static ImGuiCol GetWindowBgColorIdxFromFlags(ImGuiWindowFlags flags) return ImGuiCol_WindowBg; } +static void CalcResizePosSizeFromAnyCorner(ImGuiWindow* window, const ImVec2& corner_target, const ImVec2& corner_norm, ImVec2* out_pos, ImVec2* out_size) +{ + ImVec2 pos_min = ImLerp(corner_target, window->Pos, corner_norm); // Expected window upper-left + ImVec2 pos_max = ImLerp(window->Pos + window->Size, corner_target, corner_norm); // Expected window lower-right + ImVec2 size_expected = pos_max - pos_min; + ImVec2 size_constrained = CalcSizeFullWithConstraint(window, size_expected); + *out_pos = pos_min; + if (corner_norm.x == 0.0f) + out_pos->x -= (size_constrained.x - size_expected.x); + if (corner_norm.y == 0.0f) + out_pos->y -= (size_constrained.y - size_expected.y); + *out_size = size_constrained; +} + +struct ImGuiResizeGripDef +{ + const char* StrId; + ImVec2 CornerNorm; + ImVec2 InnerDir; + int AngleMin12, AngleMax12; + ImGuiMouseCursor MouseCursor; +}; + +const ImGuiResizeGripDef resize_grip_def[4] = +{ + { "#RESIZE0", ImVec2(1,1), ImVec2(-1,-1), 0, 3, ImGuiMouseCursor_ResizeNWSE }, // Lower right + { "#RESIZE1", ImVec2(0,1), ImVec2(+1,-1), 3, 6, ImGuiMouseCursor_ResizeNESW }, // Lower left + { "#RESIZE2", ImVec2(0,0), ImVec2(+1,+1), 6, 9, ImGuiMouseCursor_ResizeNWSE }, // Upper left + { "#RESIZE3", ImVec2(1,0), ImVec2(-1,+1), 9,12, ImGuiMouseCursor_ResizeNESW }, // Upper right +}; + // Push a new ImGui window to add widgets to. // - A default window called "Debug" is automatically stacked at the beginning of every frame so you can use widgets without explicitly calling a Begin/End pair. // - Begin/End can be called multiple times during the frame with the same window name to append content. @@ -4533,39 +4564,58 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) } else { - ImU32 resize_col = 0; - const float resize_corner_size = ImMax(g.FontSize * 1.35f, window_rounding + 1.0f + g.FontSize * 0.2f); + // Handle resize for: Resize Grips, Gamepad + ImU32 resize_grip_col[4] = { 0 }; + const int resize_grip_count = (flags & ImGuiWindowFlags_ResizeFromAnySide) ? 2 : 1; // 4 + const float resize_corner_size = (float)(int)ImMax(g.FontSize * 1.35f, window_rounding + 1.0f + g.FontSize * 0.2f); if (!(flags & ImGuiWindowFlags_AlwaysAutoResize) && window->AutoFitFramesX <= 0 && window->AutoFitFramesY <= 0 && !(flags & ImGuiWindowFlags_NoResize)) { - // Manual resize - // Using the FlattenChilds button flag, we make the resize button accessible even if we are hovering over a child window - const ImVec2 br = window->Rect().GetBR(); - const ImRect resize_rect(br - ImFloor(ImVec2(resize_corner_size * 0.75f, resize_corner_size * 0.75f)), br); - const ImGuiID resize_id = window->GetID("#RESIZE"); - bool hovered, held; - ButtonBehavior(resize_rect, resize_id, &hovered, &held, ImGuiButtonFlags_FlattenChilds); - resize_col = GetColorU32(held ? ImGuiCol_ResizeGripActive : hovered ? ImGuiCol_ResizeGripHovered : ImGuiCol_ResizeGrip); - if (hovered || held) - g.MouseCursor = ImGuiMouseCursor_ResizeNWSE; + ImVec2 pos_target(FLT_MAX, FLT_MAX); + ImVec2 size_target(FLT_MAX, FLT_MAX); - ImVec2 size_target(FLT_MAX,FLT_MAX); - if (g.HoveredWindow == window && held && g.IO.MouseDoubleClicked[0]) + // Manual resize grips + for (int resize_grip_n = 0; resize_grip_n < resize_grip_count; resize_grip_n++) { - // Manual auto-fit when double-clicking - size_target = size_auto_fit; - ClearActiveID(); + const ImGuiResizeGripDef& grip = resize_grip_def[resize_grip_n]; + const ImVec2 corner = ImLerp(window->Pos, window->Pos + window->Size, grip.CornerNorm); + + // Using the FlattenChilds button flag we make the resize button accessible even if we are hovering over a child window + ImRect resize_rect; + resize_rect.Add(corner); + resize_rect.Add(corner + grip.InnerDir * (float)(int)(resize_corner_size * 0.75f)); + bool hovered, held; + ButtonBehavior(resize_rect, window->GetID(grip.StrId), &hovered, &held, ImGuiButtonFlags_FlattenChilds); + if (hovered || held) + g.MouseCursor = grip.MouseCursor; + + if (g.HoveredWindow == window && held && g.IO.MouseDoubleClicked[0]) + { + // Manual auto-fit when double-clicking + size_target = CalcSizeFullWithConstraint(window, size_auto_fit); + ClearActiveID(); + } + else if (held) + { + // Resize from any of the four corners + // We don't use an incremental MouseDelta but rather compute an absolute target size based on mouse position + ImVec2 corner_target = g.IO.MousePos - g.ActiveIdClickOffset + resize_rect.GetSize() * grip.CornerNorm; // Corner of the window corresponding to our corner grip + CalcResizePosSizeFromAnyCorner(window, corner_target, grip.CornerNorm, &pos_target, &size_target); + } + resize_grip_col[resize_grip_n] = GetColorU32(held ? ImGuiCol_ResizeGripActive : hovered ? ImGuiCol_ResizeGripHovered : ImGuiCol_ResizeGrip); } - else if (held) + + // Apply back modified position/size to window + if (size_target.x != FLT_MAX) { - // We don't use an incremental MouseDelta but rather compute an absolute target size based on mouse position - size_target = (g.IO.MousePos - g.ActiveIdClickOffset - window->Pos) + resize_rect.GetSize(); + window->SizeFull = size_target; + MarkIniSettingsDirty(window); } - - if (size_target.x != FLT_MAX && size_target.y != FLT_MAX) + if (pos_target.x != FLT_MAX) { - window->SizeFull = CalcSizeFullWithConstraint(window, size_target); + window->Pos = window->PosFloat = ImVec2((float)(int)pos_target.x, (float)(int)pos_target.y); MarkIniSettingsDirty(window); } + window->Size = window->SizeFull; title_bar_rect = window->TitleBarRect(); } @@ -4595,15 +4645,18 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) if (window->ScrollbarY) Scrollbar(ImGuiLayoutType_Vertical); - // Render resize grip - // (after the input handling so we don't have a frame of latency) + // Render resize grips (after their input handling so we don't have a frame of latency) if (!(flags & ImGuiWindowFlags_NoResize)) { - const ImVec2 br = window->Rect().GetBR(); - window->DrawList->PathLineTo(br + ImVec2(-resize_corner_size, -window_border_size)); - window->DrawList->PathLineTo(br + ImVec2(-window_border_size, -resize_corner_size)); - window->DrawList->PathArcToFast(ImVec2(br.x - window_rounding - window_border_size, br.y - window_rounding - window_border_size), window_rounding, 0, 3); - window->DrawList->PathFillConvex(resize_col); + for (int resize_grip_n = 0; resize_grip_n < resize_grip_count; resize_grip_n++) + { + const ImGuiResizeGripDef& grip = resize_grip_def[resize_grip_n]; + const ImVec2 corner = ImLerp(window->Pos, window->Pos + window->Size, grip.CornerNorm); + window->DrawList->PathLineTo(corner + grip.InnerDir * ((resize_grip_n & 1) ? ImVec2(window_border_size, resize_corner_size) : ImVec2(resize_corner_size, window_border_size))); + window->DrawList->PathLineTo(corner + grip.InnerDir * ((resize_grip_n & 1) ? ImVec2(resize_corner_size, window_border_size) : ImVec2(window_border_size, resize_corner_size))); + window->DrawList->PathArcToFast(ImVec2(corner.x + grip.InnerDir.x * (window_rounding + window_border_size), corner.y + grip.InnerDir.y * (window_rounding + window_border_size)), window_rounding, grip.AngleMin12, grip.AngleMax12); + window->DrawList->PathFillConvex(resize_grip_col[resize_grip_n]); + } } // Borders diff --git a/imgui.h b/imgui.h index f09209103e29..ec5692e1a572 100644 --- a/imgui.h +++ b/imgui.h @@ -513,6 +513,8 @@ enum ImGuiWindowFlags_ ImGuiWindowFlags_AlwaysVerticalScrollbar= 1 << 14, // Always show vertical scrollbar (even if ContentSize.y < Size.y) ImGuiWindowFlags_AlwaysHorizontalScrollbar=1<< 15, // Always show horizontal scrollbar (even if ContentSize.x < Size.x) ImGuiWindowFlags_AlwaysUseWindowPadding = 1 << 16, // Ensure child windows without border uses style.WindowPadding (ignored by default for non-bordered child windows, because more convenient) + ImGuiWindowFlags_ResizeFromAnySide = 1 << 17, + // [Internal] ImGuiWindowFlags_ChildWindow = 1 << 22, // Don't use! For internal use by BeginChild() ImGuiWindowFlags_ComboBox = 1 << 23, // Don't use! For internal use by ComboBox() From b9dc0caee339e8b661e7ebf511138f68bfb0ee43 Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 5 Dec 2017 22:05:24 +0100 Subject: [PATCH 242/823] Tweak four-corners resize grip code. Added ImRect::FixInverted() helper. (#822) --- imgui.cpp | 39 ++++++++++++++++++++------------------- imgui_internal.h | 1 + 2 files changed, 21 insertions(+), 19 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 1eaf0efac732..5d95827b1c88 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -4214,19 +4214,17 @@ static void CalcResizePosSizeFromAnyCorner(ImGuiWindow* window, const ImVec2& co struct ImGuiResizeGripDef { - const char* StrId; - ImVec2 CornerNorm; + ImVec2 CornerPos; ImVec2 InnerDir; int AngleMin12, AngleMax12; - ImGuiMouseCursor MouseCursor; }; const ImGuiResizeGripDef resize_grip_def[4] = { - { "#RESIZE0", ImVec2(1,1), ImVec2(-1,-1), 0, 3, ImGuiMouseCursor_ResizeNWSE }, // Lower right - { "#RESIZE1", ImVec2(0,1), ImVec2(+1,-1), 3, 6, ImGuiMouseCursor_ResizeNESW }, // Lower left - { "#RESIZE2", ImVec2(0,0), ImVec2(+1,+1), 6, 9, ImGuiMouseCursor_ResizeNWSE }, // Upper left - { "#RESIZE3", ImVec2(1,0), ImVec2(-1,+1), 9,12, ImGuiMouseCursor_ResizeNESW }, // Upper right + { ImVec2(1,1), ImVec2(-1,-1), 0, 3 }, // Lower right + { ImVec2(0,1), ImVec2(+1,-1), 3, 6 }, // Lower left + { ImVec2(0,0), ImVec2(+1,+1), 6, 9 }, // Upper left + { ImVec2(1,0), ImVec2(-1,+1), 9,12 }, // Upper right }; // Push a new ImGui window to add widgets to. @@ -4567,26 +4565,28 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) // Handle resize for: Resize Grips, Gamepad ImU32 resize_grip_col[4] = { 0 }; const int resize_grip_count = (flags & ImGuiWindowFlags_ResizeFromAnySide) ? 2 : 1; // 4 - const float resize_corner_size = (float)(int)ImMax(g.FontSize * 1.35f, window_rounding + 1.0f + g.FontSize * 0.2f); + + const float grip_draw_size = (float)(int)ImMax(g.FontSize * 1.35f, window_rounding + 1.0f + g.FontSize * 0.2f); + const float grip_hover_size = (float)(int)(grip_draw_size * 0.75f); if (!(flags & ImGuiWindowFlags_AlwaysAutoResize) && window->AutoFitFramesX <= 0 && window->AutoFitFramesY <= 0 && !(flags & ImGuiWindowFlags_NoResize)) { ImVec2 pos_target(FLT_MAX, FLT_MAX); ImVec2 size_target(FLT_MAX, FLT_MAX); // Manual resize grips + PushID("#RESIZE"); for (int resize_grip_n = 0; resize_grip_n < resize_grip_count; resize_grip_n++) { const ImGuiResizeGripDef& grip = resize_grip_def[resize_grip_n]; - const ImVec2 corner = ImLerp(window->Pos, window->Pos + window->Size, grip.CornerNorm); + const ImVec2 corner = ImLerp(window->Pos, window->Pos + window->Size, grip.CornerPos); // Using the FlattenChilds button flag we make the resize button accessible even if we are hovering over a child window - ImRect resize_rect; - resize_rect.Add(corner); - resize_rect.Add(corner + grip.InnerDir * (float)(int)(resize_corner_size * 0.75f)); + ImRect resize_rect(corner, corner + grip.InnerDir * grip_hover_size); + resize_rect.FixInverted(); bool hovered, held; - ButtonBehavior(resize_rect, window->GetID(grip.StrId), &hovered, &held, ImGuiButtonFlags_FlattenChilds); + ButtonBehavior(resize_rect, window->GetID((void*)resize_grip_n), &hovered, &held, ImGuiButtonFlags_FlattenChilds); if (hovered || held) - g.MouseCursor = grip.MouseCursor; + g.MouseCursor = (resize_grip_n & 1) ? ImGuiMouseCursor_ResizeNESW : ImGuiMouseCursor_ResizeNWSE; if (g.HoveredWindow == window && held && g.IO.MouseDoubleClicked[0]) { @@ -4598,11 +4598,12 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) { // Resize from any of the four corners // We don't use an incremental MouseDelta but rather compute an absolute target size based on mouse position - ImVec2 corner_target = g.IO.MousePos - g.ActiveIdClickOffset + resize_rect.GetSize() * grip.CornerNorm; // Corner of the window corresponding to our corner grip - CalcResizePosSizeFromAnyCorner(window, corner_target, grip.CornerNorm, &pos_target, &size_target); + ImVec2 corner_target = g.IO.MousePos - g.ActiveIdClickOffset + resize_rect.GetSize() * grip.CornerPos; // Corner of the window corresponding to our corner grip + CalcResizePosSizeFromAnyCorner(window, corner_target, grip.CornerPos, &pos_target, &size_target); } resize_grip_col[resize_grip_n] = GetColorU32(held ? ImGuiCol_ResizeGripActive : hovered ? ImGuiCol_ResizeGripHovered : ImGuiCol_ResizeGrip); } + PopID(); // Apply back modified position/size to window if (size_target.x != FLT_MAX) @@ -4651,9 +4652,9 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) for (int resize_grip_n = 0; resize_grip_n < resize_grip_count; resize_grip_n++) { const ImGuiResizeGripDef& grip = resize_grip_def[resize_grip_n]; - const ImVec2 corner = ImLerp(window->Pos, window->Pos + window->Size, grip.CornerNorm); - window->DrawList->PathLineTo(corner + grip.InnerDir * ((resize_grip_n & 1) ? ImVec2(window_border_size, resize_corner_size) : ImVec2(resize_corner_size, window_border_size))); - window->DrawList->PathLineTo(corner + grip.InnerDir * ((resize_grip_n & 1) ? ImVec2(resize_corner_size, window_border_size) : ImVec2(window_border_size, resize_corner_size))); + const ImVec2 corner = ImLerp(window->Pos, window->Pos + window->Size, grip.CornerPos); + window->DrawList->PathLineTo(corner + grip.InnerDir * ((resize_grip_n & 1) ? ImVec2(window_border_size, grip_draw_size) : ImVec2(grip_draw_size, window_border_size))); + window->DrawList->PathLineTo(corner + grip.InnerDir * ((resize_grip_n & 1) ? ImVec2(grip_draw_size, window_border_size) : ImVec2(window_border_size, grip_draw_size))); window->DrawList->PathArcToFast(ImVec2(corner.x + grip.InnerDir.x * (window_rounding + window_border_size), corner.y + grip.InnerDir.y * (window_rounding + window_border_size)), window_rounding, grip.AngleMin12, grip.AngleMax12); window->DrawList->PathFillConvex(resize_grip_col[resize_grip_n]); } diff --git a/imgui_internal.h b/imgui_internal.h index b3371f5c1a8a..23992c438fd8 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -281,6 +281,7 @@ struct IMGUI_API ImRect void Translate(const ImVec2& v) { Min.x += v.x; Min.y += v.y; Max.x += v.x; Max.y += v.y; } void ClipWith(const ImRect& clip) { if (Min.x < clip.Min.x) Min.x = clip.Min.x; if (Min.y < clip.Min.y) Min.y = clip.Min.y; if (Max.x > clip.Max.x) Max.x = clip.Max.x; if (Max.y > clip.Max.y) Max.y = clip.Max.y; } void Floor() { Min.x = (float)(int)Min.x; Min.y = (float)(int)Min.y; Max.x = (float)(int)Max.x; Max.y = (float)(int)Max.y; } + void FixInverted() { if (Min.x > Max.x) ImSwap(Min.x, Max.x); if (Min.y > Max.y) ImSwap(Min.y, Max.y); } bool IsFinite() const { return Min.x != FLT_MAX; } ImVec2 GetClosestPoint(ImVec2 p, bool on_edge) const { From 5686c72bbdb01c120e3eae4c8271c534c92c6c94 Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 5 Dec 2017 22:38:02 +0100 Subject: [PATCH 243/823] Windows can be resized from their borders when ImGuiWindowFlags_ResizeFromAnySide is set. (#822) The interaction is currently unsatisfying because we can only reach a window from its inner rectangle (because of HoveredWindow filtering). --- imgui.cpp | 45 ++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 44 insertions(+), 1 deletion(-) diff --git a/imgui.cpp b/imgui.cpp index 5d95827b1c88..c02e29203a12 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -4227,6 +4227,18 @@ const ImGuiResizeGripDef resize_grip_def[4] = { ImVec2(1,0), ImVec2(-1,+1), 9,12 }, // Upper right }; +static ImRect GetBorderRect(ImGuiWindow* window, int border_n, float perp_padding, float thickness) +{ + ImRect rect = window->Rect(); + if (thickness == 0.0f) rect.Max -= ImVec2(1,1); + if (border_n == 0) return ImRect(rect.Min.x + perp_padding, rect.Min.y, rect.Max.x - perp_padding, rect.Min.y + thickness); + if (border_n == 1) return ImRect(rect.Max.x - thickness, rect.Min.y + perp_padding, rect.Max.x, rect.Max.y - perp_padding); + if (border_n == 2) return ImRect(rect.Min.x + perp_padding, rect.Max.y - thickness, rect.Max.x - perp_padding, rect.Max.y); + if (border_n == 3) return ImRect(rect.Min.x, rect.Min.y + perp_padding, rect.Min.x + thickness, rect.Max.y - perp_padding); + IM_ASSERT(0); + return ImRect(); +} + // Push a new ImGui window to add widgets to. // - A default window called "Debug" is automatically stacked at the beginning of every frame so you can use widgets without explicitly calling a Begin/End pair. // - Begin/End can be called multiple times during the frame with the same window name to append content. @@ -4562,9 +4574,11 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) } else { - // Handle resize for: Resize Grips, Gamepad + // Handle resize for: Resize Grips, Borders, Gamepad + int border_hovered = -1, border_held = -1; ImU32 resize_grip_col[4] = { 0 }; const int resize_grip_count = (flags & ImGuiWindowFlags_ResizeFromAnySide) ? 2 : 1; // 4 + const int resize_border_count = (flags & ImGuiWindowFlags_ResizeFromAnySide) ? 4 : 0; const float grip_draw_size = (float)(int)ImMax(g.FontSize * 1.35f, window_rounding + 1.0f + g.FontSize * 0.2f); const float grip_hover_size = (float)(int)(grip_draw_size * 0.75f); @@ -4603,6 +4617,30 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) } resize_grip_col[resize_grip_n] = GetColorU32(held ? ImGuiCol_ResizeGripActive : hovered ? ImGuiCol_ResizeGripHovered : ImGuiCol_ResizeGrip); } + for (int border_n = 0; border_n < resize_border_count; border_n++) + { + const float BORDER_SIZE = 5.0f; // FIXME: Only works _inside_ window because of HoveredWindow check. + const float BORDER_APPEAR_TIMER = 0.05f; // Reduce visual noise + bool hovered, held; + ImRect border_rect = GetBorderRect(window, border_n, grip_hover_size, BORDER_SIZE); + ButtonBehavior(border_rect, window->GetID((void*)(border_n+4)), &hovered, &held, ImGuiButtonFlags_FlattenChilds); + if ((hovered && g.HoveredIdTimer > BORDER_APPEAR_TIMER) || (held && g.ActiveIdTimer > BORDER_APPEAR_TIMER)) + { + g.MouseCursor = (border_n & 1) ? ImGuiMouseCursor_ResizeEW : ImGuiMouseCursor_ResizeNS; + if (hovered) border_hovered = border_n; + if (held) border_held = border_n; + } + if (held) + { + ImVec2 border_target = window->Pos; + ImVec2 border_posn; + if (border_n == 0) { border_posn = ImVec2(0, 0); border_target.y = (g.IO.MousePos.y - g.ActiveIdClickOffset.y); } + if (border_n == 1) { border_posn = ImVec2(1, 0); border_target.x = (g.IO.MousePos.x - g.ActiveIdClickOffset.x + BORDER_SIZE); } + if (border_n == 2) { border_posn = ImVec2(0, 1); border_target.y = (g.IO.MousePos.y - g.ActiveIdClickOffset.y + BORDER_SIZE); } + if (border_n == 3) { border_posn = ImVec2(0, 0); border_target.x = (g.IO.MousePos.x - g.ActiveIdClickOffset.x); } + CalcResizePosSizeFromAnyCorner(window, border_target, border_posn, &pos_target, &size_target); + } + } PopID(); // Apply back modified position/size to window @@ -4663,6 +4701,11 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) // Borders if (window_border_size > 0.0f) window->DrawList->AddRect(window->Pos, window->Pos+window->Size, GetColorU32(ImGuiCol_Border), window_rounding, ImDrawCornerFlags_All, window_border_size); + if (border_held != -1 || border_hovered != -1) + { + ImRect border = GetBorderRect(window, border_held != -1 ? border_held : border_hovered, grip_draw_size, 0.0f); + window->DrawList->AddLine(border.Min, border.Max, GetColorU32(border_held != -1 ? ImGuiCol_SeparatorActive : ImGuiCol_SeparatorHovered), ImMax(1.0f, window_border_size)); + } if (style.FrameBorderSize > 0 && !(flags & ImGuiWindowFlags_NoTitleBar)) window->DrawList->AddLine(title_bar_rect.GetBL()+ImVec2(1,-1), title_bar_rect.GetBR()+ImVec2(-1,-1), GetColorU32(ImGuiCol_Border), style.FrameBorderSize); } From 0f119865a67cd5d92e89a2da49656d3a9e6c4873 Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 5 Dec 2017 22:53:58 +0100 Subject: [PATCH 244/823] Comments about ImGuiWindowFlags_ResizeFromAnySide. Removed hovering color. May need its own color. (#822) --- imgui.cpp | 11 +++++------ imgui.h | 2 +- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index c02e29203a12..5c5a7f7b0dbb 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -4575,7 +4575,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) else { // Handle resize for: Resize Grips, Borders, Gamepad - int border_hovered = -1, border_held = -1; + int border_held = -1; ImU32 resize_grip_col[4] = { 0 }; const int resize_grip_count = (flags & ImGuiWindowFlags_ResizeFromAnySide) ? 2 : 1; // 4 const int resize_border_count = (flags & ImGuiWindowFlags_ResizeFromAnySide) ? 4 : 0; @@ -4624,10 +4624,9 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) bool hovered, held; ImRect border_rect = GetBorderRect(window, border_n, grip_hover_size, BORDER_SIZE); ButtonBehavior(border_rect, window->GetID((void*)(border_n+4)), &hovered, &held, ImGuiButtonFlags_FlattenChilds); - if ((hovered && g.HoveredIdTimer > BORDER_APPEAR_TIMER) || (held && g.ActiveIdTimer > BORDER_APPEAR_TIMER)) + if ((hovered && g.HoveredIdTimer > BORDER_APPEAR_TIMER) || held) { g.MouseCursor = (border_n & 1) ? ImGuiMouseCursor_ResizeEW : ImGuiMouseCursor_ResizeNS; - if (hovered) border_hovered = border_n; if (held) border_held = border_n; } if (held) @@ -4701,10 +4700,10 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) // Borders if (window_border_size > 0.0f) window->DrawList->AddRect(window->Pos, window->Pos+window->Size, GetColorU32(ImGuiCol_Border), window_rounding, ImDrawCornerFlags_All, window_border_size); - if (border_held != -1 || border_hovered != -1) + if (border_held != -1) { - ImRect border = GetBorderRect(window, border_held != -1 ? border_held : border_hovered, grip_draw_size, 0.0f); - window->DrawList->AddLine(border.Min, border.Max, GetColorU32(border_held != -1 ? ImGuiCol_SeparatorActive : ImGuiCol_SeparatorHovered), ImMax(1.0f, window_border_size)); + ImRect border = GetBorderRect(window, border_held, grip_draw_size, 0.0f); + window->DrawList->AddLine(border.Min, border.Max, GetColorU32(ImGuiCol_SeparatorActive), ImMax(1.0f, window_border_size)); } if (style.FrameBorderSize > 0 && !(flags & ImGuiWindowFlags_NoTitleBar)) window->DrawList->AddLine(title_bar_rect.GetBL()+ImVec2(1,-1), title_bar_rect.GetBR()+ImVec2(-1,-1), GetColorU32(ImGuiCol_Border), style.FrameBorderSize); diff --git a/imgui.h b/imgui.h index ec5692e1a572..71fe24c2d607 100644 --- a/imgui.h +++ b/imgui.h @@ -513,7 +513,7 @@ enum ImGuiWindowFlags_ ImGuiWindowFlags_AlwaysVerticalScrollbar= 1 << 14, // Always show vertical scrollbar (even if ContentSize.y < Size.y) ImGuiWindowFlags_AlwaysHorizontalScrollbar=1<< 15, // Always show horizontal scrollbar (even if ContentSize.x < Size.x) ImGuiWindowFlags_AlwaysUseWindowPadding = 1 << 16, // Ensure child windows without border uses style.WindowPadding (ignored by default for non-bordered child windows, because more convenient) - ImGuiWindowFlags_ResizeFromAnySide = 1 << 17, + ImGuiWindowFlags_ResizeFromAnySide = 1 << 17, // (WIP) Enable resize from any corners and borders. Your back-end needs to honor the different values of io.MouseCursor set by imgui. // [Internal] ImGuiWindowFlags_ChildWindow = 1 << 22, // Don't use! For internal use by BeginChild() From 2fc9a2e6e7f36a2b36dc0359ea3316558795c22f Mon Sep 17 00:00:00 2001 From: omar Date: Wed, 6 Dec 2017 15:20:36 +0100 Subject: [PATCH 245/823] Fixed nav branch merge issue. --- imgui.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/imgui.cpp b/imgui.cpp index a99c37438eaf..a84cd9702b9f 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -5520,7 +5520,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) ImRect resize_rect(corner, corner + grip.InnerDir * grip_hover_size); resize_rect.FixInverted(); bool hovered, held; - ButtonBehavior(resize_rect, window->GetID((void*)resize_grip_n), &hovered, &held, ImGuiButtonFlags_NoNavFocus); + ButtonBehavior(resize_rect, window->GetID((void*)resize_grip_n), &hovered, &held, ImGuiButtonFlags_FlattenChilds|ImGuiButtonFlags_NoNavFocus); if (hovered || held) g.MouseCursor = (resize_grip_n & 1) ? ImGuiMouseCursor_ResizeNESW : ImGuiMouseCursor_ResizeNWSE; From 6deb865f78c377004aae03658c88e0d8dee89f04 Mon Sep 17 00:00:00 2001 From: omar Date: Wed, 6 Dec 2017 17:48:28 +0100 Subject: [PATCH 246/823] Nav: Merge fix. --- imgui.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 73e77f762282..4b487a2aa620 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -5521,7 +5521,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) ImRect resize_rect(corner, corner + grip.InnerDir * grip_hover_size); resize_rect.FixInverted(); bool hovered, held; - ButtonBehavior(resize_rect, window->GetID((void*)resize_grip_n), &hovered, &held, ImGuiButtonFlags_FlattenChilds); + ButtonBehavior(resize_rect, window->GetID((void*)resize_grip_n), &hovered, &held, ImGuiButtonFlags_FlattenChilds | ImGuiButtonFlags_NoNavFocus); if (hovered || held) g.MouseCursor = (resize_grip_n & 1) ? ImGuiMouseCursor_ResizeNESW : ImGuiMouseCursor_ResizeNWSE; @@ -5547,7 +5547,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) const float BORDER_APPEAR_TIMER = 0.05f; // Reduce visual noise bool hovered, held; ImRect border_rect = GetBorderRect(window, border_n, grip_hover_size, BORDER_SIZE); - ButtonBehavior(border_rect, window->GetID((void*)(border_n+4)), &hovered, &held, ImGuiButtonFlags_FlattenChilds); + ButtonBehavior(border_rect, window->GetID((void*)(border_n+4)), &hovered, &held, ImGuiButtonFlags_FlattenChilds | ImGuiButtonFlags_NoNavFocus); if ((hovered && g.HoveredIdTimer > BORDER_APPEAR_TIMER) || held) { g.MouseCursor = (border_n & 1) ? ImGuiMouseCursor_ResizeEW : ImGuiMouseCursor_ResizeNS; From 7bf85db6c451163133a1197457a7a1dd7ff6fbdb Mon Sep 17 00:00:00 2001 From: omar Date: Fri, 8 Dec 2017 12:48:53 +0100 Subject: [PATCH 247/823] Drag and drop: Added COL3F payload for color without alpha overwrite. Exposed standard color payload types in imgui.h (#143) --- imgui.cpp | 13 ++++++++++--- imgui.h | 4 ++++ imgui_internal.h | 3 +-- 3 files changed, 15 insertions(+), 5 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 950addd730ab..c64a83393aff 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -9677,7 +9677,10 @@ bool ImGui::ColorButton(const char* desc_id, const ImVec4& col, ImGuiColorEditFl if (g.ActiveId == id && BeginDragDropSource()) // NB: The ActiveId test is merely an optional micro-optimization { - SetDragDropPayload(IMGUI_PAYLOAD_TYPE_COLOR_4F, &col, sizeof(col), ImGuiCond_Once); + if (flags & ImGuiColorEditFlags_NoAlpha) + SetDragDropPayload(IMGUI_PAYLOAD_TYPE_COLOR_3F, &col, sizeof(float) * 3, ImGuiCond_Once); + else + SetDragDropPayload(IMGUI_PAYLOAD_TYPE_COLOR_4F, &col, sizeof(float) * 4, ImGuiCond_Once); ColorButton(desc_id, col, flags); SameLine(); TextUnformatted("Color"); @@ -9963,10 +9966,14 @@ bool ImGui::ColorEdit4(const char* label, float col[4], ImGuiColorEditFlags flag if (window->DC.LastItemRectHoveredRect && BeginDragDropTarget()) // NB: The LastItemRectHoveredRect test is merely an optional micro-optimization { + if (const ImGuiPayload* payload = AcceptDragDropPayload(IMGUI_PAYLOAD_TYPE_COLOR_3F)) + { + memcpy((float*)col, payload->Data, sizeof(float) * 3); + value_changed = true; + } if (const ImGuiPayload* payload = AcceptDragDropPayload(IMGUI_PAYLOAD_TYPE_COLOR_4F)) { - IM_ASSERT(payload->DataSize == sizeof(ImVec4)); - memcpy((float*)col, payload->Data, sizeof(ImVec4)); + memcpy((float*)col, payload->Data, sizeof(float) * components); value_changed = true; } EndDragDropTarget(); diff --git a/imgui.h b/imgui.h index 0bc00310932c..294f669515be 100644 --- a/imgui.h +++ b/imgui.h @@ -610,6 +610,10 @@ enum ImGuiDragDropFlags_ ImGuiDragDropFlags_AcceptPeekOnly = ImGuiDragDropFlags_AcceptBeforeDelivery | ImGuiDragDropFlags_AcceptNoDrawDefaultRect // For peeking ahead and inspecting the payload before delivery. }; +// Standard Drag and Drop payload types. Types starting with '_' are defined by Dear ImGui. +#define IMGUI_PAYLOAD_TYPE_COLOR_3F "_COL3F" // float[3] // Standard type for colors, without alpha. User code may use this type. +#define IMGUI_PAYLOAD_TYPE_COLOR_4F "_COL4F" // float[4] // Standard type for colors. User code may use this type. + // User fill ImGuiIO.KeyMap[] array with indices into the ImGuiIO.KeysDown[512] array enum ImGuiKey_ { diff --git a/imgui_internal.h b/imgui_internal.h index 92d98876b27d..1bf61084310f 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -169,8 +169,7 @@ inline void operator delete(void*, ImPlacementNewDummy, void*) {} // Types //----------------------------------------------------------------------------- -// Drag and Drop payload types. String starting with '_' are managed by Dear ImGui. -#define IMGUI_PAYLOAD_TYPE_COLOR_4F "_COL4F" // float[4] // Standard type for colors. User code may use this type. Build a float[4] out of a float[3] if you don't have alpha. +// Internal Drag and Drop payload types. String starting with '_' are reserved for Dear ImGui. #define IMGUI_PAYLOAD_TYPE_DOCKABLE "_IMDOCK" // ImGuiWindow* // [Internal] Docking/tabs enum ImGuiButtonFlags_ From a4863e8084e4b80a38e2b76a9dd724c971ee5e7d Mon Sep 17 00:00:00 2001 From: omar Date: Fri, 8 Dec 2017 12:49:35 +0100 Subject: [PATCH 248/823] Demo: Picker with palette demo supports drag and drop. (#143, #346) --- imgui_demo.cpp | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 6b0fed769312..c74df6009908 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -775,12 +775,19 @@ void ImGui::ShowTestWindow(bool* p_open) ImGui::ColorEdit4("MyColor##3", (float*)&color, ImGuiColorEditFlags_NoInputs | ImGuiColorEditFlags_NoLabel | misc_flags); ImGui::Text("Color button with Custom Picker Popup:"); + + // Generate a dummy palette static bool saved_palette_inited = false; static ImVec4 saved_palette[32]; - static ImVec4 backup_color; if (!saved_palette_inited) for (int n = 0; n < IM_ARRAYSIZE(saved_palette); n++) + { ImGui::ColorConvertHSVtoRGB(n / 31.0f, 0.8f, 0.8f, saved_palette[n].x, saved_palette[n].y, saved_palette[n].z); + saved_palette[n].w = 1.0f; // Alpha + } + saved_palette_inited = true; + + static ImVec4 backup_color; bool open_popup = ImGui::ColorButton("MyColor##3b", color, misc_flags); ImGui::SameLine(); open_popup |= ImGui::Button("Palette"); @@ -809,8 +816,18 @@ void ImGui::ShowTestWindow(bool* p_open) ImGui::PushID(n); if ((n % 8) != 0) ImGui::SameLine(0.0f, ImGui::GetStyle().ItemSpacing.y); - if (ImGui::ColorButton("##palette", saved_palette[n], ImGuiColorEditFlags_NoPicker | ImGuiColorEditFlags_NoTooltip, ImVec2(20,20))) + if (ImGui::ColorButton("##palette", saved_palette[n], ImGuiColorEditFlags_NoAlpha | ImGuiColorEditFlags_NoPicker | ImGuiColorEditFlags_NoTooltip, ImVec2(20,20))) color = ImVec4(saved_palette[n].x, saved_palette[n].y, saved_palette[n].z, color.w); // Preserve alpha! + + if (ImGui::BeginDragDropTarget()) + { + if (const ImGuiPayload* payload = AcceptDragDropPayload(IMGUI_PAYLOAD_TYPE_COLOR_3F)) + memcpy((float*)&saved_palette[n], payload->Data, sizeof(float) * 3); + if (const ImGuiPayload* payload = AcceptDragDropPayload(IMGUI_PAYLOAD_TYPE_COLOR_4F)) + memcpy((float*)&saved_palette[n], payload->Data, sizeof(float) * 4); + EndDragDropTarget(); + } + ImGui::PopID(); } ImGui::EndGroup(); From 9ce51ad9f6c39a3b21799e39991484debf95fb5a Mon Sep 17 00:00:00 2001 From: omar Date: Fri, 8 Dec 2017 15:11:35 +0100 Subject: [PATCH 249/823] Fix bad merge --- imgui.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/imgui.cpp b/imgui.cpp index 5d6e5df6e290..f30884ab79b4 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -5633,7 +5633,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) { // FIXME-NAVIGATION: Should store and accumulate into a separate size buffer to handle sizing constraints properly, right now a constraint will make us stuck. g.NavWindowingToggleLayer = false; - size_target = CalcSizeFullWithConstraint(window, window->SizeFull + nav_resize_delta); + size_target = CalcSizeAfterConstraint(window, window->SizeFull + nav_resize_delta); } } } From a8c7b1a2a2fdd9119ae72a815171a9ab25df61bc Mon Sep 17 00:00:00 2001 From: omar Date: Sat, 9 Dec 2017 21:17:27 +0100 Subject: [PATCH 250/823] ColorEdit4: Made IsItemActive() return true when picker popup is active. (#1489) --- imgui.cpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 7bc95f5d64bb..5a0b2461ace0 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -10036,7 +10036,7 @@ bool ImGui::ColorEdit4(const char* label, float col[4], ImGuiColorEditFlags flag PopItemWidth(); } - bool picker_active = false; + ImGuiWindow* picker_active_window = NULL; if (!(flags & ImGuiColorEditFlags_NoSmallPreview)) { if (!(flags & ImGuiColorEditFlags_NoInputs)) @@ -10058,7 +10058,7 @@ bool ImGui::ColorEdit4(const char* label, float col[4], ImGuiColorEditFlags flag if (BeginPopup("picker")) { - picker_active = true; + picker_active_window = g.CurrentWindow; if (label != label_display_end) { TextUnformatted(label, label_display_end); @@ -10080,7 +10080,7 @@ bool ImGui::ColorEdit4(const char* label, float col[4], ImGuiColorEditFlags flag } // Convert back - if (!picker_active) + if (picker_active_window == NULL) { if (!value_changed_as_float) for (int n = 0; n < 4; n++) @@ -10100,6 +10100,10 @@ bool ImGui::ColorEdit4(const char* label, float col[4], ImGuiColorEditFlags flag PopID(); EndGroup(); + // When picker is being actively used, use its active id so IsItemActive() will function on ColorEdit4(). + if (picker_active_window && g.ActiveId != 0 && g.ActiveIdWindow == picker_active_window) + window->DC.LastItemId = g.ActiveId; + return value_changed; } From 0365c524a2f4641538ea3b9e5bde7c8342eec158 Mon Sep 17 00:00:00 2001 From: omar Date: Sat, 9 Dec 2017 21:25:20 +0100 Subject: [PATCH 251/823] ColorPicker4: Fixed returning true when holding mouse button on the sat/value/alpha locations. (#1489) --- imgui.cpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 5a0b2461ace0..f1c3af418e46 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -9883,7 +9883,7 @@ void ImGui::ColorEditOptionsPopup(const float* col, ImGuiColorEditFlags flags) EndPopup(); } -static void ColorPickerOptionsPopup(ImGuiColorEditFlags flags, float* ref_col) +static void ColorPickerOptionsPopup(ImGuiColorEditFlags flags, const float* ref_col) { bool allow_opt_picker = !(flags & ImGuiColorEditFlags__PickerMask); bool allow_opt_alpha_bar = !(flags & ImGuiColorEditFlags_NoAlpha) && !(flags & ImGuiColorEditFlags_AlphaBar); @@ -10167,6 +10167,7 @@ bool ImGui::ColorPicker4(const char* label, float col[4], ImGuiColorEditFlags fl flags |= (g.ColorEditOptions & ImGuiColorEditFlags_AlphaBar); // Setup + int components = (flags & ImGuiColorEditFlags_NoAlpha) ? 3 : 4; bool alpha_bar = (flags & ImGuiColorEditFlags_AlphaBar) && !(flags & ImGuiColorEditFlags_NoAlpha); ImVec2 picker_pos = window->DC.CursorPos; float square_sz = SmallSquareSize(); @@ -10176,6 +10177,9 @@ bool ImGui::ColorPicker4(const char* label, float col[4], ImGuiColorEditFlags fl float bar1_pos_x = bar0_pos_x + bars_width + style.ItemInnerSpacing.x; float bars_triangles_half_sz = (float)(int)(bars_width * 0.20f); + float backup_initial_col[4]; + memcpy(backup_initial_col, col, components * sizeof(float)); + float wheel_thickness = sv_picker_size * 0.08f; float wheel_r_outer = sv_picker_size * 0.50f; float wheel_r_inner = wheel_r_outer - wheel_thickness; @@ -10291,7 +10295,7 @@ bool ImGui::ColorPicker4(const char* label, float col[4], ImGuiColorEditFlags fl ImVec4 ref_col_v4(ref_col[0], ref_col[1], ref_col[2], (flags & ImGuiColorEditFlags_NoAlpha) ? 1.0f : ref_col[3]); if (ColorButton("##original", ref_col_v4, (flags & (ImGuiColorEditFlags_HDR|ImGuiColorEditFlags_AlphaPreview|ImGuiColorEditFlags_AlphaPreviewHalf|ImGuiColorEditFlags_NoTooltip)), ImVec2(square_sz * 3, square_sz * 2))) { - memcpy(col, ref_col, ((flags & ImGuiColorEditFlags_NoAlpha) ? 3 : 4) * sizeof(float)); + memcpy(col, ref_col, components * sizeof(float)); value_changed = true; } } @@ -10421,7 +10425,7 @@ bool ImGui::ColorPicker4(const char* label, float col[4], ImGuiColorEditFlags fl EndGroup(); PopID(); - return value_changed; + return value_changed && memcmp(backup_initial_col, col, components * sizeof(float)); } // Horizontal separating line. From e23083a080909042d8eda880d14299080116c9d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Branimir=20Karad=C5=BEi=C4=87?= Date: Sat, 9 Dec 2017 13:47:54 -0800 Subject: [PATCH 252/823] =?UTF-8?q?Fixed=20warning:=20logical=20=E2=80=98a?= =?UTF-8?q?nd=E2=80=99=20of=20equal=20expressions?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- imgui.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/imgui.cpp b/imgui.cpp index f1c3af418e46..04105d5244fd 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -4517,7 +4517,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) window->Size = window->Collapsed ? window->TitleBarRect().GetSize() : window->SizeFull; if ((flags & ImGuiWindowFlags_ChildWindow) && !(flags & ImGuiWindowFlags_Popup)) { - IM_ASSERT(window_size_x_set_by_api && window_size_x_set_by_api); // Submitted by BeginChild() + IM_ASSERT(window_size_x_set_by_api && window_size_y_set_by_api); // Submitted by BeginChild() window->Size = window->SizeFull; } From f72b002da876d783d72c63e0a4c41d2c7b519677 Mon Sep 17 00:00:00 2001 From: omar Date: Sun, 10 Dec 2017 16:05:47 +0100 Subject: [PATCH 253/823] Removed SetNextWindowContentWidth(), prefer using SetNextWindowContentSize(). Kept redirection function (will obsolete). (#246, #519, #1444) --- imgui.cpp | 8 +------- imgui.h | 4 ++-- 2 files changed, 3 insertions(+), 9 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 04105d5244fd..a9e4dce7484c 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -213,6 +213,7 @@ Here is a change-log of API breaking changes, if you are using one of the functions listed, expect to have to fix some code. Also read releases logs https://github.com/ocornut/imgui/releases for more details. + - 2017/12/10 (1.53) - removed SetNextWindowContentWidth(), prefer using SetNextWindowContentSize(). Kept redirection function (will obsolete). - 2017/11/27 (1.53) - renamed ImGuiTextBuffer::append() helper to appendf(), appendv() to appendfv(). If you copied the 'Log' demo in your code, it uses appendv() so that needs to be renamed. - 2017/11/18 (1.53) - Style, Begin: removed ImGuiWindowFlags_ShowBorders window flag. Borders are now fully set up in the ImGuiStyle structure (see e.g. style.FrameBorderSize, style.WindowBorderSize). Use ImGui::ShowStyleEditor() to look them up. Please note that the style system will keep evolving (hopefully stabilizing in Q1 2018), and so custom styles will probably subtly break over time. It is recommended you use the StyleColorsClassic(), StyleColorsDark(), StyleColorsLight() functions. @@ -5665,13 +5666,6 @@ void ImGui::SetNextWindowContentSize(const ImVec2& size) g.SetNextWindowContentSizeCond = ImGuiCond_Always; } -void ImGui::SetNextWindowContentWidth(float width) -{ - ImGuiContext& g = *GImGui; - g.SetNextWindowContentSizeVal = ImVec2(width, g.SetNextWindowContentSizeCond ? g.SetNextWindowContentSizeVal.y : 0.0f); - g.SetNextWindowContentSizeCond = ImGuiCond_Always; -} - void ImGui::SetNextWindowCollapsed(bool collapsed, ImGuiCond cond) { ImGuiContext& g = *GImGui; diff --git a/imgui.h b/imgui.h index 6bf33b77104c..5c426593a72e 100644 --- a/imgui.h +++ b/imgui.h @@ -159,8 +159,7 @@ namespace ImGui IMGUI_API void SetNextWindowPos(const ImVec2& pos, ImGuiCond cond = 0, const ImVec2& pivot = ImVec2(0,0)); // set next window position. call before Begin(). use pivot=(0.5f,0.5f) to center on given point, etc. IMGUI_API void SetNextWindowSize(const ImVec2& size, ImGuiCond cond = 0); // set next window size. set axis to 0.0f to force an auto-fit on this axis. call before Begin() IMGUI_API void SetNextWindowSizeConstraints(const ImVec2& size_min, const ImVec2& size_max, ImGuiSizeConstraintCallback custom_callback = NULL, void* custom_callback_data = NULL); // set next window size limits. use -1,-1 on either X/Y axis to preserve the current size. Use callback to apply non-trivial programmatic constraints. - IMGUI_API void SetNextWindowContentSize(const ImVec2& size); // set next window content size (enforce the range of scrollbars). set axis to 0.0f to leave it automatic. call before Begin() - IMGUI_API void SetNextWindowContentWidth(float width); // set next window content width (enforce the range of horizontal scrollbar). call before Begin() + IMGUI_API void SetNextWindowContentSize(const ImVec2& size); // set next window content size (~ enforce the range of scrollbars). set axis to 0.0f to leave it automatic. call before Begin() IMGUI_API void SetNextWindowCollapsed(bool collapsed, ImGuiCond cond = 0); // set next window collapsed state. call before Begin() IMGUI_API void SetNextWindowFocus(); // set next window to be focused / front-most. call before Begin() IMGUI_API void SetWindowPos(const ImVec2& pos, ImGuiCond cond = 0); // (not recommended) set current window position - call within Begin()/End(). prefer using SetNextWindowPos(), as this may incur tearing and side-effects. @@ -914,6 +913,7 @@ struct ImGuiIO #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS namespace ImGui { + static inline void SetNextWindowContentWidth(float width) { ImGui::SetNextWindowContentSize(ImVec2(width, 0.0f)); } // OBSOLETE 1.53+ (nb: original version preserved last Y value set by SetNextWindowContentSize()) static inline bool IsRootWindowOrAnyChildHovered(ImGuiHoveredFlags flags = 0) { return IsItemHovered(flags | ImGuiHoveredFlags_FlattenChilds); } // OBSOLETE 1.53+ use flags directly bool Begin(const char* name, bool* p_open, const ImVec2& size_on_first_use, float bg_alpha_override = -1.0f, ImGuiWindowFlags flags = 0); // OBSOLETE 1.52+. use SetNextWindowSize() instead if you want to set a window size. static inline void AlignFirstTextHeightToWidgets() { AlignTextToFramePadding(); } // OBSOLETE 1.52+ From 0872020c5c64cec0cfe5eaf060532865cb080dc2 Mon Sep 17 00:00:00 2001 From: omar Date: Sun, 10 Dec 2017 16:11:29 +0100 Subject: [PATCH 254/823] Comments --- imgui.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/imgui.h b/imgui.h index 5c426593a72e..8af7756771f6 100644 --- a/imgui.h +++ b/imgui.h @@ -277,7 +277,7 @@ namespace ImGui // Widgets: Main IMGUI_API bool Button(const char* label, const ImVec2& size = ImVec2(0,0)); // button IMGUI_API bool SmallButton(const char* label); // button with FramePadding=(0,0) to easily embed within text - IMGUI_API bool InvisibleButton(const char* str_id, const ImVec2& size); + IMGUI_API bool InvisibleButton(const char* str_id, const ImVec2& size); // button behavior without the visuals, useful to build custom behaviors using the public api (along with IsItemActive, IsItemHovered, etc.) IMGUI_API void Image(ImTextureID user_texture_id, const ImVec2& size, const ImVec2& uv0 = ImVec2(0,0), const ImVec2& uv1 = ImVec2(1,1), const ImVec4& tint_col = ImVec4(1,1,1,1), const ImVec4& border_col = ImVec4(0,0,0,0)); IMGUI_API bool ImageButton(ImTextureID user_texture_id, const ImVec2& size, const ImVec2& uv0 = ImVec2(0,0), const ImVec2& uv1 = ImVec2(1,1), int frame_padding = -1, const ImVec4& bg_col = ImVec4(0,0,0,0), const ImVec4& tint_col = ImVec4(1,1,1,1)); // <0 frame_padding uses default frame padding settings. 0 for no padding IMGUI_API bool Checkbox(const char* label, bool* v); From b75acc21b09fdcb3a8f9d7a84ba6cc197519f09d Mon Sep 17 00:00:00 2001 From: omar Date: Sun, 10 Dec 2017 16:48:18 +0100 Subject: [PATCH 255/823] Fix for border under title bar when WindowBorderSize == 0 and FrameBorderSize > 0 --- imgui.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/imgui.cpp b/imgui.cpp index a9e4dce7484c..ec20f7daf5a6 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -4766,7 +4766,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) window->DrawList->AddLine(border.Min, border.Max, GetColorU32(ImGuiCol_SeparatorActive), ImMax(1.0f, window_border_size)); } if (style.FrameBorderSize > 0 && !(flags & ImGuiWindowFlags_NoTitleBar)) - window->DrawList->AddLine(title_bar_rect.GetBL()+ImVec2(1,-1), title_bar_rect.GetBR()+ImVec2(-1,-1), GetColorU32(ImGuiCol_Border), style.FrameBorderSize); + window->DrawList->AddLine(title_bar_rect.GetBL() + ImVec2(style.WindowBorderSize, -1), title_bar_rect.GetBR() + ImVec2(-style.WindowBorderSize,-1), GetColorU32(ImGuiCol_Border), style.FrameBorderSize); } // Store a backup of SizeFull which we will use next frame to decide if we need scrollbars. From 20ba79aa56dd27fd9f52fd59f36bbd92d3ac23a4 Mon Sep 17 00:00:00 2001 From: omar Date: Sun, 10 Dec 2017 17:02:41 +0100 Subject: [PATCH 256/823] Demo: Added "No close" option. --- imgui_demo.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 7c3c71e2e28f..e1d7a99fb954 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -170,6 +170,7 @@ void ImGui::ShowTestWindow(bool* p_open) static bool no_move = false; static bool no_resize = false; static bool no_collapse = false; + static bool no_close = false; // Demonstrate the various window flags. Typically you would just use the default. ImGuiWindowFlags window_flags = 0; @@ -179,6 +180,8 @@ void ImGui::ShowTestWindow(bool* p_open) if (no_move) window_flags |= ImGuiWindowFlags_NoMove; if (no_resize) window_flags |= ImGuiWindowFlags_NoResize; if (no_collapse) window_flags |= ImGuiWindowFlags_NoCollapse; + if (no_close) p_open = NULL; // Don't pass our bool* to Begin + ImGui::SetNextWindowSize(ImVec2(550,680), ImGuiCond_FirstUseEver); if (!ImGui::Begin("ImGui Demo", p_open, window_flags)) { @@ -241,6 +244,7 @@ void ImGui::ShowTestWindow(bool* p_open) ImGui::Checkbox("No move", &no_move); ImGui::SameLine(150); ImGui::Checkbox("No resize", &no_resize); ImGui::SameLine(300); ImGui::Checkbox("No collapse", &no_collapse); + ImGui::Checkbox("No close", &no_close); if (ImGui::TreeNode("Style")) { @@ -248,7 +252,7 @@ void ImGui::ShowTestWindow(bool* p_open) ImGui::TreePop(); } - if (ImGui::TreeNode("Logging")) + if (ImGui::TreeNode("Capture/Logging")) { ImGui::TextWrapped("The logging API redirects all text output so you can easily capture the content of a window or a block. Tree nodes can be automatically expanded. You can also call ImGui::LogText() to output directly to the log without a visual output."); ImGui::LogButtons(); From a9b01600ac309706ac6f798ca26abfa06d3c896e Mon Sep 17 00:00:00 2001 From: omar Date: Sun, 10 Dec 2017 17:24:10 +0100 Subject: [PATCH 257/823] Internals: window->InnerRect includes removal of borders so it'll be easier to use from other locations. --- imgui.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index ec20f7daf5a6..522d2b156094 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -4874,10 +4874,10 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) // Inner rectangle // We set this up after processing the resize grip so that our clip rectangle doesn't lag by a frame // Note that if our window is collapsed we will end up with a null clipping rectangle which is the correct behavior. - window->InnerRect.Min.x = title_bar_rect.Min.x; - window->InnerRect.Min.y = title_bar_rect.Max.y + window->MenuBarHeight(); - window->InnerRect.Max.x = window->Pos.x + window->Size.x - window->ScrollbarSizes.x; - window->InnerRect.Max.y = window->Pos.y + window->Size.y - window->ScrollbarSizes.y; + window->InnerRect.Min.x = title_bar_rect.Min.x + window->WindowBorderSize; + window->InnerRect.Min.y = title_bar_rect.Max.y + window->MenuBarHeight() + (((flags & ImGuiWindowFlags_MenuBar) || !(flags & ImGuiWindowFlags_NoTitleBar)) ? style.FrameBorderSize : window->WindowBorderSize); + window->InnerRect.Max.x = window->Pos.x + window->Size.x - window->ScrollbarSizes.x - window->WindowBorderSize; + window->InnerRect.Max.y = window->Pos.y + window->Size.y - window->ScrollbarSizes.y - window->WindowBorderSize; //window->DrawList->AddRect(window->InnerRect.Min, window->InnerRect.Max, IM_COL32_WHITE); // After Begin() we fill the last item / hovered data using the title bar data. Make that a standard behavior (to allow usage of context menus on title bar only, etc.). @@ -4890,10 +4890,10 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) // Force round operator last to ensure that e.g. (int)(max.x-min.x) in user's render code produce correct result. const float border_size = window->WindowBorderSize; ImRect clip_rect; - clip_rect.Min.x = ImFloor(0.5f + window->InnerRect.Min.x + ImMax(border_size, ImFloor(window->WindowPadding.x*0.5f))); - clip_rect.Min.y = ImFloor(0.5f + window->InnerRect.Min.y + border_size); - clip_rect.Max.x = ImFloor(0.5f + window->InnerRect.Max.x - ImMax(border_size, ImFloor(window->WindowPadding.x*0.5f))); - clip_rect.Max.y = ImFloor(0.5f + window->InnerRect.Max.y - border_size); + clip_rect.Min.x = ImFloor(0.5f + window->InnerRect.Min.x + ImMax(0.0f, ImFloor(window->WindowPadding.x*0.5f - border_size))); + clip_rect.Min.y = ImFloor(0.5f + window->InnerRect.Min.y); + clip_rect.Max.x = ImFloor(0.5f + window->InnerRect.Max.x - ImMax(0.0f, ImFloor(window->WindowPadding.x*0.5f - border_size))); + clip_rect.Max.y = ImFloor(0.5f + window->InnerRect.Max.y); PushClipRect(clip_rect.Min, clip_rect.Max, true); // Clear 'accessed' flag last thing (After PushClipRect which will set the flag. We want the flag to stay false when the default "Debug" window is unused) From 7ac1583411095fe8a82ccbc56d09777f87222e9d Mon Sep 17 00:00:00 2001 From: omar Date: Sun, 10 Dec 2017 17:27:37 +0100 Subject: [PATCH 258/823] Scrollbar: Minor simplication of the code using InnerRect data. --- imgui.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 522d2b156094..4aba5aa82e85 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -4994,10 +4994,8 @@ void ImGui::Scrollbar(ImGuiLayoutType direction) const ImRect window_rect = window->Rect(); const float border_size = window->WindowBorderSize; ImRect bb = horizontal - ? ImRect(window->Pos.x + border_size, window_rect.Max.y - style.ScrollbarSize, window_rect.Max.x - other_scrollbar_size_w - border_size, window_rect.Max.y - border_size) - : ImRect(window_rect.Max.x - style.ScrollbarSize, window->Pos.y + border_size, window_rect.Max.x - border_size, window_rect.Max.y - other_scrollbar_size_w - border_size); - if (!horizontal) - bb.Min.y += window->TitleBarHeight() + ((window->Flags & ImGuiWindowFlags_MenuBar) ? window->MenuBarHeight() : 0.0f); + ? ImRect(window->InnerRect.Min.x, window_rect.Max.y - style.ScrollbarSize, window->InnerRect.Max.x, window_rect.Max.y - border_size) + : ImRect(window_rect.Max.x - style.ScrollbarSize, window->InnerRect.Min.y, window_rect.Max.x - border_size, window->InnerRect.Max.y); if (bb.GetWidth() <= 0.0f || bb.GetHeight() <= 0.0f) return; From eab6333a0b96bd30413bb17408303a5df438ffde Mon Sep 17 00:00:00 2001 From: omar Date: Sun, 10 Dec 2017 17:36:30 +0100 Subject: [PATCH 259/823] SetNextWindowContentSize() adjust for client->window size, but the fate of borders isn't really clear for now (until now we always tried to make borders not affect layout, so if we want a 200x200 fully visible space with borders and zero window padding user need to include the borders) (#1490) --- imgui.cpp | 4 +++- imgui.h | 2 +- imgui_internal.h | 4 ++-- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 4aba5aa82e85..88b6a0c29bc0 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -4388,7 +4388,9 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) } if (g.SetNextWindowContentSizeCond) { + // Adjust passed "client size" to become a "window size" window->SizeContentsExplicit = g.SetNextWindowContentSizeVal; + window->SizeContentsExplicit.y += window->TitleBarHeight() + window->MenuBarHeight(); g.SetNextWindowContentSizeCond = 0; } else if (first_begin_of_the_frame) @@ -5660,7 +5662,7 @@ void ImGui::SetNextWindowSizeConstraints(const ImVec2& size_min, const ImVec2& s void ImGui::SetNextWindowContentSize(const ImVec2& size) { ImGuiContext& g = *GImGui; - g.SetNextWindowContentSizeVal = size; + g.SetNextWindowContentSizeVal = size; // In Begin() we will add the size of window decorations (title bar, menu etc.) to that to form a SizeContents value. g.SetNextWindowContentSizeCond = ImGuiCond_Always; } diff --git a/imgui.h b/imgui.h index 8af7756771f6..e57a8143292a 100644 --- a/imgui.h +++ b/imgui.h @@ -159,7 +159,7 @@ namespace ImGui IMGUI_API void SetNextWindowPos(const ImVec2& pos, ImGuiCond cond = 0, const ImVec2& pivot = ImVec2(0,0)); // set next window position. call before Begin(). use pivot=(0.5f,0.5f) to center on given point, etc. IMGUI_API void SetNextWindowSize(const ImVec2& size, ImGuiCond cond = 0); // set next window size. set axis to 0.0f to force an auto-fit on this axis. call before Begin() IMGUI_API void SetNextWindowSizeConstraints(const ImVec2& size_min, const ImVec2& size_max, ImGuiSizeConstraintCallback custom_callback = NULL, void* custom_callback_data = NULL); // set next window size limits. use -1,-1 on either X/Y axis to preserve the current size. Use callback to apply non-trivial programmatic constraints. - IMGUI_API void SetNextWindowContentSize(const ImVec2& size); // set next window content size (~ enforce the range of scrollbars). set axis to 0.0f to leave it automatic. call before Begin() + IMGUI_API void SetNextWindowContentSize(const ImVec2& size); // set next window content size (~ enforce the range of scrollbars). not including window decorations (title bar, menu bar, etc.). set an axis to 0.0f to leave it automatic. call before Begin() IMGUI_API void SetNextWindowCollapsed(bool collapsed, ImGuiCond cond = 0); // set next window collapsed state. call before Begin() IMGUI_API void SetNextWindowFocus(); // set next window to be focused / front-most. call before Begin() IMGUI_API void SetWindowPos(const ImVec2& pos, ImGuiCond cond = 0); // (not recommended) set current window position - call within Begin()/End(). prefer using SetNextWindowPos(), as this may incur tearing and side-effects. diff --git a/imgui_internal.h b/imgui_internal.h index 3774a8b839c2..3238c90a6628 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -630,7 +630,7 @@ struct IMGUI_API ImGuiDrawContext ImVec2 CursorPos; ImVec2 CursorPosPrevLine; ImVec2 CursorStartPos; - ImVec2 CursorMaxPos; // Implicitly calculate the size of our contents, always extending. Saved into window->SizeContents at the end of the frame + ImVec2 CursorMaxPos; // Used to implicitly calculate the size of our contents, always growing during the frame. Turned into window->SizeContents at the beginning of next frame float CurrentLineHeight; float CurrentLineTextBaseOffset; float PrevLineHeight; @@ -716,7 +716,7 @@ struct IMGUI_API ImGuiWindow ImVec2 Size; // Current size (==SizeFull or collapsed title bar size) ImVec2 SizeFull; // Size when non collapsed ImVec2 SizeFullAtLastBegin; // Copy of SizeFull at the end of Begin. This is the reference value we'll use on the next frame to decide if we need scrollbars. - ImVec2 SizeContents; // Size of contents (== extents reach of the drawing cursor) from previous frame + ImVec2 SizeContents; // Size of contents (== extents reach of the drawing cursor) from previous frame. Include decoration, window title, border, menu, etc. ImVec2 SizeContentsExplicit; // Size of contents explicitly set by the user via SetNextWindowContentSize() ImRect ContentsRegionRect; // Maximum visible content position in window coordinates. ~~ (SizeContentsExplicit ? SizeContentsExplicit : Size - ScrollbarSizes) - CursorStartPos, per axis ImVec2 WindowPadding; // Window padding at the time of begin. From 080f61858f03f5dbea3611ef6f1027febe277d7b Mon Sep 17 00:00:00 2001 From: omar Date: Sun, 10 Dec 2017 17:57:27 +0100 Subject: [PATCH 260/823] Sorted typedefs/enumations forward declarations in imgui.h --- imgui.h | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/imgui.h b/imgui.h index e57a8143292a..a65e713363f4 100644 --- a/imgui.h +++ b/imgui.h @@ -72,18 +72,18 @@ typedef unsigned int ImGuiID; // unique ID used by widgets (typically hash typedef unsigned short ImWchar; // character for keyboard input/display typedef void* ImTextureID; // user data to identify a texture (this is whatever to you want it to be! read the FAQ about ImTextureID in imgui.cpp) typedef int ImGuiCol; // enum: a color identifier for styling // enum ImGuiCol_ -typedef int ImGuiStyleVar; // enum: a variable identifier for styling // enum ImGuiStyleVar_ +typedef int ImGuiCond; // enum: a condition for Set*() // enum ImGuiCond_ typedef int ImGuiKey; // enum: a key identifier (ImGui-side enum) // enum ImGuiKey_ typedef int ImGuiMouseCursor; // enum: a mouse cursor identifier // enum ImGuiMouseCursor_ -typedef int ImGuiCond; // enum: a condition for Set*() // enum ImGuiCond_ -typedef int ImDrawCornerFlags; // flags: corner flags for AddRect*() etc. // enum ImDrawCornerFlags_ -typedef int ImGuiColorEditFlags; // flags: color edit flags for Color*() // enum ImGuiColorEditFlags_ -typedef int ImGuiWindowFlags; // flags: window flags for Begin*() // enum ImGuiWindowFlags_ +typedef int ImGuiStyleVar; // enum: a variable identifier for styling // enum ImGuiStyleVar_ +typedef int ImDrawCornerFlags; // flags: for ImDrawList::AddRect*() etc. // enum ImDrawCornerFlags_ +typedef int ImGuiColorEditFlags; // flags: for ColorEdit*(), ColorPicker*() // enum ImGuiColorEditFlags_ typedef int ImGuiColumnsFlags; // flags: for *Columns*() // enum ImGuiColumnsFlags_ +typedef int ImGuiHoveredFlags; // flags: for IsItemHovered() // enum ImGuiHoveredFlags_ typedef int ImGuiInputTextFlags; // flags: for InputText*() // enum ImGuiInputTextFlags_ typedef int ImGuiSelectableFlags; // flags: for Selectable() // enum ImGuiSelectableFlags_ -typedef int ImGuiTreeNodeFlags; // flags: for TreeNode*(), Collapsing*() // enum ImGuiTreeNodeFlags_ -typedef int ImGuiHoveredFlags; // flags: for IsItemHovered() // enum ImGuiHoveredFlags_ +typedef int ImGuiTreeNodeFlags; // flags: for TreeNode*(),CollapsingHeader()// enum ImGuiTreeNodeFlags_ +typedef int ImGuiWindowFlags; // flags: for Begin*() // enum ImGuiWindowFlags_ typedef int (*ImGuiTextEditCallback)(ImGuiTextEditCallbackData *data); typedef void (*ImGuiSizeConstraintCallback)(ImGuiSizeConstraintCallbackData* data); #ifdef _MSC_VER From e3e0326ea9d0fdac19d447301cc9953fc31b0f67 Mon Sep 17 00:00:00 2001 From: omar Date: Sun, 10 Dec 2017 18:08:59 +0100 Subject: [PATCH 261/823] Exposed BeginCombo() publicly. --- imgui.cpp | 8 +++++--- imgui.h | 25 +++++++++++++++++++++---- imgui_internal.h | 17 ----------------- 3 files changed, 26 insertions(+), 24 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 88b6a0c29bc0..bef60f64c32c 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -9166,7 +9166,7 @@ void ImGui::EndCombo() EndPopup(); } -// Combo box function. +// Old API, prefer using BeginCombo() nowadays if you can. bool ImGui::Combo(const char* label, int* current_item, bool (*items_getter)(void*, int, const char**), void* data, int items_count, int popup_max_height_in_items) { ImGuiContext& g = *GImGui; @@ -9175,16 +9175,18 @@ bool ImGui::Combo(const char* label, int* current_item, bool (*items_getter)(voi if (*current_item >= 0 && *current_item < items_count) items_getter(data, *current_item, &preview_text); + // The old Combo() API exposed "popup_max_height_in_items", however the new more general BeginCombo() API doesn't, so we emulate it here. if (popup_max_height_in_items != -1 && !g.SetNextWindowSizeConstraint) { float popup_max_height = CalcMaxPopupHeightFromItemCount(popup_max_height_in_items); SetNextWindowSizeConstraints(ImVec2(0,0), ImVec2(FLT_MAX, popup_max_height)); } + if (!BeginCombo(label, preview_text, 0)) return false; // Display items - // FIXME-OPT: Use clipper + // FIXME-OPT: Use clipper (if we can disable it on the appearing frame to make sure our call to SetScrollHere() is processed) bool value_changed = false; for (int i = 0; i < items_count; i++) { @@ -9236,7 +9238,7 @@ static bool Items_SingleStringGetter(void* data, int idx, const char** out_text) } // Combo box helper allowing to pass an array of strings. -bool ImGui::Combo(const char* label, int* current_item, const char* const* items, int items_count, int height_in_items) +bool ImGui::Combo(const char* label, int* current_item, const char* const items[], int items_count, int height_in_items) { const bool value_changed = Combo(label, current_item, Items_ArrayGetter, (void*)items, items_count, height_in_items); return value_changed; diff --git a/imgui.h b/imgui.h index a65e713363f4..a85d68b72512 100644 --- a/imgui.h +++ b/imgui.h @@ -79,6 +79,7 @@ typedef int ImGuiStyleVar; // enum: a variable identifier for styling typedef int ImDrawCornerFlags; // flags: for ImDrawList::AddRect*() etc. // enum ImDrawCornerFlags_ typedef int ImGuiColorEditFlags; // flags: for ColorEdit*(), ColorPicker*() // enum ImGuiColorEditFlags_ typedef int ImGuiColumnsFlags; // flags: for *Columns*() // enum ImGuiColumnsFlags_ +typedef int ImGuiComboFlags; // flags: for BeginCombo() // enum ImGuiComboFlags_ typedef int ImGuiHoveredFlags; // flags: for IsItemHovered() // enum ImGuiHoveredFlags_ typedef int ImGuiInputTextFlags; // flags: for InputText*() // enum ImGuiInputTextFlags_ typedef int ImGuiSelectableFlags; // flags: for Selectable() // enum ImGuiSelectableFlags_ @@ -284,15 +285,20 @@ namespace ImGui IMGUI_API bool CheckboxFlags(const char* label, unsigned int* flags, unsigned int flags_value); IMGUI_API bool RadioButton(const char* label, bool active); IMGUI_API bool RadioButton(const char* label, int* v, int v_button); - IMGUI_API bool Combo(const char* label, int* current_item, const char* const* items, int items_count, int height_in_items = -1); - IMGUI_API bool Combo(const char* label, int* current_item, const char* items_separated_by_zeros, int height_in_items = -1); // separate items with \0, end item-list with \0\0 - IMGUI_API bool Combo(const char* label, int* current_item, bool (*items_getter)(void* data, int idx, const char** out_text), void* data, int items_count, int height_in_items = -1); IMGUI_API void PlotLines(const char* label, const float* values, int values_count, int values_offset = 0, const char* overlay_text = NULL, float scale_min = FLT_MAX, float scale_max = FLT_MAX, ImVec2 graph_size = ImVec2(0,0), int stride = sizeof(float)); IMGUI_API void PlotLines(const char* label, float (*values_getter)(void* data, int idx), void* data, int values_count, int values_offset = 0, const char* overlay_text = NULL, float scale_min = FLT_MAX, float scale_max = FLT_MAX, ImVec2 graph_size = ImVec2(0,0)); IMGUI_API void PlotHistogram(const char* label, const float* values, int values_count, int values_offset = 0, const char* overlay_text = NULL, float scale_min = FLT_MAX, float scale_max = FLT_MAX, ImVec2 graph_size = ImVec2(0,0), int stride = sizeof(float)); IMGUI_API void PlotHistogram(const char* label, float (*values_getter)(void* data, int idx), void* data, int values_count, int values_offset = 0, const char* overlay_text = NULL, float scale_min = FLT_MAX, float scale_max = FLT_MAX, ImVec2 graph_size = ImVec2(0,0)); IMGUI_API void ProgressBar(float fraction, const ImVec2& size_arg = ImVec2(-1,0), const char* overlay = NULL); + // Widgets: Combo Box + // The new BeginCombo()/EndCombo() api allows you to manage your contents and selection state however you want it. + IMGUI_API bool BeginCombo(const char* label, const char* preview_value, ImGuiComboFlags flags = 0); + IMGUI_API void EndCombo(); + IMGUI_API bool Combo(const char* label, int* current_item, const char* const items[], int items_count, int popup_max_height_in_items = -1); + IMGUI_API bool Combo(const char* label, int* current_item, const char* items_separated_by_zeros, int popup_max_height_in_items = -1); // Separate items with \0 within a string, end item-list with \0\0. e.g. "One\0Two\0Three\0" + IMGUI_API bool Combo(const char* label, int* current_item, bool(*items_getter)(void* data, int idx, const char** out_text), void* data, int items_count, int popup_max_height_in_items = -1); + // Widgets: Drags (tip: ctrl+click on a drag box to input with keyboard. manually input values aren't clamped, can go off-bounds) // For all the Float2/Float3/Float4/Int2/Int3/Int4 versions of every functions, note that a 'float v[X]' function argument is the same as 'float* v', the array syntax is just a way to document the number of elements that are expected to be accessible. You can pass address of your first element out of a contiguous set, e.g. &myvector.x IMGUI_API bool DragFloat(const char* label, float* v, float v_speed = 1.0f, float v_min = 0.0f, float v_max = 0.0f, const char* display_format = "%.3f", float power = 1.0f); // If v_min >= v_max we have no bound @@ -403,7 +409,7 @@ namespace ImGui IMGUI_API bool IsPopupOpen(const char* str_id); // return true if the popup is open IMGUI_API void CloseCurrentPopup(); // close the popup we have begin-ed into. clicking on a MenuItem or Selectable automatically close the current popup. - // Logging: all text output from interface is redirected to tty/file/clipboard. By default, tree nodes are automatically opened during logging. + // Logging/Capture: all text output from interface is captured to tty/file/clipboard. By default, tree nodes are automatically opened during logging. IMGUI_API void LogToTTY(int max_depth = -1); // start logging to tty IMGUI_API void LogToFile(int max_depth = -1, const char* filename = NULL); // start logging to file IMGUI_API void LogToClipboard(int max_depth = -1); // start logging to OS clipboard @@ -575,6 +581,17 @@ enum ImGuiSelectableFlags_ ImGuiSelectableFlags_AllowDoubleClick = 1 << 2 // Generate press events on double clicks too }; +// Flags for ImGui::BeginCombo() +enum ImGuiComboFlags_ +{ + ImGuiComboFlags_PopupAlignLeft = 1 << 0, // Align the popup toward the left by default + ImGuiComboFlags_HeightSmall = 1 << 1, // Max ~4 items visible. Tip: If you want your combo popup to be a specific size you can use SetNextWindowSizeConstraints() prior to calling BeginCombo() + ImGuiComboFlags_HeightRegular = 1 << 2, // Max ~8 items visible (default) + ImGuiComboFlags_HeightLarge = 1 << 3, // Max ~20 items visible + ImGuiComboFlags_HeightLargest = 1 << 4, // As many fitting items as possible + ImGuiComboFlags_HeightMask_ = ImGuiComboFlags_HeightSmall | ImGuiComboFlags_HeightRegular | ImGuiComboFlags_HeightLarge | ImGuiComboFlags_HeightLargest +}; + // Flags for ImGui::IsItemHovered(), ImGui::IsWindowHovered() enum ImGuiHoveredFlags_ { diff --git a/imgui_internal.h b/imgui_internal.h index 3238c90a6628..18e44c443f74 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -48,7 +48,6 @@ typedef int ImGuiButtonFlags; // flags: for ButtonEx(), ButtonBehavior() typedef int ImGuiItemFlags; // flags: for PushItemFlag() // enum ImGuiItemFlags_ typedef int ImGuiSeparatorFlags; // flags: for Separator() - internal // enum ImGuiSeparatorFlags_ typedef int ImGuiSliderFlags; // flags: for SliderBehavior() // enum ImGuiSliderFlags_ -typedef int ImGuiComboFlags; // flags: for BeginCombo() // enum ImGuiComboFlags_ //------------------------------------------------------------------------- // STB libraries @@ -210,18 +209,6 @@ enum ImGuiSelectableFlagsPrivate_ ImGuiSelectableFlags_DrawFillAvailWidth = 1 << 6 }; -enum ImGuiComboFlags_ -{ - ImGuiComboFlags_PopupAlignLeft = 1 << 0, // Align the popup toward the left by default - - // If you want your combo popup to be a specific size you can use SetNextWindowSizeConstraints() prior to calling BeginCombo() - ImGuiComboFlags_HeightSmall = 1 << 1, // Max ~4 items visible - ImGuiComboFlags_HeightRegular = 1 << 2, // Max ~8 items visible (default) - ImGuiComboFlags_HeightLarge = 1 << 3, // Max ~20 items visible - ImGuiComboFlags_HeightLargest = 1 << 4, // As many fitting items as possible - ImGuiComboFlags_HeightMask_ = ImGuiComboFlags_HeightSmall | ImGuiComboFlags_HeightRegular | ImGuiComboFlags_HeightLarge | ImGuiComboFlags_HeightLargest -}; - enum ImGuiSeparatorFlags_ { ImGuiSeparatorFlags_Horizontal = 1 << 0, // Axis default to current layout type, so generally Horizontal unless e.g. in a menu bar @@ -859,10 +846,6 @@ namespace ImGui IMGUI_API void EndColumns(); // close columns IMGUI_API void PushColumnClipRect(int column_index = -1); - // FIXME-WIP: New Combo API - IMGUI_API bool BeginCombo(const char* label, const char* preview_value, ImGuiComboFlags flags = 0); - IMGUI_API void EndCombo(); - // NB: All position are in absolute pixels coordinates (never using window coordinates internally) // AVOID USING OUTSIDE OF IMGUI.CPP! NOT FOR PUBLIC CONSUMPTION. THOSE FUNCTIONS ARE A MESS. THEIR SIGNATURE AND BEHAVIOR WILL CHANGE, THEY NEED TO BE REFACTORED INTO SOMETHING DECENT. IMGUI_API void RenderText(ImVec2 pos, const char* text, const char* text_end = NULL, bool hide_text_after_hash = true); From 1096e14356270e842bbaecd3489e9b44479ad733 Mon Sep 17 00:00:00 2001 From: omar Date: Sun, 10 Dec 2017 18:34:32 +0100 Subject: [PATCH 262/823] ImFont: Added GetDebugName() helper. --- imgui.h | 1 + 1 file changed, 1 insertion(+) diff --git a/imgui.h b/imgui.h index a85d68b72512..9c35c494d61b 100644 --- a/imgui.h +++ b/imgui.h @@ -1568,6 +1568,7 @@ struct ImFont IMGUI_API void SetFallbackChar(ImWchar c); float GetCharAdvance(ImWchar c) const { return ((int)c < IndexAdvanceX.Size) ? IndexAdvanceX[(int)c] : FallbackAdvanceX; } bool IsLoaded() const { return ContainerAtlas != NULL; } + const char* GetDebugName() const { return ConfigData ? ConfigData->Name : ""; } // 'max_width' stops rendering after a certain width (could be turned into a 2d size). FLT_MAX to disable. // 'wrap_width' enable automatic word-wrapping across multiple lines to fit into given width. 0.0f to disable. From 4b8857d536e533e6cbca764d43d54acb35a1930e Mon Sep 17 00:00:00 2001 From: omar Date: Sun, 10 Dec 2017 18:45:05 +0100 Subject: [PATCH 263/823] Demo: About box tweaks. --- imgui_demo.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/imgui_demo.cpp b/imgui_demo.cpp index e1d7a99fb954..82dcac3d63c4 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -156,11 +156,11 @@ void ImGui::ShowTestWindow(bool* p_open) if (show_app_style_editor) { ImGui::Begin("Style Editor", &show_app_style_editor); ImGui::ShowStyleEditor(); ImGui::End(); } if (show_app_about) { - ImGui::Begin("About ImGui", &show_app_about, ImGuiWindowFlags_AlwaysAutoResize); + ImGui::Begin("About Dear ImGui", &show_app_about, ImGuiWindowFlags_AlwaysAutoResize); ImGui::Text("dear imgui, %s", ImGui::GetVersion()); ImGui::Separator(); - ImGui::Text("By Omar Cornut and all github contributors."); - ImGui::Text("ImGui is licensed under the MIT License, see LICENSE for more information."); + ImGui::Text("By Omar Cornut and all dear imgui contributors."); + ImGui::Text("Dear ImGui is licensed under the MIT License, see LICENSE for more information."); ImGui::End(); } @@ -222,7 +222,7 @@ void ImGui::ShowTestWindow(bool* p_open) { ImGui::MenuItem("Metrics", NULL, &show_app_metrics); ImGui::MenuItem("Style Editor", NULL, &show_app_style_editor); - ImGui::MenuItem("About ImGui", NULL, &show_app_about); + ImGui::MenuItem("About Dear ImGui", NULL, &show_app_about); ImGui::EndMenu(); } ImGui::EndMenuBar(); From 71296910a02fe9cc6488ee71daf293396c2a5786 Mon Sep 17 00:00:00 2001 From: omar Date: Sun, 10 Dec 2017 18:49:47 +0100 Subject: [PATCH 264/823] Demo: Tweaks and spacing. Stopped using rand() function in demo code. --- imgui_demo.cpp | 42 +++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 82dcac3d63c4..fc8bbec9518f 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -80,7 +80,7 @@ static void ShowExampleAppLongText(bool* p_open); static void ShowExampleAppAutoResize(bool* p_open); static void ShowExampleAppConstrainedResize(bool* p_open); static void ShowExampleAppFixedOverlay(bool* p_open); -static void ShowExampleAppManipulatingWindowTitle(bool* p_open); +static void ShowExampleAppWindowTitles(bool* p_open); static void ShowExampleAppCustomRendering(bool* p_open); static void ShowExampleAppMainMenuBar(); static void ShowExampleMenuFile(); @@ -133,27 +133,27 @@ void ImGui::ShowTestWindow(bool* p_open) static bool show_app_auto_resize = false; static bool show_app_constrained_resize = false; static bool show_app_fixed_overlay = false; - static bool show_app_manipulating_window_title = false; + static bool show_app_window_titles = false; static bool show_app_custom_rendering = false; static bool show_app_style_editor = false; static bool show_app_metrics = false; static bool show_app_about = false; - if (show_app_main_menu_bar) ShowExampleAppMainMenuBar(); - if (show_app_console) ShowExampleAppConsole(&show_app_console); - if (show_app_log) ShowExampleAppLog(&show_app_log); - if (show_app_layout) ShowExampleAppLayout(&show_app_layout); - if (show_app_property_editor) ShowExampleAppPropertyEditor(&show_app_property_editor); - if (show_app_long_text) ShowExampleAppLongText(&show_app_long_text); - if (show_app_auto_resize) ShowExampleAppAutoResize(&show_app_auto_resize); - if (show_app_constrained_resize) ShowExampleAppConstrainedResize(&show_app_constrained_resize); - if (show_app_fixed_overlay) ShowExampleAppFixedOverlay(&show_app_fixed_overlay); - if (show_app_manipulating_window_title) ShowExampleAppManipulatingWindowTitle(&show_app_manipulating_window_title); - if (show_app_custom_rendering) ShowExampleAppCustomRendering(&show_app_custom_rendering); - - if (show_app_metrics) ImGui::ShowMetricsWindow(&show_app_metrics); - if (show_app_style_editor) { ImGui::Begin("Style Editor", &show_app_style_editor); ImGui::ShowStyleEditor(); ImGui::End(); } + if (show_app_main_menu_bar) ShowExampleAppMainMenuBar(); + if (show_app_console) ShowExampleAppConsole(&show_app_console); + if (show_app_log) ShowExampleAppLog(&show_app_log); + if (show_app_layout) ShowExampleAppLayout(&show_app_layout); + if (show_app_property_editor) ShowExampleAppPropertyEditor(&show_app_property_editor); + if (show_app_long_text) ShowExampleAppLongText(&show_app_long_text); + if (show_app_auto_resize) ShowExampleAppAutoResize(&show_app_auto_resize); + if (show_app_constrained_resize) ShowExampleAppConstrainedResize(&show_app_constrained_resize); + if (show_app_fixed_overlay) ShowExampleAppFixedOverlay(&show_app_fixed_overlay); + if (show_app_window_titles) ShowExampleAppWindowTitles(&show_app_window_titles); + if (show_app_custom_rendering) ShowExampleAppCustomRendering(&show_app_custom_rendering); + + if (show_app_metrics) { ImGui::ShowMetricsWindow(&show_app_metrics); } + if (show_app_style_editor) { ImGui::Begin("Style Editor", &show_app_style_editor); ImGui::ShowStyleEditor(); ImGui::End(); } if (show_app_about) { ImGui::Begin("About Dear ImGui", &show_app_about, ImGuiWindowFlags_AlwaysAutoResize); @@ -214,7 +214,7 @@ void ImGui::ShowTestWindow(bool* p_open) ImGui::MenuItem("Auto-resizing window", NULL, &show_app_auto_resize); ImGui::MenuItem("Constrained-resizing window", NULL, &show_app_constrained_resize); ImGui::MenuItem("Simple overlay", NULL, &show_app_fixed_overlay); - ImGui::MenuItem("Manipulating window title", NULL, &show_app_manipulating_window_title); + ImGui::MenuItem("Manipulating window titles", NULL, &show_app_window_titles); ImGui::MenuItem("Custom rendering", NULL, &show_app_custom_rendering); ImGui::EndMenu(); } @@ -2269,8 +2269,8 @@ static void ShowExampleAppFixedOverlay(bool* p_open) } // Demonstrate using "##" and "###" in identifiers to manipulate ID generation. -// Read section "How can I have multiple widgets with the same label? Can I have widget without a label? (Yes). A primer on the purpose of labels/IDs." about ID. -static void ShowExampleAppManipulatingWindowTitle(bool*) +// This apply to regular items as well. Read FAQ section "How can I have multiple widgets with the same label? Can I have widget without a label? (Yes). A primer on the purpose of labels/IDs." for details. +static void ShowExampleAppWindowTitles(bool*) { // By default, Windows are uniquely identified by their title. // You can use the "##" and "###" markers to manipulate the display/ID. @@ -2288,7 +2288,7 @@ static void ShowExampleAppManipulatingWindowTitle(bool*) // Using "###" to display a changing title but keep a static identifier "AnimatedTitle" char buf[128]; - sprintf(buf, "Animated title %c %d###AnimatedTitle", "|/-\\"[(int)(ImGui::GetTime()/0.25f)&3], rand()); + sprintf(buf, "Animated title %c %d###AnimatedTitle", "|/-\\"[(int)(ImGui::GetTime()/0.25f)&3], ImGui::GetFrameCount()); ImGui::SetNextWindowPos(ImVec2(100,300), ImGuiCond_FirstUseEver); ImGui::Begin(buf); ImGui::Text("This window has a changing title."); @@ -2774,7 +2774,7 @@ static void ShowExampleAppLog(bool* p_open) if (time - last_time >= 0.20f && !ImGui::GetIO().KeyCtrl) { const char* random_words[] = { "system", "info", "warning", "error", "fatal", "notice", "log" }; - log.AddLog("[%s] Hello, time is %.1f, rand() %d\n", random_words[rand() % IM_ARRAYSIZE(random_words)], time, (int)rand()); + log.AddLog("[%s] Hello, time is %.1f, frame count is %d\n", random_words[rand() % IM_ARRAYSIZE(random_words)], time, ImGui::GetFrameCount()); last_time = time; } From e67f3809ed7c9c0ea727fa148ddc45fd37c3b848 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Branimir=20Karad=C5=BEi=C4=87?= Date: Sun, 10 Dec 2017 17:20:28 -0800 Subject: [PATCH 265/823] Replaced obsolete function with new one. --- imgui_demo.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/imgui_demo.cpp b/imgui_demo.cpp index fc8bbec9518f..6c6952a3f2fe 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -1651,7 +1651,7 @@ void ImGui::ShowTestWindow(bool* p_open) if (ImGui::TreeNode("Horizontal Scrolling")) { - ImGui::SetNextWindowContentWidth(1500); + ImGui::SetNextWindowContentSize(ImVec2(1500.0f, 0.0f)); ImGui::BeginChild("##ScrollingRegion", ImVec2(0, ImGui::GetFontSize() * 20), false, ImGuiWindowFlags_HorizontalScrollbar); ImGui::Columns(10); int ITEMS_COUNT = 2000; From 6d93011fdf781ed18748af18d7434b5c245da456 Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 11 Dec 2017 10:25:44 +0100 Subject: [PATCH 266/823] alloca fix to allow Clang with Microsoft CodeGen path --- imgui_draw.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/imgui_draw.cpp b/imgui_draw.cpp index 2c937e59749c..7a5bb2deeded 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -22,6 +22,9 @@ #if !defined(alloca) #ifdef _WIN32 #include // alloca +#if !defined(alloca) +#define alloca _alloca // for clang with MS Codegen +#endif #elif defined(__GLIBC__) || defined(__sun) #include // alloca #else From 9fd15defe485b8341ffe9368207ebdc96d65fc45 Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 11 Dec 2017 16:19:37 +0100 Subject: [PATCH 267/823] Added an implementation of SetItemDefaultFocus() in the master branch for combo patterns to use and be more forward-compatible. (#787) --- imgui.cpp | 15 ++++++++++++--- imgui.h | 9 +++++++-- 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index bef60f64c32c..9a7e1b87fe0d 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -5884,6 +5884,15 @@ void ImGui::SetScrollHere(float center_y_ratio) SetScrollFromPosY(target_y, center_y_ratio); } +// FIXME-NAV: This function is a placeholder for the upcoming Navigation branch + Focusing features. +// In the current branch this function will only set the scrolling, in the navigation branch it will also set your navigation cursor. +// Prefer using "SetItemDefaultFocus()" over "if (IsWindowAppearing()) SetScrollHere()" when applicable. +void ImGui::SetItemDefaultFocus() +{ + if (IsWindowAppearing()) + SetScrollHere(); +} + void ImGui::SetKeyboardFocusHere(int offset) { IM_ASSERT(offset >= -1); // -1 is allowed but not below @@ -9186,7 +9195,7 @@ bool ImGui::Combo(const char* label, int* current_item, bool (*items_getter)(voi return false; // Display items - // FIXME-OPT: Use clipper (if we can disable it on the appearing frame to make sure our call to SetScrollHere() is processed) + // FIXME-OPT: Use clipper (but we need to disable it on the appearing frame to make sure our call to SetItemDefaultFocus() is processed) bool value_changed = false; for (int i = 0; i < items_count; i++) { @@ -9200,8 +9209,8 @@ bool ImGui::Combo(const char* label, int* current_item, bool (*items_getter)(voi value_changed = true; *current_item = i; } - if (item_selected && IsWindowAppearing()) - SetScrollHere(); + if (item_selected) + SetItemDefaultFocus(); PopID(); } diff --git a/imgui.h b/imgui.h index 9c35c494d61b..a7e29bbe7a2c 100644 --- a/imgui.h +++ b/imgui.h @@ -178,9 +178,8 @@ namespace ImGui IMGUI_API float GetScrollMaxY(); // get maximum scrolling amount ~~ ContentSize.Y - WindowSize.Y IMGUI_API void SetScrollX(float scroll_x); // set scrolling amount [0..GetScrollMaxX()] IMGUI_API void SetScrollY(float scroll_y); // set scrolling amount [0..GetScrollMaxY()] - IMGUI_API void SetScrollHere(float center_y_ratio = 0.5f); // adjust scrolling amount to make current cursor position visible. center_y_ratio=0.0: top, 0.5: center, 1.0: bottom. + IMGUI_API void SetScrollHere(float center_y_ratio = 0.5f); // adjust scrolling amount to make current cursor position visible. center_y_ratio=0.0: top, 0.5: center, 1.0: bottom. When using to make a "default/current item" visible, consider using SetItemDefaultFocus() instead. IMGUI_API void SetScrollFromPosY(float pos_y, float center_y_ratio = 0.5f); // adjust scrolling amount to make given position valid. use GetCursorPos() or GetCursorStartPos()+offset to get valid positions. - IMGUI_API void SetKeyboardFocusHere(int offset = 0); // focus keyboard on the next widget. Use positive 'offset' to access sub components of a multiple component widget. Use -1 to access previous widget. IMGUI_API void SetStateStorage(ImGuiStorage* tree); // replace tree state storage with our own (if you want to manipulate it yourself, typically clear subsection of it) IMGUI_API ImGuiStorage* GetStateStorage(); @@ -426,6 +425,12 @@ namespace ImGui IMGUI_API void StyleColorsDark(ImGuiStyle* dst = NULL); IMGUI_API void StyleColorsLight(ImGuiStyle* dst = NULL); + // Focus + // (FIXME: Those functions will be reworked after we merge the navigation branch + have a pass at focusing/tabbing features.) + // (Prefer using "SetItemDefaultFocus()" over "if (IsWindowAppearing()) SetScrollHere()" when applicable, to make your code more forward compatible when navigation branch is merged) + IMGUI_API void SetItemDefaultFocus(); // make last item the default focused item of a window (WIP navigation branch only). Pleaase use instead of SetScrollHere(). + IMGUI_API void SetKeyboardFocusHere(int offset = 0); // focus keyboard on the next widget. Use positive 'offset' to access sub components of a multiple component widget. Use -1 to access previous widget. + // Utilities IMGUI_API bool IsItemHovered(ImGuiHoveredFlags flags = 0); // is the last item hovered by mouse (and usable)? IMGUI_API bool IsItemActive(); // is the last item active? (e.g. button being held, text field being edited- items that don't interact will always return false) From f06f68f3cea7e2527ed66f7395d1662a4df50917 Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 11 Dec 2017 16:22:52 +0100 Subject: [PATCH 268/823] Obsoleted old functions: SetScrollPosHere (marked obsolete in 1.42, July 2015). GetWindowFont(), GetWindowFontSize() (marked obsolete in 1.48, March 2016) --- imgui.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/imgui.h b/imgui.h index a7e29bbe7a2c..c75a2a06441a 100644 --- a/imgui.h +++ b/imgui.h @@ -945,9 +945,6 @@ namespace ImGui static inline bool IsMouseHoveringAnyWindow() { return IsAnyWindowHovered(); } // OBSOLETE 1.51+ static inline bool IsMouseHoveringWindow() { return IsWindowHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup | ImGuiHoveredFlags_AllowWhenBlockedByActiveItem); } // OBSOLETE 1.51+ static inline bool CollapsingHeader(const char* label, const char* str_id, bool framed = true, bool default_open = false) { (void)str_id; (void)framed; ImGuiTreeNodeFlags default_open_flags = 1 << 5; return CollapsingHeader(label, (default_open ? default_open_flags : 0)); } // OBSOLETE 1.49+ - static inline ImFont* GetWindowFont() { return GetFont(); } // OBSOLETE 1.48+ - static inline float GetWindowFontSize() { return GetFontSize(); } // OBSOLETE 1.48+ - static inline void SetScrollPosHere() { SetScrollHere(); } // OBSOLETE 1.42+ } #endif From 6b168b43ff85883469817038b09b8a8546a8e8b7 Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 11 Dec 2017 19:47:23 +0100 Subject: [PATCH 269/823] Comments (#822) --- TODO.txt | 2 +- imgui.h | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/TODO.txt b/TODO.txt index 1271d346fa4c..43df4dafc383 100644 --- a/TODO.txt +++ b/TODO.txt @@ -24,7 +24,7 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i - window: increase minimum size of a window with menus or fix the menu rendering so that it doesn't look odd. - window: double-clicking on title bar to minimize isn't consistent, perhaps move to single-click on left-most collapse icon? - window: expose contents size. (#1045) - - window: resize from borders and/or all corners. (#822) + - window: resize from borders: support some form of outer padding to make it easier to grab borders. (#822) - window: GetWindowSize() returns (0,0) when not calculated? (#1045) - window: refactor IsWindowFocused(), merge all three existing variants, add flags, similar to #1382. - window: freeze window flag: if not focused/hovered, return false, render with previous ImDrawList. and/or reduce refresh rate. diff --git a/imgui.h b/imgui.h index c75a2a06441a..3187f5ddd3e5 100644 --- a/imgui.h +++ b/imgui.h @@ -756,8 +756,8 @@ enum ImGuiMouseCursor_ ImGuiMouseCursor_Arrow = 0, ImGuiMouseCursor_TextInput, // When hovering over InputText, etc. ImGuiMouseCursor_Move, // Unused - ImGuiMouseCursor_ResizeNS, // Unused - ImGuiMouseCursor_ResizeEW, // When hovering over a column + ImGuiMouseCursor_ResizeNS, // When hovering over an horizontal border + ImGuiMouseCursor_ResizeEW, // When hovering over a vertical border or a column ImGuiMouseCursor_ResizeNESW, // When hovering over the bottom-left corner of a window ImGuiMouseCursor_ResizeNWSE, // When hovering over the bottom-right corner of a window ImGuiMouseCursor_Count_ From 45f440bb7dbb226e6375ba8643b1efda87d8f78b Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 11 Dec 2017 22:39:10 +0100 Subject: [PATCH 270/823] Internals: Renamed ImGuiButtonFlags_FlattenChilds -> ImGuiButtonFlags_FlattenChildren, ImGuiButtonFlags_AllowOverlapMode -> ImGuiButtonFlags_AllowItemOverlap --- imgui.cpp | 14 +++++++------- imgui_internal.h | 12 ++++++------ 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 9a7e1b87fe0d..5e86bc012a8e 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -4659,7 +4659,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) ImRect resize_rect(corner, corner + grip.InnerDir * grip_hover_size); resize_rect.FixInverted(); bool hovered, held; - ButtonBehavior(resize_rect, window->GetID((void*)(intptr_t)resize_grip_n), &hovered, &held, ImGuiButtonFlags_FlattenChilds); + ButtonBehavior(resize_rect, window->GetID((void*)(intptr_t)resize_grip_n), &hovered, &held, ImGuiButtonFlags_FlattenChildren); if (hovered || held) g.MouseCursor = (resize_grip_n & 1) ? ImGuiMouseCursor_ResizeNESW : ImGuiMouseCursor_ResizeNWSE; @@ -4685,7 +4685,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) const float BORDER_APPEAR_TIMER = 0.05f; // Reduce visual noise bool hovered, held; ImRect border_rect = GetBorderRect(window, border_n, grip_hover_size, BORDER_SIZE); - ButtonBehavior(border_rect, window->GetID((void*)(intptr_t)(border_n+4)), &hovered, &held, ImGuiButtonFlags_FlattenChilds); + ButtonBehavior(border_rect, window->GetID((void*)(intptr_t)(border_n+4)), &hovered, &held, ImGuiButtonFlags_FlattenChildren); if ((hovered && g.HoveredIdTimer > BORDER_APPEAR_TIMER) || held) { g.MouseCursor = (border_n & 1) ? ImGuiMouseCursor_ResizeEW : ImGuiMouseCursor_ResizeNS; @@ -6147,17 +6147,17 @@ bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool flags |= ImGuiButtonFlags_PressedOnClickRelease; ImGuiWindow* backup_hovered_window = g.HoveredWindow; - if ((flags & ImGuiButtonFlags_FlattenChilds) && g.HoveredRootWindow == window) + if ((flags & ImGuiButtonFlags_FlattenChildren) && g.HoveredRootWindow == window) g.HoveredWindow = window; bool pressed = false; bool hovered = ItemHoverable(bb, id); - if ((flags & ImGuiButtonFlags_FlattenChilds) && g.HoveredRootWindow == window) + if ((flags & ImGuiButtonFlags_FlattenChildren) && g.HoveredRootWindow == window) g.HoveredWindow = backup_hovered_window; // AllowOverlap mode (rarely used) requires previous frame HoveredId to be null or to match. This allows using patterns where a later submitted widget overlaps a previous one. - if (hovered && (flags & ImGuiButtonFlags_AllowOverlapMode) && (g.HoveredIdPreviousFrame != id && g.HoveredIdPreviousFrame != 0)) + if (hovered && (flags & ImGuiButtonFlags_AllowItemOverlap) && (g.HoveredIdPreviousFrame != id && g.HoveredIdPreviousFrame != 0)) hovered = false; if (hovered) @@ -6613,7 +6613,7 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l // - OpenOnDoubleClick .............. double-click anywhere to open // - OpenOnArrow .................... single-click on arrow to open // - OpenOnDoubleClick|OpenOnArrow .. single-click on arrow or double-click anywhere to open - ImGuiButtonFlags button_flags = ImGuiButtonFlags_NoKeyModifiers | ((flags & ImGuiTreeNodeFlags_AllowOverlapMode) ? ImGuiButtonFlags_AllowOverlapMode : 0); + ImGuiButtonFlags button_flags = ImGuiButtonFlags_NoKeyModifiers | ((flags & ImGuiTreeNodeFlags_AllowOverlapMode) ? ImGuiButtonFlags_AllowItemOverlap : 0); if (flags & ImGuiTreeNodeFlags_OpenOnDoubleClick) button_flags |= ImGuiButtonFlags_PressedOnDoubleClick | ((flags & ImGuiTreeNodeFlags_OpenOnArrow) ? ImGuiButtonFlags_PressedOnClickRelease : 0); bool hovered, held, pressed = ButtonBehavior(interact_bb, id, &hovered, &held, button_flags); @@ -10517,7 +10517,7 @@ bool ImGui::SplitterBehavior(ImGuiID id, const ImRect& bb, ImGuiAxis axis, float bool hovered, held; ImRect bb_interact = bb; bb_interact.Expand(axis == ImGuiAxis_Y ? ImVec2(0.0f, hover_extend) : ImVec2(hover_extend, 0.0f)); - ButtonBehavior(bb_interact, id, &hovered, &held, ImGuiButtonFlags_FlattenChilds | ImGuiButtonFlags_AllowOverlapMode); + ButtonBehavior(bb_interact, id, &hovered, &held, ImGuiButtonFlags_FlattenChildren | ImGuiButtonFlags_AllowItemOverlap); if (g.ActiveId != id) SetItemAllowOverlap(); diff --git a/imgui_internal.h b/imgui_internal.h index 18e44c443f74..9c4cb3e4854b 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -176,12 +176,12 @@ enum ImGuiButtonFlags_ ImGuiButtonFlags_PressedOnClick = 1 << 2, // return true on click (default requires click+release) ImGuiButtonFlags_PressedOnRelease = 1 << 3, // return true on release (default requires click+release) ImGuiButtonFlags_PressedOnDoubleClick = 1 << 4, // return true on double-click (default requires click+release) - ImGuiButtonFlags_FlattenChilds = 1 << 5, // allow interactions even if a child window is overlapping - ImGuiButtonFlags_DontClosePopups = 1 << 6, // disable automatically closing parent popup on press // [UNUSED] - ImGuiButtonFlags_Disabled = 1 << 7, // disable interactions - ImGuiButtonFlags_AlignTextBaseLine = 1 << 8, // vertically align button to match text baseline (ButtonEx() only) - ImGuiButtonFlags_NoKeyModifiers = 1 << 9, // disable interaction if a key modifier is held - ImGuiButtonFlags_AllowOverlapMode = 1 << 10, // require previous frame HoveredId to either match id or be null before being usable + ImGuiButtonFlags_FlattenChildren = 1 << 5, // allow interactions even if a child window is overlapping + ImGuiButtonFlags_AllowItemOverlap = 1 << 6, // require previous frame HoveredId to either match id or be null before being usable, use along with SetItemAllowOverlap() + ImGuiButtonFlags_DontClosePopups = 1 << 7, // disable automatically closing parent popup on press // [UNUSED] + ImGuiButtonFlags_Disabled = 1 << 8, // disable interactions + ImGuiButtonFlags_AlignTextBaseLine = 1 << 9, // vertically align button to match text baseline (ButtonEx() only) + ImGuiButtonFlags_NoKeyModifiers = 1 << 10, // disable interaction if a key modifier is held ImGuiButtonFlags_NoHoldingActiveID = 1 << 11 // don't set ActiveId while holding the mouse (ImGuiButtonFlags_PressedOnClick only) }; From f93945540ff8191164e9e33d2bd13e14f3612b21 Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 11 Dec 2017 22:41:33 +0100 Subject: [PATCH 271/823] Renamed ImGuiTreeNodeFlags_AllowOverlapMode to ImGuiTreeNodeFlags_AllowItemOverlap. (#600, #1330) --- imgui.cpp | 7 ++++--- imgui.h | 7 ++++++- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 5e86bc012a8e..58b70196b741 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -213,6 +213,7 @@ Here is a change-log of API breaking changes, if you are using one of the functions listed, expect to have to fix some code. Also read releases logs https://github.com/ocornut/imgui/releases for more details. + - 2017/12/12 (1.53) - renamed ImGuiTreeNodeFlags_AllowOverlapMode to ImGuiTreeNodeFlags_AllowItemOverlap. Kept redirection enum (will obsolete). - 2017/12/10 (1.53) - removed SetNextWindowContentWidth(), prefer using SetNextWindowContentSize(). Kept redirection function (will obsolete). - 2017/11/27 (1.53) - renamed ImGuiTextBuffer::append() helper to appendf(), appendv() to appendfv(). If you copied the 'Log' demo in your code, it uses appendv() so that needs to be renamed. - 2017/11/18 (1.53) - Style, Begin: removed ImGuiWindowFlags_ShowBorders window flag. Borders are now fully set up in the ImGuiStyle structure (see e.g. style.FrameBorderSize, style.WindowBorderSize). Use ImGui::ShowStyleEditor() to look them up. @@ -6613,7 +6614,7 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l // - OpenOnDoubleClick .............. double-click anywhere to open // - OpenOnArrow .................... single-click on arrow to open // - OpenOnDoubleClick|OpenOnArrow .. single-click on arrow or double-click anywhere to open - ImGuiButtonFlags button_flags = ImGuiButtonFlags_NoKeyModifiers | ((flags & ImGuiTreeNodeFlags_AllowOverlapMode) ? ImGuiButtonFlags_AllowItemOverlap : 0); + ImGuiButtonFlags button_flags = ImGuiButtonFlags_NoKeyModifiers | ((flags & ImGuiTreeNodeFlags_AllowItemOverlap) ? ImGuiButtonFlags_AllowItemOverlap : 0); if (flags & ImGuiTreeNodeFlags_OpenOnDoubleClick) button_flags |= ImGuiButtonFlags_PressedOnDoubleClick | ((flags & ImGuiTreeNodeFlags_OpenOnArrow) ? ImGuiButtonFlags_PressedOnClickRelease : 0); bool hovered, held, pressed = ButtonBehavior(interact_bb, id, &hovered, &held, button_flags); @@ -6630,7 +6631,7 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l window->DC.StateStorage->SetInt(id, is_open); } } - if (flags & ImGuiTreeNodeFlags_AllowOverlapMode) + if (flags & ImGuiTreeNodeFlags_AllowItemOverlap) SetItemAllowOverlap(); // Render @@ -6696,7 +6697,7 @@ bool ImGui::CollapsingHeader(const char* label, bool* p_open, ImGuiTreeNodeFlags return false; ImGuiID id = window->GetID(label); - bool is_open = TreeNodeBehavior(id, flags | ImGuiTreeNodeFlags_CollapsingHeader | ImGuiTreeNodeFlags_NoTreePushOnOpen | (p_open ? ImGuiTreeNodeFlags_AllowOverlapMode : 0), label); + bool is_open = TreeNodeBehavior(id, flags | ImGuiTreeNodeFlags_CollapsingHeader | ImGuiTreeNodeFlags_NoTreePushOnOpen | (p_open ? ImGuiTreeNodeFlags_AllowItemOverlap : 0), label); if (p_open) { // Create a small overlapping close button // FIXME: We can evolve this into user accessible helpers to add extra buttons on title bars, headers, etc. diff --git a/imgui.h b/imgui.h index 3187f5ddd3e5..bd53d6cf4b47 100644 --- a/imgui.h +++ b/imgui.h @@ -563,7 +563,7 @@ enum ImGuiTreeNodeFlags_ { ImGuiTreeNodeFlags_Selected = 1 << 0, // Draw as selected ImGuiTreeNodeFlags_Framed = 1 << 1, // Full colored frame (e.g. for CollapsingHeader) - ImGuiTreeNodeFlags_AllowOverlapMode = 1 << 2, // Hit testing to allow subsequent widgets to overlap this one + ImGuiTreeNodeFlags_AllowItemOverlap = 1 << 2, // Hit testing to allow subsequent widgets to overlap this one ImGuiTreeNodeFlags_NoTreePushOnOpen = 1 << 3, // Don't do a TreePush() when open (e.g. for CollapsingHeader) = no extra indent nor pushing on ID stack ImGuiTreeNodeFlags_NoAutoOpenOnLog = 1 << 4, // Don't automatically and temporarily open node when Logging is active (by default logging will automatically open tree nodes) ImGuiTreeNodeFlags_DefaultOpen = 1 << 5, // Default node to be open @@ -575,6 +575,11 @@ enum ImGuiTreeNodeFlags_ //ImGuITreeNodeFlags_SpanAllAvailWidth = 1 << 11, // FIXME: TODO: Extend hit box horizontally even if not framed //ImGuiTreeNodeFlags_NoScrollOnOpen = 1 << 12, // FIXME: TODO: Disable automatic scroll on TreePop() if node got just open and contents is not visible ImGuiTreeNodeFlags_CollapsingHeader = ImGuiTreeNodeFlags_Framed | ImGuiTreeNodeFlags_NoAutoOpenOnLog + + // Obsolete names (will be removed) +#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS + , ImGuiTreeNodeFlags_AllowOverlapMode = ImGuiTreeNodeFlags_AllowItemOverlap +#endif }; // Flags for ImGui::Selectable() From 185c1eaaf341f9d8932c41b657d2eb66143b09cd Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 11 Dec 2017 22:54:03 +0100 Subject: [PATCH 272/823] Alignment + removed comments --- imgui.h | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/imgui.h b/imgui.h index bd53d6cf4b47..c33b04a52ab9 100644 --- a/imgui.h +++ b/imgui.h @@ -506,7 +506,6 @@ namespace ImGui // Flags for ImGui::Begin() enum ImGuiWindowFlags_ { - // Default: 0 ImGuiWindowFlags_NoTitleBar = 1 << 0, // Disable title-bar ImGuiWindowFlags_NoResize = 1 << 1, // Disable user resizing with the lower-right grip ImGuiWindowFlags_NoMove = 1 << 2, // Disable user moving the window @@ -537,7 +536,6 @@ enum ImGuiWindowFlags_ // Flags for ImGui::InputText() enum ImGuiInputTextFlags_ { - // Default: 0 ImGuiInputTextFlags_CharsDecimal = 1 << 0, // Allow 0123456789.+-*/ ImGuiInputTextFlags_CharsHexadecimal = 1 << 1, // Allow 0123456789ABCDEFabcdef ImGuiInputTextFlags_CharsUppercase = 1 << 2, // Turn a..z into A..Z @@ -585,7 +583,6 @@ enum ImGuiTreeNodeFlags_ // Flags for ImGui::Selectable() enum ImGuiSelectableFlags_ { - // Default: 0 ImGuiSelectableFlags_DontClosePopups = 1 << 0, // Clicking this don't close parent popup window ImGuiSelectableFlags_SpanAllColumns = 1 << 1, // Selectable frame can span all columns (text will still fit in current column) ImGuiSelectableFlags_AllowDoubleClick = 1 << 2 // Generate press events on double clicks too @@ -594,12 +591,12 @@ enum ImGuiSelectableFlags_ // Flags for ImGui::BeginCombo() enum ImGuiComboFlags_ { - ImGuiComboFlags_PopupAlignLeft = 1 << 0, // Align the popup toward the left by default - ImGuiComboFlags_HeightSmall = 1 << 1, // Max ~4 items visible. Tip: If you want your combo popup to be a specific size you can use SetNextWindowSizeConstraints() prior to calling BeginCombo() - ImGuiComboFlags_HeightRegular = 1 << 2, // Max ~8 items visible (default) - ImGuiComboFlags_HeightLarge = 1 << 3, // Max ~20 items visible - ImGuiComboFlags_HeightLargest = 1 << 4, // As many fitting items as possible - ImGuiComboFlags_HeightMask_ = ImGuiComboFlags_HeightSmall | ImGuiComboFlags_HeightRegular | ImGuiComboFlags_HeightLarge | ImGuiComboFlags_HeightLargest + ImGuiComboFlags_PopupAlignLeft = 1 << 0, // Align the popup toward the left by default + ImGuiComboFlags_HeightSmall = 1 << 1, // Max ~4 items visible. Tip: If you want your combo popup to be a specific size you can use SetNextWindowSizeConstraints() prior to calling BeginCombo() + ImGuiComboFlags_HeightRegular = 1 << 2, // Max ~8 items visible (default) + ImGuiComboFlags_HeightLarge = 1 << 3, // Max ~20 items visible + ImGuiComboFlags_HeightLargest = 1 << 4, // As many fitting items as possible + ImGuiComboFlags_HeightMask_ = ImGuiComboFlags_HeightSmall | ImGuiComboFlags_HeightRegular | ImGuiComboFlags_HeightLarge | ImGuiComboFlags_HeightLargest }; // Flags for ImGui::IsItemHovered(), ImGui::IsWindowHovered() From 4a555d35f0ba48618942984fd7bdfe12422b43ae Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 11 Dec 2017 23:16:27 +0100 Subject: [PATCH 273/823] IsWindowHovered(): split ImGuiHoveredFlags_FlattenChild into separate ChildWindows and RootWindow flags. Allowing more combination and a better symetry with IsWindowFocused() flags. (#1382) --- imgui.cpp | 35 +++++++++++++++++++++++++++++------ imgui.h | 7 ++++--- imgui_demo.cpp | 12 ++++++++++-- imgui_internal.h | 1 + 4 files changed, 44 insertions(+), 11 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 58b70196b741..61a1217c5204 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -221,7 +221,7 @@ - 2017/11/18 (1.53) - Style: removed ImGuiCol_ComboBg in favor of combo boxes using ImGuiCol_PopupBg for consistency. - 2017/11/18 (1.53) - Style: renamed ImGuiCol_ChildWindowBg to ImGuiCol_ChildBg. - 2017/11/18 (1.53) - Style: renamed style.ChildWindowRounding to style.ChildRounding, ImGuiStyleVar_ChildWindowRounding to ImGuiStyleVar_ChildRounding. - - 2017/11/02 (1.53) - marked IsRootWindowOrAnyChildHovered() as obsolete is favor of using IsWindowHovered(ImGuiHoveredFlags_FlattenChilds); + - 2017/11/02 (1.53) - marked IsRootWindowOrAnyChildHovered() as obsolete is favor of using IsWindowHovered(ImGuiHoveredFlags_RootWindow | ImGuiHoveredFlags_ChildWindows); - 2017/10/24 (1.52) - renamed IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCS/IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCS to IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCTIONS/IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS for consistency. - 2017/10/20 (1.52) - changed IsWindowHovered() default parameters behavior to return false if an item is active in another window (e.g. click-dragging item from another window to this window). You can use the newly introduced IsWindowHovered() flags to requests this specific behavior if you need it. - 2017/10/20 (1.52) - marked IsItemHoveredRect()/IsMouseHoveringWindow() as obsolete, in favor of using the newly introduced flags for IsItemHovered() and IsWindowHovered(). See https://github.com/ocornut/imgui/issues/1382 for details. @@ -2032,7 +2032,7 @@ bool ImGui::IsItemHovered(ImGuiHoveredFlags flags) // Test for bounding box overlap, as updated as ItemAdd() if (!window->DC.LastItemRectHoveredRect) return false; - IM_ASSERT((flags & ImGuiHoveredFlags_FlattenChilds) == 0); // Flags not supported by this function + IM_ASSERT((flags & (ImGuiHoveredFlags_RootWindow | ImGuiHoveredFlags_ChildWindows)) == 0); // Flags not supported by this function // Test if we are hovering the right window (our window could be behind another window) // [2017/10/16] Reverted commit 344d48be3 and testing RootWindow instead. I believe it is correct to NOT test for RootWindow but this leaves us unable to use IsItemHovered() after EndChild() itself. @@ -5440,20 +5440,43 @@ const char* ImGui::GetStyleColorName(ImGuiCol idx) return "Unknown"; } +bool ImGui::IsWindowChildOf(ImGuiWindow* window, ImGuiWindow* potential_parent) +{ + if (window->RootWindow == potential_parent) + return true; + while (window != NULL) + { + if (window == potential_parent) + return true; + window = window->ParentWindow; + } + return false; +} + bool ImGui::IsWindowHovered(ImGuiHoveredFlags flags) { IM_ASSERT((flags & ImGuiHoveredFlags_AllowWhenOverlapped) == 0); // Flags not supported by this function ImGuiContext& g = *GImGui; - if (flags & ImGuiHoveredFlags_FlattenChilds) + switch (flags & (ImGuiHoveredFlags_RootWindow | ImGuiHoveredFlags_ChildWindows)) { + case ImGuiHoveredFlags_RootWindow | ImGuiHoveredFlags_ChildWindows: if (g.HoveredRootWindow != g.CurrentWindow->RootWindow) return false; - } - else - { + break; + case ImGuiHoveredFlags_RootWindow: + if (g.HoveredWindow != g.CurrentWindow->RootWindow) + return false; + break; + case ImGuiHoveredFlags_ChildWindows: + if (g.HoveredWindow == NULL || !IsWindowChildOf(g.HoveredWindow, g.CurrentWindow)) + return false; + break; + default: if (g.HoveredWindow != g.CurrentWindow) return false; + break; } + if (!IsWindowContentHoverable(g.HoveredRootWindow, flags)) return false; if (!(flags & ImGuiHoveredFlags_AllowWhenBlockedByActiveItem)) diff --git a/imgui.h b/imgui.h index c33b04a52ab9..79c54c7061f3 100644 --- a/imgui.h +++ b/imgui.h @@ -607,7 +607,8 @@ enum ImGuiHoveredFlags_ //ImGuiHoveredFlags_AllowWhenBlockedByModal = 1 << 1, // Return true even if a modal popup window is normally blocking access to this item/window. FIXME-TODO: Unavailable yet. ImGuiHoveredFlags_AllowWhenBlockedByActiveItem = 1 << 2, // Return true even if an active item is blocking access to this item/window ImGuiHoveredFlags_AllowWhenOverlapped = 1 << 3, // Return true even if the position is overlapped by another window - ImGuiHoveredFlags_FlattenChilds = 1 << 4, // Treat all child windows as the same window (for IsWindowHovered()) + ImGuiHoveredFlags_ChildWindows = 1 << 4, // IsWindowHovered() only: Return true if any children of the window is hovered + ImGuiHoveredFlags_RootWindow = 1 << 5, // IsWindowHovered() only: Test from root window (top most parent of the current hierarchy) ImGuiHoveredFlags_RectOnly = ImGuiHoveredFlags_AllowWhenBlockedByPopup | ImGuiHoveredFlags_AllowWhenBlockedByActiveItem | ImGuiHoveredFlags_AllowWhenOverlapped }; @@ -937,8 +938,8 @@ struct ImGuiIO #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS namespace ImGui { - static inline void SetNextWindowContentWidth(float width) { ImGui::SetNextWindowContentSize(ImVec2(width, 0.0f)); } // OBSOLETE 1.53+ (nb: original version preserved last Y value set by SetNextWindowContentSize()) - static inline bool IsRootWindowOrAnyChildHovered(ImGuiHoveredFlags flags = 0) { return IsItemHovered(flags | ImGuiHoveredFlags_FlattenChilds); } // OBSOLETE 1.53+ use flags directly + static inline void SetNextWindowContentWidth(float width) { SetNextWindowContentSize(ImVec2(width, 0.0f)); } // OBSOLETE 1.53+ (nb: original version preserved last Y value set by SetNextWindowContentSize()) + static inline bool IsRootWindowOrAnyChildHovered(ImGuiHoveredFlags flags = 0) { return IsItemHovered(flags | ImGuiHoveredFlags_RootWindow | ImGuiHoveredFlags_ChildWindows); } // OBSOLETE 1.53+ use flags directly bool Begin(const char* name, bool* p_open, const ImVec2& size_on_first_use, float bg_alpha_override = -1.0f, ImGuiWindowFlags flags = 0); // OBSOLETE 1.52+. use SetNextWindowSize() instead if you want to set a window size. static inline void AlignFirstTextHeightToWidgets() { AlignTextToFramePadding(); } // OBSOLETE 1.52+ static inline void SetNextWindowPosCenter(ImGuiCond cond = 0) { SetNextWindowPos(ImVec2(GetIO().DisplaySize.x * 0.5f, GetIO().DisplaySize.y * 0.5f), cond, ImVec2(0.5f, 0.5f)); } // OBSOLETE 1.52+ diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 6c6952a3f2fe..c82f99e5082f 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -1788,11 +1788,15 @@ void ImGui::ShowTestWindow(bool* p_open) "IsWindowHovered() = %d\n" "IsWindowHovered(_AllowWhenBlockedByPopup) = %d\n" "IsWindowHovered(_AllowWhenBlockedByActiveItem) = %d\n" - "IsWindowHovered(_FlattenChilds) = %d\n", + "IsWindowHovered(_ChildWindows) = %d\n" + "IsWindowHovered(_ChildWindows|_RootWindow) = %d\n" + "IsWindowHovered(_RootWindow) = %d\n", ImGui::IsWindowHovered(), ImGui::IsWindowHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup), ImGui::IsWindowHovered(ImGuiHoveredFlags_AllowWhenBlockedByActiveItem), - ImGui::IsWindowHovered(ImGuiHoveredFlags_FlattenChilds)); + ImGui::IsWindowHovered(ImGuiHoveredFlags_ChildWindows), + ImGui::IsWindowHovered(ImGuiHoveredFlags_ChildWindows | ImGuiHoveredFlags_RootWindow), + ImGui::IsWindowHovered(ImGuiHoveredFlags_RootWindow)); // Testing IsItemHovered() function (because BulletText is an item itself and that would affect the output of IsItemHovered, we pass all lines in a single items to shorten the code) ImGui::Button("ITEM"); @@ -1808,6 +1812,10 @@ void ImGui::ShowTestWindow(bool* p_open) ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenOverlapped), ImGui::IsItemHovered(ImGuiHoveredFlags_RectOnly)); + ImGui::BeginChild("child", ImVec2(0,50), true); + ImGui::Text("This is a child window for testing IsWindowHovered() flags."); + ImGui::EndChild(); + ImGui::TreePop(); } diff --git a/imgui_internal.h b/imgui_internal.h index 9c4cb3e4854b..5a84f2f68a92 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -804,6 +804,7 @@ namespace ImGui IMGUI_API void FocusWindow(ImGuiWindow* window); IMGUI_API void BringWindowToFront(ImGuiWindow* window); IMGUI_API void BringWindowToBack(ImGuiWindow* window); + IMGUI_API bool IsWindowChildOf(ImGuiWindow* window, ImGuiWindow* potential_parent); IMGUI_API void Initialize(); From f42d7b89e2430e02905cdd284b20ae0fe7a558fd Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 12 Dec 2017 00:18:31 +0100 Subject: [PATCH 274/823] Internals: Removed misleading GetWindowParent() function. + renaming to clear confusing. --- imgui.cpp | 15 ++++----------- imgui_internal.h | 1 - 2 files changed, 4 insertions(+), 12 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 61a1217c5204..cf83b2ea3caa 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1910,13 +1910,6 @@ static void SetCurrentWindow(ImGuiWindow* window) g.FontSize = window->CalcFontSize(); } -ImGuiWindow* ImGui::GetParentWindow() -{ - ImGuiContext& g = *GImGui; - IM_ASSERT(g.CurrentWindowStack.Size >= 2); - return g.CurrentWindowStack[(unsigned int)g.CurrentWindowStack.Size - 2]; -} - void ImGui::SetActiveID(ImGuiID id, ImGuiWindow* window) { ImGuiContext& g = *GImGui; @@ -3686,9 +3679,9 @@ void ImGui::EndTooltip() void ImGui::OpenPopupEx(ImGuiID id, bool reopen_existing) { ImGuiContext& g = *GImGui; - ImGuiWindow* window = g.CurrentWindow; + ImGuiWindow* parent_window = g.CurrentWindow; int current_stack_size = g.CurrentPopupStack.Size; - ImGuiPopupRef popup_ref = ImGuiPopupRef(id, window, window->GetID("##Menus"), g.IO.MousePos); // Tagged as new ref because constructor sets Window to NULL (we are passing the ParentWindow info here) + ImGuiPopupRef popup_ref = ImGuiPopupRef(id, parent_window, parent_window->GetID("##Menus"), g.IO.MousePos); // Tagged as new ref because constructor sets Window to NULL. if (g.OpenPopupStack.Size < current_stack_size + 1) g.OpenPopupStack.push_back(popup_ref); else if (reopen_existing || g.OpenPopupStack[current_stack_size].PopupId != id) @@ -3699,7 +3692,7 @@ void ImGui::OpenPopupEx(ImGuiID id, bool reopen_existing) // When reopening a popup we first refocus its parent, otherwise if its parent is itself a popup it would get closed by CloseInactivePopups(). // This is equivalent to what ClosePopupToLevel() does. if (g.OpenPopupStack[current_stack_size].PopupId == id) - FocusWindow(window); + FocusWindow(parent_window); } } @@ -9426,7 +9419,7 @@ bool ImGui::ListBoxHeader(const char* label, int items_count, int height_in_item void ImGui::ListBoxFooter() { - ImGuiWindow* parent_window = GetParentWindow(); + ImGuiWindow* parent_window = GetCurrentWindow()->ParentWindow; const ImRect bb = parent_window->DC.LastItemRect; const ImGuiStyle& style = GetStyle(); diff --git a/imgui_internal.h b/imgui_internal.h index 5a84f2f68a92..b1dab53fbb1b 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -799,7 +799,6 @@ namespace ImGui // - You are calling ImGui functions after ImGui::Render() and before the next ImGui::NewFrame(), which is also illegal. inline ImGuiWindow* GetCurrentWindowRead() { ImGuiContext& g = *GImGui; return g.CurrentWindow; } inline ImGuiWindow* GetCurrentWindow() { ImGuiContext& g = *GImGui; g.CurrentWindow->WriteAccessed = true; return g.CurrentWindow; } - IMGUI_API ImGuiWindow* GetParentWindow(); IMGUI_API ImGuiWindow* FindWindowByName(const char* name); IMGUI_API void FocusWindow(ImGuiWindow* window); IMGUI_API void BringWindowToFront(ImGuiWindow* window); From c65124f415ae081b1aacaf299c539a32968809a7 Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 12 Dec 2017 00:48:28 +0100 Subject: [PATCH 275/823] Internals: ParentWindow is now NULL for non-child windows and means what everyone expects. --- imgui.cpp | 13 +++++++------ imgui_internal.h | 2 +- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index cf83b2ea3caa..55fb5516f9c9 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -4338,7 +4338,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) SetWindowConditionAllowFlags(window, ImGuiCond_Appearing, true); // Parent window is latched only on the first call to Begin() of the frame, so further append-calls can be done from a different window stack - ImGuiWindow* parent_window = first_begin_of_the_frame ? (!g.CurrentWindowStack.empty() ? g.CurrentWindowStack.back() : NULL) : window->ParentWindow; + ImGuiWindow* parent_window = first_begin_of_the_frame ? ((flags & ImGuiWindowFlags_ChildWindow) && !g.CurrentWindowStack.empty() ? g.CurrentWindowStack.back() : NULL) : window->ParentWindow; IM_ASSERT(parent_window != NULL || !(flags & ImGuiWindowFlags_ChildWindow)); // Add to stack @@ -4409,8 +4409,8 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) { // Initialize window->ParentWindow = parent_window; - window->RootWindow = !(flags & ImGuiWindowFlags_ChildWindow) ? window : parent_window->RootWindow; - window->RootNonPopupWindow = !(flags & (ImGuiWindowFlags_ChildWindow | ImGuiWindowFlags_Popup)) || (flags & ImGuiWindowFlags_Modal) ? window : parent_window->RootNonPopupWindow; // Used to display TitleBgActive color and for selecting which window to use for NavWindowing + window->RootWindow = ((flags & ImGuiWindowFlags_ChildWindow) && parent_window) ? parent_window->RootWindow : window; + window->RootNonPopupWindow = !(flags & (ImGuiWindowFlags_ChildWindow | ImGuiWindowFlags_Popup)) || (flags & ImGuiWindowFlags_Modal) || (parent_window == NULL) ? window : parent_window->RootNonPopupWindow; // Used to display TitleBgActive color and for selecting which window to use for NavWindowing //window->RootNavWindow = window; //while (window->RootNavWindow->Flags & ImGuiWindowFlags_NavFlattened) // window->RootNavWindow = window->RootNavWindow->ParentWindow; @@ -4556,11 +4556,12 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) // This is how we end up with child menus appearing (most-commonly) on the right of the parent menu. IM_ASSERT(window_pos_set_by_api); float horizontal_overlap = style.ItemSpacing.x; // We want some overlap to convey the relative depth of each popup (currently the amount of overlap it is hard-coded to style.ItemSpacing.x, may need to introduce another style value). + ImGuiWindow* parent_menu = g.CurrentWindowStack[g.CurrentWindowStack.Size - 2]; ImRect rect_to_avoid; - if (parent_window->DC.MenuBarAppending) - rect_to_avoid = ImRect(-FLT_MAX, parent_window->Pos.y + parent_window->TitleBarHeight(), FLT_MAX, parent_window->Pos.y + parent_window->TitleBarHeight() + parent_window->MenuBarHeight()); + if (parent_menu->DC.MenuBarAppending) + rect_to_avoid = ImRect(-FLT_MAX, parent_menu->Pos.y + parent_menu->TitleBarHeight(), FLT_MAX, parent_menu->Pos.y + parent_menu->TitleBarHeight() + parent_menu->MenuBarHeight()); else - rect_to_avoid = ImRect(parent_window->Pos.x + horizontal_overlap, -FLT_MAX, parent_window->Pos.x + parent_window->Size.x - horizontal_overlap - parent_window->ScrollbarSizes.x, FLT_MAX); + rect_to_avoid = ImRect(parent_menu->Pos.x + horizontal_overlap, -FLT_MAX, parent_menu->Pos.x + parent_menu->Size.x - horizontal_overlap - parent_menu->ScrollbarSizes.x, FLT_MAX); window->PosFloat = FindBestWindowPosForPopup(window->PosFloat, window->Size, &window->AutoPosLastDirection, rect_to_avoid); } else if ((flags & ImGuiWindowFlags_Popup) != 0 && !window_pos_set_by_api && window_just_appearing_after_hidden_for_resize) diff --git a/imgui_internal.h b/imgui_internal.h index b1dab53fbb1b..417a0fb15131 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -746,7 +746,7 @@ struct IMGUI_API ImGuiWindow ImGuiStorage StateStorage; float FontWindowScale; // Scale multiplier per-window ImDrawList* DrawList; - ImGuiWindow* ParentWindow; // Immediate parent in the window stack *regardless* of whether this window is a child window or not) + ImGuiWindow* ParentWindow; // If we are a child window, this is pointing to our parent. ImGuiWindow* RootWindow; // Generally point to ourself. If we are a child window, this is pointing to the first non-child parent window. ImGuiWindow* RootNonPopupWindow; // Generally point to ourself. Used to display TitleBgActive color and for selecting which window to use for NavWindowing From de4a851f954fbf50022d3b4715f8cac3c62f2416 Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 12 Dec 2017 11:20:45 +0100 Subject: [PATCH 276/823] Font documentation update (#1498) --- extra_fonts/README.txt | 94 ++++++++++++++++++++++++++++++------------ 1 file changed, 67 insertions(+), 27 deletions(-) diff --git a/extra_fonts/README.txt b/extra_fonts/README.txt index 5d41a6bb83ed..2287f6eaab08 100644 --- a/extra_fonts/README.txt +++ b/extra_fonts/README.txt @@ -1,25 +1,48 @@ - The code in imgui.cpp embeds a copy of 'ProggyClean.ttf' (by Tristan Grimmer) that is used by default. - We embed the font in source code so you can use Dear ImGui without any file system access. - You may also load external .TTF/.OTF files. - The files in this folder are suggested fonts, provided as a convenience. - (Note: .OTF support in stb_truetype.h currently doesn't appear to load every font) +The code in imgui.cpp embeds a copy of 'ProggyClean.ttf' (by Tristan Grimmer) that is used by default. +We embed the font in source code so you can use Dear ImGui without any file system access. +You may also load external .TTF/.OTF files. +The files in this folder are suggested fonts, provided as a convenience. +(Note: .OTF support in stb_truetype.h currently doesn't appear to load every font) - Fonts are rasterized in a single texture at the time of calling either of io.Fonts.GetTexDataAsAlpha8()/GetTexDataAsRGBA32()/Build(). +Fonts are rasterized in a single texture at the time of calling either of io.Fonts.GetTexDataAsAlpha8()/GetTexDataAsRGBA32()/Build(). +Also read dear imgui FAQ in imgui.cpp! ---------------------------------- +In this document: + +- Using Icons +- Fonts Loading Instructions +- FreeType rasterizer, Small font sizes +- Building Custom Glyph Ranges +- Remapping Codepoints +- Embedding Fonts in Source Code +- Credits/Licences for fonts included in this folder +- Links, Other fonts + + +--------------------------------------- USING ICONS ---------------------------------- +--------------------------------------- Using an icon font (such as FontAwesome: http://fontawesome.io) is an easy and practical way to use icons in your ImGui application. - A common pattern is to merge the icon font within your main font, so you can refer to the icons directly from your strings without having to change fonts back and forth. - To refer to the icon from your C++ code, you can use headers files created by Juliette Foucaut, at https://github.com/juliettef/IconFontCppHeaders - See Links below for other icons fonts and related tools. + A common pattern is to merge the icon font within your main font, so you can embed icons directly from your strings without + having to change fonts back and forth. + + To refer to the icon UTF-8 codepoints from your C++ code, you may use those headers files created by Juliette Foucaut: + https://github.com/juliettef/IconFontCppHeaders + + The C++11 version of those files uses the u8"" utf-8 encoding syntax + \u + #define ICON_FA_SEARCH u8"\uf002" + The pre-C++11 version has the values directly encoded as utf-8: + #define ICON_FA_SEARCH "\xEF\x80\x82" + + Example: // Merge icons into default tool font #include "IconsFontAwesome.h" ImGuiIO& io = ImGui::GetIO(); io.Fonts->AddFontDefault(); + ImFontConfig config; config.MergeMode = true; static const ImWchar icon_ranges[] = { ICON_MIN_FA, ICON_MAX_FA, 0 }; @@ -28,10 +51,12 @@ // Usage, e.g. ImGui::Text("%s Search", ICON_FA_SEARCH); + See Links below for other icons fonts and related tools. + ---------------------------------- +--------------------------------------- FONTS LOADING INSTRUCTIONS ---------------------------------- +--------------------------------------- Load default font with: @@ -43,7 +68,7 @@ ImGuiIO& io = ImGui::GetIO(); io.Fonts->AddFontFromFileTTF("font.ttf", size_pixels); - Advanced options: + For advanced options create a ImFontConfig structure and pass it to the AddFont function (it will be copied internally) ImFontConfig config; config.OversampleH = 3; @@ -89,9 +114,23 @@ font->DisplayOffset.y += 1; // Render 1 pixel down ---------------------------------- +--------------------------------------- + FREETYPE RASTERIZER, SMALL FONT SIZES +--------------------------------------- + + Dear Imgui uses stb_truetype.h to rasterize fonts (with optional oversampling). + This technique and implementation are not ideal for fonts rendered at _small sizes_, which may appear a little blurry. + There is an implementation of the ImFontAtlas builder using FreeType that you can use: + + https://github.com/ocornut/imgui_club + + FreeType supports auto-hinting which tends to improve the readability of small fonts. + Note that this code currently creates textures that are unoptimally too large (could be fixed with some work) + + +--------------------------------------- BUILDING CUSTOM GLYPH RANGES ---------------------------------- +--------------------------------------- You can use the ImFontAtlas::GlyphRangesBuilder helper to create glyph ranges based on text input. For exemple: for a game where your script is known, if you can feed your entire script to it and only build the characters the game needs. @@ -105,9 +144,9 @@ io.Fonts->AddFontFromFileTTF("myfontfile.ttf", size_in_pixels, NULL, ranges.Data); ---------------------------------- +--------------------------------------- REMAPPING CODEPOINTS ---------------------------------- +--------------------------------------- All your strings needs to use UTF-8 encoding. Specifying literal in your source code using a local code page (such as CP-923 for Japanese, or CP-1251 for Cyrillic) will NOT work! In C++11 you can encode a string literal in UTF-8 by using the u8"hello" syntax. Otherwise you can convert yourself to UTF-8 or load text data from file already saved as UTF-8. @@ -117,9 +156,9 @@ You may also try to remap your local codepage characters to their Unicode codepoint using font->AddRemapChar(), but international users may have problems reading/editing your source code. ---------------------------------- - EMBEDDING FONT IN SOURCE CODE ---------------------------------- +--------------------------------------- + EMBEDDING FONTS IN SOURCE CODE +--------------------------------------- Compile and use 'binary_to_compressed_c.cpp' to create a compressed C style array that you can embed in source code. See the documentation in binary_to_compressed_c.cpp for instruction on how to use the tool. @@ -135,9 +174,9 @@ ImFont* font = io.Fonts->AddFontFromMemoryCompressedBase85TTF(compressed_data_base85, size_pixels, ...); ---------------------------------- - FONT FILES INCLUDED IN THIS FOLDER ---------------------------------- +--------------------------------------- + CREDITS/LICENSES FOR FONTS INCLUDED IN THIS FOLDER +--------------------------------------- Roboto-Medium.ttf Apache License 2.0 @@ -172,9 +211,9 @@ SIL OPEN FONT LICENSE Version 1.1 ---------------------------------- - LINKS & OTHER FONTS ---------------------------------- +--------------------------------------- + LINKS, OTHER FONTS +--------------------------------------- (Icons) Icon fonts https://fortawesome.github.io/Font-Awesome/ @@ -213,3 +252,4 @@ http://mplus-fonts.sourceforge.jp/mplus-outline-fonts/index-en.html Or use Arial Unicode or other Unicode fonts provided with Windows for full characters coverage (not sure of their licensing). + From fa179d0ad8e9b2706b5b7704cbc7b513b685e86e Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 12 Dec 2017 12:52:24 +0100 Subject: [PATCH 277/823] Reordered ImGuiHoveredFlags to match upcoming ImGuiFocusedFlags (#1382) --- imgui.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/imgui.h b/imgui.h index 79c54c7061f3..495f6b3696ae 100644 --- a/imgui.h +++ b/imgui.h @@ -603,12 +603,12 @@ enum ImGuiComboFlags_ enum ImGuiHoveredFlags_ { ImGuiHoveredFlags_Default = 0, // Return true if directly over the item/window, not obstructed by another window, not obstructed by an active popup or modal blocking inputs under them. - ImGuiHoveredFlags_AllowWhenBlockedByPopup = 1 << 0, // Return true even if a popup window is normally blocking access to this item/window - //ImGuiHoveredFlags_AllowWhenBlockedByModal = 1 << 1, // Return true even if a modal popup window is normally blocking access to this item/window. FIXME-TODO: Unavailable yet. - ImGuiHoveredFlags_AllowWhenBlockedByActiveItem = 1 << 2, // Return true even if an active item is blocking access to this item/window - ImGuiHoveredFlags_AllowWhenOverlapped = 1 << 3, // Return true even if the position is overlapped by another window - ImGuiHoveredFlags_ChildWindows = 1 << 4, // IsWindowHovered() only: Return true if any children of the window is hovered - ImGuiHoveredFlags_RootWindow = 1 << 5, // IsWindowHovered() only: Test from root window (top most parent of the current hierarchy) + ImGuiHoveredFlags_ChildWindows = 1 << 0, // IsWindowHovered() only: Return true if any children of the window is hovered + ImGuiHoveredFlags_RootWindow = 1 << 1, // IsWindowHovered() only: Test from root window (top most parent of the current hierarchy) + ImGuiHoveredFlags_AllowWhenBlockedByPopup = 1 << 2, // Return true even if a popup window is normally blocking access to this item/window + //ImGuiHoveredFlags_AllowWhenBlockedByModal = 1 << 3, // Return true even if a modal popup window is normally blocking access to this item/window. FIXME-TODO: Unavailable yet. + ImGuiHoveredFlags_AllowWhenBlockedByActiveItem = 1 << 4, // Return true even if an active item is blocking access to this item/window + ImGuiHoveredFlags_AllowWhenOverlapped = 1 << 5, // Return true even if the position is overlapped by another window ImGuiHoveredFlags_RectOnly = ImGuiHoveredFlags_AllowWhenBlockedByPopup | ImGuiHoveredFlags_AllowWhenBlockedByActiveItem | ImGuiHoveredFlags_AllowWhenOverlapped }; From 8d8f4934fb0a2a00e8011495cee761d2eb51598f Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 12 Dec 2017 13:11:40 +0100 Subject: [PATCH 278/823] Demo: mouse dragging demo tweaks --- imgui_demo.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/imgui_demo.cpp b/imgui_demo.cpp index c82f99e5082f..e5c2e15f55d2 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -1704,7 +1704,7 @@ void ImGui::ShowTestWindow(bool* p_open) { ImGuiIO& io = ImGui::GetIO(); ImGui::Checkbox("io.MouseDrawCursor", &io.MouseDrawCursor); - ImGui::SameLine(); ShowHelpMarker("Request ImGui to render a mouse cursor for you in software. Note that a mouse cursor rendered via regular GPU rendering will feel more laggy than hardware cursor, but will be more in sync with your other visuals."); + ImGui::SameLine(); ShowHelpMarker("Request ImGui to render a mouse cursor for you in software. Note that a mouse cursor rendered via your application GPU rendering path will feel more laggy than hardware cursor, but will be more in sync with your other visuals.\n\nSome desktop applications may use both kinds of cursors (e.g. enable software cursor only when resizing/dragging something)."); ImGui::Text("WantCaptureMouse: %d", io.WantCaptureMouse); ImGui::Text("WantCaptureKeyboard: %d", io.WantCaptureKeyboard); @@ -1823,7 +1823,8 @@ void ImGui::ShowTestWindow(bool* p_open) { ImGui::TextWrapped("You can use ImGui::GetMouseDragDelta(0) to query for the dragged amount on any widget."); for (int button = 0; button < 3; button++) - ImGui::Text("IsMouseDragging(%d) = %d", button, ImGui::IsMouseDragging(button)); + ImGui::Text("IsMouseDragging(%d):\n w/ default threshold: %d,\n w/ zero threshold: %d\n w/ large threshold: %d", + button, ImGui::IsMouseDragging(button), ImGui::IsMouseDragging(button, 0.0f), ImGui::IsMouseDragging(button, 20.0f)); ImGui::Button("Drag Me"); if (ImGui::IsItemActive()) { @@ -1832,6 +1833,9 @@ void ImGui::ShowTestWindow(bool* p_open) draw_list->PushClipRectFullScreen(); draw_list->AddLine(ImGui::CalcItemRectClosestPoint(io.MousePos, true, -2.0f), io.MousePos, ImColor(ImGui::GetStyle().Colors[ImGuiCol_Button]), 4.0f); draw_list->PopClipRect(); + + // Drag operations gets "unlocked" when the mouse has moved past a certain threshold (the default threshold is stored in io.MouseDragThreshold) + // You can request a lower or higher threshold using the second parameter of IsMouseDragging() and GetMouseDragDelta() ImVec2 value_raw = ImGui::GetMouseDragDelta(0, 0.0f); ImVec2 value_with_lock_threshold = ImGui::GetMouseDragDelta(0); ImVec2 mouse_delta = io.MouseDelta; From 08b72eb5c04429c6a34e99db4b5c1c2d5fe19964 Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 12 Dec 2017 14:06:24 +0100 Subject: [PATCH 279/823] IsWindowFocused() refactor will flags. (#1382) Marked IsRootWindowFocused() as obsolete in favor of using IsWindowFocused(ImGuiFocusedFlags_RootWindow). Marked IsRootWindowOrAnyChildFocused() as obsolete in favor of using IsWindowFocused(ImGuiFocusedFlags_RootAndChildWindows). --- imgui.cpp | 29 ++++++++++++++--------------- imgui.h | 19 ++++++++++++++----- imgui_demo.cpp | 23 +++++++++++++++++++++-- 3 files changed, 49 insertions(+), 22 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 55fb5516f9c9..f4ca2411cf31 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -213,6 +213,8 @@ Here is a change-log of API breaking changes, if you are using one of the functions listed, expect to have to fix some code. Also read releases logs https://github.com/ocornut/imgui/releases for more details. + - 2017/12/23 (1.53) - marked IsRootWindowFocused() as obsolete in favor of using IsWindowFocused(ImGuiFocusedFlags_RootWindow). + - marked IsRootWindowOrAnyChildFocused() as obsolete in favor of using IsWindowFocused(ImGuiFocusedFlags_RootAndChildWindows). - 2017/12/12 (1.53) - renamed ImGuiTreeNodeFlags_AllowOverlapMode to ImGuiTreeNodeFlags_AllowItemOverlap. Kept redirection enum (will obsolete). - 2017/12/10 (1.53) - removed SetNextWindowContentWidth(), prefer using SetNextWindowContentSize(). Kept redirection function (will obsolete). - 2017/11/27 (1.53) - renamed ImGuiTextBuffer::append() helper to appendf(), appendv() to appendfv(). If you copied the 'Log' demo in your code, it uses appendv() so that needs to be renamed. @@ -5479,25 +5481,22 @@ bool ImGui::IsWindowHovered(ImGuiHoveredFlags flags) return true; } -bool ImGui::IsWindowFocused() +bool ImGui::IsWindowFocused(ImGuiFocusedFlags flags) { ImGuiContext& g = *GImGui; IM_ASSERT(g.CurrentWindow); // Not inside a Begin()/End() - return g.NavWindow == g.CurrentWindow; -} -bool ImGui::IsRootWindowFocused() -{ - ImGuiContext& g = *GImGui; - IM_ASSERT(g.CurrentWindow); // Not inside a Begin()/End() - return g.NavWindow == g.CurrentWindow->RootWindow; -} - -bool ImGui::IsRootWindowOrAnyChildFocused() -{ - ImGuiContext& g = *GImGui; - IM_ASSERT(g.CurrentWindow); // Not inside a Begin()/End() - return g.NavWindow && g.NavWindow->RootWindow == g.CurrentWindow->RootWindow; + switch (flags & (ImGuiFocusedFlags_RootWindow | ImGuiHoveredFlags_ChildWindows)) + { + case ImGuiFocusedFlags_RootWindow | ImGuiHoveredFlags_ChildWindows: + return g.NavWindow && g.CurrentWindow->RootWindow == g.NavWindow->RootWindow; + case ImGuiFocusedFlags_RootWindow: + return g.CurrentWindow->RootWindow == g.NavWindow; + case ImGuiHoveredFlags_ChildWindows: + return g.NavWindow && IsWindowChildOf(g.NavWindow, g.CurrentWindow); + default: + return g.CurrentWindow == g.NavWindow; + } } float ImGui::GetWindowWidth() diff --git a/imgui.h b/imgui.h index 495f6b3696ae..17f594694a36 100644 --- a/imgui.h +++ b/imgui.h @@ -80,7 +80,8 @@ typedef int ImDrawCornerFlags; // flags: for ImDrawList::AddRect*() etc. typedef int ImGuiColorEditFlags; // flags: for ColorEdit*(), ColorPicker*() // enum ImGuiColorEditFlags_ typedef int ImGuiColumnsFlags; // flags: for *Columns*() // enum ImGuiColumnsFlags_ typedef int ImGuiComboFlags; // flags: for BeginCombo() // enum ImGuiComboFlags_ -typedef int ImGuiHoveredFlags; // flags: for IsItemHovered() // enum ImGuiHoveredFlags_ +typedef int ImGuiFocusedFlags; // flags: for IsWindowFocused() // enum ImGuiFocusedFlags_ +typedef int ImGuiHoveredFlags; // flags: for IsItemHovered() etc. // enum ImGuiHoveredFlags_ typedef int ImGuiInputTextFlags; // flags: for InputText*() // enum ImGuiInputTextFlags_ typedef int ImGuiSelectableFlags; // flags: for Selectable() // enum ImGuiSelectableFlags_ typedef int ImGuiTreeNodeFlags; // flags: for TreeNode*(),CollapsingHeader()// enum ImGuiTreeNodeFlags_ @@ -442,10 +443,8 @@ namespace ImGui IMGUI_API ImVec2 GetItemRectMax(); // " IMGUI_API ImVec2 GetItemRectSize(); // " IMGUI_API void SetItemAllowOverlap(); // allow last item to be overlapped by a subsequent item. sometimes useful with invisible buttons, selectables, etc. to catch unused area. - IMGUI_API bool IsWindowFocused(); // is current Begin()-ed window focused? - IMGUI_API bool IsWindowHovered(ImGuiHoveredFlags flags = 0); // is current Begin()-ed window hovered (and typically: not blocked by a popup/modal)? - IMGUI_API bool IsRootWindowFocused(); // is current Begin()-ed root window focused (root = top-most parent of a child, otherwise self)? - IMGUI_API bool IsRootWindowOrAnyChildFocused(); // is current Begin()-ed root window or any of its child (including current window) focused? + IMGUI_API bool IsWindowFocused(ImGuiFocusedFlags flags = 0); // is current window focused? or its root/child, depending on flags. see flags for options. + IMGUI_API bool IsWindowHovered(ImGuiHoveredFlags flags = 0); // is current window hovered (and typically: not blocked by a popup/modal)? see flags for options. IMGUI_API bool IsAnyWindowHovered(); // is mouse hovering any visible window IMGUI_API bool IsRectVisible(const ImVec2& size); // test if rectangle (of given size, starting from cursor position) is visible / not clipped. IMGUI_API bool IsRectVisible(const ImVec2& rect_min, const ImVec2& rect_max); // test if rectangle (in screen space) is visible / not clipped. to perform coarse clipping on user's side. @@ -599,6 +598,14 @@ enum ImGuiComboFlags_ ImGuiComboFlags_HeightMask_ = ImGuiComboFlags_HeightSmall | ImGuiComboFlags_HeightRegular | ImGuiComboFlags_HeightLarge | ImGuiComboFlags_HeightLargest }; +// Flags for ImGui::IsWindowFocused() +enum ImGuiFocusedFlags_ +{ + ImGuiFocusedFlags_ChildWindows = 1 << 0, // IsWindowFocused(): Return true if any children of the window is focused + ImGuiFocusedFlags_RootWindow = 1 << 1, // IsWindowFocused(): Test from root window (top most parent of the current hierarchy) + ImGuiFocusedFlags_RootAndChildWindows = ImGuiFocusedFlags_RootWindow | ImGuiFocusedFlags_ChildWindows, +}; + // Flags for ImGui::IsItemHovered(), ImGui::IsWindowHovered() enum ImGuiHoveredFlags_ { @@ -938,6 +945,8 @@ struct ImGuiIO #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS namespace ImGui { + static inline bool IsRootWindowFocused() { return IsWindowFocused(ImGuiFocusedFlags_RootWindow); } // OBSOLETE 1.53+ + static inline bool IsRootWindowOrAnyChildFocused() { return IsWindowFocused(ImGuiFocusedFlags_RootAndChildWindows); } // OBSOLETE 1.53+ static inline void SetNextWindowContentWidth(float width) { SetNextWindowContentSize(ImVec2(width, 0.0f)); } // OBSOLETE 1.53+ (nb: original version preserved last Y value set by SetNextWindowContentSize()) static inline bool IsRootWindowOrAnyChildHovered(ImGuiHoveredFlags flags = 0) { return IsItemHovered(flags | ImGuiHoveredFlags_RootWindow | ImGuiHoveredFlags_ChildWindows); } // OBSOLETE 1.53+ use flags directly bool Begin(const char* name, bool* p_open, const ImVec2& size_on_first_use, float bg_alpha_override = -1.0f, ImGuiWindowFlags flags = 0); // OBSOLETE 1.52+. use SetNextWindowSize() instead if you want to set a window size. diff --git a/imgui_demo.cpp b/imgui_demo.cpp index e5c2e15f55d2..293cc22d4050 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -1781,8 +1781,24 @@ void ImGui::ShowTestWindow(bool* p_open) ImGui::TreePop(); } - if (ImGui::TreeNode("Hovering")) + if (ImGui::TreeNode("Focused & Hovered Test")) { + static bool embed_all_inside_a_child_window = false; + ImGui::Checkbox("Embed everything inside a child window (for additional testing)", &embed_all_inside_a_child_window); + if (embed_all_inside_a_child_window) + ImGui::BeginChild("embeddingchild", ImVec2(0, ImGui::GetFontSize() * 25), true); + + // Testing IsWindowFocused() function with its various flags (note that the flags can be combined) + ImGui::BulletText( + "IsWindowFocused() = %d\n" + "IsWindowFocused(_ChildWindows) = %d\n" + "IsWindowFocused(_ChildWindows|_RootWindow) = %d\n" + "IsWindowFocused(_RootWindow) = %d\n", + ImGui::IsWindowFocused(), + ImGui::IsWindowFocused(ImGuiHoveredFlags_ChildWindows), + ImGui::IsWindowFocused(ImGuiHoveredFlags_ChildWindows | ImGuiHoveredFlags_RootWindow), + ImGui::IsWindowFocused(ImGuiHoveredFlags_RootWindow)); + // Testing IsWindowHovered() function with its various flags (note that the flags can be combined) ImGui::BulletText( "IsWindowHovered() = %d\n" @@ -1813,9 +1829,12 @@ void ImGui::ShowTestWindow(bool* p_open) ImGui::IsItemHovered(ImGuiHoveredFlags_RectOnly)); ImGui::BeginChild("child", ImVec2(0,50), true); - ImGui::Text("This is a child window for testing IsWindowHovered() flags."); + ImGui::Text("This is another child window for testing IsWindowHovered() flags."); ImGui::EndChild(); + if (embed_all_inside_a_child_window) + EndChild(); + ImGui::TreePop(); } From ee7f1921e88e827f8eec6eea2ba0d796190f574f Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 12 Dec 2017 00:57:45 +0100 Subject: [PATCH 280/823] Internals: Added GetSmallSquareSize() --- imgui.cpp | 18 ++++++------------ imgui_internal.h | 2 ++ 2 files changed, 8 insertions(+), 12 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index f4ca2411cf31..7b1ad34a1fcc 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -8921,12 +8921,6 @@ bool ImGui::InputTextMultiline(const char* label, char* buf, size_t buf_size, co return InputTextEx(label, buf, (int)buf_size, size, flags | ImGuiInputTextFlags_Multiline, callback, user_data); } -static inline float SmallSquareSize() -{ - ImGuiContext& g = *GImGui; - return g.FontSize + g.Style.FramePadding.y * 2.0f; -} - // NB: scalar_format here must be a simple "%xx" format string with no prefix/suffix (unlike the Drag/Slider functions "display_format" argument) bool ImGui::InputScalarEx(const char* label, ImGuiDataType data_type, void* data_ptr, void* step_ptr, void* step_fast_ptr, const char* scalar_format, ImGuiInputTextFlags extra_flags) { @@ -8940,7 +8934,7 @@ bool ImGui::InputScalarEx(const char* label, ImGuiDataType data_type, void* data BeginGroup(); PushID(label); - const ImVec2 button_sz = ImVec2(SmallSquareSize(), SmallSquareSize()); + const ImVec2 button_sz = ImVec2(GetSmallSquareSize(), GetSmallSquareSize()); if (step_ptr) PushItemWidth(ImMax(1.0f, CalcItemWidth() - (button_sz.x + style.ItemInnerSpacing.x)*2)); @@ -9119,7 +9113,7 @@ bool ImGui::BeginCombo(const char* label, const char* preview_value, ImGuiComboF bool pressed = ButtonBehavior(frame_bb, id, &hovered, &held); bool popup_open = IsPopupOpen(id); - const float arrow_size = SmallSquareSize(); + const float arrow_size = GetSmallSquareSize(); const ImRect value_bb(frame_bb.Min, frame_bb.Max - ImVec2(arrow_size, 0.0f)); RenderFrame(frame_bb.Min, frame_bb.Max, GetColorU32(ImGuiCol_FrameBg), true, style.FrameRounding); RenderFrame(ImVec2(frame_bb.Max.x-arrow_size, frame_bb.Min.y), frame_bb.Max, GetColorU32(popup_open || hovered ? ImGuiCol_ButtonHovered : ImGuiCol_Button), true, style.FrameRounding); // FIXME-ROUNDING @@ -9804,7 +9798,7 @@ bool ImGui::ColorButton(const char* desc_id, const ImVec4& col, ImGuiColorEditFl ImGuiContext& g = *GImGui; const ImGuiID id = window->GetID(desc_id); - float default_size = SmallSquareSize(); + float default_size = GetSmallSquareSize(); if (size.x == 0.0f) size.x = default_size; if (size.y == 0.0f) @@ -9914,7 +9908,7 @@ static void ColorPickerOptionsPopup(ImGuiColorEditFlags flags, const float* ref_ ImGuiContext& g = *GImGui; if (allow_opt_picker) { - ImVec2 picker_size(g.FontSize * 8, ImMax(g.FontSize * 8 - (SmallSquareSize() + g.Style.ItemInnerSpacing.x), 1.0f)); // FIXME: Picker size copied from main picker function + ImVec2 picker_size(g.FontSize * 8, ImMax(g.FontSize * 8 - (ImGui::GetSmallSquareSize() + g.Style.ItemInnerSpacing.x), 1.0f)); // FIXME: Picker size copied from main picker function ImGui::PushItemWidth(picker_size.x); for (int picker_type = 0; picker_type < 2; picker_type++) { @@ -9954,7 +9948,7 @@ bool ImGui::ColorEdit4(const char* label, float col[4], ImGuiColorEditFlags flag ImGuiContext& g = *GImGui; const ImGuiStyle& style = g.Style; - const float square_sz = SmallSquareSize(); + const float square_sz = GetSmallSquareSize(); const float w_extra = (flags & ImGuiColorEditFlags_NoSmallPreview) ? 0.0f : (square_sz + style.ItemInnerSpacing.x); const float w_items_all = CalcItemWidth() - w_extra; const char* label_display_end = FindRenderedTextEnd(label); @@ -10192,7 +10186,7 @@ bool ImGui::ColorPicker4(const char* label, float col[4], ImGuiColorEditFlags fl int components = (flags & ImGuiColorEditFlags_NoAlpha) ? 3 : 4; bool alpha_bar = (flags & ImGuiColorEditFlags_AlphaBar) && !(flags & ImGuiColorEditFlags_NoAlpha); ImVec2 picker_pos = window->DC.CursorPos; - float square_sz = SmallSquareSize(); + float square_sz = GetSmallSquareSize(); float bars_width = square_sz; // Arbitrary smallish width of Hue/Alpha picking bars float sv_picker_size = ImMax(bars_width * 1, CalcItemWidth() - (alpha_bar ? 2 : 1) * (bars_width + style.ItemInnerSpacing.x)); // Saturation/Value picking box float bar0_pos_x = picker_pos.x + sv_picker_size + style.ItemInnerSpacing.x; diff --git a/imgui_internal.h b/imgui_internal.h index 417a0fb15131..41af164a26b4 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -829,6 +829,8 @@ namespace ImGui IMGUI_API void PushItemFlag(ImGuiItemFlags option, bool enabled); IMGUI_API void PopItemFlag(); + inline float GetSmallSquareSize() { ImGuiContext& g = *GImGui; return g.FontSize + g.Style.FramePadding.y * 2.0f; } + IMGUI_API void OpenPopupEx(ImGuiID id, bool reopen_existing); IMGUI_API void ClosePopup(ImGuiID id); IMGUI_API bool IsPopupOpen(ImGuiID id); From c22657985a8b33f07c91724aacc314c9deff14a0 Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 12 Dec 2017 14:12:49 +0100 Subject: [PATCH 281/823] Added GetFrameHeight() function (used to be SmallSquareSize internally) --- imgui.cpp | 18 ++++++++++++------ imgui.h | 7 ++++--- imgui_internal.h | 2 -- 3 files changed, 16 insertions(+), 11 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 7b1ad34a1fcc..825313ba224d 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -5748,6 +5748,12 @@ float ImGui::GetTextLineHeightWithSpacing() return g.FontSize + g.Style.ItemSpacing.y; } +float ImGui::GetFrameHeight() +{ + ImGuiContext& g = *GImGui; + return g.FontSize + g.Style.FramePadding.y * 2.0f; +} + float ImGui::GetItemsLineHeightWithSpacing() { ImGuiContext& g = *GImGui; @@ -8934,7 +8940,7 @@ bool ImGui::InputScalarEx(const char* label, ImGuiDataType data_type, void* data BeginGroup(); PushID(label); - const ImVec2 button_sz = ImVec2(GetSmallSquareSize(), GetSmallSquareSize()); + const ImVec2 button_sz = ImVec2(GetFrameHeight(), GetFrameHeight()); if (step_ptr) PushItemWidth(ImMax(1.0f, CalcItemWidth() - (button_sz.x + style.ItemInnerSpacing.x)*2)); @@ -9113,7 +9119,7 @@ bool ImGui::BeginCombo(const char* label, const char* preview_value, ImGuiComboF bool pressed = ButtonBehavior(frame_bb, id, &hovered, &held); bool popup_open = IsPopupOpen(id); - const float arrow_size = GetSmallSquareSize(); + const float arrow_size = GetFrameHeight(); const ImRect value_bb(frame_bb.Min, frame_bb.Max - ImVec2(arrow_size, 0.0f)); RenderFrame(frame_bb.Min, frame_bb.Max, GetColorU32(ImGuiCol_FrameBg), true, style.FrameRounding); RenderFrame(ImVec2(frame_bb.Max.x-arrow_size, frame_bb.Min.y), frame_bb.Max, GetColorU32(popup_open || hovered ? ImGuiCol_ButtonHovered : ImGuiCol_Button), true, style.FrameRounding); // FIXME-ROUNDING @@ -9798,7 +9804,7 @@ bool ImGui::ColorButton(const char* desc_id, const ImVec4& col, ImGuiColorEditFl ImGuiContext& g = *GImGui; const ImGuiID id = window->GetID(desc_id); - float default_size = GetSmallSquareSize(); + float default_size = GetFrameHeight(); if (size.x == 0.0f) size.x = default_size; if (size.y == 0.0f) @@ -9908,7 +9914,7 @@ static void ColorPickerOptionsPopup(ImGuiColorEditFlags flags, const float* ref_ ImGuiContext& g = *GImGui; if (allow_opt_picker) { - ImVec2 picker_size(g.FontSize * 8, ImMax(g.FontSize * 8 - (ImGui::GetSmallSquareSize() + g.Style.ItemInnerSpacing.x), 1.0f)); // FIXME: Picker size copied from main picker function + ImVec2 picker_size(g.FontSize * 8, ImMax(g.FontSize * 8 - (ImGui::GetFrameHeight() + g.Style.ItemInnerSpacing.x), 1.0f)); // FIXME: Picker size copied from main picker function ImGui::PushItemWidth(picker_size.x); for (int picker_type = 0; picker_type < 2; picker_type++) { @@ -9948,7 +9954,7 @@ bool ImGui::ColorEdit4(const char* label, float col[4], ImGuiColorEditFlags flag ImGuiContext& g = *GImGui; const ImGuiStyle& style = g.Style; - const float square_sz = GetSmallSquareSize(); + const float square_sz = GetFrameHeight(); const float w_extra = (flags & ImGuiColorEditFlags_NoSmallPreview) ? 0.0f : (square_sz + style.ItemInnerSpacing.x); const float w_items_all = CalcItemWidth() - w_extra; const char* label_display_end = FindRenderedTextEnd(label); @@ -10186,7 +10192,7 @@ bool ImGui::ColorPicker4(const char* label, float col[4], ImGuiColorEditFlags fl int components = (flags & ImGuiColorEditFlags_NoAlpha) ? 3 : 4; bool alpha_bar = (flags & ImGuiColorEditFlags_AlphaBar) && !(flags & ImGuiColorEditFlags_NoAlpha); ImVec2 picker_pos = window->DC.CursorPos; - float square_sz = GetSmallSquareSize(); + float square_sz = GetFrameHeight(); float bars_width = square_sz; // Arbitrary smallish width of Hue/Alpha picking bars float sv_picker_size = ImMax(bars_width * 1, CalcItemWidth() - (alpha_bar ? 2 : 1) * (bars_width + style.ItemInnerSpacing.x)); // Saturation/Value picking box float bar0_pos_x = picker_pos.x + sv_picker_size + style.ItemInnerSpacing.x; diff --git a/imgui.h b/imgui.h index 17f594694a36..c8bd80cb2be2 100644 --- a/imgui.h +++ b/imgui.h @@ -232,9 +232,10 @@ namespace ImGui IMGUI_API ImVec2 GetCursorScreenPos(); // cursor position in absolute screen coordinates [0..io.DisplaySize] (useful to work with ImDrawList API) IMGUI_API void SetCursorScreenPos(const ImVec2& pos); // cursor position in absolute screen coordinates [0..io.DisplaySize] IMGUI_API void AlignTextToFramePadding(); // vertically align/lower upcoming text to FramePadding.y so that it will aligns to upcoming widgets (call if you have text on a line before regular widgets) - IMGUI_API float GetTextLineHeight(); // height of font == GetWindowFontSize() - IMGUI_API float GetTextLineHeightWithSpacing(); // distance (in pixels) between 2 consecutive lines of text == GetWindowFontSize() + GetStyle().ItemSpacing.y - IMGUI_API float GetItemsLineHeightWithSpacing(); // distance (in pixels) between 2 consecutive lines of standard height widgets == GetWindowFontSize() + GetStyle().FramePadding.y*2 + GetStyle().ItemSpacing.y + IMGUI_API float GetFrameHeight(); // ~ FontSize + style.FramePadding.y * 2 + IMGUI_API float GetTextLineHeight(); // ~ FontSize + IMGUI_API float GetTextLineHeightWithSpacing(); // ~ FontSize + style.ItemSpacing.y (distance in pixels between 2 consecutive lines of text) + IMGUI_API float GetItemsLineHeightWithSpacing(); // ~ FontSize + style.FramePadding.y * 2 + style.ItemSpacing.y (distance in pixels between 2 consecutive lines of framed widgets) // Columns // You can also use SameLine(pos_x) for simplified columns. The columns API is still work-in-progress and rather lacking. diff --git a/imgui_internal.h b/imgui_internal.h index 41af164a26b4..417a0fb15131 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -829,8 +829,6 @@ namespace ImGui IMGUI_API void PushItemFlag(ImGuiItemFlags option, bool enabled); IMGUI_API void PopItemFlag(); - inline float GetSmallSquareSize() { ImGuiContext& g = *GImGui; return g.FontSize + g.Style.FramePadding.y * 2.0f; } - IMGUI_API void OpenPopupEx(ImGuiID id, bool reopen_existing); IMGUI_API void ClosePopup(ImGuiID id); IMGUI_API bool IsPopupOpen(ImGuiID id); From 6190ab008420087c6d0dbbb64e55d668e66a91c0 Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 12 Dec 2017 14:14:58 +0100 Subject: [PATCH 282/823] Renamed GetItemsLineHeightWithSpacing() to GetFrameHeightWithSpacing() --- imgui.cpp | 7 ++++--- imgui.h | 6 +++--- imgui_demo.cpp | 6 +++--- 3 files changed, 10 insertions(+), 9 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 825313ba224d..1dd4d630f075 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -213,8 +213,9 @@ Here is a change-log of API breaking changes, if you are using one of the functions listed, expect to have to fix some code. Also read releases logs https://github.com/ocornut/imgui/releases for more details. - - 2017/12/23 (1.53) - marked IsRootWindowFocused() as obsolete in favor of using IsWindowFocused(ImGuiFocusedFlags_RootWindow). - - marked IsRootWindowOrAnyChildFocused() as obsolete in favor of using IsWindowFocused(ImGuiFocusedFlags_RootAndChildWindows). + - 2017/12/13 (1.53) - renamed GetItemsLineHeightWithSpacing() to GetFrameHeightWithSpacing(). Kept redirection function (will obsolete). + - 2017/12/13 (1.53) - marked IsRootWindowFocused() as obsolete in favor of using IsWindowFocused(ImGuiFocusedFlags_RootWindow). Kept redirection function (will obsolete). + - marked IsRootWindowOrAnyChildFocused() as obsolete in favor of using IsWindowFocused(ImGuiFocusedFlags_RootAndChildWindows). Kept redirection function (will obsolete). - 2017/12/12 (1.53) - renamed ImGuiTreeNodeFlags_AllowOverlapMode to ImGuiTreeNodeFlags_AllowItemOverlap. Kept redirection enum (will obsolete). - 2017/12/10 (1.53) - removed SetNextWindowContentWidth(), prefer using SetNextWindowContentSize(). Kept redirection function (will obsolete). - 2017/11/27 (1.53) - renamed ImGuiTextBuffer::append() helper to appendf(), appendv() to appendfv(). If you copied the 'Log' demo in your code, it uses appendv() so that needs to be renamed. @@ -5754,7 +5755,7 @@ float ImGui::GetFrameHeight() return g.FontSize + g.Style.FramePadding.y * 2.0f; } -float ImGui::GetItemsLineHeightWithSpacing() +float ImGui::GetFrameHeightWithSpacing() { ImGuiContext& g = *GImGui; return g.FontSize + g.Style.FramePadding.y * 2.0f + g.Style.ItemSpacing.y; diff --git a/imgui.h b/imgui.h index c8bd80cb2be2..328f260b5ede 100644 --- a/imgui.h +++ b/imgui.h @@ -232,10 +232,10 @@ namespace ImGui IMGUI_API ImVec2 GetCursorScreenPos(); // cursor position in absolute screen coordinates [0..io.DisplaySize] (useful to work with ImDrawList API) IMGUI_API void SetCursorScreenPos(const ImVec2& pos); // cursor position in absolute screen coordinates [0..io.DisplaySize] IMGUI_API void AlignTextToFramePadding(); // vertically align/lower upcoming text to FramePadding.y so that it will aligns to upcoming widgets (call if you have text on a line before regular widgets) - IMGUI_API float GetFrameHeight(); // ~ FontSize + style.FramePadding.y * 2 IMGUI_API float GetTextLineHeight(); // ~ FontSize IMGUI_API float GetTextLineHeightWithSpacing(); // ~ FontSize + style.ItemSpacing.y (distance in pixels between 2 consecutive lines of text) - IMGUI_API float GetItemsLineHeightWithSpacing(); // ~ FontSize + style.FramePadding.y * 2 + style.ItemSpacing.y (distance in pixels between 2 consecutive lines of framed widgets) + IMGUI_API float GetFrameHeight(); // ~ FontSize + style.FramePadding.y * 2 + IMGUI_API float GetFrameHeightWithSpacing(); // ~ FontSize + style.FramePadding.y * 2 + style.ItemSpacing.y (distance in pixels between 2 consecutive lines of framed widgets) // Columns // You can also use SameLine(pos_x) for simplified columns. The columns API is still work-in-progress and rather lacking. @@ -1236,7 +1236,7 @@ struct ImGuiListClipper int ItemsCount, StepNo, DisplayStart, DisplayEnd; // items_count: Use -1 to ignore (you can call Begin later). Use INT_MAX if you don't know how many items you have (in which case the cursor won't be advanced in the final step). - // items_height: Use -1.0f to be calculated automatically on first step. Otherwise pass in the distance between your items, typically GetTextLineHeightWithSpacing() or GetItemsLineHeightWithSpacing(). + // items_height: Use -1.0f to be calculated automatically on first step. Otherwise pass in the distance between your items, typically GetTextLineHeightWithSpacing() or GetFrameHeightWithSpacing(). // If you don't specify an items_height, you NEED to call Step(). If you specify items_height you may call the old Begin()/End() api directly, but prefer calling Step(). ImGuiListClipper(int items_count = -1, float items_height = -1.0f) { Begin(items_count, items_height); } // NB: Begin() initialize every fields (as we allow user to call Begin/End multiple times on a same instance if they want). ~ImGuiListClipper() { IM_ASSERT(ItemsCount == -1); } // Assert if user forgot to call End() or Step() until false. diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 293cc22d4050..1e7fcab1b8b9 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -1272,7 +1272,7 @@ void ImGui::ShowTestWindow(bool* p_open) ImGui::SliderInt("Lines", &lines, 1, 15); ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, 3.0f); ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(2.0f, 1.0f)); - ImGui::BeginChild("scrolling", ImVec2(0, ImGui::GetItemsLineHeightWithSpacing()*7 + 30), true, ImGuiWindowFlags_HorizontalScrollbar); + ImGui::BeginChild("scrolling", ImVec2(0, ImGui::GetFrameHeightWithSpacing()*7 + 30), true, ImGuiWindowFlags_HorizontalScrollbar); for (int line = 0; line < lines; line++) { // Display random stuff (for the sake of this trivial demo we are using basic Button+SameLine. If you want to create your own time line for a real application you may be better off @@ -2521,7 +2521,7 @@ struct ExampleAppConsole ImGui::PopStyleVar(); ImGui::Separator(); - ImGui::BeginChild("ScrollingRegion", ImVec2(0, -ImGui::GetStyle().ItemSpacing.y - ImGui::GetItemsLineHeightWithSpacing()), false, ImGuiWindowFlags_HorizontalScrollbar); // Leave room for 1 separator + 1 InputText + ImGui::BeginChild("ScrollingRegion", ImVec2(0, -ImGui::GetStyle().ItemSpacing.y - ImGui::GetFrameHeightWithSpacing()), false, ImGuiWindowFlags_HorizontalScrollbar); // Leave room for 1 separator + 1 InputText if (ImGui::BeginPopupContextWindow()) { if (ImGui::Selectable("Clear")) ClearLog(); @@ -2843,7 +2843,7 @@ static void ShowExampleAppLayout(bool* p_open) // right ImGui::BeginGroup(); - ImGui::BeginChild("item view", ImVec2(0, -ImGui::GetItemsLineHeightWithSpacing())); // Leave room for 1 line below us + ImGui::BeginChild("item view", ImVec2(0, -ImGui::GetFrameHeightWithSpacing())); // Leave room for 1 line below us ImGui::Text("MyObject: %d", selected); ImGui::Separator(); ImGui::TextWrapped("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. "); From 7ec934f43910ff917239942aed36169996bfdadc Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 12 Dec 2017 15:33:26 +0100 Subject: [PATCH 283/823] Drag and Drop: Comments --- imgui.cpp | 4 +++- imgui.h | 1 + 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/imgui.cpp b/imgui.cpp index 24d60b729dab..39290f60f85d 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -6685,7 +6685,7 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l toggled |= IsMouseHoveringRect(interact_bb.Min, ImVec2(interact_bb.Min.x + text_offset_x, interact_bb.Max.y)); if (flags & ImGuiTreeNodeFlags_OpenOnDoubleClick) toggled |= g.IO.MouseDoubleClicked[0]; - if (g.DragDropActive && is_open) // We don't nodes to be highlighted when holding ever after the node has been opened, but don't close them! + if (g.DragDropActive && is_open) // When using Drag and Drop "hold to open" we keep the node highlighted after opening, but never close it again. toggled = false; if (toggled) { @@ -9886,6 +9886,7 @@ bool ImGui::ColorButton(const char* desc_id, const ImVec4& col, ImGuiColorEditFl else window->DrawList->AddRect(bb.Min, bb.Max, GetColorU32(ImGuiCol_FrameBg), rounding); // Color button are often in need of some sort of border + // Drag and Drop Source if (g.ActiveId == id && BeginDragDropSource()) // NB: The ActiveId test is merely an optional micro-optimization { if (flags & ImGuiColorEditFlags_NoAlpha) @@ -9899,6 +9900,7 @@ bool ImGui::ColorButton(const char* desc_id, const ImVec4& col, ImGuiColorEditFl hovered = false; } + // Tooltip if (!(flags & ImGuiColorEditFlags_NoTooltip) && hovered) ColorTooltip(desc_id, &col.x, flags & (ImGuiColorEditFlags_NoAlpha | ImGuiColorEditFlags_AlphaPreview | ImGuiColorEditFlags_AlphaPreviewHalf)); diff --git a/imgui.h b/imgui.h index 3cdec027270b..3622dfc80115 100644 --- a/imgui.h +++ b/imgui.h @@ -421,6 +421,7 @@ namespace ImGui IMGUI_API void LogText(const char* fmt, ...) IM_FMTARGS(1); // pass text data straight to log (without being displayed) // Drag and Drop + // [BETA API] Missing Demo code. API may evolve. IMGUI_API bool BeginDragDropSource(ImGuiDragDropFlags flags = 0, int mouse_button = 0); // Call when the current item is active. If this return true, you can call SetDragDropPayload() + EndDragDropSource() IMGUI_API bool SetDragDropPayload(const char* type, const void* data, size_t data_size, ImGuiCond cond = 0); // Type is a user defined string of maximum 8 characters. Strings starting with '_' are reserved for dear imgui internal types. Data is copied and held by imgui. IMGUI_API void EndDragDropSource(); From e98df91dc47b8fc17cb2c0963ed9e85d9fc5ce0a Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 12 Dec 2017 15:44:22 +0100 Subject: [PATCH 284/823] Drag and Drop: Added ImGuiCol_DragDropTarget (#143, #707) --- imgui.cpp | 8 ++++---- imgui.h | 1 + imgui_draw.cpp | 4 +++- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 39290f60f85d..9e632e546700 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -5454,6 +5454,7 @@ const char* ImGui::GetStyleColorName(ImGuiCol idx) case ImGuiCol_PlotHistogramHovered: return "PlotHistogramHovered"; case ImGuiCol_TextSelectedBg: return "TextSelectedBg"; case ImGuiCol_ModalWindowDarkening: return "ModalWindowDarkening"; + case ImGuiCol_DragDropTarget: return "DragDropTarget"; } IM_ASSERT(0); return "Unknown"; @@ -11345,12 +11346,11 @@ const ImGuiPayload* ImGui::AcceptDragDropPayload(const char* type, ImGuiDragDrop payload.Preview = was_accepted_previously; if (!(flags & ImGuiDragDropFlags_AcceptNoDrawDefaultRect) && payload.Preview) { - // FIXME-DRAG FIXME-STYLE: Settle on a proper default visuals for drop target, w/ ImGuiCol enum value probably. - r.Expand(5.0f); + // FIXME-DRAG: Settle on a proper default visuals for drop target. + r.Expand(3.5f); bool push_clip_rect = !window->ClipRect.Contains(r); if (push_clip_rect) window->DrawList->PushClipRectFullScreen(); - window->DrawList->AddRectFilled(r.Min, r.Max, IM_COL32(255, 255, 0, 20), 0.0f); - window->DrawList->AddRect(r.Min + ImVec2(1.5f,1.5f), r.Max - ImVec2(1.5f,1.5f), IM_COL32(255, 255, 0, 255), 0.0f, ~0, 2.0f); + window->DrawList->AddRect(r.Min, r.Max, GetColorU32(ImGuiCol_DragDropTarget), 0.0f, ~0, 2.0f); if (push_clip_rect) window->DrawList->PopClipRect(); } diff --git a/imgui.h b/imgui.h index 3622dfc80115..5f749316509c 100644 --- a/imgui.h +++ b/imgui.h @@ -719,6 +719,7 @@ enum ImGuiCol_ ImGuiCol_PlotHistogramHovered, ImGuiCol_TextSelectedBg, ImGuiCol_ModalWindowDarkening, // darken entire screen when a modal window is active + ImGuiCol_DragDropTarget, ImGuiCol_COUNT // Obsolete names (will be removed) diff --git a/imgui_draw.cpp b/imgui_draw.cpp index 7a5bb2deeded..69e93689ff65 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -171,6 +171,7 @@ void ImGui::StyleColorsClassic(ImGuiStyle* dst) colors[ImGuiCol_PlotHistogramHovered] = ImVec4(1.00f, 0.60f, 0.00f, 1.00f); colors[ImGuiCol_TextSelectedBg] = ImVec4(0.00f, 0.00f, 1.00f, 0.35f); colors[ImGuiCol_ModalWindowDarkening] = ImVec4(0.20f, 0.20f, 0.20f, 0.35f); + colors[ImGuiCol_DragDropTarget] = ImVec4(1.00f, 1.00f, 0.00f, 0.90f); } void ImGui::StyleColorsDark(ImGuiStyle* dst) @@ -220,6 +221,7 @@ void ImGui::StyleColorsDark(ImGuiStyle* dst) colors[ImGuiCol_PlotHistogramHovered] = ImVec4(1.00f, 0.60f, 0.00f, 1.00f); colors[ImGuiCol_TextSelectedBg] = ImVec4(0.26f, 0.59f, 0.98f, 0.35f); colors[ImGuiCol_ModalWindowDarkening] = ImVec4(0.80f, 0.80f, 0.80f, 0.35f); + colors[ImGuiCol_DragDropTarget] = ImVec4(1.00f, 1.00f, 0.00f, 0.90f); } void ImGui::StyleColorsLight(ImGuiStyle* dst) @@ -271,9 +273,9 @@ void ImGui::StyleColorsLight(ImGuiStyle* dst) colors[ImGuiCol_PlotHistogramHovered] = ImVec4(1.00f, 0.45f, 0.00f, 1.00f); colors[ImGuiCol_TextSelectedBg] = ImVec4(0.26f, 0.59f, 0.98f, 0.35f); colors[ImGuiCol_ModalWindowDarkening] = ImVec4(0.20f, 0.20f, 0.20f, 0.35f); + colors[ImGuiCol_DragDropTarget] = ImVec4(0.26f, 0.59f, 0.98f, 0.95f); } - //----------------------------------------------------------------------------- // ImDrawList //----------------------------------------------------------------------------- From ef1a683ebe0e0e8bd0ac272f3bf5fc4ab22bcd16 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Branimir=20Karad=C5=BEi=C4=87?= Date: Tue, 12 Dec 2017 08:54:51 -0800 Subject: [PATCH 285/823] Removed use of obsolete ImGui API. --- imgui_demo.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 1e7fcab1b8b9..4a039482fdce 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -2574,7 +2574,7 @@ struct ExampleAppConsole } // Demonstrate keeping auto focus on the input box - if (ImGui::IsItemHovered() || (ImGui::IsRootWindowOrAnyChildFocused() && !ImGui::IsAnyItemActive() && !ImGui::IsMouseClicked(0))) + if (ImGui::IsItemHovered() || (ImGui::IsWindowFocused(ImGuiFocusedFlags_RootAndChildWindows) && !ImGui::IsAnyItemActive() && !ImGui::IsMouseClicked(0))) ImGui::SetKeyboardFocusHere(-1); // Auto focus previous widget ImGui::End(); From d561a43a4d81259f32822a19b2a30e3883e48923 Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 12 Dec 2017 18:17:18 +0100 Subject: [PATCH 286/823] Drag and Drop: Drop target infer a fallback ID from the rectangle. Avoid Preview being accepted on drop frame when drop target has no ID. (#143) --- imgui.cpp | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 9e632e546700..033b1e513ad1 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -11292,7 +11292,8 @@ bool ImGui::BeginDragDropTargetCustom(const ImRect& bb, ImGuiID id) ImGuiWindow* window = g.CurrentWindow; if (g.HoveredWindow == NULL || window->RootWindow != g.HoveredWindow->RootWindow) return false; - if (!IsMouseHoveringRect(bb.Min, bb.Max) || (id && id == g.DragDropPayload.SourceId)) + IM_ASSERT(id != 0); + if (!IsMouseHoveringRect(bb.Min, bb.Max) || (id == g.DragDropPayload.SourceId)) return false; g.DragDropTargetRect = bb; @@ -11301,7 +11302,7 @@ bool ImGui::BeginDragDropTargetCustom(const ImRect& bb, ImGuiID id) } // We don't use BeginDragDropTargetCustom() and duplicate its code because: -// 1) LastItemRectHoveredRect which handles items that pushes a temporarily clip rectangle in their code. Calling BeginDragDropTargetCustom(LastItemRect) would not handle it. +// 1) we use LastItemRectHoveredRect which handles items that pushes a temporarily clip rectangle in their code. Calling BeginDragDropTargetCustom(LastItemRect) would not handle them. // 2) and it's faster. as this code may be very frequently called, we want to early out as fast as we can. // Also note how the HoveredWindow test is positioned differently in both functions (in both functions we optimize for the cheapest early out case) bool ImGui::BeginDragDropTarget() @@ -11311,13 +11312,19 @@ bool ImGui::BeginDragDropTarget() return false; ImGuiWindow* window = g.CurrentWindow; - if (!window->DC.LastItemRectHoveredRect || (window->DC.LastItemId && window->DC.LastItemId == g.DragDropPayload.SourceId)) + if (!window->DC.LastItemRectHoveredRect) return false; if (g.HoveredWindow == NULL || window->RootWindow != g.HoveredWindow->RootWindow) return false; + ImGuiID id = window->DC.LastItemId; + if (id == 0) + id = window->GetIDFromRectangle(window->DC.LastItemRect); + if (g.DragDropPayload.SourceId == id) + return false; + g.DragDropTargetRect = window->DC.LastItemRect; - g.DragDropTargetId = window->DC.LastItemId; + g.DragDropTargetId = id; return true; } From 28bbf1ade6ba868d4f5fd89ff40b922f4323e573 Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 12 Dec 2017 18:45:57 +0100 Subject: [PATCH 287/823] Fixed ParentWindow setup which broke Modal windows (fix c65124f415ae081b1aacaf299c539a32968809a7) --- imgui.cpp | 7 ++----- imgui_internal.h | 2 +- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 1dd4d630f075..c0f31f0d9721 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2387,10 +2387,7 @@ void ImGui::NewFrame() if (ImGuiWindow* modal_window = GetFrontMostModalRootWindow()) { g.ModalWindowDarkeningRatio = ImMin(g.ModalWindowDarkeningRatio + g.IO.DeltaTime * 6.0f, 1.0f); - ImGuiWindow* window = g.HoveredRootWindow; - while (window && window != modal_window) - window = window->ParentWindow; - if (!window) + if (g.HoveredRootWindow && !IsWindowChildOf(g.HoveredRootWindow, modal_window)) g.HoveredRootWindow = g.HoveredWindow = NULL; } else @@ -4341,7 +4338,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) SetWindowConditionAllowFlags(window, ImGuiCond_Appearing, true); // Parent window is latched only on the first call to Begin() of the frame, so further append-calls can be done from a different window stack - ImGuiWindow* parent_window = first_begin_of_the_frame ? ((flags & ImGuiWindowFlags_ChildWindow) && !g.CurrentWindowStack.empty() ? g.CurrentWindowStack.back() : NULL) : window->ParentWindow; + ImGuiWindow* parent_window = first_begin_of_the_frame ? ((flags & (ImGuiWindowFlags_ChildWindow | ImGuiWindowFlags_Popup)) && !g.CurrentWindowStack.empty() ? g.CurrentWindowStack.back() : NULL) : window->ParentWindow; IM_ASSERT(parent_window != NULL || !(flags & ImGuiWindowFlags_ChildWindow)); // Add to stack diff --git a/imgui_internal.h b/imgui_internal.h index 417a0fb15131..adaa39fc559b 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -746,7 +746,7 @@ struct IMGUI_API ImGuiWindow ImGuiStorage StateStorage; float FontWindowScale; // Scale multiplier per-window ImDrawList* DrawList; - ImGuiWindow* ParentWindow; // If we are a child window, this is pointing to our parent. + ImGuiWindow* ParentWindow; // If we are a child _or_ popup window, this is pointing to our parent. Otherwise NULL. ImGuiWindow* RootWindow; // Generally point to ourself. If we are a child window, this is pointing to the first non-child parent window. ImGuiWindow* RootNonPopupWindow; // Generally point to ourself. Used to display TitleBgActive color and for selecting which window to use for NavWindowing From 02e0a078f4ebe9c56ea689f6561c71573a2fe997 Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 12 Dec 2017 18:46:42 +0100 Subject: [PATCH 288/823] Begin: Tidying up code to make it more readable. --- imgui.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index c0f31f0d9721..acea4565c381 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -4409,8 +4409,11 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) { // Initialize window->ParentWindow = parent_window; - window->RootWindow = ((flags & ImGuiWindowFlags_ChildWindow) && parent_window) ? parent_window->RootWindow : window; - window->RootNonPopupWindow = !(flags & (ImGuiWindowFlags_ChildWindow | ImGuiWindowFlags_Popup)) || (flags & ImGuiWindowFlags_Modal) || (parent_window == NULL) ? window : parent_window->RootNonPopupWindow; // Used to display TitleBgActive color and for selecting which window to use for NavWindowing + window->RootWindow = window->RootNonPopupWindow = window; + if (parent_window && (flags & ImGuiWindowFlags_ChildWindow)) + window->RootWindow = parent_window->RootWindow; + if (parent_window && !(flags & ImGuiWindowFlags_Modal) && (flags & (ImGuiWindowFlags_ChildWindow | ImGuiWindowFlags_Popup))) + window->RootNonPopupWindow = parent_window->RootNonPopupWindow; //window->RootNavWindow = window; //while (window->RootNavWindow->Flags & ImGuiWindowFlags_NavFlattened) // window->RootNavWindow = window->RootNavWindow->ParentWindow; From 7faa5b16bb55d44b87605844d3b715743eebd617 Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 12 Dec 2017 19:15:00 +0100 Subject: [PATCH 289/823] Tweak --- imgui.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index acea4565c381..09f0442fe0d8 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -4338,7 +4338,8 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) SetWindowConditionAllowFlags(window, ImGuiCond_Appearing, true); // Parent window is latched only on the first call to Begin() of the frame, so further append-calls can be done from a different window stack - ImGuiWindow* parent_window = first_begin_of_the_frame ? ((flags & (ImGuiWindowFlags_ChildWindow | ImGuiWindowFlags_Popup)) && !g.CurrentWindowStack.empty() ? g.CurrentWindowStack.back() : NULL) : window->ParentWindow; + ImGuiWindow* parent_window_in_stack = g.CurrentWindowStack.empty() ? NULL : g.CurrentWindowStack.back(); + ImGuiWindow* parent_window = first_begin_of_the_frame ? ((flags & (ImGuiWindowFlags_ChildWindow | ImGuiWindowFlags_Popup)) ? parent_window_in_stack : NULL) : window->ParentWindow; IM_ASSERT(parent_window != NULL || !(flags & ImGuiWindowFlags_ChildWindow)); // Add to stack @@ -4559,7 +4560,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) // This is how we end up with child menus appearing (most-commonly) on the right of the parent menu. IM_ASSERT(window_pos_set_by_api); float horizontal_overlap = style.ItemSpacing.x; // We want some overlap to convey the relative depth of each popup (currently the amount of overlap it is hard-coded to style.ItemSpacing.x, may need to introduce another style value). - ImGuiWindow* parent_menu = g.CurrentWindowStack[g.CurrentWindowStack.Size - 2]; + ImGuiWindow* parent_menu = parent_window_in_stack; ImRect rect_to_avoid; if (parent_menu->DC.MenuBarAppending) rect_to_avoid = ImRect(-FLT_MAX, parent_menu->Pos.y + parent_menu->TitleBarHeight(), FLT_MAX, parent_menu->Pos.y + parent_menu->TitleBarHeight() + parent_menu->MenuBarHeight()); From ab049c6fc02d68ba0741cb9789612a8a06d0164d Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 12 Dec 2017 20:34:16 +0100 Subject: [PATCH 290/823] Drag and Drop: Fix merge for IMGUI_DISABLE_OBSOLETE_FUNCTIONS --- imgui.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/imgui.cpp b/imgui.cpp index 033b1e513ad1..11b8dcbc0241 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -6674,7 +6674,7 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l // - OpenOnDoubleClick .............. double-click anywhere to open // - OpenOnArrow .................... single-click on arrow to open // - OpenOnDoubleClick|OpenOnArrow .. single-click on arrow or double-click anywhere to open - ImGuiButtonFlags button_flags = ImGuiButtonFlags_NoKeyModifiers | ((flags & ImGuiTreeNodeFlags_AllowOverlapMode) ? ImGuiButtonFlags_AllowItemOverlap : 0); + ImGuiButtonFlags button_flags = ImGuiButtonFlags_NoKeyModifiers | ((flags & ImGuiTreeNodeFlags_AllowItemOverlap) ? ImGuiButtonFlags_AllowItemOverlap : 0); button_flags |= ImGuiButtonFlags_PressedOnDragDropHold; if (flags & ImGuiTreeNodeFlags_OpenOnDoubleClick) button_flags |= ImGuiButtonFlags_PressedOnDoubleClick | ((flags & ImGuiTreeNodeFlags_OpenOnArrow) ? ImGuiButtonFlags_PressedOnClickRelease : 0); From b174fcc9af7ee1c91f3e6fa16444b07c24e3cbfa Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 12 Dec 2017 23:35:04 +0100 Subject: [PATCH 291/823] Added IsAnyWindowFocused() (from Nav branch). --- imgui.cpp | 6 ++++++ imgui.h | 1 + 2 files changed, 7 insertions(+) diff --git a/imgui.cpp b/imgui.cpp index 7fcc21e791eb..0dd930bd4869 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -3399,6 +3399,12 @@ bool ImGui::IsAnyWindowHovered() return g.HoveredWindow != NULL; } +bool ImGui::IsAnyWindowFocused() +{ + ImGuiContext& g = *GImGui; + return g.NavWindow != NULL; +} + static bool IsKeyPressedMap(ImGuiKey key, bool repeat) { const int key_index = GImGui->IO.KeyMap[key]; diff --git a/imgui.h b/imgui.h index 5f749316509c..b44f3936988d 100644 --- a/imgui.h +++ b/imgui.h @@ -457,6 +457,7 @@ namespace ImGui IMGUI_API void SetItemAllowOverlap(); // allow last item to be overlapped by a subsequent item. sometimes useful with invisible buttons, selectables, etc. to catch unused area. IMGUI_API bool IsWindowFocused(ImGuiFocusedFlags flags = 0); // is current window focused? or its root/child, depending on flags. see flags for options. IMGUI_API bool IsWindowHovered(ImGuiHoveredFlags flags = 0); // is current window hovered (and typically: not blocked by a popup/modal)? see flags for options. + IMGUI_API bool IsAnyWindowFocused(); IMGUI_API bool IsAnyWindowHovered(); // is mouse hovering any visible window IMGUI_API bool IsRectVisible(const ImVec2& size); // test if rectangle (of given size, starting from cursor position) is visible / not clipped. IMGUI_API bool IsRectVisible(const ImVec2& rect_min, const ImVec2& rect_max); // test if rectangle (in screen space) is visible / not clipped. to perform coarse clipping on user's side. From 7c7a7baf7683f03ed24a88ccfba34b93fe938e13 Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 12 Dec 2017 23:36:25 +0100 Subject: [PATCH 292/823] Merged miscellaneous small stuff (from nav/dock branches). --- imgui.cpp | 29 +++++++++++++++++------------ imgui.h | 4 ++-- imgui_internal.h | 16 ++++++++++------ 3 files changed, 29 insertions(+), 20 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 0dd930bd4869..dc418eba3f6e 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1826,7 +1826,6 @@ ImGuiWindow::ImGuiWindow(const char* name) ID = ImHash(name, 0); IDStack.push_back(ID); Flags = 0; - OrderWithinParent = 0; PosFloat = Pos = ImVec2(0.0f, 0.0f); Size = SizeFull = ImVec2(0.0f, 0.0f); SizeContents = SizeContentsExplicit = ImVec2(0.0f, 0.0f); @@ -1845,6 +1844,8 @@ ImGuiWindow::ImGuiWindow(const char* name) SkipItems = false; Appearing = false; CloseButton = false; + BeginOrderWithinParent = -1; + BeginOrderWithinContext = -1; BeginCount = 0; PopupId = 0; AutoFitFramesX = AutoFitFramesY = -1; @@ -2271,7 +2272,7 @@ void ImGui::NewFrame() // Initialize on first frame if (!g.Initialized) - ImGui::Initialize(); + Initialize(); SetCurrentFont(GetDefaultFont()); IM_ASSERT(g.Font->IsLoaded()); @@ -2279,6 +2280,7 @@ void ImGui::NewFrame() g.Time += g.IO.DeltaTime; g.FrameCount += 1; g.TooltipOverrideCount = 0; + g.WindowsActiveCount = 0; g.OverlayDrawList.Clear(); g.OverlayDrawList.PushTextureID(g.IO.Fonts->TexID); g.OverlayDrawList.PushClipRectFullScreen(); @@ -2497,8 +2499,8 @@ void ImGui::NewFrame() // Create implicit window - we will only render it if the user has added something to it. // We don't use "Debug" to avoid colliding with user trying to create a "Debug" window with custom flags. - ImGui::SetNextWindowSize(ImVec2(400,400), ImGuiCond_FirstUseEver); - ImGui::Begin("Debug##Default"); + SetNextWindowSize(ImVec2(400,400), ImGuiCond_FirstUseEver); + Begin("Debug##Default"); } static void* SettingsHandlerWindow_ReadOpen(ImGuiContext&, const char* name) @@ -2785,7 +2787,7 @@ static int ChildWindowComparer(const void* lhs, const void* rhs) return d; if (int d = (a->Flags & ImGuiWindowFlags_Tooltip) - (b->Flags & ImGuiWindowFlags_Tooltip)) return d; - return (a->OrderWithinParent - b->OrderWithinParent); + return (a->BeginOrderWithinParent - b->BeginOrderWithinParent); } static void AddWindowToSortedBuffer(ImVector& out_sorted_windows, ImGuiWindow* window) @@ -3359,7 +3361,7 @@ void ImGui::CalcListClipping(int items_count, float items_height, int* out_items static ImGuiWindow* FindHoveredWindow(ImVec2 pos) { ImGuiContext& g = *GImGui; - for (int i = g.Windows.Size-1; i >= 0; i--) + for (int i = g.Windows.Size - 1; i >= 0; i--) { ImGuiWindow* window = g.Windows[i]; if (!window->Active) @@ -3598,7 +3600,8 @@ bool ImGui::IsItemClicked(int mouse_button) bool ImGui::IsAnyItemHovered() { - return GImGui->HoveredId != 0 || GImGui->HoveredIdPreviousFrame != 0; + ImGuiContext& g = *GImGui; + return g.HoveredId != 0 || g.HoveredIdPreviousFrame != 0; } bool ImGui::IsAnyItemActive() @@ -3914,8 +3917,9 @@ bool ImGui::BeginPopupContextItem(const char* str_id, int mouse_button) ImGuiWindow* window = GImGui->CurrentWindow; ImGuiID id = str_id ? window->GetID(str_id) : window->DC.LastItemId; // If user hasn't passed an ID, we can use the LastItemID. Using LastItemID as a Popup ID won't conflict! IM_ASSERT(id != 0); // However, you cannot pass a NULL str_id if the last item has no identifier (e.g. a Text() item) - if (IsMouseClicked(mouse_button) && IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup)) - OpenPopupEx(id, true); + if (IsMouseClicked(mouse_button)) + if (IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup)) + OpenPopupEx(id, true); return BeginPopupEx(id, ImGuiWindowFlags_AlwaysAutoResize); } @@ -4448,7 +4452,8 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) // window->RootNavWindow = window->RootNavWindow->ParentWindow; window->Active = true; - window->OrderWithinParent = 0; + window->BeginOrderWithinParent = 0; + window->BeginOrderWithinContext = g.WindowsActiveCount++; window->BeginCount = 0; window->ClipRect = ImVec4(-FLT_MAX,-FLT_MAX,+FLT_MAX,+FLT_MAX); window->LastFrameActive = current_frame; @@ -4570,7 +4575,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) // Position child window if (flags & ImGuiWindowFlags_ChildWindow) { - window->OrderWithinParent = parent_window->DC.ChildWindows.Size; + window->BeginOrderWithinParent = parent_window->DC.ChildWindows.Size; parent_window->DC.ChildWindows.push_back(window); } if ((flags & ImGuiWindowFlags_ChildWindow) && !(flags & ImGuiWindowFlags_Popup) && !window_pos_set_by_api) @@ -6685,6 +6690,7 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l button_flags |= ImGuiButtonFlags_PressedOnDragDropHold; if (flags & ImGuiTreeNodeFlags_OpenOnDoubleClick) button_flags |= ImGuiButtonFlags_PressedOnDoubleClick | ((flags & ImGuiTreeNodeFlags_OpenOnArrow) ? ImGuiButtonFlags_PressedOnClickRelease : 0); + bool hovered, held, pressed = ButtonBehavior(interact_bb, id, &hovered, &held, button_flags); if (pressed && !(flags & ImGuiTreeNodeFlags_Leaf)) { @@ -6774,7 +6780,6 @@ bool ImGui::CollapsingHeader(const char* label, bool* p_open, ImGuiTreeNodeFlags ImGuiContext& g = *GImGui; float button_sz = g.FontSize * 0.5f; ImGuiItemHoveredDataBackup last_item_backup; - last_item_backup.Backup(); if (CloseButton(window->GetID((void*)(intptr_t)(id+1)), ImVec2(ImMin(window->DC.LastItemRect.Max.x, window->ClipRect.Max.x) - g.Style.FramePadding.x - button_sz, window->DC.LastItemRect.Min.y + g.Style.FramePadding.y + button_sz), button_sz)) *p_open = false; last_item_backup.Restore(); diff --git a/imgui.h b/imgui.h index b44f3936988d..6bbf2df58cc2 100644 --- a/imgui.h +++ b/imgui.h @@ -79,8 +79,8 @@ typedef int ImGuiMouseCursor; // enum: a mouse cursor identifier typedef int ImGuiStyleVar; // enum: a variable identifier for styling // enum ImGuiStyleVar_ typedef int ImDrawCornerFlags; // flags: for ImDrawList::AddRect*() etc. // enum ImDrawCornerFlags_ typedef int ImGuiColorEditFlags; // flags: for ColorEdit*(), ColorPicker*() // enum ImGuiColorEditFlags_ -typedef int ImGuiDragDropFlags; // flags: for *DragDrop*() // enum ImGuiDragDropFlags_ typedef int ImGuiColumnsFlags; // flags: for *Columns*() // enum ImGuiColumnsFlags_ +typedef int ImGuiDragDropFlags; // flags: for *DragDrop*() // enum ImGuiDragDropFlags_ typedef int ImGuiComboFlags; // flags: for BeginCombo() // enum ImGuiComboFlags_ typedef int ImGuiFocusedFlags; // flags: for IsWindowFocused() // enum ImGuiFocusedFlags_ typedef int ImGuiHoveredFlags; // flags: for IsItemHovered() etc. // enum ImGuiHoveredFlags_ @@ -627,7 +627,7 @@ enum ImGuiHoveredFlags_ ImGuiHoveredFlags_RootWindow = 1 << 1, // IsWindowHovered() only: Test from root window (top most parent of the current hierarchy) ImGuiHoveredFlags_AllowWhenBlockedByPopup = 1 << 2, // Return true even if a popup window is normally blocking access to this item/window //ImGuiHoveredFlags_AllowWhenBlockedByModal = 1 << 3, // Return true even if a modal popup window is normally blocking access to this item/window. FIXME-TODO: Unavailable yet. - ImGuiHoveredFlags_AllowWhenBlockedByActiveItem = 1 << 4, // Return true even if an active item is blocking access to this item/window + ImGuiHoveredFlags_AllowWhenBlockedByActiveItem = 1 << 4, // Return true even if an active item is blocking access to this item/window. Useful for Drag and Drop patterns. ImGuiHoveredFlags_AllowWhenOverlapped = 1 << 5, // Return true even if the position is overlapped by another window ImGuiHoveredFlags_RectOnly = ImGuiHoveredFlags_AllowWhenBlockedByPopup | ImGuiHoveredFlags_AllowWhenBlockedByActiveItem | ImGuiHoveredFlags_AllowWhenOverlapped }; diff --git a/imgui_internal.h b/imgui_internal.h index 16b71bad3f98..5c0705ad7f3b 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -183,7 +183,7 @@ enum ImGuiButtonFlags_ ImGuiButtonFlags_AllowItemOverlap = 1 << 6, // require previous frame HoveredId to either match id or be null before being usable, use along with SetItemAllowOverlap() ImGuiButtonFlags_DontClosePopups = 1 << 7, // disable automatically closing parent popup on press // [UNUSED] ImGuiButtonFlags_Disabled = 1 << 8, // disable interactions - ImGuiButtonFlags_AlignTextBaseLine = 1 << 9, // vertically align button to match text baseline (ButtonEx() only) + ImGuiButtonFlags_AlignTextBaseLine = 1 << 9, // vertically align button to match text baseline - ButtonEx() only // FIXME: Should be removed and handled by SmallButton(), not possible currently because of DC.CursorPosPrevLine ImGuiButtonFlags_NoKeyModifiers = 1 << 10, // disable interaction if a key modifier is held ImGuiButtonFlags_NoHoldingActiveID = 1 << 11, // don't set ActiveId while holding the mouse (ImGuiButtonFlags_PressedOnClick only) ImGuiButtonFlags_PressedOnDragDropHold = 1 << 12 // press when held into while we are drag and dropping another item (used by e.g. tree nodes, collapsing headers) @@ -207,8 +207,8 @@ enum ImGuiColumnsFlags_ enum ImGuiSelectableFlagsPrivate_ { // NB: need to be in sync with last value of ImGuiSelectableFlags_ - ImGuiSelectableFlags_Menu = 1 << 3, - ImGuiSelectableFlags_MenuItem = 1 << 4, + ImGuiSelectableFlags_Menu = 1 << 3, // -> PressedOnClick + ImGuiSelectableFlags_MenuItem = 1 << 4, // -> PressedOnRelease ImGuiSelectableFlags_Disabled = 1 << 5, ImGuiSelectableFlags_DrawFillAvailWidth = 1 << 6 }; @@ -439,6 +439,7 @@ struct ImGuiContext ImVector WindowsSortBuffer; ImVector CurrentWindowStack; ImGuiStorage WindowsById; + int WindowsActiveCount; ImGuiWindow* CurrentWindow; // Being drawn into ImGuiWindow* NavWindow; // Nav/focused window for navigation ImGuiWindow* HoveredWindow; // Will catch mouse inputs @@ -550,6 +551,7 @@ struct ImGuiContext Time = 0.0f; FrameCount = 0; FrameCountEnded = FrameCountRendered = -1; + WindowsActiveCount = 0; CurrentWindow = NULL; NavWindow = NULL; HoveredWindow = NULL; @@ -723,7 +725,6 @@ struct IMGUI_API ImGuiWindow char* Name; ImGuiID ID; // == ImHash(Name) ImGuiWindowFlags Flags; // See enum ImGuiWindowFlags_ - int OrderWithinParent; // Order within immediate parent window, if we are a child window. Otherwise 0. ImVec2 PosFloat; ImVec2 Pos; // Position rounded-up to nearest pixel ImVec2 Size; // Current size (==SizeFull or collapsed title bar size) @@ -748,6 +749,8 @@ struct IMGUI_API ImGuiWindow bool SkipItems; // Set when items can safely be all clipped (e.g. window not visible or collapsed) bool Appearing; // Set during the frame where the window is appearing (or re-appearing) bool CloseButton; // Set when the window has a close button (p_open != NULL) + int BeginOrderWithinParent; // Order within immediate parent window, if we are a child window. Otherwise 0. + int BeginOrderWithinContext; // Order within entire imgui context. This is mostly used for debugging submission order related issues. int BeginCount; // Number of Begin() during the current frame (generally 0 or 1, 1+ if appending via multiple Begin/End pairs) ImGuiID PopupId; // ID in the popup stack when this window is used as a popup/menu (because we use generic Name/ID for recycling) int AutoFitFramesX, AutoFitFramesY; @@ -809,8 +812,9 @@ struct ImGuiItemHoveredDataBackup ImRect LastItemRect; bool LastItemRectHoveredRect; - void Backup() { ImGuiWindow* window = GImGui->CurrentWindow; LastItemId = window->DC.LastItemId; LastItemRect = window->DC.LastItemRect; LastItemRectHoveredRect = window->DC.LastItemRectHoveredRect; } - void Restore() { ImGuiWindow* window = GImGui->CurrentWindow; window->DC.LastItemId = LastItemId; window->DC.LastItemRect = LastItemRect; window->DC.LastItemRectHoveredRect = LastItemRectHoveredRect; } + ImGuiItemHoveredDataBackup() { Backup(); } + void Backup() { ImGuiWindow* window = GImGui->CurrentWindow; LastItemId = window->DC.LastItemId; LastItemRect = window->DC.LastItemRect; LastItemRectHoveredRect = window->DC.LastItemRectHoveredRect; } + void Restore() const { ImGuiWindow* window = GImGui->CurrentWindow; window->DC.LastItemId = LastItemId; window->DC.LastItemRect = LastItemRect; window->DC.LastItemRectHoveredRect = LastItemRectHoveredRect; } }; //----------------------------------------------------------------------------- From 90788a12423fa169ffc17a41af19e98ccd975216 Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 12 Dec 2017 23:36:42 +0100 Subject: [PATCH 293/823] ImVector: Added ImVector::contains() helper --- imgui.h | 1 + 1 file changed, 1 insertion(+) diff --git a/imgui.h b/imgui.h index 6bbf2df58cc2..52a0239feea6 100644 --- a/imgui.h +++ b/imgui.h @@ -1052,6 +1052,7 @@ class ImVector inline iterator erase(const_iterator it) { IM_ASSERT(it >= Data && it < Data+Size); const ptrdiff_t off = it - Data; memmove(Data + off, Data + off + 1, ((size_t)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 >= Data && it <= Data+Size); const ptrdiff_t off = it - Data; if (Size == Capacity) reserve(Capacity ? Capacity * 2 : 4); if (off < (int)Size) memmove(Data + off + 1, Data + off, ((size_t)Size - (size_t)off) * sizeof(value_type)); Data[off] = v; Size++; return Data + off; } + inline bool contains(const value_type& v) const { const T* data = Data; const T* data_end = Data + Size; while (data < data_end) if (*data++ == v) return true; return false; } }; // Helper: execute a block of code at maximum once a frame. Convenient if you want to quickly create an UI within deep-nested code that runs multiple times every frame. From 8b59ed070895b319a5f11f816ad0feb682fed30e Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 12 Dec 2017 23:37:27 +0100 Subject: [PATCH 294/823] Drag and Drop: Exposed some internals. --- imgui.cpp | 9 +++++++-- imgui_internal.h | 2 ++ 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index dc418eba3f6e..b032d549f04c 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -673,7 +673,6 @@ static bool DataTypeApplyOpFromText(const char* buf, const char* ini namespace ImGui { -static void ClearDragDrop(); static void FocusPreviousWindow(); } @@ -11151,7 +11150,7 @@ void ImGui::Value(const char* prefix, float v, const char* float_format) // DRAG AND DROP //----------------------------------------------------------------------------- -static void ImGui::ClearDragDrop() +void ImGui::ClearDragDrop() { ImGuiContext& g = *GImGui; g.DragDropActive = false; @@ -11340,6 +11339,12 @@ bool ImGui::BeginDragDropTarget() return true; } +bool ImGui::IsDragDropPayloadBeingAccepted() +{ + ImGuiContext& g = *GImGui; + return g.DragDropActive && g.DragDropAcceptIdPrev != 0; +} + const ImGuiPayload* ImGui::AcceptDragDropPayload(const char* type, ImGuiDragDropFlags flags) { ImGuiContext& g = *GImGui; diff --git a/imgui_internal.h b/imgui_internal.h index 5c0705ad7f3b..b8f7e9920368 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -873,6 +873,8 @@ namespace ImGui IMGUI_API bool SplitterBehavior(ImGuiID id, const ImRect& bb, ImGuiAxis axis, float* size1, float* size2, float min_size1, float min_size2, float hover_extend = 0.0f); IMGUI_API bool BeginDragDropTargetCustom(const ImRect& bb, ImGuiID id); + IMGUI_API void ClearDragDrop(); + IMGUI_API bool IsDragDropPayloadBeingAccepted(); // FIXME-WIP: New Columns API IMGUI_API void BeginColumns(const char* id, int count, ImGuiColumnsFlags flags = 0); // setup number of columns. use an identifier to distinguish multiple column sets. close with EndColumns(). From 90d0b8b58b7957b6e73fde769d00ac110ff6bebe Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 12 Dec 2017 23:41:20 +0100 Subject: [PATCH 295/823] Navigation: minor sync to reduce drifts between changes --- imgui.cpp | 8 +++++--- imgui_internal.h | 2 +- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 22202004511b..54f5e2292b9a 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -4794,8 +4794,9 @@ bool ImGui::BeginPopupContextItem(const char* str_id, int mouse_button) ImGuiWindow* window = GImGui->CurrentWindow; ImGuiID id = str_id ? window->GetID(str_id) : window->DC.LastItemId; // If user hasn't passed an ID, we can use the LastItemID. Using LastItemID as a Popup ID won't conflict! IM_ASSERT(id != 0); // However, you cannot pass a NULL str_id if the last item has no identifier (e.g. a Text() item) - if (IsMouseClicked(mouse_button) && IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup)) - OpenPopupEx(id, true); + if (IsMouseClicked(mouse_button)) + if (IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup)) + OpenPopupEx(id, true); return BeginPopupEx(id, ImGuiWindowFlags_AlwaysAutoResize); } @@ -11525,9 +11526,10 @@ bool ImGui::ColorPicker4(const char* label, float col[4], ImGuiColorEditFlags fl value_changed = value_changed_h = true; } } + + // Alpha bar logic if (alpha_bar) { - // Alpha bar logic SetCursorScreenPos(ImVec2(bar1_pos_x, picker_pos.y)); InvisibleButton("alpha", ImVec2(bars_width, sv_picker_size)); if (IsItemActive()) diff --git a/imgui_internal.h b/imgui_internal.h index b6afde127788..f85e4bb566c4 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -182,7 +182,7 @@ enum ImGuiButtonFlags_ ImGuiButtonFlags_PressedOnRelease = 1 << 3, // return true on release (default requires click+release) ImGuiButtonFlags_PressedOnDoubleClick = 1 << 4, // return true on double-click (default requires click+release) ImGuiButtonFlags_FlattenChildren = 1 << 5, // allow interactions even if a child window is overlapping - ImGuiButtonFlags_AllowItemOverlap = 1 << 6, // require previous frame HoveredId to either match id or be null before being usable + ImGuiButtonFlags_AllowItemOverlap = 1 << 6, // require previous frame HoveredId to either match id or be null before being usable, use along with SetItemAllowOverlap() ImGuiButtonFlags_DontClosePopups = 1 << 7, // disable automatically closing parent popup on press // [UNUSED] ImGuiButtonFlags_Disabled = 1 << 8, // disable interactions ImGuiButtonFlags_AlignTextBaseLine = 1 << 9, // vertically align button to match text baseline - ButtonEx() only // FIXME: Should be removed and handled by SmallButton(), not possible currently because of DC.CursorPosPrevLine From 027ffd91ead699e577dd294030158a4307d0b0df Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 12 Dec 2017 23:49:04 +0100 Subject: [PATCH 296/823] IsWindowFocused(): oops, that was bound to happen with loosely typed enums (this is sort of why I made both values identical - no direct side effects). --- imgui.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index b032d549f04c..c20916ef96b8 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -5521,13 +5521,13 @@ bool ImGui::IsWindowFocused(ImGuiFocusedFlags flags) ImGuiContext& g = *GImGui; IM_ASSERT(g.CurrentWindow); // Not inside a Begin()/End() - switch (flags & (ImGuiFocusedFlags_RootWindow | ImGuiHoveredFlags_ChildWindows)) + switch (flags & (ImGuiFocusedFlags_RootWindow | ImGuiFocusedFlags_ChildWindows)) { - case ImGuiFocusedFlags_RootWindow | ImGuiHoveredFlags_ChildWindows: + case ImGuiFocusedFlags_RootWindow | ImGuiFocusedFlags_ChildWindows: return g.NavWindow && g.CurrentWindow->RootWindow == g.NavWindow->RootWindow; case ImGuiFocusedFlags_RootWindow: return g.CurrentWindow->RootWindow == g.NavWindow; - case ImGuiHoveredFlags_ChildWindows: + case ImGuiFocusedFlags_ChildWindows: return g.NavWindow && IsWindowChildOf(g.NavWindow, g.CurrentWindow); default: return g.CurrentWindow == g.NavWindow; From 78320aa633a2bb107d3da7925d7f4ab1cdd65704 Mon Sep 17 00:00:00 2001 From: omar Date: Wed, 13 Dec 2017 18:37:58 +0100 Subject: [PATCH 297/823] Columns: Refactor: Moved columns data into their own data structure. Minimum changes now to ease diffing. (#125, #1499) --- imgui.cpp | 214 ++++++++++++++++++++++++++--------------------- imgui_internal.h | 70 +++++++++------- 2 files changed, 158 insertions(+), 126 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index c20916ef96b8..bc60f574ae2f 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -627,8 +627,6 @@ // Forward Declarations //------------------------------------------------------------------------- -static float GetDraggedColumnOffset(int column_index); - static bool IsKeyPressedMap(ImGuiKey key, bool repeat = true); static ImFont* GetDefaultFont(); @@ -1744,8 +1742,8 @@ static void SetCursorPosYAndSetupDummyPrevLine(float pos_y, float line_height) ImGuiWindow* window = ImGui::GetCurrentWindow(); window->DC.CursorPosPrevLine.y = window->DC.CursorPos.y - line_height; // Setting those fields so that SetScrollHere() can properly function after the end of our clipper usage. window->DC.PrevLineHeight = (line_height - GImGui->Style.ItemSpacing.y); // If we end up needing more accurate data (to e.g. use SameLine) we may as well make the clipper have a fourth step to let user process and display the last item in their list. - if (window->DC.ColumnsCount > 1) - window->DC.ColumnsCellMinY = window->DC.CursorPos.y; // Setting this so that cell Y position are set properly + if (window->DC.ColumnsSet) + window->DC.ColumnsSet->ColumnsCellMinY = window->DC.CursorPos.y; // Setting this so that cell Y position are set properly } // Use case A: Begin() called from constructor with items_height<0, then called again from Sync() in StepNo 1 @@ -4833,11 +4831,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) window->DC.ItemFlagsStack.resize(0); window->DC.ItemWidthStack.resize(0); window->DC.TextWrapPosStack.resize(0); - window->DC.ColumnsCurrent = 0; - window->DC.ColumnsCount = 1; - window->DC.ColumnsStartPosY = window->DC.CursorPos.y; - window->DC.ColumnsStartMaxPosX = window->DC.CursorMaxPos.x; - window->DC.ColumnsCellMinY = window->DC.ColumnsCellMaxY = window->DC.ColumnsStartPosY; + window->DC.ColumnsSet = NULL; window->DC.TreeDepth = 0; window->DC.StateStorage = &window->StateStorage; window->DC.GroupStack.resize(0); @@ -4990,7 +4984,7 @@ void ImGui::End() ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; - if (window->DC.ColumnsCount != 1) // close columns set if any is open + if (window->DC.ColumnsSet != NULL) EndColumns(); PopClipRect(); // inner window clip rectangle @@ -5736,8 +5730,8 @@ ImVec2 ImGui::GetContentRegionMax() { ImGuiWindow* window = GetCurrentWindowRead(); ImVec2 mx = window->ContentsRegionRect.Max; - if (window->DC.ColumnsCount != 1) - mx.x = GetColumnOffset(window->DC.ColumnsCurrent + 1) - window->WindowPadding.x; + if (window->DC.ColumnsSet) + mx.x = GetColumnOffset(window->DC.ColumnsSet->ColumnsCurrent + 1) - window->WindowPadding.x; return mx; } @@ -9347,7 +9341,7 @@ bool ImGui::Selectable(const char* label, bool selected, ImGuiSelectableFlags fl ImGuiContext& g = *GImGui; const ImGuiStyle& style = g.Style; - if ((flags & ImGuiSelectableFlags_SpanAllColumns) && window->DC.ColumnsCount > 1) // FIXME-OPT: Avoid if vertically clipped. + if ((flags & ImGuiSelectableFlags_SpanAllColumns) && window->DC.ColumnsSet) // FIXME-OPT: Avoid if vertically clipped. PopClipRect(); ImGuiID id = window->GetID(label); @@ -9378,7 +9372,7 @@ bool ImGui::Selectable(const char* label, bool selected, ImGuiSelectableFlags fl bb_with_spacing.Max.y += spacing_D; if (!ItemAdd(bb_with_spacing, id)) { - if ((flags & ImGuiSelectableFlags_SpanAllColumns) && window->DC.ColumnsCount > 1) + if ((flags & ImGuiSelectableFlags_SpanAllColumns) && window->DC.ColumnsSet) PushColumnClipRect(); return false; } @@ -9400,7 +9394,7 @@ bool ImGui::Selectable(const char* label, bool selected, ImGuiSelectableFlags fl RenderFrame(bb_with_spacing.Min, bb_with_spacing.Max, col, false, 0.0f); } - if ((flags & ImGuiSelectableFlags_SpanAllColumns) && window->DC.ColumnsCount > 1) + if ((flags & ImGuiSelectableFlags_SpanAllColumns) && window->DC.ColumnsSet) { PushColumnClipRect(); bb_with_spacing.Max.x -= (GetContentRegionMax().x - max_x); @@ -10552,7 +10546,7 @@ void ImGui::Separator() } // Horizontal Separator - if (window->DC.ColumnsCount > 1) + if (window->DC.ColumnsSet) PopClipRect(); float x1 = window->Pos.x; @@ -10564,7 +10558,7 @@ void ImGui::Separator() ItemSize(ImVec2(0.0f, 0.0f)); // NB: we don't provide our width so that it doesn't get feed back into AutoFit, we don't provide height to not alter layout. if (!ItemAdd(bb, 0)) { - if (window->DC.ColumnsCount > 1) + if (window->DC.ColumnsSet) PushColumnClipRect(); return; } @@ -10574,10 +10568,10 @@ void ImGui::Separator() if (g.LogEnabled) LogRenderedText(NULL, IM_NEWLINE "--------------------------------"); - if (window->DC.ColumnsCount > 1) + if (window->DC.ColumnsSet) { PushColumnClipRect(); - window->DC.ColumnsCellMinY = window->DC.CursorPos.y; + window->DC.ColumnsSet->ColumnsCellMinY = window->DC.CursorPos.y; } } @@ -10790,29 +10784,30 @@ void ImGui::NewLine() void ImGui::NextColumn() { ImGuiWindow* window = GetCurrentWindow(); - if (window->SkipItems || window->DC.ColumnsCount <= 1) + if (window->SkipItems || window->DC.ColumnsSet == NULL) return; ImGuiContext& g = *GImGui; PopItemWidth(); PopClipRect(); - window->DC.ColumnsCellMaxY = ImMax(window->DC.ColumnsCellMaxY, window->DC.CursorPos.y); - if (++window->DC.ColumnsCurrent < window->DC.ColumnsCount) + ImGuiColumnsSet* columns = window->DC.ColumnsSet; + columns->ColumnsCellMaxY = ImMax(columns->ColumnsCellMaxY, window->DC.CursorPos.y); + if (++columns->ColumnsCurrent < columns->ColumnsCount) { // Columns 1+ cancel out IndentX - window->DC.ColumnsOffsetX = GetColumnOffset(window->DC.ColumnsCurrent) - window->DC.IndentX + g.Style.ItemSpacing.x; - window->DrawList->ChannelsSetCurrent(window->DC.ColumnsCurrent); + window->DC.ColumnsOffsetX = GetColumnOffset(columns->ColumnsCurrent) - window->DC.IndentX + g.Style.ItemSpacing.x; + window->DrawList->ChannelsSetCurrent(columns->ColumnsCurrent); } else { - window->DC.ColumnsCurrent = 0; window->DC.ColumnsOffsetX = 0.0f; - window->DC.ColumnsCellMinY = window->DC.ColumnsCellMaxY; + columns->ColumnsCurrent = 0; + columns->ColumnsCellMinY = columns->ColumnsCellMaxY; window->DrawList->ChannelsSetCurrent(0); } window->DC.CursorPos.x = (float)(int)(window->Pos.x + window->DC.IndentX + window->DC.ColumnsOffsetX); - window->DC.CursorPos.y = window->DC.ColumnsCellMinY; + window->DC.CursorPos.y = columns->ColumnsCellMinY; window->DC.CurrentLineHeight = 0.0f; window->DC.CurrentLineTextBaseOffset = 0.0f; @@ -10823,37 +10818,37 @@ void ImGui::NextColumn() int ImGui::GetColumnIndex() { ImGuiWindow* window = GetCurrentWindowRead(); - return window->DC.ColumnsCurrent; + return window->DC.ColumnsSet ? window->DC.ColumnsSet->ColumnsCurrent : 0; } int ImGui::GetColumnsCount() { ImGuiWindow* window = GetCurrentWindowRead(); - return window->DC.ColumnsCount; + return window->DC.ColumnsSet ? window->DC.ColumnsSet->ColumnsCount : 1; } -static float OffsetNormToPixels(ImGuiWindow* window, float offset_norm) +static float OffsetNormToPixels(const ImGuiColumnsSet* columns, float offset_norm) { - return offset_norm * (window->DC.ColumnsMaxX - window->DC.ColumnsMinX); + return offset_norm * (columns->ColumnsMaxX - columns->ColumnsMinX); } -static float PixelsToOffsetNorm(ImGuiWindow* window, float offset) +static float PixelsToOffsetNorm(const ImGuiColumnsSet* columns, float offset) { - return (offset - window->DC.ColumnsMinX) / (window->DC.ColumnsMaxX - window->DC.ColumnsMinX); + return (offset - columns->ColumnsMinX) / (columns->ColumnsMaxX - columns->ColumnsMinX); } -static float GetDraggedColumnOffset(int column_index) +static float GetDraggedColumnOffset(ImGuiColumnsSet* columns, int column_index) { // Active (dragged) column always follow mouse. The reason we need this is that dragging a column to the right edge of an auto-resizing // window creates a feedback loop because we store normalized positions. So while dragging we enforce absolute positioning. ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; IM_ASSERT(column_index > 0); // We cannot drag column 0. If you get this assert you may have a conflict between the ID of your columns and another widgets. - IM_ASSERT(g.ActiveId == window->DC.ColumnsSetId + ImGuiID(column_index)); + IM_ASSERT(g.ActiveId == columns->ColumnsSetId + ImGuiID(column_index)); float x = g.IO.MousePos.x - g.ActiveIdClickOffset.x - window->Pos.x; x = ImMax(x, ImGui::GetColumnOffset(column_index-1) + g.Style.ColumnsMinSpacing); - if ((window->DC.ColumnsFlags & ImGuiColumnsFlags_NoPreserveWidths)) + if ((columns->ColumnsFlags & ImGuiColumnsFlags_NoPreserveWidths)) x = ImMin(x, ImGui::GetColumnOffset(column_index+1) - g.Style.ColumnsMinSpacing); return x; @@ -10862,44 +10857,50 @@ static float GetDraggedColumnOffset(int column_index) float ImGui::GetColumnOffset(int column_index) { ImGuiWindow* window = GetCurrentWindowRead(); + ImGuiColumnsSet* columns = window->DC.ColumnsSet; + IM_ASSERT(columns != NULL); + if (column_index < 0) - column_index = window->DC.ColumnsCurrent; + column_index = columns->ColumnsCurrent; /* if (g.ActiveId) { ImGuiContext& g = *GImGui; - const ImGuiID column_id = window->DC.ColumnsSetId + ImGuiID(column_index); + const ImGuiID column_id = columns->ColumnsSetId + ImGuiID(column_index); if (g.ActiveId == column_id) - return GetDraggedColumnOffset(column_index); + return GetDraggedColumnOffset(columns, column_index); } */ - IM_ASSERT(column_index < window->DC.ColumnsData.Size); - const float t = window->DC.ColumnsData[column_index].OffsetNorm; - const float x_offset = ImLerp(window->DC.ColumnsMinX, window->DC.ColumnsMaxX, t); + IM_ASSERT(column_index < columns->ColumnsData.Size); + const float t = columns->ColumnsData[column_index].OffsetNorm; + const float x_offset = ImLerp(columns->ColumnsMinX, columns->ColumnsMaxX, t); return x_offset; } void ImGui::SetColumnOffset(int column_index, float offset) { ImGuiContext& g = *GImGui; - ImGuiWindow* window = GetCurrentWindow(); + ImGuiWindow* window = g.CurrentWindow; + ImGuiColumnsSet* columns = window->DC.ColumnsSet; + IM_ASSERT(columns != NULL); + if (column_index < 0) - column_index = window->DC.ColumnsCurrent; + column_index = columns->ColumnsCurrent; - IM_ASSERT(column_index < window->DC.ColumnsData.Size); + IM_ASSERT(column_index < columns->ColumnsData.Size); - const bool preserve_width = !(window->DC.ColumnsFlags & ImGuiColumnsFlags_NoPreserveWidths) && (column_index < window->DC.ColumnsCount-1); + const bool preserve_width = !(columns->ColumnsFlags & ImGuiColumnsFlags_NoPreserveWidths) && (column_index < columns->ColumnsCount-1); const float width = preserve_width ? GetColumnWidth(column_index) : 0.0f; - if (!(window->DC.ColumnsFlags & ImGuiColumnsFlags_NoForceWithinWindow)) - offset = ImMin(offset, window->DC.ColumnsMaxX - g.Style.ColumnsMinSpacing * (window->DC.ColumnsCount - column_index)); - const float offset_norm = PixelsToOffsetNorm(window, offset); + if (!(columns->ColumnsFlags & ImGuiColumnsFlags_NoForceWithinWindow)) + offset = ImMin(offset, columns->ColumnsMaxX - g.Style.ColumnsMinSpacing * (columns->ColumnsCount - column_index)); + const float offset_norm = PixelsToOffsetNorm(columns, offset); - const ImGuiID column_id = window->DC.ColumnsSetId + ImGuiID(column_index); + const ImGuiID column_id = columns->ColumnsSetId + ImGuiID(column_index); window->DC.StateStorage->SetFloat(column_id, offset_norm); - window->DC.ColumnsData[column_index].OffsetNorm = offset_norm; + columns->ColumnsData[column_index].OffsetNorm = offset_norm; if (preserve_width) SetColumnOffset(column_index + 1, offset + ImMax(g.Style.ColumnsMinSpacing, width)); @@ -10908,70 +10909,91 @@ void ImGui::SetColumnOffset(int column_index, float offset) float ImGui::GetColumnWidth(int column_index) { ImGuiWindow* window = GetCurrentWindowRead(); - if (column_index < 0) - column_index = window->DC.ColumnsCurrent; + ImGuiColumnsSet* columns = window->DC.ColumnsSet; + IM_ASSERT(columns != NULL); - return OffsetNormToPixels(window, window->DC.ColumnsData[column_index+1].OffsetNorm - window->DC.ColumnsData[column_index].OffsetNorm); + if (column_index < 0) + column_index = columns->ColumnsCurrent; + return OffsetNormToPixels(columns, columns->ColumnsData[column_index+1].OffsetNorm - columns->ColumnsData[column_index].OffsetNorm); } void ImGui::SetColumnWidth(int column_index, float width) { ImGuiWindow* window = GetCurrentWindowRead(); - if (column_index < 0) - column_index = window->DC.ColumnsCurrent; + ImGuiColumnsSet* columns = window->DC.ColumnsSet; + IM_ASSERT(columns != NULL); + if (column_index < 0) + column_index = columns->ColumnsCurrent; SetColumnOffset(column_index+1, GetColumnOffset(column_index) + width); } void ImGui::PushColumnClipRect(int column_index) { ImGuiWindow* window = GetCurrentWindowRead(); + ImGuiColumnsSet* columns = window->DC.ColumnsSet; if (column_index < 0) - column_index = window->DC.ColumnsCurrent; + column_index = columns->ColumnsCurrent; - PushClipRect(window->DC.ColumnsData[column_index].ClipRect.Min, window->DC.ColumnsData[column_index].ClipRect.Max, false); + PushClipRect(columns->ColumnsData[column_index].ClipRect.Min, columns->ColumnsData[column_index].ClipRect.Max, false); } -void ImGui::BeginColumns(const char* id, int columns_count, ImGuiColumnsFlags flags) +static ImGuiColumnsSet* FindOrAddColumnsSet(ImGuiWindow* window, ImGuiID id) +{ + for (int n = 0; n < window->DC.ColumnsSets.Size; n++) + if (window->DC.ColumnsSets[n].ColumnsSetId == id) + return &window->DC.ColumnsSets[n]; + + window->DC.ColumnsSets.push_back(ImGuiColumnsSet()); + ImGuiColumnsSet* columns = &window->DC.ColumnsSets.back(); + columns->ColumnsSetId = id; + return columns; +} + +void ImGui::BeginColumns(const char* str_id, int columns_count, ImGuiColumnsFlags flags) { ImGuiContext& g = *GImGui; ImGuiWindow* window = GetCurrentWindow(); IM_ASSERT(columns_count > 1); - IM_ASSERT(window->DC.ColumnsCount == 1); // Nested columns are currently not supported + IM_ASSERT(window->DC.ColumnsSet == NULL); // Nested columns are currently not supported // Differentiate column ID with an arbitrary prefix for cases where users name their columns set the same as another widget. // In addition, when an identifier isn't explicitly provided we include the number of columns in the hash to make it uniquer. - PushID(0x11223347 + (id ? 0 : columns_count)); - window->DC.ColumnsSetId = window->GetID(id ? id : "columns"); + PushID(0x11223347 + (str_id ? 0 : columns_count)); + ImGuiID id = window->GetID(str_id ? str_id : "columns"); PopID(); + ImGuiColumnsSet* columns = FindOrAddColumnsSet(window, id); + IM_ASSERT(columns->ColumnsSetId == id); + window->DC.ColumnsSet = columns; + // Set state for first column - window->DC.ColumnsCurrent = 0; - window->DC.ColumnsCount = columns_count; - window->DC.ColumnsFlags = flags; + columns->ColumnsCurrent = 0; + columns->ColumnsCount = columns_count; + columns->ColumnsFlags = flags; const float content_region_width = (window->SizeContentsExplicit.x != 0.0f) ? (window->SizeContentsExplicit.x) : (window->Size.x -window->ScrollbarSizes.x); - window->DC.ColumnsMinX = window->DC.IndentX - g.Style.ItemSpacing.x; // Lock our horizontal range - //window->DC.ColumnsMaxX = content_region_width - window->Scroll.x -((window->Flags & ImGuiWindowFlags_NoScrollbar) ? 0 : g.Style.ScrollbarSize);// - window->WindowPadding().x; - window->DC.ColumnsMaxX = content_region_width - window->Scroll.x; - window->DC.ColumnsStartPosY = window->DC.CursorPos.y; - window->DC.ColumnsStartMaxPosX = window->DC.CursorMaxPos.x; - window->DC.ColumnsCellMinY = window->DC.ColumnsCellMaxY = window->DC.CursorPos.y; + columns->ColumnsMinX = window->DC.IndentX - g.Style.ItemSpacing.x; // Lock our horizontal range + //column->ColumnsMaxX = content_region_width - window->Scroll.x -((window->Flags & ImGuiWindowFlags_NoScrollbar) ? 0 : g.Style.ScrollbarSize);// - window->WindowPadding().x; + columns->ColumnsMaxX = content_region_width - window->Scroll.x; + columns->ColumnsStartPosY = window->DC.CursorPos.y; + columns->ColumnsStartMaxPosX = window->DC.CursorMaxPos.x; + columns->ColumnsCellMinY = columns->ColumnsCellMaxY = window->DC.CursorPos.y; window->DC.ColumnsOffsetX = 0.0f; window->DC.CursorPos.x = (float)(int)(window->Pos.x + window->DC.IndentX + window->DC.ColumnsOffsetX); // Cache column offsets - window->DC.ColumnsData.resize(columns_count + 1); + columns->ColumnsData.resize(columns_count + 1); for (int column_index = 0; column_index < columns_count + 1; column_index++) { - const ImGuiID column_id = window->DC.ColumnsSetId + ImGuiID(column_index); + const ImGuiID column_id = columns->ColumnsSetId + ImGuiID(column_index); KeepAliveID(column_id); - const float default_t = column_index / (float)window->DC.ColumnsCount; + const float default_t = column_index / (float)columns_count; float t = window->DC.StateStorage->GetFloat(column_id, default_t); - if (!(window->DC.ColumnsFlags & ImGuiColumnsFlags_NoForceWithinWindow)) - t = ImMin(t, PixelsToOffsetNorm(window, window->DC.ColumnsMaxX - g.Style.ColumnsMinSpacing * (window->DC.ColumnsCount - column_index))); - window->DC.ColumnsData[column_index].OffsetNorm = t; + if (!(columns->ColumnsFlags & ImGuiColumnsFlags_NoForceWithinWindow)) + t = ImMin(t, PixelsToOffsetNorm(columns, columns->ColumnsMaxX - g.Style.ColumnsMinSpacing * (columns->ColumnsCount - column_index))); + columns->ColumnsData[column_index].OffsetNorm = t; } // Cache clipping rectangles @@ -10979,11 +11001,11 @@ void ImGui::BeginColumns(const char* id, int columns_count, ImGuiColumnsFlags fl { float clip_x1 = ImFloor(0.5f + window->Pos.x + GetColumnOffset(column_index) - 1.0f); float clip_x2 = ImFloor(0.5f + window->Pos.x + GetColumnOffset(column_index + 1) - 1.0f); - window->DC.ColumnsData[column_index].ClipRect = ImRect(clip_x1, -FLT_MAX, clip_x2, +FLT_MAX); - window->DC.ColumnsData[column_index].ClipRect.ClipWith(window->ClipRect); + columns->ColumnsData[column_index].ClipRect = ImRect(clip_x1, -FLT_MAX, clip_x2, +FLT_MAX); + columns->ColumnsData[column_index].ClipRect.ClipWith(window->ClipRect); } - window->DrawList->ChannelsSplit(window->DC.ColumnsCount); + window->DrawList->ChannelsSplit(columns->ColumnsCount); PushColumnClipRect(); PushItemWidth(GetColumnWidth() * 0.65f); } @@ -10992,34 +11014,35 @@ void ImGui::EndColumns() { ImGuiContext& g = *GImGui; ImGuiWindow* window = GetCurrentWindow(); - IM_ASSERT(window->DC.ColumnsCount > 1); + ImGuiColumnsSet* columns = window->DC.ColumnsSet; + IM_ASSERT(columns != NULL); PopItemWidth(); PopClipRect(); window->DrawList->ChannelsMerge(); - window->DC.ColumnsCellMaxY = ImMax(window->DC.ColumnsCellMaxY, window->DC.CursorPos.y); - window->DC.CursorPos.y = window->DC.ColumnsCellMaxY; - if (!(window->DC.ColumnsFlags & ImGuiColumnsFlags_GrowParentContentsSize)) - window->DC.CursorMaxPos.x = ImMax(window->DC.ColumnsStartMaxPosX, window->DC.ColumnsMaxX); // Restore cursor max pos, as columns don't grow parent + columns->ColumnsCellMaxY = ImMax(columns->ColumnsCellMaxY, window->DC.CursorPos.y); + window->DC.CursorPos.y = columns->ColumnsCellMaxY; + if (!(columns->ColumnsFlags & ImGuiColumnsFlags_GrowParentContentsSize)) + window->DC.CursorMaxPos.x = ImMax(columns->ColumnsStartMaxPosX, columns->ColumnsMaxX); // Restore cursor max pos, as columns don't grow parent // Draw columns borders and handle resize - if (!(window->DC.ColumnsFlags & ImGuiColumnsFlags_NoBorder) && !window->SkipItems) + if (!(columns->ColumnsFlags & ImGuiColumnsFlags_NoBorder) && !window->SkipItems) { - const float y1 = window->DC.ColumnsStartPosY; + const float y1 = columns->ColumnsStartPosY; const float y2 = window->DC.CursorPos.y; int dragging_column = -1; - for (int i = 1; i < window->DC.ColumnsCount; i++) + for (int i = 1; i < columns->ColumnsCount; i++) { float x = window->Pos.x + GetColumnOffset(i); - const ImGuiID column_id = window->DC.ColumnsSetId + ImGuiID(i); + const ImGuiID column_id = columns->ColumnsSetId + ImGuiID(i); const float column_hw = 4.0f; // Half-width for interaction const ImRect column_rect(ImVec2(x - column_hw, y1), ImVec2(x + column_hw, y2)); if (IsClippedEx(column_rect, column_id, false)) continue; bool hovered = false, held = false; - if (!(window->DC.ColumnsFlags & ImGuiColumnsFlags_NoResize)) + if (!(columns->ColumnsFlags & ImGuiColumnsFlags_NoResize)) { ButtonBehavior(column_rect, column_id, &hovered, &held); if (hovered || held) @@ -11040,16 +11063,13 @@ void ImGui::EndColumns() // Apply dragging after drawing the column lines, so our rendered lines are in sync with how items were displayed during the frame. if (dragging_column != -1) { - float x = GetDraggedColumnOffset(dragging_column); + float x = GetDraggedColumnOffset(columns, dragging_column); SetColumnOffset(dragging_column, x); } } - window->DC.ColumnsSetId = 0; - window->DC.ColumnsCurrent = 0; - window->DC.ColumnsCount = 1; - window->DC.ColumnsFlags = 0; - window->DC.ColumnsData.resize(0); + columns->ColumnsData.resize(0); + window->DC.ColumnsSet = NULL; window->DC.ColumnsOffsetX = 0.0f; window->DC.CursorPos.x = (float)(int)(window->Pos.x + window->DC.IndentX + window->DC.ColumnsOffsetX); } @@ -11060,7 +11080,7 @@ void ImGui::Columns(int columns_count, const char* id, bool border) ImGuiWindow* window = GetCurrentWindow(); IM_ASSERT(columns_count >= 1); - if (window->DC.ColumnsCount != columns_count && window->DC.ColumnsCount != 1) + if (window->DC.ColumnsSet != NULL && window->DC.ColumnsSet->ColumnsCount != columns_count) EndColumns(); ImGuiColumnsFlags flags = (border ? 0 : ImGuiColumnsFlags_NoBorder); diff --git a/imgui_internal.h b/imgui_internal.h index b8f7e9920368..30ac9707381c 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -331,14 +331,6 @@ struct ImGuiGroupData bool AdvanceCursor; }; -// Per column data for Columns() -struct ImGuiColumnData -{ - float OffsetNorm; // Column start offset, normalized 0.0 (far left) -> 1.0 (far right) - ImRect ClipRect; - //float IndentX; -}; - // Simple column measurement currently used for MenuItem() only. This is very short-sighted/throw-away code and NOT a generic helper. struct IMGUI_API ImGuiSimpleColumns { @@ -420,6 +412,42 @@ struct ImGuiPopupRef ImGuiPopupRef(ImGuiID id, ImGuiWindow* parent_window, ImGuiID parent_menu_set, const ImVec2& mouse_pos) { PopupId = id; Window = NULL; ParentWindow = parent_window; ParentMenuSet = parent_menu_set; MousePosOnOpen = mouse_pos; } }; +// Per column data for Columns() +struct ImGuiColumnData +{ + float OffsetNorm; // Column start offset, normalized 0.0 (far left) -> 1.0 (far right) + ImRect ClipRect; +}; + +struct ImGuiColumnsSet +{ + int ColumnsCurrent; + int ColumnsCount; + float ColumnsMinX; + float ColumnsMaxX; + float ColumnsStartPosY; + float ColumnsStartMaxPosX; // Backup of CursorMaxPos + float ColumnsCellMinY; + float ColumnsCellMaxY; + ImGuiColumnsFlags ColumnsFlags; + ImGuiID ColumnsSetId; + ImVector ColumnsData; + + ImGuiColumnsSet() { Clear(); } + void Clear() + { + ColumnsCurrent = 0; + ColumnsCount = 1; + ColumnsMinX = ColumnsMaxX = 0.0f; + ColumnsStartPosY = 0.0f; + ColumnsStartMaxPosX = 0.0f; + ColumnsCellMinY = ColumnsCellMaxY = 0.0f; + ColumnsFlags = 0; + ColumnsSetId = 0; + ColumnsData.clear(); + } +}; + // Main state for ImGui struct ImGuiContext { @@ -674,17 +702,8 @@ struct IMGUI_API ImGuiDrawContext float IndentX; // Indentation / start position from left of window (increased by TreePush/TreePop, etc.) float GroupOffsetX; float ColumnsOffsetX; // Offset to the current column (if ColumnsCurrent > 0). FIXME: This and the above should be a stack to allow use cases like Tree->Column->Tree. Need revamp columns API. - int ColumnsCurrent; - int ColumnsCount; - float ColumnsMinX; - float ColumnsMaxX; - float ColumnsStartPosY; - float ColumnsStartMaxPosX; // Backup of CursorMaxPos - float ColumnsCellMinY; - float ColumnsCellMaxY; - ImGuiColumnsFlags ColumnsFlags; - ImGuiID ColumnsSetId; - ImVector ColumnsData; + ImGuiColumnsSet* ColumnsSet; + ImVector ColumnsSets; ImGuiDrawContext() { @@ -708,14 +727,7 @@ struct IMGUI_API ImGuiDrawContext IndentX = 0.0f; GroupOffsetX = 0.0f; ColumnsOffsetX = 0.0f; - ColumnsCurrent = 0; - ColumnsCount = 1; - ColumnsMinX = ColumnsMaxX = 0.0f; - ColumnsStartPosY = 0.0f; - ColumnsStartMaxPosX = 0.0f; - ColumnsCellMinY = ColumnsCellMaxY = 0.0f; - ColumnsFlags = 0; - ColumnsSetId = 0; + ColumnsSet = NULL; } }; @@ -877,8 +889,8 @@ namespace ImGui IMGUI_API bool IsDragDropPayloadBeingAccepted(); // FIXME-WIP: New Columns API - IMGUI_API void BeginColumns(const char* id, int count, ImGuiColumnsFlags flags = 0); // setup number of columns. use an identifier to distinguish multiple column sets. close with EndColumns(). - IMGUI_API void EndColumns(); // close columns + IMGUI_API void BeginColumns(const char* str_id, int count, ImGuiColumnsFlags flags = 0); // setup number of columns. use an identifier to distinguish multiple column sets. close with EndColumns(). + IMGUI_API void EndColumns(); // close columns IMGUI_API void PushColumnClipRect(int column_index = -1); // NB: All position are in absolute pixels coordinates (never using window coordinates internally) From 3a31a75e3b9c184a8aab05c8c093bde833215eb6 Mon Sep 17 00:00:00 2001 From: omar Date: Wed, 13 Dec 2017 18:42:06 +0100 Subject: [PATCH 298/823] Columns: Refactor: Renamed all members. (#125, #1499) --- imgui.cpp | 124 +++++++++++++++++++++++------------------------ imgui_internal.h | 38 +++++++-------- 2 files changed, 80 insertions(+), 82 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index bc60f574ae2f..38af186694ba 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1743,7 +1743,7 @@ static void SetCursorPosYAndSetupDummyPrevLine(float pos_y, float line_height) window->DC.CursorPosPrevLine.y = window->DC.CursorPos.y - line_height; // Setting those fields so that SetScrollHere() can properly function after the end of our clipper usage. window->DC.PrevLineHeight = (line_height - GImGui->Style.ItemSpacing.y); // If we end up needing more accurate data (to e.g. use SameLine) we may as well make the clipper have a fourth step to let user process and display the last item in their list. if (window->DC.ColumnsSet) - window->DC.ColumnsSet->ColumnsCellMinY = window->DC.CursorPos.y; // Setting this so that cell Y position are set properly + window->DC.ColumnsSet->CellMinY = window->DC.CursorPos.y; // Setting this so that cell Y position are set properly } // Use case A: Begin() called from constructor with items_height<0, then called again from Sync() in StepNo 1 @@ -5731,7 +5731,7 @@ ImVec2 ImGui::GetContentRegionMax() ImGuiWindow* window = GetCurrentWindowRead(); ImVec2 mx = window->ContentsRegionRect.Max; if (window->DC.ColumnsSet) - mx.x = GetColumnOffset(window->DC.ColumnsSet->ColumnsCurrent + 1) - window->WindowPadding.x; + mx.x = GetColumnOffset(window->DC.ColumnsSet->Current + 1) - window->WindowPadding.x; return mx; } @@ -10571,7 +10571,7 @@ void ImGui::Separator() if (window->DC.ColumnsSet) { PushColumnClipRect(); - window->DC.ColumnsSet->ColumnsCellMinY = window->DC.CursorPos.y; + window->DC.ColumnsSet->CellMinY = window->DC.CursorPos.y; } } @@ -10792,22 +10792,22 @@ void ImGui::NextColumn() PopClipRect(); ImGuiColumnsSet* columns = window->DC.ColumnsSet; - columns->ColumnsCellMaxY = ImMax(columns->ColumnsCellMaxY, window->DC.CursorPos.y); - if (++columns->ColumnsCurrent < columns->ColumnsCount) + columns->CellMaxY = ImMax(columns->CellMaxY, window->DC.CursorPos.y); + if (++columns->Current < columns->Count) { // Columns 1+ cancel out IndentX - window->DC.ColumnsOffsetX = GetColumnOffset(columns->ColumnsCurrent) - window->DC.IndentX + g.Style.ItemSpacing.x; - window->DrawList->ChannelsSetCurrent(columns->ColumnsCurrent); + window->DC.ColumnsOffsetX = GetColumnOffset(columns->Current) - window->DC.IndentX + g.Style.ItemSpacing.x; + window->DrawList->ChannelsSetCurrent(columns->Current); } else { window->DC.ColumnsOffsetX = 0.0f; - columns->ColumnsCurrent = 0; - columns->ColumnsCellMinY = columns->ColumnsCellMaxY; + columns->Current = 0; + columns->CellMinY = columns->CellMaxY; window->DrawList->ChannelsSetCurrent(0); } window->DC.CursorPos.x = (float)(int)(window->Pos.x + window->DC.IndentX + window->DC.ColumnsOffsetX); - window->DC.CursorPos.y = columns->ColumnsCellMinY; + window->DC.CursorPos.y = columns->CellMinY; window->DC.CurrentLineHeight = 0.0f; window->DC.CurrentLineTextBaseOffset = 0.0f; @@ -10818,23 +10818,23 @@ void ImGui::NextColumn() int ImGui::GetColumnIndex() { ImGuiWindow* window = GetCurrentWindowRead(); - return window->DC.ColumnsSet ? window->DC.ColumnsSet->ColumnsCurrent : 0; + return window->DC.ColumnsSet ? window->DC.ColumnsSet->Current : 0; } int ImGui::GetColumnsCount() { ImGuiWindow* window = GetCurrentWindowRead(); - return window->DC.ColumnsSet ? window->DC.ColumnsSet->ColumnsCount : 1; + return window->DC.ColumnsSet ? window->DC.ColumnsSet->Count : 1; } static float OffsetNormToPixels(const ImGuiColumnsSet* columns, float offset_norm) { - return offset_norm * (columns->ColumnsMaxX - columns->ColumnsMinX); + return offset_norm * (columns->MaxX - columns->MinX); } static float PixelsToOffsetNorm(const ImGuiColumnsSet* columns, float offset) { - return (offset - columns->ColumnsMinX) / (columns->ColumnsMaxX - columns->ColumnsMinX); + return (offset - columns->MinX) / (columns->MaxX - columns->MinX); } static float GetDraggedColumnOffset(ImGuiColumnsSet* columns, int column_index) @@ -10844,11 +10844,11 @@ static float GetDraggedColumnOffset(ImGuiColumnsSet* columns, int column_index) ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; IM_ASSERT(column_index > 0); // We cannot drag column 0. If you get this assert you may have a conflict between the ID of your columns and another widgets. - IM_ASSERT(g.ActiveId == columns->ColumnsSetId + ImGuiID(column_index)); + IM_ASSERT(g.ActiveId == columns->ID + ImGuiID(column_index)); float x = g.IO.MousePos.x - g.ActiveIdClickOffset.x - window->Pos.x; x = ImMax(x, ImGui::GetColumnOffset(column_index-1) + g.Style.ColumnsMinSpacing); - if ((columns->ColumnsFlags & ImGuiColumnsFlags_NoPreserveWidths)) + if ((columns->Flags & ImGuiColumnsFlags_NoPreserveWidths)) x = ImMin(x, ImGui::GetColumnOffset(column_index+1) - g.Style.ColumnsMinSpacing); return x; @@ -10861,7 +10861,7 @@ float ImGui::GetColumnOffset(int column_index) IM_ASSERT(columns != NULL); if (column_index < 0) - column_index = columns->ColumnsCurrent; + column_index = columns->Current; /* if (g.ActiveId) @@ -10873,9 +10873,9 @@ float ImGui::GetColumnOffset(int column_index) } */ - IM_ASSERT(column_index < columns->ColumnsData.Size); - const float t = columns->ColumnsData[column_index].OffsetNorm; - const float x_offset = ImLerp(columns->ColumnsMinX, columns->ColumnsMaxX, t); + IM_ASSERT(column_index < columns->Columns.Size); + const float t = columns->Columns[column_index].OffsetNorm; + const float x_offset = ImLerp(columns->MinX, columns->MaxX, t); return x_offset; } @@ -10887,20 +10887,20 @@ void ImGui::SetColumnOffset(int column_index, float offset) IM_ASSERT(columns != NULL); if (column_index < 0) - column_index = columns->ColumnsCurrent; + column_index = columns->Current; - IM_ASSERT(column_index < columns->ColumnsData.Size); + IM_ASSERT(column_index < columns->Columns.Size); - const bool preserve_width = !(columns->ColumnsFlags & ImGuiColumnsFlags_NoPreserveWidths) && (column_index < columns->ColumnsCount-1); + const bool preserve_width = !(columns->Flags & ImGuiColumnsFlags_NoPreserveWidths) && (column_index < columns->Count-1); const float width = preserve_width ? GetColumnWidth(column_index) : 0.0f; - if (!(columns->ColumnsFlags & ImGuiColumnsFlags_NoForceWithinWindow)) - offset = ImMin(offset, columns->ColumnsMaxX - g.Style.ColumnsMinSpacing * (columns->ColumnsCount - column_index)); + if (!(columns->Flags & ImGuiColumnsFlags_NoForceWithinWindow)) + offset = ImMin(offset, columns->MaxX - g.Style.ColumnsMinSpacing * (columns->Count - column_index)); const float offset_norm = PixelsToOffsetNorm(columns, offset); - const ImGuiID column_id = columns->ColumnsSetId + ImGuiID(column_index); + const ImGuiID column_id = columns->ID + ImGuiID(column_index); window->DC.StateStorage->SetFloat(column_id, offset_norm); - columns->ColumnsData[column_index].OffsetNorm = offset_norm; + columns->Columns[column_index].OffsetNorm = offset_norm; if (preserve_width) SetColumnOffset(column_index + 1, offset + ImMax(g.Style.ColumnsMinSpacing, width)); @@ -10913,8 +10913,8 @@ float ImGui::GetColumnWidth(int column_index) IM_ASSERT(columns != NULL); if (column_index < 0) - column_index = columns->ColumnsCurrent; - return OffsetNormToPixels(columns, columns->ColumnsData[column_index+1].OffsetNorm - columns->ColumnsData[column_index].OffsetNorm); + column_index = columns->Current; + return OffsetNormToPixels(columns, columns->Columns[column_index+1].OffsetNorm - columns->Columns[column_index].OffsetNorm); } void ImGui::SetColumnWidth(int column_index, float width) @@ -10924,7 +10924,7 @@ void ImGui::SetColumnWidth(int column_index, float width) IM_ASSERT(columns != NULL); if (column_index < 0) - column_index = columns->ColumnsCurrent; + column_index = columns->Current; SetColumnOffset(column_index+1, GetColumnOffset(column_index) + width); } @@ -10933,20 +10933,20 @@ void ImGui::PushColumnClipRect(int column_index) ImGuiWindow* window = GetCurrentWindowRead(); ImGuiColumnsSet* columns = window->DC.ColumnsSet; if (column_index < 0) - column_index = columns->ColumnsCurrent; + column_index = columns->Current; - PushClipRect(columns->ColumnsData[column_index].ClipRect.Min, columns->ColumnsData[column_index].ClipRect.Max, false); + PushClipRect(columns->Columns[column_index].ClipRect.Min, columns->Columns[column_index].ClipRect.Max, false); } static ImGuiColumnsSet* FindOrAddColumnsSet(ImGuiWindow* window, ImGuiID id) { for (int n = 0; n < window->DC.ColumnsSets.Size; n++) - if (window->DC.ColumnsSets[n].ColumnsSetId == id) + if (window->DC.ColumnsSets[n].ID == id) return &window->DC.ColumnsSets[n]; window->DC.ColumnsSets.push_back(ImGuiColumnsSet()); ImGuiColumnsSet* columns = &window->DC.ColumnsSets.back(); - columns->ColumnsSetId = id; + columns->ID = id; return columns; } @@ -10965,35 +10965,35 @@ void ImGui::BeginColumns(const char* str_id, int columns_count, ImGuiColumnsFlag PopID(); ImGuiColumnsSet* columns = FindOrAddColumnsSet(window, id); - IM_ASSERT(columns->ColumnsSetId == id); + IM_ASSERT(columns->ID == id); window->DC.ColumnsSet = columns; // Set state for first column - columns->ColumnsCurrent = 0; - columns->ColumnsCount = columns_count; - columns->ColumnsFlags = flags; + columns->Current = 0; + columns->Count = columns_count; + columns->Flags = flags; const float content_region_width = (window->SizeContentsExplicit.x != 0.0f) ? (window->SizeContentsExplicit.x) : (window->Size.x -window->ScrollbarSizes.x); - columns->ColumnsMinX = window->DC.IndentX - g.Style.ItemSpacing.x; // Lock our horizontal range + columns->MinX = window->DC.IndentX - g.Style.ItemSpacing.x; // Lock our horizontal range //column->ColumnsMaxX = content_region_width - window->Scroll.x -((window->Flags & ImGuiWindowFlags_NoScrollbar) ? 0 : g.Style.ScrollbarSize);// - window->WindowPadding().x; - columns->ColumnsMaxX = content_region_width - window->Scroll.x; - columns->ColumnsStartPosY = window->DC.CursorPos.y; - columns->ColumnsStartMaxPosX = window->DC.CursorMaxPos.x; - columns->ColumnsCellMinY = columns->ColumnsCellMaxY = window->DC.CursorPos.y; + columns->MaxX = content_region_width - window->Scroll.x; + columns->StartPosY = window->DC.CursorPos.y; + columns->StartMaxPosX = window->DC.CursorMaxPos.x; + columns->CellMinY = columns->CellMaxY = window->DC.CursorPos.y; window->DC.ColumnsOffsetX = 0.0f; window->DC.CursorPos.x = (float)(int)(window->Pos.x + window->DC.IndentX + window->DC.ColumnsOffsetX); // Cache column offsets - columns->ColumnsData.resize(columns_count + 1); + columns->Columns.resize(columns_count + 1); for (int column_index = 0; column_index < columns_count + 1; column_index++) { - const ImGuiID column_id = columns->ColumnsSetId + ImGuiID(column_index); + const ImGuiID column_id = columns->ID + ImGuiID(column_index); KeepAliveID(column_id); const float default_t = column_index / (float)columns_count; float t = window->DC.StateStorage->GetFloat(column_id, default_t); - if (!(columns->ColumnsFlags & ImGuiColumnsFlags_NoForceWithinWindow)) - t = ImMin(t, PixelsToOffsetNorm(columns, columns->ColumnsMaxX - g.Style.ColumnsMinSpacing * (columns->ColumnsCount - column_index))); - columns->ColumnsData[column_index].OffsetNorm = t; + if (!(columns->Flags & ImGuiColumnsFlags_NoForceWithinWindow)) + t = ImMin(t, PixelsToOffsetNorm(columns, columns->MaxX - g.Style.ColumnsMinSpacing * (columns->Count - column_index))); + columns->Columns[column_index].OffsetNorm = t; } // Cache clipping rectangles @@ -11001,11 +11001,11 @@ void ImGui::BeginColumns(const char* str_id, int columns_count, ImGuiColumnsFlag { float clip_x1 = ImFloor(0.5f + window->Pos.x + GetColumnOffset(column_index) - 1.0f); float clip_x2 = ImFloor(0.5f + window->Pos.x + GetColumnOffset(column_index + 1) - 1.0f); - columns->ColumnsData[column_index].ClipRect = ImRect(clip_x1, -FLT_MAX, clip_x2, +FLT_MAX); - columns->ColumnsData[column_index].ClipRect.ClipWith(window->ClipRect); + columns->Columns[column_index].ClipRect = ImRect(clip_x1, -FLT_MAX, clip_x2, +FLT_MAX); + columns->Columns[column_index].ClipRect.ClipWith(window->ClipRect); } - window->DrawList->ChannelsSplit(columns->ColumnsCount); + window->DrawList->ChannelsSplit(columns->Count); PushColumnClipRect(); PushItemWidth(GetColumnWidth() * 0.65f); } @@ -11021,28 +11021,28 @@ void ImGui::EndColumns() PopClipRect(); window->DrawList->ChannelsMerge(); - columns->ColumnsCellMaxY = ImMax(columns->ColumnsCellMaxY, window->DC.CursorPos.y); - window->DC.CursorPos.y = columns->ColumnsCellMaxY; - if (!(columns->ColumnsFlags & ImGuiColumnsFlags_GrowParentContentsSize)) - window->DC.CursorMaxPos.x = ImMax(columns->ColumnsStartMaxPosX, columns->ColumnsMaxX); // Restore cursor max pos, as columns don't grow parent + columns->CellMaxY = ImMax(columns->CellMaxY, window->DC.CursorPos.y); + window->DC.CursorPos.y = columns->CellMaxY; + if (!(columns->Flags & ImGuiColumnsFlags_GrowParentContentsSize)) + window->DC.CursorMaxPos.x = ImMax(columns->StartMaxPosX, columns->MaxX); // Restore cursor max pos, as columns don't grow parent // Draw columns borders and handle resize - if (!(columns->ColumnsFlags & ImGuiColumnsFlags_NoBorder) && !window->SkipItems) + if (!(columns->Flags & ImGuiColumnsFlags_NoBorder) && !window->SkipItems) { - const float y1 = columns->ColumnsStartPosY; + const float y1 = columns->StartPosY; const float y2 = window->DC.CursorPos.y; int dragging_column = -1; - for (int i = 1; i < columns->ColumnsCount; i++) + for (int i = 1; i < columns->Count; i++) { float x = window->Pos.x + GetColumnOffset(i); - const ImGuiID column_id = columns->ColumnsSetId + ImGuiID(i); + const ImGuiID column_id = columns->ID + ImGuiID(i); const float column_hw = 4.0f; // Half-width for interaction const ImRect column_rect(ImVec2(x - column_hw, y1), ImVec2(x + column_hw, y2)); if (IsClippedEx(column_rect, column_id, false)) continue; bool hovered = false, held = false; - if (!(columns->ColumnsFlags & ImGuiColumnsFlags_NoResize)) + if (!(columns->Flags & ImGuiColumnsFlags_NoResize)) { ButtonBehavior(column_rect, column_id, &hovered, &held); if (hovered || held) @@ -11068,7 +11068,7 @@ void ImGui::EndColumns() } } - columns->ColumnsData.resize(0); + columns->Columns.resize(0); window->DC.ColumnsSet = NULL; window->DC.ColumnsOffsetX = 0.0f; window->DC.CursorPos.x = (float)(int)(window->Pos.x + window->DC.IndentX + window->DC.ColumnsOffsetX); @@ -11080,7 +11080,7 @@ void ImGui::Columns(int columns_count, const char* id, bool border) ImGuiWindow* window = GetCurrentWindow(); IM_ASSERT(columns_count >= 1); - if (window->DC.ColumnsSet != NULL && window->DC.ColumnsSet->ColumnsCount != columns_count) + if (window->DC.ColumnsSet != NULL && window->DC.ColumnsSet->Count != columns_count) EndColumns(); ImGuiColumnsFlags flags = (border ? 0 : ImGuiColumnsFlags_NoBorder); diff --git a/imgui_internal.h b/imgui_internal.h index 30ac9707381c..ab990e5080b0 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -421,30 +421,28 @@ struct ImGuiColumnData struct ImGuiColumnsSet { - int ColumnsCurrent; - int ColumnsCount; - float ColumnsMinX; - float ColumnsMaxX; - float ColumnsStartPosY; - float ColumnsStartMaxPosX; // Backup of CursorMaxPos - float ColumnsCellMinY; - float ColumnsCellMaxY; - ImGuiColumnsFlags ColumnsFlags; - ImGuiID ColumnsSetId; - ImVector ColumnsData; + ImGuiID ID; + ImGuiColumnsFlags Flags; + int Current; + int Count; + float MinX, MaxX; + float StartPosY; + float StartMaxPosX; // Backup of CursorMaxPos + float CellMinY, CellMaxY; + ImVector Columns; ImGuiColumnsSet() { Clear(); } void Clear() { - ColumnsCurrent = 0; - ColumnsCount = 1; - ColumnsMinX = ColumnsMaxX = 0.0f; - ColumnsStartPosY = 0.0f; - ColumnsStartMaxPosX = 0.0f; - ColumnsCellMinY = ColumnsCellMaxY = 0.0f; - ColumnsFlags = 0; - ColumnsSetId = 0; - ColumnsData.clear(); + ID = 0; + Flags = 0; + Current = 0; + Count = 1; + MinX = MaxX = 0.0f; + StartPosY = 0.0f; + StartMaxPosX = 0.0f; + CellMinY = CellMaxY = 0.0f; + Columns.clear(); } }; From b016215c80f64fef17b8aaad843167c3c8d3855b Mon Sep 17 00:00:00 2001 From: omar Date: Wed, 13 Dec 2017 19:07:09 +0100 Subject: [PATCH 299/823] Columns: Refactor: Not using statestorage lookup anymore. (#125, #1499) --- imgui.cpp | 71 +++++++++++++++++++++++++----------------------- imgui_internal.h | 5 ++-- 2 files changed, 40 insertions(+), 36 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 38af186694ba..e12e6ea641ab 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -10847,9 +10847,9 @@ static float GetDraggedColumnOffset(ImGuiColumnsSet* columns, int column_index) IM_ASSERT(g.ActiveId == columns->ID + ImGuiID(column_index)); float x = g.IO.MousePos.x - g.ActiveIdClickOffset.x - window->Pos.x; - x = ImMax(x, ImGui::GetColumnOffset(column_index-1) + g.Style.ColumnsMinSpacing); + x = ImMax(x, ImGui::GetColumnOffset(column_index - 1) + g.Style.ColumnsMinSpacing); if ((columns->Flags & ImGuiColumnsFlags_NoPreserveWidths)) - x = ImMin(x, ImGui::GetColumnOffset(column_index+1) - g.Style.ColumnsMinSpacing); + x = ImMin(x, ImGui::GetColumnOffset(column_index + 1) - g.Style.ColumnsMinSpacing); return x; } @@ -10862,6 +10862,7 @@ float ImGui::GetColumnOffset(int column_index) if (column_index < 0) column_index = columns->Current; + IM_ASSERT(column_index < columns->Columns.Size); /* if (g.ActiveId) @@ -10873,7 +10874,6 @@ float ImGui::GetColumnOffset(int column_index) } */ - IM_ASSERT(column_index < columns->Columns.Size); const float t = columns->Columns[column_index].OffsetNorm; const float x_offset = ImLerp(columns->MinX, columns->MaxX, t); return x_offset; @@ -10888,7 +10888,6 @@ void ImGui::SetColumnOffset(int column_index, float offset) if (column_index < 0) column_index = columns->Current; - IM_ASSERT(column_index < columns->Columns.Size); const bool preserve_width = !(columns->Flags & ImGuiColumnsFlags_NoPreserveWidths) && (column_index < columns->Count-1); @@ -10896,11 +10895,7 @@ void ImGui::SetColumnOffset(int column_index, float offset) if (!(columns->Flags & ImGuiColumnsFlags_NoForceWithinWindow)) offset = ImMin(offset, columns->MaxX - g.Style.ColumnsMinSpacing * (columns->Count - column_index)); - const float offset_norm = PixelsToOffsetNorm(columns, offset); - - const ImGuiID column_id = columns->ID + ImGuiID(column_index); - window->DC.StateStorage->SetFloat(column_id, offset_norm); - columns->Columns[column_index].OffsetNorm = offset_norm; + columns->Columns[column_index].OffsetNorm = PixelsToOffsetNorm(columns, offset); if (preserve_width) SetColumnOffset(column_index + 1, offset + ImMax(g.Style.ColumnsMinSpacing, width)); @@ -10925,7 +10920,7 @@ void ImGui::SetColumnWidth(int column_index, float width) if (column_index < 0) column_index = columns->Current; - SetColumnOffset(column_index+1, GetColumnOffset(column_index) + width); + SetColumnOffset(column_index + 1, GetColumnOffset(column_index) + width); } void ImGui::PushColumnClipRect(int column_index) @@ -10964,15 +10959,15 @@ void ImGui::BeginColumns(const char* str_id, int columns_count, ImGuiColumnsFlag ImGuiID id = window->GetID(str_id ? str_id : "columns"); PopID(); + // Acquire storage for the columns set ImGuiColumnsSet* columns = FindOrAddColumnsSet(window, id); IM_ASSERT(columns->ID == id); - window->DC.ColumnsSet = columns; - - // Set state for first column columns->Current = 0; columns->Count = columns_count; columns->Flags = flags; + window->DC.ColumnsSet = columns; + // Set state for first column const float content_region_width = (window->SizeContentsExplicit.x != 0.0f) ? (window->SizeContentsExplicit.x) : (window->Size.x -window->ScrollbarSizes.x); columns->MinX = window->DC.IndentX - g.Style.ItemSpacing.x; // Lock our horizontal range //column->ColumnsMaxX = content_region_width - window->Scroll.x -((window->Flags & ImGuiWindowFlags_NoScrollbar) ? 0 : g.Style.ScrollbarSize);// - window->WindowPadding().x; @@ -10983,26 +10978,36 @@ void ImGui::BeginColumns(const char* str_id, int columns_count, ImGuiColumnsFlag window->DC.ColumnsOffsetX = 0.0f; window->DC.CursorPos.x = (float)(int)(window->Pos.x + window->DC.IndentX + window->DC.ColumnsOffsetX); - // Cache column offsets - columns->Columns.resize(columns_count + 1); - for (int column_index = 0; column_index < columns_count + 1; column_index++) + // Initialize defaults + if (columns->Columns.Size == 0) { - const ImGuiID column_id = columns->ID + ImGuiID(column_index); - KeepAliveID(column_id); - const float default_t = column_index / (float)columns_count; - float t = window->DC.StateStorage->GetFloat(column_id, default_t); - if (!(columns->Flags & ImGuiColumnsFlags_NoForceWithinWindow)) - t = ImMin(t, PixelsToOffsetNorm(columns, columns->MaxX - g.Style.ColumnsMinSpacing * (columns->Count - column_index))); - columns->Columns[column_index].OffsetNorm = t; + columns->Columns.reserve(columns_count + 1); + for (int n = 0; n < columns_count + 1; n++) + { + ImGuiColumnData column; + column.OffsetNorm = n / (float)columns_count; + columns->Columns.push_back(column); + } } + IM_ASSERT(columns->Columns.Size == columns_count + 1); - // Cache clipping rectangles - for (int column_index = 0; column_index < columns_count; column_index++) + for (int n = 0; n < columns_count + 1; n++) { - float clip_x1 = ImFloor(0.5f + window->Pos.x + GetColumnOffset(column_index) - 1.0f); - float clip_x2 = ImFloor(0.5f + window->Pos.x + GetColumnOffset(column_index + 1) - 1.0f); - columns->Columns[column_index].ClipRect = ImRect(clip_x1, -FLT_MAX, clip_x2, +FLT_MAX); - columns->Columns[column_index].ClipRect.ClipWith(window->ClipRect); + // Clamp + ImGuiColumnData* column = &columns->Columns[n]; + float t = column->OffsetNorm; + if (!(columns->Flags & ImGuiColumnsFlags_NoForceWithinWindow)) + t = ImMin(t, PixelsToOffsetNorm(columns, columns->MaxX - g.Style.ColumnsMinSpacing * (columns->Count - n))); + column->OffsetNorm = t; + + if (n == columns_count) + continue; + + // Compute clipping rectangles + float clip_x1 = ImFloor(0.5f + window->Pos.x + GetColumnOffset(n) - 1.0f); + float clip_x2 = ImFloor(0.5f + window->Pos.x + GetColumnOffset(n + 1) - 1.0f); + column->ClipRect = ImRect(clip_x1, -FLT_MAX, clip_x2, +FLT_MAX); + column->ClipRect.ClipWith(window->ClipRect); } window->DrawList->ChannelsSplit(columns->Count); @@ -11038,6 +11043,7 @@ void ImGui::EndColumns() const ImGuiID column_id = columns->ID + ImGuiID(i); const float column_hw = 4.0f; // Half-width for interaction const ImRect column_rect(ImVec2(x - column_hw, y1), ImVec2(x + column_hw, y2)); + KeepAliveID(column_id); if (IsClippedEx(column_rect, column_id, false)) continue; @@ -11053,8 +11059,7 @@ void ImGui::EndColumns() dragging_column = i; } - // Draw column - // We clip the Y boundaries CPU side because very long triangles are mishandled by some GPU drivers. + // Draw column (we clip the Y boundaries CPU side because very long triangles are mishandled by some GPU drivers.) const ImU32 col = GetColorU32(held ? ImGuiCol_SeparatorActive : hovered ? ImGuiCol_SeparatorHovered : ImGuiCol_Separator); const float xi = (float)(int)x; window->DrawList->AddLine(ImVec2(xi, ImMax(y1 + 1.0f, window->ClipRect.Min.y)), ImVec2(xi, ImMin(y2, window->ClipRect.Max.y)), col); @@ -11068,18 +11073,16 @@ void ImGui::EndColumns() } } - columns->Columns.resize(0); window->DC.ColumnsSet = NULL; window->DC.ColumnsOffsetX = 0.0f; window->DC.CursorPos.x = (float)(int)(window->Pos.x + window->DC.IndentX + window->DC.ColumnsOffsetX); } -// [2017/08: This is currently the only public API, while we are working on making BeginColumns/EndColumns user-facing] +// [2017/12: This is currently the only public API, while we are working on making BeginColumns/EndColumns user-facing] void ImGui::Columns(int columns_count, const char* id, bool border) { ImGuiWindow* window = GetCurrentWindow(); IM_ASSERT(columns_count >= 1); - if (window->DC.ColumnsSet != NULL && window->DC.ColumnsSet->Count != columns_count) EndColumns(); diff --git a/imgui_internal.h b/imgui_internal.h index ab990e5080b0..e2975ecee63e 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -412,11 +412,12 @@ struct ImGuiPopupRef ImGuiPopupRef(ImGuiID id, ImGuiWindow* parent_window, ImGuiID parent_menu_set, const ImVec2& mouse_pos) { PopupId = id; Window = NULL; ParentWindow = parent_window; ParentMenuSet = parent_menu_set; MousePosOnOpen = mouse_pos; } }; -// Per column data for Columns() struct ImGuiColumnData { - float OffsetNorm; // Column start offset, normalized 0.0 (far left) -> 1.0 (far right) + float OffsetNorm; // Column start offset, normalized 0.0 (far left) -> 1.0 (far right) ImRect ClipRect; + + ImGuiColumnData() { OffsetNorm = 0.0f; } }; struct ImGuiColumnsSet From 4ae5c7e22716a4f1d0555b7f317d5850052506fa Mon Sep 17 00:00:00 2001 From: omar Date: Wed, 13 Dec 2017 19:21:21 +0100 Subject: [PATCH 300/823] Columns: Refactor: Moved ColumnsSet[] to window out of DC as they are persistent data for most + fix for pre C++11 compilers. (#125, #1499) --- imgui.cpp | 10 +++++----- imgui_internal.h | 20 ++++++++++---------- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index e12e6ea641ab..e28b99393e62 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -10935,12 +10935,12 @@ void ImGui::PushColumnClipRect(int column_index) static ImGuiColumnsSet* FindOrAddColumnsSet(ImGuiWindow* window, ImGuiID id) { - for (int n = 0; n < window->DC.ColumnsSets.Size; n++) - if (window->DC.ColumnsSets[n].ID == id) - return &window->DC.ColumnsSets[n]; + for (int n = 0; n < window->ColumnsStorage.Size; n++) + if (window->ColumnsStorage[n].ID == id) + return &window->ColumnsStorage[n]; - window->DC.ColumnsSets.push_back(ImGuiColumnsSet()); - ImGuiColumnsSet* columns = &window->DC.ColumnsSets.back(); + window->ColumnsStorage.push_back(ImGuiColumnsSet()); + ImGuiColumnsSet* columns = &window->ColumnsStorage.back(); columns->ID = id; return columns; } diff --git a/imgui_internal.h b/imgui_internal.h index e2975ecee63e..f79f46b10082 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -201,7 +201,7 @@ enum ImGuiColumnsFlags_ ImGuiColumnsFlags_NoResize = 1 << 1, // Disable resizing columns when clicking on the dividers ImGuiColumnsFlags_NoPreserveWidths = 1 << 2, // Disable column width preservation when adjusting columns ImGuiColumnsFlags_NoForceWithinWindow = 1 << 3, // Disable forcing columns to fit within window - ImGuiColumnsFlags_GrowParentContentsSize= 1 << 4, // (WIP) Restore pre-1.51 behavior of extending the parent window contents size but _without affecting the columns width at all_. Will eventually remove. + ImGuiColumnsFlags_GrowParentContentsSize= 1 << 4 // (WIP) Restore pre-1.51 behavior of extending the parent window contents size but _without affecting the columns width at all_. Will eventually remove. }; enum ImGuiSelectableFlagsPrivate_ @@ -403,19 +403,19 @@ struct ImGuiMouseCursorData // Storage for current popup stack struct ImGuiPopupRef { - ImGuiID PopupId; // Set on OpenPopup() - ImGuiWindow* Window; // Resolved on BeginPopup() - may stay unresolved if user never calls OpenPopup() - ImGuiWindow* ParentWindow; // Set on OpenPopup() - ImGuiID ParentMenuSet; // Set on OpenPopup() - ImVec2 MousePosOnOpen; // Copy of mouse position at the time of opening popup + ImGuiID PopupId; // Set on OpenPopup() + ImGuiWindow* Window; // Resolved on BeginPopup() - may stay unresolved if user never calls OpenPopup() + ImGuiWindow* ParentWindow; // Set on OpenPopup() + ImGuiID ParentMenuSet; // Set on OpenPopup() + ImVec2 MousePosOnOpen; // Copy of mouse position at the time of opening popup ImGuiPopupRef(ImGuiID id, ImGuiWindow* parent_window, ImGuiID parent_menu_set, const ImVec2& mouse_pos) { PopupId = id; Window = NULL; ParentWindow = parent_window; ParentMenuSet = parent_menu_set; MousePosOnOpen = mouse_pos; } }; struct ImGuiColumnData { - float OffsetNorm; // Column start offset, normalized 0.0 (far left) -> 1.0 (far right) - ImRect ClipRect; + float OffsetNorm; // Column start offset, normalized 0.0 (far left) -> 1.0 (far right) + ImRect ClipRect; ImGuiColumnData() { OffsetNorm = 0.0f; } }; @@ -701,8 +701,7 @@ struct IMGUI_API ImGuiDrawContext float IndentX; // Indentation / start position from left of window (increased by TreePush/TreePop, etc.) float GroupOffsetX; float ColumnsOffsetX; // Offset to the current column (if ColumnsCurrent > 0). FIXME: This and the above should be a stack to allow use cases like Tree->Column->Tree. Need revamp columns API. - ImGuiColumnsSet* ColumnsSet; - ImVector ColumnsSets; + ImGuiColumnsSet* ColumnsSet; // Current columns set ImGuiDrawContext() { @@ -784,6 +783,7 @@ struct IMGUI_API ImGuiWindow float ItemWidthDefault; ImGuiSimpleColumns MenuColumns; // Simplified columns storage for menu items ImGuiStorage StateStorage; + ImVector ColumnsStorage; float FontWindowScale; // Scale multiplier per-window ImDrawList* DrawList; ImGuiWindow* ParentWindow; // If we are a child _or_ popup window, this is pointing to our parent. Otherwise NULL. From e8e84a6ad68c339f3e1c537069655b6d228b7eae Mon Sep 17 00:00:00 2001 From: omar Date: Wed, 13 Dec 2017 19:26:04 +0100 Subject: [PATCH 301/823] Columns: Added internal tracking of a few flag temporarily, to facilitate the work of third-parties who have columns patches. (#125) --- imgui.cpp | 3 +++ imgui_internal.h | 4 ++++ 2 files changed, 7 insertions(+) diff --git a/imgui.cpp b/imgui.cpp index e28b99393e62..bd6282255860 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -10979,6 +10979,7 @@ void ImGui::BeginColumns(const char* str_id, int columns_count, ImGuiColumnsFlag window->DC.CursorPos.x = (float)(int)(window->Pos.x + window->DC.IndentX + window->DC.ColumnsOffsetX); // Initialize defaults + columns->IsFirstFrame = (columns->Columns.Size == 0); if (columns->Columns.Size == 0) { columns->Columns.reserve(columns_count + 1); @@ -11032,6 +11033,7 @@ void ImGui::EndColumns() window->DC.CursorMaxPos.x = ImMax(columns->StartMaxPosX, columns->MaxX); // Restore cursor max pos, as columns don't grow parent // Draw columns borders and handle resize + columns->IsBeingResized = false; if (!(columns->Flags & ImGuiColumnsFlags_NoBorder) && !window->SkipItems) { const float y1 = columns->StartPosY; @@ -11070,6 +11072,7 @@ void ImGui::EndColumns() { float x = GetDraggedColumnOffset(columns, dragging_column); SetColumnOffset(dragging_column, x); + columns->IsBeingResized = true; } } diff --git a/imgui_internal.h b/imgui_internal.h index f79f46b10082..ca1086b9167d 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -424,6 +424,8 @@ struct ImGuiColumnsSet { ImGuiID ID; ImGuiColumnsFlags Flags; + bool IsFirstFrame; + bool IsBeingResized; int Current; int Count; float MinX, MaxX; @@ -437,6 +439,8 @@ struct ImGuiColumnsSet { ID = 0; Flags = 0; + IsFirstFrame = false; + IsBeingResized = false; Current = 0; Count = 1; MinX = MaxX = 0.0f; From f7c5f420e7e87dd420a553eac5c2a1e55904d3ec Mon Sep 17 00:00:00 2001 From: omar Date: Wed, 13 Dec 2017 19:44:54 +0100 Subject: [PATCH 302/823] BeginChild() fix using negative sizes as window position because of erroneous clamping. It was hard to notice until we added asserts for it. (#1500) --- imgui.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index bd6282255860..0055b05f0574 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -3953,9 +3953,9 @@ static bool BeginChildEx(const char* name, ImGuiID id, const ImVec2& size_arg, b ImVec2 size = ImFloor(size_arg); const int auto_fit_axises = ((size.x == 0.0f) ? (1 << ImGuiAxis_X) : 0x00) | ((size.y == 0.0f) ? (1 << ImGuiAxis_Y) : 0x00); if (size.x <= 0.0f) - size.x = ImMax(content_avail.x, 4.0f) - fabsf(size.x); // Arbitrary minimum zero-ish child size of 4.0f (0.0f causing too much issues) + size.x = ImMax(content_avail.x + size.x, 4.0f); // Arbitrary minimum child size (0.0f causing too much issues) if (size.y <= 0.0f) - size.y = ImMax(content_avail.y, 4.0f) - fabsf(size.y); + size.y = ImMax(content_avail.y + size.y, 4.0f); const float backup_border_size = g.Style.ChildBorderSize; if (!border) From ba71e1c0e4afab77f263d2b5c5a445e85bca87a2 Mon Sep 17 00:00:00 2001 From: omar Date: Wed, 13 Dec 2017 21:48:56 +0100 Subject: [PATCH 303/823] Columns: Minor stylistic fixes. (#125) --- imgui.cpp | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 0055b05f0574..91b777734890 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -10879,6 +10879,17 @@ float ImGui::GetColumnOffset(int column_index) return x_offset; } +float ImGui::GetColumnWidth(int column_index) +{ + ImGuiWindow* window = GetCurrentWindowRead(); + ImGuiColumnsSet* columns = window->DC.ColumnsSet; + IM_ASSERT(columns != NULL); + + if (column_index < 0) + column_index = columns->Current; + return OffsetNormToPixels(columns, columns->Columns[column_index + 1].OffsetNorm - columns->Columns[column_index].OffsetNorm); +} + void ImGui::SetColumnOffset(int column_index, float offset) { ImGuiContext& g = *GImGui; @@ -10901,17 +10912,6 @@ void ImGui::SetColumnOffset(int column_index, float offset) SetColumnOffset(column_index + 1, offset + ImMax(g.Style.ColumnsMinSpacing, width)); } -float ImGui::GetColumnWidth(int column_index) -{ - ImGuiWindow* window = GetCurrentWindowRead(); - ImGuiColumnsSet* columns = window->DC.ColumnsSet; - IM_ASSERT(columns != NULL); - - if (column_index < 0) - column_index = columns->Current; - return OffsetNormToPixels(columns, columns->Columns[column_index+1].OffsetNorm - columns->Columns[column_index].OffsetNorm); -} - void ImGui::SetColumnWidth(int column_index, float width) { ImGuiWindow* window = GetCurrentWindowRead(); @@ -11039,10 +11039,10 @@ void ImGui::EndColumns() const float y1 = columns->StartPosY; const float y2 = window->DC.CursorPos.y; int dragging_column = -1; - for (int i = 1; i < columns->Count; i++) + for (int n = 1; n < columns->Count; n++) { - float x = window->Pos.x + GetColumnOffset(i); - const ImGuiID column_id = columns->ID + ImGuiID(i); + float x = window->Pos.x + GetColumnOffset(n); + const ImGuiID column_id = columns->ID + ImGuiID(n); const float column_hw = 4.0f; // Half-width for interaction const ImRect column_rect(ImVec2(x - column_hw, y1), ImVec2(x + column_hw, y2)); KeepAliveID(column_id); @@ -11058,7 +11058,7 @@ void ImGui::EndColumns() if (held && g.ActiveIdIsJustActivated) g.ActiveIdClickOffset.x -= column_hw; // Store from center of column line (we used a 8 wide rect for columns clicking). This is used by GetDraggedColumnOffset(). if (held) - dragging_column = i; + dragging_column = n; } // Draw column (we clip the Y boundaries CPU side because very long triangles are mishandled by some GPU drivers.) From ddbcda8c1bc6987d0adae2ac9bc7a1aad14c10f0 Mon Sep 17 00:00:00 2001 From: omar Date: Wed, 13 Dec 2017 21:51:23 +0100 Subject: [PATCH 304/823] Columns: Column width data is no longer lost while dragging toward the right side. (#1499, #125) --- imgui.cpp | 23 ++++++++++++++++++++--- imgui_internal.h | 5 +++-- 2 files changed, 23 insertions(+), 5 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 91b777734890..cf21d0e982da 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -10879,6 +10879,19 @@ float ImGui::GetColumnOffset(int column_index) return x_offset; } +static float GetColumnWidthEx(ImGuiColumnsSet* columns, int column_index, bool before_resize = false) +{ + if (column_index < 0) + column_index = columns->Current; + + float offset_norm; + if (before_resize) + offset_norm = columns->Columns[column_index + 1].OffsetNormBeforeResize - columns->Columns[column_index].OffsetNormBeforeResize; + else + offset_norm = columns->Columns[column_index + 1].OffsetNorm - columns->Columns[column_index].OffsetNorm; + return OffsetNormToPixels(columns, offset_norm); +} + float ImGui::GetColumnWidth(int column_index) { ImGuiWindow* window = GetCurrentWindowRead(); @@ -10902,7 +10915,7 @@ void ImGui::SetColumnOffset(int column_index, float offset) IM_ASSERT(column_index < columns->Columns.Size); const bool preserve_width = !(columns->Flags & ImGuiColumnsFlags_NoPreserveWidths) && (column_index < columns->Count-1); - const float width = preserve_width ? GetColumnWidth(column_index) : 0.0f; + const float width = preserve_width ? GetColumnWidthEx(columns, column_index, columns->IsBeingResized) : 0.0f; if (!(columns->Flags & ImGuiColumnsFlags_NoForceWithinWindow)) offset = ImMin(offset, columns->MaxX - g.Style.ColumnsMinSpacing * (columns->Count - column_index)); @@ -11033,7 +11046,7 @@ void ImGui::EndColumns() window->DC.CursorMaxPos.x = ImMax(columns->StartMaxPosX, columns->MaxX); // Restore cursor max pos, as columns don't grow parent // Draw columns borders and handle resize - columns->IsBeingResized = false; + bool is_being_resized = false; if (!(columns->Flags & ImGuiColumnsFlags_NoBorder) && !window->SkipItems) { const float y1 = columns->StartPosY; @@ -11070,11 +11083,15 @@ void ImGui::EndColumns() // Apply dragging after drawing the column lines, so our rendered lines are in sync with how items were displayed during the frame. if (dragging_column != -1) { + if (!columns->IsBeingResized) + for (int n = 0; n < columns->Count + 1; n++) + columns->Columns[n].OffsetNormBeforeResize = columns->Columns[n].OffsetNorm; + columns->IsBeingResized = is_being_resized = true; float x = GetDraggedColumnOffset(columns, dragging_column); SetColumnOffset(dragging_column, x); - columns->IsBeingResized = true; } } + columns->IsBeingResized = is_being_resized; window->DC.ColumnsSet = NULL; window->DC.ColumnsOffsetX = 0.0f; diff --git a/imgui_internal.h b/imgui_internal.h index ca1086b9167d..f0d598b49c60 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -414,10 +414,11 @@ struct ImGuiPopupRef struct ImGuiColumnData { - float OffsetNorm; // Column start offset, normalized 0.0 (far left) -> 1.0 (far right) + float OffsetNorm; // Column start offset, normalized 0.0 (far left) -> 1.0 (far right) + float OffsetNormBeforeResize; ImRect ClipRect; - ImGuiColumnData() { OffsetNorm = 0.0f; } + ImGuiColumnData() { OffsetNorm = OffsetNormBeforeResize = 0.0f; } }; struct ImGuiColumnsSet From 39058160825eff27d0e39a2c0d56b11bcec9f09e Mon Sep 17 00:00:00 2001 From: omar Date: Wed, 13 Dec 2017 21:59:16 +0100 Subject: [PATCH 305/823] Added ShowFontSelector(), ShowStyleSelector(). (#707) --- imgui.h | 4 +++- imgui_demo.cpp | 49 +++++++++++++++++++++++++++++++++++++------------ 2 files changed, 40 insertions(+), 13 deletions(-) diff --git a/imgui.h b/imgui.h index 52a0239feea6..c05d92c6e74c 100644 --- a/imgui.h +++ b/imgui.h @@ -133,10 +133,12 @@ namespace ImGui IMGUI_API void EndFrame(); // ends the ImGui frame. automatically called by Render(), so most likely don't need to ever call that yourself directly. If you don't need to render you may call EndFrame() but you'll have wasted CPU already. If you don't need to render, better to not create any imgui windows instead! IMGUI_API void Shutdown(); - // Demo/Debug/Info + // Demo, Debug, Informations IMGUI_API void ShowTestWindow(bool* p_open = NULL); // create demo/test window. demonstrate most ImGui features. call this to learn about the library! try to make it always available in your application! IMGUI_API void ShowMetricsWindow(bool* p_open = NULL); // create metrics window. display ImGui internals: draw commands (with individual draw calls and vertices), window list, basic internal state, etc. IMGUI_API void ShowStyleEditor(ImGuiStyle* ref = NULL); // add style editor block (not a window). you can pass in a reference ImGuiStyle structure to compare to, revert to and save to (else it uses the default style) + IMGUI_API bool ShowStyleSelector(const char* label); + IMGUI_API void ShowFontSelector(const char* label); IMGUI_API void ShowUserGuide(); // add basic help/info block (not a window): how to manipulate ImGui as a end-user (mouse/keyboard controls). // Window diff --git a/imgui_demo.cpp b/imgui_demo.cpp index f45a85826f7d..50aecce9af91 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -1903,6 +1903,41 @@ void ImGui::ShowTestWindow(bool* p_open) ImGui::End(); } +bool ImGui::ShowStyleSelector(const char* label) +{ + static int style_idx = 0; + if (ImGui::Combo(label, &style_idx, "Classic\0Dark\0Light\0")) + { + switch (style_idx) + { + case 0: ImGui::StyleColorsClassic(); break; + case 1: ImGui::StyleColorsDark(); break; + case 2: ImGui::StyleColorsLight(); break; + } + return true; + } + return false; +} + +void ImGui::ShowFontSelector(const char* label) +{ + ImGuiIO& io = ImGui::GetIO(); + ImFont* font_current = ImGui::GetFont(); + if (ImGui::BeginCombo(label, font_current->GetDebugName())) + { + for (int n = 0; n < io.Fonts->Fonts.Size; n++) + if (ImGui::Selectable(io.Fonts->Fonts[n]->GetDebugName(), io.Fonts->Fonts[n] == font_current)) + io.FontDefault = io.Fonts->Fonts[n]; + ImGui::EndCombo(); + } + ImGui::SameLine(); + ShowHelpMarker( + "- Load additional fonts with io.Fonts->AddFontFromFileTTF().\n" + "- The font atlas is built when calling io.Fonts->GetTexDataAsXXXX() or io.Fonts->Build().\n" + "- Read FAQ and documentation in extra_fonts/ for more details.\n" + "- If you need to add/remove fonts at runtime (e.g. for DPI change), do it before calling NewFrame()."); +} + void ImGui::ShowStyleEditor(ImGuiStyle* ref) { // You can pass in a reference ImGuiStyle structure to compare to, revert to and save to (else it compares to an internally stored reference) @@ -1919,18 +1954,9 @@ void ImGui::ShowStyleEditor(ImGuiStyle* ref) ImGui::PushItemWidth(ImGui::GetWindowWidth() * 0.50f); - // Default Styles Selector - static int style_idx = 0; - if (ImGui::Combo("Colors##Selector", &style_idx, "Classic\0Dark\0Light\0")) - { - switch (style_idx) - { - case 0: ImGui::StyleColorsClassic(); break; - case 1: ImGui::StyleColorsDark(); break; - case 2: ImGui::StyleColorsLight(); break; - } + if (ImGui::ShowStyleSelector("Colors##Selector")) ref_saved_style = style; - } + ImGui::ShowFontSelector("Fonts##Selector"); // Simplified Settings if (ImGui::SliderFloat("FrameRounding", &style.FrameRounding, 0.0f, 12.0f, "%.0f")) @@ -2050,7 +2076,6 @@ void ImGui::ShowStyleEditor(ImGuiStyle* ref) } bool fonts_opened = ImGui::TreeNode("Fonts", "Fonts (%d)", ImGui::GetIO().Fonts->Fonts.Size); - ImGui::SameLine(); ShowHelpMarker("Tip: Load fonts with io.Fonts->AddFontFromFileTTF()\nbefore calling io.Fonts->GetTex* functions."); if (fonts_opened) { ImFontAtlas* atlas = ImGui::GetIO().Fonts; From f265e16b840f3352fc54f0d3a03bfb5bfd1b8b17 Mon Sep 17 00:00:00 2001 From: omar Date: Wed, 13 Dec 2017 22:05:48 +0100 Subject: [PATCH 306/823] Revert "Scrollbar: Minor simplication of the code using InnerRect data." > Introduced sheering on the scrollbar rectangle because InnerRect isn't setup at this point. This reverts commit 7ac1583411095fe8a82ccbc56d09777f87222e9d. --- imgui.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index cf21d0e982da..69f04d8c00dd 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -5021,8 +5021,10 @@ void ImGui::Scrollbar(ImGuiLayoutType direction) const ImRect window_rect = window->Rect(); const float border_size = window->WindowBorderSize; ImRect bb = horizontal - ? ImRect(window->InnerRect.Min.x, window_rect.Max.y - style.ScrollbarSize, window->InnerRect.Max.x, window_rect.Max.y - border_size) - : ImRect(window_rect.Max.x - style.ScrollbarSize, window->InnerRect.Min.y, window_rect.Max.x - border_size, window->InnerRect.Max.y); + ? ImRect(window->Pos.x + border_size, window_rect.Max.y - style.ScrollbarSize, window_rect.Max.x - other_scrollbar_size_w - border_size, window_rect.Max.y - border_size) + : ImRect(window_rect.Max.x - style.ScrollbarSize, window->Pos.y + border_size, window_rect.Max.x - border_size, window_rect.Max.y - other_scrollbar_size_w - border_size); + if (!horizontal) + bb.Min.y += window->TitleBarHeight() + ((window->Flags & ImGuiWindowFlags_MenuBar) ? window->MenuBarHeight() : 0.0f); if (bb.GetWidth() <= 0.0f || bb.GetHeight() <= 0.0f) return; From 5f397582025e3559b19c16a432a068020bc459b2 Mon Sep 17 00:00:00 2001 From: omar Date: Wed, 13 Dec 2017 22:21:49 +0100 Subject: [PATCH 307/823] Minor tweaks, comments, spacing fixes --- imgui.h | 54 +++++++++++++++++++++++++++--------------------------- 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/imgui.h b/imgui.h index c05d92c6e74c..bbbeaef46df3 100644 --- a/imgui.h +++ b/imgui.h @@ -367,7 +367,7 @@ namespace ImGui IMGUI_API void TreePop(); // ~ Unindent()+PopId() IMGUI_API void TreeAdvanceToLabelPos(); // advance cursor x position by GetTreeNodeToLabelSpacing() IMGUI_API float GetTreeNodeToLabelSpacing(); // horizontal distance preceding label when using TreeNode*() or Bullet() == (g.FontSize + style.FramePadding.x*2) for a regular unframed TreeNode - IMGUI_API void SetNextTreeNodeOpen(bool is_open, ImGuiCond cond = 0); // set next TreeNode/CollapsingHeader open state. + IMGUI_API void SetNextTreeNodeOpen(bool is_open, ImGuiCond cond = 0); // set next TreeNode/CollapsingHeader open state. IMGUI_API bool CollapsingHeader(const char* label, ImGuiTreeNodeFlags flags = 0); // if returning 'true' the header is open. doesn't indent nor push on ID stack. user doesn't have to call TreePop(). IMGUI_API bool CollapsingHeader(const char* label, bool* p_open, ImGuiTreeNodeFlags flags = 0); // when 'p_open' isn't NULL, display an additional small close button on upper right of the header @@ -376,9 +376,9 @@ namespace ImGui IMGUI_API bool Selectable(const char* label, bool* p_selected, ImGuiSelectableFlags flags = 0, const ImVec2& size = ImVec2(0,0)); IMGUI_API bool ListBox(const char* label, int* current_item, const char* const* items, int items_count, int height_in_items = -1); IMGUI_API bool ListBox(const char* label, int* current_item, bool (*items_getter)(void* data, int idx, const char** out_text), void* data, int items_count, int height_in_items = -1); - IMGUI_API bool ListBoxHeader(const char* label, const ImVec2& size = ImVec2(0,0)); // use if you want to reimplement ListBox() will custom data or interactions. make sure to call ListBoxFooter() afterwards. + IMGUI_API bool ListBoxHeader(const char* label, const ImVec2& size = ImVec2(0,0)); // use if you want to reimplement ListBox() will custom data or interactions. make sure to call ListBoxFooter() afterwards. IMGUI_API bool ListBoxHeader(const char* label, int items_count, int height_in_items = -1); // " - IMGUI_API void ListBoxFooter(); // terminate the scrolling region + IMGUI_API void ListBoxFooter(); // terminate the scrolling region // Widgets: Value() Helpers. Output single value in "name: value" format (tip: freely declare more in your code to handle your types. you can add functions to the ImGui namespace) IMGUI_API void Value(const char* prefix, bool b); @@ -424,11 +424,11 @@ namespace ImGui // Drag and Drop // [BETA API] Missing Demo code. API may evolve. - IMGUI_API bool BeginDragDropSource(ImGuiDragDropFlags flags = 0, int mouse_button = 0); // Call when the current item is active. If this return true, you can call SetDragDropPayload() + EndDragDropSource() - IMGUI_API bool SetDragDropPayload(const char* type, const void* data, size_t data_size, ImGuiCond cond = 0); // Type is a user defined string of maximum 8 characters. Strings starting with '_' are reserved for dear imgui internal types. Data is copied and held by imgui. + IMGUI_API bool BeginDragDropSource(ImGuiDragDropFlags flags = 0, int mouse_button = 0); // call when the current item is active. If this return true, you can call SetDragDropPayload() + EndDragDropSource() + IMGUI_API bool SetDragDropPayload(const char* type, const void* data, size_t size, ImGuiCond cond = 0);// type is a user defined string of maximum 8 characters. Strings starting with '_' are reserved for dear imgui internal types. Data is copied and held by imgui. IMGUI_API void EndDragDropSource(); - IMGUI_API bool BeginDragDropTarget(); // Call after submitting an item that may receive an item. If this returns true, you can call AcceptDragDropPayload() + EndDragDropTarget() - IMGUI_API const ImGuiPayload* AcceptDragDropPayload(const char* type, ImGuiDragDropFlags flags = 0); // Accept contents of a given type. If ImGuiDragDropFlags_AcceptBeforeDelivery is set you can peek into the payload before the mouse button is released. + IMGUI_API bool BeginDragDropTarget(); // call after submitting an item that may receive an item. If this returns true, you can call AcceptDragDropPayload() + EndDragDropTarget() + IMGUI_API const ImGuiPayload* AcceptDragDropPayload(const char* type, ImGuiDragDropFlags flags = 0); // accept contents of a given type. If ImGuiDragDropFlags_AcceptBeforeDelivery is set you can peek into the payload before the mouse button is released. IMGUI_API void EndDragDropTarget(); // Clipping @@ -447,15 +447,15 @@ namespace ImGui IMGUI_API void SetKeyboardFocusHere(int offset = 0); // focus keyboard on the next widget. Use positive 'offset' to access sub components of a multiple component widget. Use -1 to access previous widget. // Utilities - IMGUI_API bool IsItemHovered(ImGuiHoveredFlags flags = 0); // is the last item hovered by mouse (and usable)? + IMGUI_API bool IsItemHovered(ImGuiHoveredFlags flags = 0); // is the last item hovered? (and usable, aka not blocked by a popup, etc.). See ImGuiHoveredFlags for more options. IMGUI_API bool IsItemActive(); // is the last item active? (e.g. button being held, text field being edited- items that don't interact will always return false) IMGUI_API bool IsItemClicked(int mouse_button = 0); // is the last item clicked? (e.g. button/node just clicked on) IMGUI_API bool IsItemVisible(); // is the last item visible? (aka not out of sight due to clipping/scrolling.) IMGUI_API bool IsAnyItemHovered(); IMGUI_API bool IsAnyItemActive(); - IMGUI_API ImVec2 GetItemRectMin(); // get bounding rect of last item in screen space + IMGUI_API ImVec2 GetItemRectMin(); // get bounding rectangle of last item, in screen space IMGUI_API ImVec2 GetItemRectMax(); // " - IMGUI_API ImVec2 GetItemRectSize(); // " + IMGUI_API ImVec2 GetItemRectSize(); // get size of last item, in screen space IMGUI_API void SetItemAllowOverlap(); // allow last item to be overlapped by a subsequent item. sometimes useful with invisible buttons, selectables, etc. to catch unused area. IMGUI_API bool IsWindowFocused(ImGuiFocusedFlags flags = 0); // is current window focused? or its root/child, depending on flags. see flags for options. IMGUI_API bool IsWindowHovered(ImGuiHoveredFlags flags = 0); // is current window hovered (and typically: not blocked by a popup/modal)? see flags for options. @@ -648,7 +648,7 @@ enum ImGuiDragDropFlags_ ImGuiDragDropFlags_AcceptPeekOnly = ImGuiDragDropFlags_AcceptBeforeDelivery | ImGuiDragDropFlags_AcceptNoDrawDefaultRect // For peeking ahead and inspecting the payload before delivery. }; -// Standard Drag and Drop payload types. Types starting with '_' are defined by Dear ImGui. +// Standard Drag and Drop payload types. You can define you own payload types using 8-characters long strings. Types starting with '_' are defined by Dear ImGui. #define IMGUI_PAYLOAD_TYPE_COLOR_3F "_COL3F" // float[3] // Standard type for colors, without alpha. User code may use this type. #define IMGUI_PAYLOAD_TYPE_COLOR_4F "_COL4F" // float[4] // Standard type for colors. User code may use this type. @@ -733,7 +733,7 @@ enum ImGuiCol_ }; // Enumeration for PushStyleVar() / PopStyleVar() to temporarily modify the ImGuiStyle structure. -// NB: the enum only refers to fields of ImGuiStyle which makes sense to be pushed/poped inside UI code. During initialization, feel free to just poke into ImGuiStyle directly. +// NB: the enum only refers to fields of ImGuiStyle which makes sense to be pushed/popped inside UI code. During initialization, feel free to just poke into ImGuiStyle directly. // NB: if changing this enum, you need to update the associated internal table GStyleVarInfo[] accordingly. This is where we link enum values to members offset/type. enum ImGuiStyleVar_ { @@ -979,18 +979,18 @@ struct ImGuiIO #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS namespace ImGui { - static inline bool IsRootWindowFocused() { return IsWindowFocused(ImGuiFocusedFlags_RootWindow); } // OBSOLETE 1.53+ - static inline bool IsRootWindowOrAnyChildFocused() { return IsWindowFocused(ImGuiFocusedFlags_RootAndChildWindows); } // OBSOLETE 1.53+ - static inline void SetNextWindowContentWidth(float width) { SetNextWindowContentSize(ImVec2(width, 0.0f)); } // OBSOLETE 1.53+ (nb: original version preserved last Y value set by SetNextWindowContentSize()) - static inline bool IsRootWindowOrAnyChildHovered(ImGuiHoveredFlags flags = 0) { return IsItemHovered(flags | ImGuiHoveredFlags_RootWindow | ImGuiHoveredFlags_ChildWindows); } // OBSOLETE 1.53+ use flags directly - bool Begin(const char* name, bool* p_open, const ImVec2& size_on_first_use, float bg_alpha_override = -1.0f, ImGuiWindowFlags flags = 0); // OBSOLETE 1.52+. use SetNextWindowSize() instead if you want to set a window size. - static inline void AlignFirstTextHeightToWidgets() { AlignTextToFramePadding(); } // OBSOLETE 1.52+ - static inline void SetNextWindowPosCenter(ImGuiCond cond = 0) { SetNextWindowPos(ImVec2(GetIO().DisplaySize.x * 0.5f, GetIO().DisplaySize.y * 0.5f), cond, ImVec2(0.5f, 0.5f)); } // OBSOLETE 1.52+ - static inline bool IsItemHoveredRect() { return IsItemHovered(ImGuiHoveredFlags_RectOnly); } // OBSOLETE 1.51+ - static inline bool IsPosHoveringAnyWindow(const ImVec2&) { IM_ASSERT(0); return false; } // OBSOLETE 1.51+. This was partly broken. You probably wanted to use ImGui::GetIO().WantCaptureMouse instead. - static inline bool IsMouseHoveringAnyWindow() { return IsAnyWindowHovered(); } // OBSOLETE 1.51+ - static inline bool IsMouseHoveringWindow() { return IsWindowHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup | ImGuiHoveredFlags_AllowWhenBlockedByActiveItem); } // OBSOLETE 1.51+ - static inline bool CollapsingHeader(const char* label, const char* str_id, bool framed = true, bool default_open = false) { (void)str_id; (void)framed; ImGuiTreeNodeFlags default_open_flags = 1 << 5; return CollapsingHeader(label, (default_open ? default_open_flags : 0)); } // OBSOLETE 1.49+ + static inline bool IsRootWindowFocused() { return IsWindowFocused(ImGuiFocusedFlags_RootWindow); } // OBSOLETE 1.53+ + static inline bool IsRootWindowOrAnyChildFocused() { return IsWindowFocused(ImGuiFocusedFlags_RootAndChildWindows); } // OBSOLETE 1.53+ + static inline void SetNextWindowContentWidth(float width) { SetNextWindowContentSize(ImVec2(width, 0.0f)); } // OBSOLETE 1.53+ (nb: original version preserved last Y value set by SetNextWindowContentSize()) + static inline bool IsRootWindowOrAnyChildHovered(ImGuiHoveredFlags flags = 0) { return IsItemHovered(flags | ImGuiHoveredFlags_RootWindow | ImGuiHoveredFlags_ChildWindows); } // OBSOLETE 1.53+ use flags directly + bool Begin(const char* name, bool* p_open, const ImVec2& size_on_first_use, float bg_alpha_override = -1.0f, ImGuiWindowFlags flags = 0); // OBSOLETE 1.52+. use SetNextWindowSize() instead if you want to set a window size. + static inline void AlignFirstTextHeightToWidgets() { AlignTextToFramePadding(); } // OBSOLETE 1.52+ + static inline void SetNextWindowPosCenter(ImGuiCond cond = 0) { SetNextWindowPos(ImVec2(GetIO().DisplaySize.x * 0.5f, GetIO().DisplaySize.y * 0.5f), cond, ImVec2(0.5f, 0.5f)); } // OBSOLETE 1.52+ + static inline bool IsItemHoveredRect() { return IsItemHovered(ImGuiHoveredFlags_RectOnly); } // OBSOLETE 1.51+ + static inline bool IsPosHoveringAnyWindow(const ImVec2&) { IM_ASSERT(0); return false; } // OBSOLETE 1.51+. This was partly broken. You probably wanted to use ImGui::GetIO().WantCaptureMouse instead. + static inline bool IsMouseHoveringAnyWindow() { return IsAnyWindowHovered(); } // OBSOLETE 1.51+ + static inline bool IsMouseHoveringWindow() { return IsWindowHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup | ImGuiHoveredFlags_AllowWhenBlockedByActiveItem); } // OBSOLETE 1.51+ + static inline bool CollapsingHeader(const char* label, const char* str_id, bool framed = true, bool default_open = false) { (void)str_id; (void)framed; ImGuiTreeNodeFlags default_open_flags = 1 << 5; return CollapsingHeader(label, (default_open ? default_open_flags : 0)); } // OBSOLETE 1.49+ } #endif @@ -1205,8 +1205,8 @@ struct ImGuiTextEditCallbackData struct ImGuiSizeConstraintCallbackData { void* UserData; // Read-only. What user passed to SetNextWindowSizeConstraints() - ImVec2 Pos; // Read-only. Window position, for reference. - ImVec2 CurrentSize; // Read-only. Current window size. + ImVec2 Pos; // Read-only. Window position, for reference. + ImVec2 CurrentSize; // Read-only. Current window size. ImVec2 DesiredSize; // Read-write. Desired size, based on user's mouse position. Write to this field to restrain resizing. }; @@ -1313,7 +1313,7 @@ struct ImGuiListClipper // The expected behavior from your rendering function is 'if (cmd.UserCallback != NULL) cmd.UserCallback(parent_list, cmd); else RenderTriangles()' typedef void (*ImDrawCallback)(const ImDrawList* parent_list, const ImDrawCmd* cmd); -// Typically, 1 command = 1 gpu draw call (unless command is a callback) +// Typically, 1 command = 1 GPU draw call (unless command is a callback) struct ImDrawCmd { unsigned int ElemCount; // Number of indices (multiple of 3) to be rendered as triangles. Vertices are stored in the callee ImDrawList's vtx_buffer[] array, indices in idx_buffer[]. From 45bca7851d194ff4393c6a884c282020f93291b0 Mon Sep 17 00:00:00 2001 From: omar Date: Wed, 13 Dec 2017 22:30:16 +0100 Subject: [PATCH 308/823] Added ImGuiHoveredFlags_RootAndChildWindows helper for consistency with focused flags. (#1382) --- imgui.cpp | 6 +++--- imgui.h | 3 ++- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 69f04d8c00dd..75d06b3b45cf 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -214,8 +214,8 @@ Also read releases logs https://github.com/ocornut/imgui/releases for more details. - 2017/12/13 (1.53) - renamed GetItemsLineHeightWithSpacing() to GetFrameHeightWithSpacing(). Kept redirection function (will obsolete). - - 2017/12/13 (1.53) - marked IsRootWindowFocused() as obsolete in favor of using IsWindowFocused(ImGuiFocusedFlags_RootWindow). Kept redirection function (will obsolete). - - marked IsRootWindowOrAnyChildFocused() as obsolete in favor of using IsWindowFocused(ImGuiFocusedFlags_RootAndChildWindows). Kept redirection function (will obsolete). + - 2017/12/13 (1.53) - obsoleted IsRootWindowFocused() in favor of using IsWindowFocused(ImGuiFocusedFlags_RootWindow). Kept redirection function (will obsolete). + - obsoleted IsRootWindowOrAnyChildFocused() in favor of using IsWindowFocused(ImGuiFocusedFlags_RootAndChildWindows). Kept redirection function (will obsolete). - 2017/12/12 (1.53) - renamed ImGuiTreeNodeFlags_AllowOverlapMode to ImGuiTreeNodeFlags_AllowItemOverlap. Kept redirection enum (will obsolete). - 2017/12/10 (1.53) - removed SetNextWindowContentWidth(), prefer using SetNextWindowContentSize(). Kept redirection function (will obsolete). - 2017/11/27 (1.53) - renamed ImGuiTextBuffer::append() helper to appendf(), appendv() to appendfv(). If you copied the 'Log' demo in your code, it uses appendv() so that needs to be renamed. @@ -224,7 +224,7 @@ - 2017/11/18 (1.53) - Style: removed ImGuiCol_ComboBg in favor of combo boxes using ImGuiCol_PopupBg for consistency. - 2017/11/18 (1.53) - Style: renamed ImGuiCol_ChildWindowBg to ImGuiCol_ChildBg. - 2017/11/18 (1.53) - Style: renamed style.ChildWindowRounding to style.ChildRounding, ImGuiStyleVar_ChildWindowRounding to ImGuiStyleVar_ChildRounding. - - 2017/11/02 (1.53) - marked IsRootWindowOrAnyChildHovered() as obsolete is favor of using IsWindowHovered(ImGuiHoveredFlags_RootWindow | ImGuiHoveredFlags_ChildWindows); + - 2017/11/02 (1.53) - obsoleted IsRootWindowOrAnyChildHovered() in favor of using IsWindowHovered(ImGuiHoveredFlags_RootAndChildWindows); - 2017/10/24 (1.52) - renamed IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCS/IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCS to IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCTIONS/IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS for consistency. - 2017/10/20 (1.52) - changed IsWindowHovered() default parameters behavior to return false if an item is active in another window (e.g. click-dragging item from another window to this window). You can use the newly introduced IsWindowHovered() flags to requests this specific behavior if you need it. - 2017/10/20 (1.52) - marked IsItemHoveredRect()/IsMouseHoveringWindow() as obsolete, in favor of using the newly introduced flags for IsItemHovered() and IsWindowHovered(). See https://github.com/ocornut/imgui/issues/1382 for details. diff --git a/imgui.h b/imgui.h index bbbeaef46df3..0e54fc9fcefb 100644 --- a/imgui.h +++ b/imgui.h @@ -631,7 +631,8 @@ enum ImGuiHoveredFlags_ //ImGuiHoveredFlags_AllowWhenBlockedByModal = 1 << 3, // Return true even if a modal popup window is normally blocking access to this item/window. FIXME-TODO: Unavailable yet. ImGuiHoveredFlags_AllowWhenBlockedByActiveItem = 1 << 4, // Return true even if an active item is blocking access to this item/window. Useful for Drag and Drop patterns. ImGuiHoveredFlags_AllowWhenOverlapped = 1 << 5, // Return true even if the position is overlapped by another window - ImGuiHoveredFlags_RectOnly = ImGuiHoveredFlags_AllowWhenBlockedByPopup | ImGuiHoveredFlags_AllowWhenBlockedByActiveItem | ImGuiHoveredFlags_AllowWhenOverlapped + ImGuiHoveredFlags_RectOnly = ImGuiHoveredFlags_AllowWhenBlockedByPopup | ImGuiHoveredFlags_AllowWhenBlockedByActiveItem | ImGuiHoveredFlags_AllowWhenOverlapped, + ImGuiHoveredFlags_RootAndChildWindows = ImGuiHoveredFlags_RootWindow | ImGuiHoveredFlags_ChildWindows }; // Flags for ImGui::BeginDragDropSource(), ImGui::AcceptDragDropPayload() From fa68cb53648f05e8a3df6fe68c2a567f178bcb28 Mon Sep 17 00:00:00 2001 From: omar Date: Wed, 13 Dec 2017 23:07:07 +0100 Subject: [PATCH 309/823] Demo: Console: Tweak. --- imgui_demo.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 50aecce9af91..a1c09f4a8c3b 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -2563,7 +2563,8 @@ struct ExampleAppConsole ImGui::PopStyleVar(); ImGui::Separator(); - ImGui::BeginChild("ScrollingRegion", ImVec2(0, -ImGui::GetStyle().ItemSpacing.y - ImGui::GetFrameHeightWithSpacing()), false, ImGuiWindowFlags_HorizontalScrollbar); // Leave room for 1 separator + 1 InputText + const float footer_height_to_reserve = ImGui::GetStyle().ItemSpacing.y + ImGui::GetFrameHeightWithSpacing(); // 1 separator, 1 input text + ImGui::BeginChild("ScrollingRegion", ImVec2(0, -footer_height_to_reserve), false, ImGuiWindowFlags_HorizontalScrollbar); // Leave room for 1 separator + 1 InputText if (ImGui::BeginPopupContextWindow()) { if (ImGui::Selectable("Clear")) ClearLog(); From 07ed9f8451c67fb665523b1521465a5804460e1b Mon Sep 17 00:00:00 2001 From: omar Date: Thu, 14 Dec 2017 11:08:16 +0100 Subject: [PATCH 310/823] TODO list update --- TODO.txt | 41 ++++++++++++++++++----------------------- 1 file changed, 18 insertions(+), 23 deletions(-) diff --git a/TODO.txt b/TODO.txt index 43df4dafc383..41270c4d9cf8 100644 --- a/TODO.txt +++ b/TODO.txt @@ -15,8 +15,9 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i - window: auto-fit feedback loop when user relies on any dynamic layout (window width multiplier, column) appears weird to end-user. clarify. - window: allow resizing of child windows (possibly given min/max for each axis?.) - window: background options for child windows, border option (disable rounding). - - window: resizing from any sides? + mouse cursor directives for app. (#822) -!- window: begin with *p_open == false should return false. + - window: resizing from any sides? done. > need backends to honor mouse cursors properly. (#822) + - window: resize from borders: support some form of outer padding to make it easier to grab borders. (#822) + - window: begin with *p_open == false should return false. - window: get size/pos helpers given names (see discussion in #249) - window: a collapsed window can be stuck behind the main menu bar? - window: when window is very small, prioritize resize button over close button. @@ -24,9 +25,7 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i - window: increase minimum size of a window with menus or fix the menu rendering so that it doesn't look odd. - window: double-clicking on title bar to minimize isn't consistent, perhaps move to single-click on left-most collapse icon? - window: expose contents size. (#1045) - - window: resize from borders: support some form of outer padding to make it easier to grab borders. (#822) - window: GetWindowSize() returns (0,0) when not calculated? (#1045) - - window: refactor IsWindowFocused(), merge all three existing variants, add flags, similar to #1382. - window: freeze window flag: if not focused/hovered, return false, render with previous ImDrawList. and/or reduce refresh rate. !- scrolling: allow immediately effective change of scroll after Begin() if we haven't appended items yet. - scrolling/clipping: separator on the initial position of a window is not visible (cursorpos.y <= clippos.y). (2017-08-20: can't repro) @@ -38,6 +37,8 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i - drawlist: avoid passing null (-9999,+9999) rectangle to end-user, instead perhaps pass rectangle based on io.DisplaySize? - drawlist: primtiives/helpers to manipulate vertices post submission, so e.g. a quad/rect can be resized to fit later submitted content, _without_ using the ChannelSplit api - drawlist: non-AA strokes have gaps between points (#593, #288), especially RenderCheckmark(). + - drawlist: would be good to be able to deep copy a draw list (ImVector= op?). + - drawlist/opt: AddRect() axis aligned pixel aligned (no-aa) could use 8 triangles instead of 16 and no normal calculation. - main: considering adding an Init() function? some constructs are awkward in the implementation because of the lack of them. - main: find a way to preserve relative orders of multiple reappearing windows (so an app toggling between "modes" e.g. fullscreen vs all tools) won't lose relative ordering. @@ -47,7 +48,7 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i - widgets: display mode: widget-label, label-widget (aligned on column or using fixed size), label-newline-tab-widget etc. (#395) - widgets: clean up widgets internal toward exposing everything and stabilizing imgui_internals.h. - - widgets: add disabled and read-only modes (#211) + - widgets: add visauls for Disabled/ReadOnly mode and expose publicly (#211) - widgets: add always-allow-overlap mode. - widgets: alignment options in style (e.g. center Selectable, Right-Align within Button, etc.) #1260 - widgets: activate by identifier (trigger button, focus given id) @@ -80,7 +81,7 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i - layout: horizontal flow until no space left (#404) - layout: more generic alignment state (left/right/centered) for single items? - layout: clean up the InputFloatN/SliderFloatN/ColorEdit4 layout code. item width should include frame padding. - - layout: BeginGroup() needs a border option. + - layout: BeginGroup() needs a border option. (~#1496) - layout: vertical alignement of mixed height items (e.g. buttons) within a same line (#1284) - columns: sizing policy (e.g. for each column: fixed size, %, fill, distribute default size among fills) (#513, #125) @@ -135,22 +136,19 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i - drag float: up/down axis - drag float: added leeway on edge (e.g. a few invisible steps past the clamp limits) - - combo: sparse combo boxes (via function call?) / iterators - - combo: active item type could be anything else e.g. void* - - combo: use clipper - - combo: contents should extends to fit label if combo widget is small - - combo: option for ComboEx to not return true when unchanged (#1182) + - combo: use clipper: make it easier to disable clipper with a single flag. + - combo: option for BeginCombo to not return true when unchanged (#1182) - combo/listbox: keyboard control. need InputText-like non-active focus + key handling. considering keyboard for custom listbox (pr #203) - listbox: multiple selection. - listbox: unselect option (#1208) - - listbox: make it easier/more natural to implement range-select (need some sort of info/ref about the last clicked/focused item that user can translate to an index?) + - listbox: make it easier/more natural to implement range-select (need some sort of info/ref about the last clicked/focused item that user can translate to an index?) (wip stash) - listbox: user may want to initial scroll to focus on the one selected value? - listbox: expose hovered item for a basic ListBox - listbox: keyboard navigation. - listbox: scrolling should track modified selection. !- popups/menus: clarify usage of popups id, how MenuItem/Selectable closing parent popups affects the ID, etc. this is quite fishy needs improvement! (#331, #402) - - popups: reopening context menu at new position should be the behavior by default? (equivalent to internal OpenPopupEx() with reopen_existing=true) + - popups: reopening context menu at new position should be the behavior by default? (equivalent to internal OpenPopupEx() with reopen_existing=true) (~#1497) - popups: if the popup functions took explicit ImGuiID it would allow the user to manage the scope of those ID. (#331) - popups: clicking outside (to close popup) and holding shouldn't drag window below. - popups: add variant using global identifier similar to Begin/End (#402) @@ -184,12 +182,10 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i - settings: api for per-tool simple persistent data (bool,int,float,columns sizes,etc.) in .ini file (#437) - stb: add defines to disable stb implementations -!- style: better default styles. -!- style: move border to style structure, remove _ShowBorder flag. +!- style: better default styles. (#707) - style: border types: out-screen, in-screen, etc. (#447) - style/optimization: store rounded corners in texture to use 1 quad per corner (filled and wireframe) to lower the cost of rounding. - style: add window shadow (fading away from the window. Paint-style calculation of vertices alpha after drawlist would be easier) - - style: color-box not always square? - style: a concept of "compact style" that the end-user can easily rely on (e.g. PushStyleCompact()?) that maps to other settings? avoid implementing duplicate helpers such as SmallCheckbox(), etc. - style: try to make PushStyleVar() more robust to incorrect parameters (to be more friendly to edit & continues situation). - style: global scale setting. @@ -207,14 +203,16 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i - filters: handle wildcards (with implicit leading/trailing *), regexps - filters: fuzzy matches (may use code at blog.forrestthewoods.com/4cffeed33fdb) - - drag'n drop, dragging helpers, demo (carry dragging info, visualize drag source before clicking, drop target, etc.) (#143, #479) + - drag and drop: add demo. (#143, #479) + - drag and drop: test with reordering nodes (in a list, or a tree node). (#143) + - drag and drop: test integrating with os drag and drop. - node/graph editor (#306) - pie menus patterns (#434) - - markup: simple markup language for color change? + - markup: simple markup language for color change? (#902) + - font: better vertical centering (based e.g on height of lowercase 'x'?). currently Roboto-Medium size 16 px isn't currently centered. - font: free the Alpha buffer if user only requested RGBA. !- font: better CalcTextSizeA() API, at least for simple use cases. current one is horrible (perhaps have simple vs extended versions). - - font: better vertical centering (based e.g on height of lowercase 'x'?). currently Roboto-Medium size 16 px isn't currently centered. - font: enforce monospace through ImFontConfig (for icons?) + create dual ImFont output from same input, reusing rasterized data but with different glyphs/AdvanceX - font: finish CustomRectRegister() to allow mapping unicode codepoint to custom texture data - font: PushFontSize API (#1018) @@ -246,17 +244,14 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i - misc: idle refresh: expose cursor blink animation timer for backend to be able to lower framerate. - misc: make the ImGuiCond values linear (non-power-of-two). internal storage for ImGuiWindow can use integers to combine into flags (Why?) - misc: provide a way to compile out the entire implementation while providing a dummy API (e.g. #define IMGUI_DUMMY_IMPL) - - misc: provide HoveredTime and ActivatedTime to ease the creation of animations. - misc: fix for compilation settings where stdcall isn't the default (e.g. vectorcall) (#1230) - - misc: detect user not calling Render() and suggest to call EndFrame()? - remote: make a system like RemoteImGui first-class citizen/project (#75) - demo: add vertical separator demo - - demo: add a virtual scrolling example? + - demo: add virtual scrolling example? - examples: directx9: save/restore device state more thoroughly. - examples: window minimize, maximize (#583) - examples: provide a zero-framerate/idle example. - - examples: document WantCaptureKeyboard, WantCaptureMouse in example apps. (#446) - examples: glfw: could go idle when minimized? if (glfwGetWindowAttrib(window, GLFW_ICONIFIED)) { glfwWaitEvents(); continue; } // the problem is that DeltaTime will be super high on resume, perhaps provide a way to let impl know (#440) - optimization: replace vsnprintf with stb_printf? or enable the defines/infrastructure to allow it (#1038) - optimization: add clipping for multi-component widgets (SliderFloatX, ColorEditX, etc.). one problem is that nav branch can't easily clip parent group when there is a move request. From ac8e708c3e710164551d81a4020885a77ed0f4b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Branimir=20Karad=C5=BEi=C4=87?= Date: Thu, 14 Dec 2017 09:08:18 -0800 Subject: [PATCH 311/823] Fixed unused variable warning. --- imgui.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/imgui.cpp b/imgui.cpp index 75d06b3b45cf..56b396105f8f 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -11434,7 +11434,7 @@ const ImGuiPayload* ImGui::AcceptDragDropPayload(const char* type, ImGuiDragDrop // We don't really use/need this now, but added it for the sake of consistency and because we might need it later. void ImGui::EndDragDropTarget() { - ImGuiContext& g = *GImGui; + ImGuiContext& g = *GImGui; (void)g; IM_ASSERT(g.DragDropActive); } From eefea0588a6a26033e92ad20955126e4f926842f Mon Sep 17 00:00:00 2001 From: omar Date: Thu, 14 Dec 2017 18:42:41 +0100 Subject: [PATCH 312/823] Using the ImGuiWindowFlags_NoScrollWithMouse flag on a child window forwards the mouse wheel event to the parent window, unless either ImGuiWindowFlags_NoInputs or ImGuiWindowFlags_NoScrollbar are also set. (#1380, #1502) --- imgui.cpp | 17 +++++++++++++---- imgui.h | 2 +- imgui_demo.cpp | 8 ++++++-- 3 files changed, 20 insertions(+), 7 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 56b396105f8f..06fc032dfded 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -213,6 +213,7 @@ Here is a change-log of API breaking changes, if you are using one of the functions listed, expect to have to fix some code. Also read releases logs https://github.com/ocornut/imgui/releases for more details. + - 2017/12/14 (1.53) - using the ImGuiWindowFlags_NoScrollWithMouse flag on a child window forwards the mouse wheel event to the parent window, unless either ImGuiWindowFlags_NoInputs or ImGuiWindowFlags_NoScrollbar are also set. - 2017/12/13 (1.53) - renamed GetItemsLineHeightWithSpacing() to GetFrameHeightWithSpacing(). Kept redirection function (will obsolete). - 2017/12/13 (1.53) - obsoleted IsRootWindowFocused() in favor of using IsWindowFocused(ImGuiFocusedFlags_RootWindow). Kept redirection function (will obsolete). - obsoleted IsRootWindowOrAnyChildFocused() in favor of using IsWindowFocused(ImGuiFocusedFlags_RootAndChildWindows). Kept redirection function (will obsolete). @@ -2462,12 +2463,20 @@ void ImGui::NewFrame() window->Size *= scale; window->SizeFull *= scale; } - else if (!g.IO.KeyCtrl && !(window->Flags & ImGuiWindowFlags_NoScrollWithMouse)) + else if (!g.IO.KeyCtrl) { // Mouse wheel Scrolling - float scroll_amount = 5 * window->CalcFontSize(); - scroll_amount = (float)(int)ImMin(scroll_amount, (window->ContentsRegionRect.GetHeight() + window->WindowPadding.y * 2.0f) * 0.67f); - SetWindowScrollY(window, window->Scroll.y - g.IO.MouseWheel * scroll_amount); + // If a child window has the ImGuiWindowFlags_NoScrollWithMouse flag, we give a chance to scroll its parent (unless either ImGuiWindowFlags_NoInputs or ImGuiWindowFlags_NoScrollbar are also set). + ImGuiWindow* scroll_window = window; + while ((scroll_window->Flags & ImGuiWindowFlags_ChildWindow) && (scroll_window->Flags & ImGuiWindowFlags_NoScrollWithMouse) && !(scroll_window->Flags & ImGuiWindowFlags_NoScrollbar) && !(scroll_window->Flags & ImGuiWindowFlags_NoInputs) && scroll_window->ParentWindow) + scroll_window = scroll_window->ParentWindow; + + if (!(scroll_window->Flags & ImGuiWindowFlags_NoScrollWithMouse) && !(scroll_window->Flags & ImGuiWindowFlags_NoInputs)) + { + float scroll_amount = 5 * scroll_window->CalcFontSize(); + scroll_amount = (float)(int)ImMin(scroll_amount, (scroll_window->ContentsRegionRect.GetHeight() + scroll_window->WindowPadding.y * 2.0f) * 0.67f); + SetWindowScrollY(scroll_window, scroll_window->Scroll.y - g.IO.MouseWheel * scroll_amount); + } } } diff --git a/imgui.h b/imgui.h index 0e54fc9fcefb..73d9b5864bb7 100644 --- a/imgui.h +++ b/imgui.h @@ -524,7 +524,7 @@ enum ImGuiWindowFlags_ ImGuiWindowFlags_NoResize = 1 << 1, // Disable user resizing with the lower-right grip ImGuiWindowFlags_NoMove = 1 << 2, // Disable user moving the window ImGuiWindowFlags_NoScrollbar = 1 << 3, // Disable scrollbars (window can still scroll with mouse or programatically) - ImGuiWindowFlags_NoScrollWithMouse = 1 << 4, // Disable user vertically scrolling with mouse wheel + ImGuiWindowFlags_NoScrollWithMouse = 1 << 4, // Disable user vertically scrolling with mouse wheel. On child window, mouse wheel will be forwarded to the parent unless NoScrollbar is also set. ImGuiWindowFlags_NoCollapse = 1 << 5, // Disable user collapsing window by double-clicking on it ImGuiWindowFlags_AlwaysAutoResize = 1 << 6, // Resize every window to its content every frame //ImGuiWindowFlags_ShowBorders = 1 << 7, // Show borders around windows and items (OBSOLETE! Use e.g. style.FrameBorderSize=1.0f to enable borders). diff --git a/imgui_demo.cpp b/imgui_demo.cpp index a1c09f4a8c3b..a2bf1be563e6 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -997,6 +997,9 @@ void ImGui::ShowTestWindow(bool* p_open) { if (ImGui::TreeNode("Child regions")) { + static bool disable_mouse_wheel = false; + ImGui::Checkbox("Disable Mouse Wheel", &disable_mouse_wheel); + ImGui::Text("Without border"); static int line = 50; bool goto_line = ImGui::Button("Goto"); @@ -1004,7 +1007,8 @@ void ImGui::ShowTestWindow(bool* p_open) ImGui::PushItemWidth(100); goto_line |= ImGui::InputInt("##Line", &line, 0, 0, ImGuiInputTextFlags_EnterReturnsTrue); ImGui::PopItemWidth(); - ImGui::BeginChild("Sub1", ImVec2(ImGui::GetWindowContentRegionWidth() * 0.5f,300), false, ImGuiWindowFlags_HorizontalScrollbar); + + ImGui::BeginChild("Sub1", ImVec2(ImGui::GetWindowContentRegionWidth() * 0.5f,300), false, ImGuiWindowFlags_HorizontalScrollbar | (disable_mouse_wheel ? ImGuiWindowFlags_NoScrollWithMouse : 0)); for (int i = 0; i < 100; i++) { ImGui::Text("%04d: scrollable region", i); @@ -1018,7 +1022,7 @@ void ImGui::ShowTestWindow(bool* p_open) ImGui::SameLine(); ImGui::PushStyleVar(ImGuiStyleVar_ChildRounding, 5.0f); - ImGui::BeginChild("Sub2", ImVec2(0,300), true); + ImGui::BeginChild("Sub2", ImVec2(0,300), true, (disable_mouse_wheel ? ImGuiWindowFlags_NoScrollWithMouse : 0)); ImGui::Text("With border"); ImGui::Columns(2); for (int i = 0; i < 100; i++) From 51433e26af14f1e240f9769142861243a1e5db4b Mon Sep 17 00:00:00 2001 From: omar Date: Fri, 15 Dec 2017 10:15:51 +0100 Subject: [PATCH 313/823] Drag and Drop: Renamed to ImGuiDragDropFlags_SourceNoAutoTooltip to ImGuiDragDropFlags_SourceNoPreviewTooltip (#143) --- imgui.cpp | 4 ++-- imgui.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 06fc032dfded..cff66bf57ebd 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -11269,7 +11269,7 @@ bool ImGui::BeginDragDropSource(ImGuiDragDropFlags flags, int mouse_button) g.DragDropMouseButton = mouse_button; } - if (!(flags & ImGuiDragDropFlags_SourceNoAutoTooltip)) + if (!(flags & ImGuiDragDropFlags_SourceNoPreviewTooltip)) { // FIXME-DRAG //SetNextWindowPos(g.IO.MousePos - g.ActiveIdClickOffset - g.Style.WindowPadding); @@ -11292,7 +11292,7 @@ void ImGui::EndDragDropSource() ImGuiContext& g = *GImGui; IM_ASSERT(g.DragDropActive); - if (!(g.DragDropSourceFlags & ImGuiDragDropFlags_SourceNoAutoTooltip)) + if (!(g.DragDropSourceFlags & ImGuiDragDropFlags_SourceNoPreviewTooltip)) { EndTooltip(); PopStyleColor(); diff --git a/imgui.h b/imgui.h index 73d9b5864bb7..c05759aae660 100644 --- a/imgui.h +++ b/imgui.h @@ -639,7 +639,7 @@ enum ImGuiHoveredFlags_ enum ImGuiDragDropFlags_ { // BeginDragDropSource() flags - ImGuiDragDropFlags_SourceNoAutoTooltip = 1 << 0, // By default, a successful call to BeginDragDropSource opens a tooltip so you can display a preview or description of the dragged contents. This flag disable this behavior. + ImGuiDragDropFlags_SourceNoPreviewTooltip = 1 << 0, // By default, a successful call to BeginDragDropSource opens a tooltip so you can display a preview or description of the source contents. This flag disable this behavior. ImGuiDragDropFlags_SourceNoDisableHover = 1 << 1, // By default, when dragging we clear data so that IsItemHovered() will return true, to avoid subsequent user code submitting tooltips. This flag disable this behavior so you can still call IsItemHovered() on the source item. ImGuiDragDropFlags_SourceNoHoldToOpenOthers = 1 << 2, // Disable the behavior that allows to open tree nodes and collapsing header by holding over them while dragging a source item. ImGuiDragDropFlags_SourceAllowNullID = 1 << 3, // Allow items such as Text(), Image() that have no unique identifier to be used as drag source, by manufacturing a temporary identifier based on their window-relative position. This is extremely unusual within the dear imgui ecosystem and so we made it explicit. From 6effcf21d62e41c5ef658fdf6839f6e955030cfc Mon Sep 17 00:00:00 2001 From: omar Date: Fri, 15 Dec 2017 11:09:18 +0100 Subject: [PATCH 314/823] Drag and Drop: Source can also inhibit the preview on target, useful for extern sources that only exists for one frame. (#143) --- imgui.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/imgui.cpp b/imgui.cpp index cff66bf57ebd..90316a8d8eee 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -11422,6 +11422,7 @@ const ImGuiPayload* ImGui::AcceptDragDropPayload(const char* type, ImGuiDragDrop // Render default drop visuals payload.Preview = was_accepted_previously; + flags |= (g.DragDropSourceFlags & ImGuiDragDropFlags_AcceptNoDrawDefaultRect); // Source can also inhibit the preview (useful for external sources that lives for 1 frame) if (!(flags & ImGuiDragDropFlags_AcceptNoDrawDefaultRect) && payload.Preview) { // FIXME-DRAG: Settle on a proper default visuals for drop target. From 0c6e260f739e9094f82c3a7555aed8292b5dc9ab Mon Sep 17 00:00:00 2001 From: omar Date: Fri, 15 Dec 2017 11:16:10 +0100 Subject: [PATCH 315/823] Drag and Drop: Added ImGuiDragDropFlags_SourceExtern to facilitate interfacing with WM_DROPFILES (#143) --- imgui.cpp | 83 +++++++++++++++++++++++++++++++++---------------------- imgui.h | 1 + 2 files changed, 51 insertions(+), 33 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 90316a8d8eee..c73e74722dd5 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -11220,50 +11220,67 @@ bool ImGui::BeginDragDropSource(ImGuiDragDropFlags flags, int mouse_button) { ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; - if (g.IO.MouseDown[mouse_button] == false) - return false; - ImGuiID id = window->DC.LastItemId; - if (id == 0) + bool source_drag_active = false; + ImGuiID source_id = 0; + ImGuiID source_parent_id = 0; + if (!(flags & ImGuiDragDropFlags_SourceExtern)) { - // If you want to use BeginDragDropSource() on an item with no unique identifier for interaction, such as Text() or Image(), you need to: - // A) Read the explanation below, B) Use the ImGuiDragDropFlags_SourceAllowNullID flag, C) Swallow your programmer pride. - if (!(flags & ImGuiDragDropFlags_SourceAllowNullID)) - { - IM_ASSERT(0); + source_id = window->DC.LastItemId; + if (source_id != 0 && g.ActiveId != source_id) // Early out for most common case return false; - } - - // Magic fallback (=somehow reprehensible) to handle items with no assigned ID, e.g. Text(), Image() - // We build a throwaway ID based on current ID stack + relative AABB of items in window. - // THE IDENTIFIER WON'T SURVIVE ANY REPOSITIONING OF THE WIDGET, so if your widget moves your dragging operation will be canceled. - // We don't need to maintain/call ClearActiveID() as releasing the button will early out this function and trigger !ActiveIdIsAlive. - bool is_hovered = window->DC.LastItemRectHoveredRect; - if (!is_hovered && (g.ActiveId == 0 || g.ActiveIdWindow != window)) + if (g.IO.MouseDown[mouse_button] == false) return false; - id = window->DC.LastItemId = window->GetIDFromRectangle(window->DC.LastItemRect); - if (is_hovered) - SetHoveredID(id); - if (is_hovered && g.IO.MouseClicked[mouse_button]) + + if (source_id == 0) { - SetActiveID(id, window); - FocusWindow(window); + // If you want to use BeginDragDropSource() on an item with no unique identifier for interaction, such as Text() or Image(), you need to: + // A) Read the explanation below, B) Use the ImGuiDragDropFlags_SourceAllowNullID flag, C) Swallow your programmer pride. + if (!(flags & ImGuiDragDropFlags_SourceAllowNullID)) + { + IM_ASSERT(0); + return false; + } + + // Magic fallback (=somehow reprehensible) to handle items with no assigned ID, e.g. Text(), Image() + // We build a throwaway ID based on current ID stack + relative AABB of items in window. + // THE IDENTIFIER WON'T SURVIVE ANY REPOSITIONING OF THE WIDGET, so if your widget moves your dragging operation will be canceled. + // We don't need to maintain/call ClearActiveID() as releasing the button will early out this function and trigger !ActiveIdIsAlive. + bool is_hovered = window->DC.LastItemRectHoveredRect; + if (!is_hovered && (g.ActiveId == 0 || g.ActiveIdWindow != window)) + return false; + source_id = window->DC.LastItemId = window->GetIDFromRectangle(window->DC.LastItemRect); + if (is_hovered) + SetHoveredID(source_id); + if (is_hovered && g.IO.MouseClicked[mouse_button]) + { + SetActiveID(source_id, window); + FocusWindow(window); + } + if (g.ActiveId == source_id) // Allow the underlying widget to display/return hovered during the mouse release frame, else we would get a flicker. + g.ActiveIdAllowOverlap = is_hovered; } - if (g.ActiveId == id) // Allow the underlying widget to display/return hovered during the mouse release frame, else we would get a flicker. - g.ActiveIdAllowOverlap = is_hovered; + if (g.ActiveId != source_id) + return false; + source_parent_id = window->IDStack.back(); + source_drag_active = IsMouseDragging(mouse_button); + } + else + { + window = NULL; + source_id = ImHash("#SourceExtern", 0); + source_drag_active = true; } - if (g.ActiveId != id) - return false; - if (IsMouseDragging(mouse_button)) + if (source_drag_active) { if (!g.DragDropActive) { - IM_ASSERT(id != 0); + IM_ASSERT(source_id != 0); ClearDragDrop(); ImGuiPayload& payload = g.DragDropPayload; - payload.SourceId = id; - payload.SourceParentId = window->IDStack.back(); + payload.SourceId = source_id; + payload.SourceParentId = source_parent_id; g.DragDropActive = true; g.DragDropSourceFlags = flags; g.DragDropMouseButton = mouse_button; @@ -11279,7 +11296,7 @@ bool ImGui::BeginDragDropSource(ImGuiDragDropFlags flags, int mouse_button) BeginTooltipEx(ImGuiWindowFlags_NoInputs); } - if (!(flags & ImGuiDragDropFlags_SourceNoDisableHover)) + if (!(flags & ImGuiDragDropFlags_SourceNoDisableHover) && !(flags & ImGuiDragDropFlags_SourceExtern)) window->DC.LastItemRectHoveredRect = false; return true; @@ -11434,7 +11451,7 @@ const ImGuiPayload* ImGui::AcceptDragDropPayload(const char* type, ImGuiDragDrop } g.DragDropAcceptFrameCount = g.FrameCount; - payload.Delivery = was_accepted_previously && IsMouseReleased(g.DragDropMouseButton); + payload.Delivery = was_accepted_previously && !IsMouseDown(g.DragDropMouseButton); // For extern drag sources affecting os window focus, it's easier to just test !IsMouseDown() instead of IsMouseReleased() if (!payload.Delivery && !(flags & ImGuiDragDropFlags_AcceptBeforeDelivery)) return NULL; diff --git a/imgui.h b/imgui.h index c05759aae660..eea0e6a4697a 100644 --- a/imgui.h +++ b/imgui.h @@ -643,6 +643,7 @@ enum ImGuiDragDropFlags_ ImGuiDragDropFlags_SourceNoDisableHover = 1 << 1, // By default, when dragging we clear data so that IsItemHovered() will return true, to avoid subsequent user code submitting tooltips. This flag disable this behavior so you can still call IsItemHovered() on the source item. ImGuiDragDropFlags_SourceNoHoldToOpenOthers = 1 << 2, // Disable the behavior that allows to open tree nodes and collapsing header by holding over them while dragging a source item. ImGuiDragDropFlags_SourceAllowNullID = 1 << 3, // Allow items such as Text(), Image() that have no unique identifier to be used as drag source, by manufacturing a temporary identifier based on their window-relative position. This is extremely unusual within the dear imgui ecosystem and so we made it explicit. + ImGuiDragDropFlags_SourceExtern = 1 << 4, // External source (from outside of imgui), won't attempt to read current item/window info. Will always return true. Only one Extern source can be active simultaneously. // AcceptDragDropPayload() flags ImGuiDragDropFlags_AcceptBeforeDelivery = 1 << 10, // AcceptDragDropPayload() will returns true even before the mouse button is released. You can then call IsDelivery() to test if the payload needs to be delivered. ImGuiDragDropFlags_AcceptNoDrawDefaultRect = 1 << 11, // Do not draw the default highlight rectangle when hovering over target. From b9391d16921ccfada8aa8ea9d245b2116ef2b1a1 Mon Sep 17 00:00:00 2001 From: omar Date: Fri, 15 Dec 2017 15:44:27 +0100 Subject: [PATCH 316/823] Columns: Internal: Columns have their no set of flags so NoResize can be setup by internal code. (#125) --- imgui.cpp | 10 +++++----- imgui_internal.h | 3 ++- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index c73e74722dd5..00c53aa2eee5 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -10807,15 +10807,15 @@ void ImGui::NextColumn() if (++columns->Current < columns->Count) { // Columns 1+ cancel out IndentX - window->DC.ColumnsOffsetX = GetColumnOffset(columns->Current) - window->DC.IndentX + g.Style.ItemSpacing.x; + window->DC.ColumnsOffsetX = columns->Columns[columns->Current].LockedOffset - window->DC.IndentX + g.Style.ItemSpacing.x; window->DrawList->ChannelsSetCurrent(columns->Current); } else { window->DC.ColumnsOffsetX = 0.0f; + window->DrawList->ChannelsSetCurrent(0); columns->Current = 0; columns->CellMinY = columns->CellMaxY; - window->DrawList->ChannelsSetCurrent(0); } window->DC.CursorPos.x = (float)(int)(window->Pos.x + window->DC.IndentX + window->DC.ColumnsOffsetX); window->DC.CursorPos.y = columns->CellMinY; @@ -11018,7 +11018,7 @@ void ImGui::BeginColumns(const char* str_id, int columns_count, ImGuiColumnsFlag for (int n = 0; n < columns_count + 1; n++) { - // Clamp + // Clamp position ImGuiColumnData* column = &columns->Columns[n]; float t = column->OffsetNorm; if (!(columns->Flags & ImGuiColumnsFlags_NoForceWithinWindow)) @@ -11028,7 +11028,7 @@ void ImGui::BeginColumns(const char* str_id, int columns_count, ImGuiColumnsFlag if (n == columns_count) continue; - // Compute clipping rectangles + // Compute clipping rectangle float clip_x1 = ImFloor(0.5f + window->Pos.x + GetColumnOffset(n) - 1.0f); float clip_x2 = ImFloor(0.5f + window->Pos.x + GetColumnOffset(n + 1) - 1.0f); column->ClipRect = ImRect(clip_x1, -FLT_MAX, clip_x2, +FLT_MAX); @@ -11081,7 +11081,7 @@ void ImGui::EndColumns() g.MouseCursor = ImGuiMouseCursor_ResizeEW; if (held && g.ActiveIdIsJustActivated) g.ActiveIdClickOffset.x -= column_hw; // Store from center of column line (we used a 8 wide rect for columns clicking). This is used by GetDraggedColumnOffset(). - if (held) + if (held && !(columns->Columns[n].Flags & ImGuiColumnsFlags_NoResize)) dragging_column = n; } diff --git a/imgui_internal.h b/imgui_internal.h index f0d598b49c60..ed19ba664434 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -416,9 +416,10 @@ struct ImGuiColumnData { float OffsetNorm; // Column start offset, normalized 0.0 (far left) -> 1.0 (far right) float OffsetNormBeforeResize; + ImGuiColumnsFlags Flags; // Not exposed ImRect ClipRect; - ImGuiColumnData() { OffsetNorm = OffsetNormBeforeResize = 0.0f; } + ImGuiColumnData() { OffsetNorm = OffsetNormBeforeResize = 0.0f; Flags = 0; } }; struct ImGuiColumnsSet From b1d90b565d9e1364254b974715824a46f9caea8c Mon Sep 17 00:00:00 2001 From: omar Date: Fri, 15 Dec 2017 17:09:41 +0100 Subject: [PATCH 317/823] Columns: Fixed previous commit (wrong chunk commited) (#125) --- imgui.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/imgui.cpp b/imgui.cpp index 00c53aa2eee5..ac5c5b9792d7 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -10807,7 +10807,7 @@ void ImGui::NextColumn() if (++columns->Current < columns->Count) { // Columns 1+ cancel out IndentX - window->DC.ColumnsOffsetX = columns->Columns[columns->Current].LockedOffset - window->DC.IndentX + g.Style.ItemSpacing.x; + window->DC.ColumnsOffsetX = GetColumnOffset(columns->Current) - window->DC.IndentX + g.Style.ItemSpacing.x; window->DrawList->ChannelsSetCurrent(columns->Current); } else From abaf347deb2ef23b6bdc58c342a802cc18d3581f Mon Sep 17 00:00:00 2001 From: ibachar Date: Sun, 17 Dec 2017 15:27:56 +0200 Subject: [PATCH 318/823] Added a flag for text input to disable undo / redo --- imgui.cpp | 9 +++++---- imgui.h | 1 + 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index ac5c5b9792d7..11589f3c247d 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -8405,6 +8405,7 @@ bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2 const bool is_multiline = (flags & ImGuiInputTextFlags_Multiline) != 0; const bool is_editable = (flags & ImGuiInputTextFlags_ReadOnly) == 0; const bool is_password = (flags & ImGuiInputTextFlags_Password) != 0; + const bool disable_undo = (flags & ImGuiInputTextFlags_DisableUndo) != 0; if (is_multiline) // Open group before calling GetID() because groups tracks id created during their spawn BeginGroup(); @@ -8631,10 +8632,10 @@ bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2 if (InputTextFilterCharacter(&c, flags, callback, user_data)) edit_state.OnKeyPressed((int)c); } - else if (IsKeyPressedMap(ImGuiKey_Escape)) { clear_active_id = cancel_edit = true; } - else if (is_shortcut_key_only && IsKeyPressedMap(ImGuiKey_Z) && is_editable) { edit_state.OnKeyPressed(STB_TEXTEDIT_K_UNDO); edit_state.ClearSelection(); } - else if (is_shortcut_key_only && IsKeyPressedMap(ImGuiKey_Y) && is_editable) { edit_state.OnKeyPressed(STB_TEXTEDIT_K_REDO); edit_state.ClearSelection(); } - else if (is_shortcut_key_only && IsKeyPressedMap(ImGuiKey_A)) { edit_state.SelectAll(); edit_state.CursorFollow = true; } + else if (IsKeyPressedMap(ImGuiKey_Escape)) { clear_active_id = cancel_edit = true; } + else if (is_shortcut_key_only && IsKeyPressedMap(ImGuiKey_Z) && is_editable && !disable_undo) { edit_state.OnKeyPressed(STB_TEXTEDIT_K_UNDO); edit_state.ClearSelection(); } + else if (is_shortcut_key_only && IsKeyPressedMap(ImGuiKey_Y) && is_editable && !disable_undo) { edit_state.OnKeyPressed(STB_TEXTEDIT_K_REDO); edit_state.ClearSelection(); } + else if (is_shortcut_key_only && IsKeyPressedMap(ImGuiKey_A)) { edit_state.SelectAll(); edit_state.CursorFollow = true; } else if (is_shortcut_key_only && !is_password && ((IsKeyPressedMap(ImGuiKey_X) && is_editable) || IsKeyPressedMap(ImGuiKey_C)) && (!is_multiline || edit_state.HasSelection())) { // Cut, Copy diff --git a/imgui.h b/imgui.h index eea0e6a4697a..5c36b1417a7d 100644 --- a/imgui.h +++ b/imgui.h @@ -566,6 +566,7 @@ enum ImGuiInputTextFlags_ ImGuiInputTextFlags_AlwaysInsertMode = 1 << 13, // Insert mode ImGuiInputTextFlags_ReadOnly = 1 << 14, // Read-only mode ImGuiInputTextFlags_Password = 1 << 15, // Password mode, display all characters as '*' + ImGuiInputTextFlags_DisableUndo = 1 << 16, // Disable undo / redo // [Internal] ImGuiInputTextFlags_Multiline = 1 << 20 // For internal use by InputTextMultiline() }; From 55c0d2b9ab2fdc7cd694a8fa2334e749c31e4ed1 Mon Sep 17 00:00:00 2001 From: omar Date: Wed, 20 Dec 2017 16:25:03 +0100 Subject: [PATCH 319/823] InputText: renamed ImGuiInputTextFlags_DisableUndo to ImGuiInputTextFlags_NoUndoRedo (#1506, #1508) --- imgui.cpp | 6 +++--- imgui.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 11589f3c247d..5d2a61a7c634 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -8405,7 +8405,7 @@ bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2 const bool is_multiline = (flags & ImGuiInputTextFlags_Multiline) != 0; const bool is_editable = (flags & ImGuiInputTextFlags_ReadOnly) == 0; const bool is_password = (flags & ImGuiInputTextFlags_Password) != 0; - const bool disable_undo = (flags & ImGuiInputTextFlags_DisableUndo) != 0; + const bool is_undoable = (flags & ImGuiInputTextFlags_NoUndoRedo) == 0; if (is_multiline) // Open group before calling GetID() because groups tracks id created during their spawn BeginGroup(); @@ -8633,8 +8633,8 @@ bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2 edit_state.OnKeyPressed((int)c); } else if (IsKeyPressedMap(ImGuiKey_Escape)) { clear_active_id = cancel_edit = true; } - else if (is_shortcut_key_only && IsKeyPressedMap(ImGuiKey_Z) && is_editable && !disable_undo) { edit_state.OnKeyPressed(STB_TEXTEDIT_K_UNDO); edit_state.ClearSelection(); } - else if (is_shortcut_key_only && IsKeyPressedMap(ImGuiKey_Y) && is_editable && !disable_undo) { edit_state.OnKeyPressed(STB_TEXTEDIT_K_REDO); edit_state.ClearSelection(); } + else if (is_shortcut_key_only && IsKeyPressedMap(ImGuiKey_Z) && is_editable && is_undoable) { edit_state.OnKeyPressed(STB_TEXTEDIT_K_UNDO); edit_state.ClearSelection(); } + else if (is_shortcut_key_only && IsKeyPressedMap(ImGuiKey_Y) && is_editable && is_undoable) { edit_state.OnKeyPressed(STB_TEXTEDIT_K_REDO); edit_state.ClearSelection(); } else if (is_shortcut_key_only && IsKeyPressedMap(ImGuiKey_A)) { edit_state.SelectAll(); edit_state.CursorFollow = true; } else if (is_shortcut_key_only && !is_password && ((IsKeyPressedMap(ImGuiKey_X) && is_editable) || IsKeyPressedMap(ImGuiKey_C)) && (!is_multiline || edit_state.HasSelection())) { diff --git a/imgui.h b/imgui.h index 5c36b1417a7d..4e5203e214f1 100644 --- a/imgui.h +++ b/imgui.h @@ -566,7 +566,7 @@ enum ImGuiInputTextFlags_ ImGuiInputTextFlags_AlwaysInsertMode = 1 << 13, // Insert mode ImGuiInputTextFlags_ReadOnly = 1 << 14, // Read-only mode ImGuiInputTextFlags_Password = 1 << 15, // Password mode, display all characters as '*' - ImGuiInputTextFlags_DisableUndo = 1 << 16, // Disable undo / redo + ImGuiInputTextFlags_NoUndoRedo = 1 << 16, // Disable undo/redo. Note that input text owns the text data while active, if you want to provide your own undo/redo stack you need e.g. to call ClearActiveID(). // [Internal] ImGuiInputTextFlags_Multiline = 1 << 20 // For internal use by InputTextMultiline() }; From b366dd932267251421e7eb4a01a05a193625cd28 Mon Sep 17 00:00:00 2001 From: omar Date: Wed, 20 Dec 2017 17:40:58 +0100 Subject: [PATCH 320/823] BeginPopup: Moved flags into individual BeginPopupXXX calls/implementations and outside of BeginPopupex(). Removed _NoResize flag which is extraneous with AlwaysAutoResize. --- imgui.cpp | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 5d2a61a7c634..2ffd8ed78441 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -3828,15 +3828,13 @@ bool ImGui::BeginPopupEx(ImGuiID id, ImGuiWindowFlags extra_flags) return false; } - ImGuiWindowFlags flags = extra_flags|ImGuiWindowFlags_Popup|ImGuiWindowFlags_NoTitleBar|ImGuiWindowFlags_NoResize|ImGuiWindowFlags_NoSavedSettings; - char name[20]; - if (flags & ImGuiWindowFlags_ChildMenu) + if (extra_flags & ImGuiWindowFlags_ChildMenu) ImFormatString(name, IM_ARRAYSIZE(name), "##Menu_%02d", g.CurrentPopupStack.Size); // Recycle windows based on depth else ImFormatString(name, IM_ARRAYSIZE(name), "##Popup_%08x", id); // Not recycling, so we can close/open during the same frame - bool is_open = Begin(name, NULL, flags); + bool is_open = Begin(name, NULL, extra_flags | ImGuiWindowFlags_Popup); if (!is_open) // NB: Begin can return false when the popup is completely clipped (e.g. zero size display) EndPopup(); @@ -3851,7 +3849,7 @@ bool ImGui::BeginPopup(const char* str_id) ClearSetNextWindowData(); // We behave like Begin() and need to consume those values return false; } - return BeginPopupEx(g.CurrentWindow->GetID(str_id), ImGuiWindowFlags_AlwaysAutoResize); + return BeginPopupEx(g.CurrentWindow->GetID(str_id), ImGuiWindowFlags_AlwaysAutoResize|ImGuiWindowFlags_NoTitleBar|ImGuiWindowFlags_NoSavedSettings); } bool ImGui::IsPopupOpen(ImGuiID id) @@ -3926,7 +3924,7 @@ bool ImGui::BeginPopupContextItem(const char* str_id, int mouse_button) if (IsMouseClicked(mouse_button)) if (IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup)) OpenPopupEx(id, true); - return BeginPopupEx(id, ImGuiWindowFlags_AlwaysAutoResize); + return BeginPopupEx(id, ImGuiWindowFlags_AlwaysAutoResize|ImGuiWindowFlags_NoTitleBar|ImGuiWindowFlags_NoSavedSettings); } bool ImGui::BeginPopupContextWindow(const char* str_id, int mouse_button, bool also_over_items) @@ -3938,7 +3936,7 @@ bool ImGui::BeginPopupContextWindow(const char* str_id, int mouse_button, bool a if (IsWindowHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup)) if (also_over_items || !IsAnyItemHovered()) OpenPopupEx(id, true); - return BeginPopupEx(id, ImGuiWindowFlags_AlwaysAutoResize); + return BeginPopupEx(id, ImGuiWindowFlags_AlwaysAutoResize|ImGuiWindowFlags_NoTitleBar|ImGuiWindowFlags_NoSavedSettings); } bool ImGui::BeginPopupContextVoid(const char* str_id, int mouse_button) @@ -3948,7 +3946,7 @@ bool ImGui::BeginPopupContextVoid(const char* str_id, int mouse_button) ImGuiID id = GImGui->CurrentWindow->GetID(str_id); if (!IsAnyWindowHovered() && IsMouseClicked(mouse_button)) OpenPopupEx(id, true); - return BeginPopupEx(id, ImGuiWindowFlags_AlwaysAutoResize); + return BeginPopupEx(id, ImGuiWindowFlags_AlwaysAutoResize|ImGuiWindowFlags_NoTitleBar|ImGuiWindowFlags_NoSavedSettings); } static bool BeginChildEx(const char* name, ImGuiID id, const ImVec2& size_arg, bool border, ImGuiWindowFlags extra_flags) @@ -9754,7 +9752,7 @@ bool ImGui::BeginMenu(const char* label, bool enabled) if (menu_is_open) { SetNextWindowPos(popup_pos, ImGuiCond_Always); - ImGuiWindowFlags flags = ImGuiWindowFlags_AlwaysAutoResize | ((window->Flags & (ImGuiWindowFlags_Popup|ImGuiWindowFlags_ChildMenu)) ? ImGuiWindowFlags_ChildMenu|ImGuiWindowFlags_ChildWindow : ImGuiWindowFlags_ChildMenu); + ImGuiWindowFlags flags = ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoSavedSettings | ((window->Flags & (ImGuiWindowFlags_Popup|ImGuiWindowFlags_ChildMenu)) ? ImGuiWindowFlags_ChildMenu|ImGuiWindowFlags_ChildWindow : ImGuiWindowFlags_ChildMenu); menu_is_open = BeginPopupEx(id, flags); // menu_is_open can be 'false' when the popup is completely clipped (e.g. zero size display) } From 6193f46af28e3ea22730286664e7573bfd7714a8 Mon Sep 17 00:00:00 2001 From: omar Date: Thu, 21 Dec 2017 11:18:30 +0100 Subject: [PATCH 321/823] Active Modal window always set the WantCaptureKeyboard flag (#744) --- imgui.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 2ffd8ed78441..3c9c1997caa7 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2406,7 +2406,8 @@ void ImGui::NewFrame() g.HoveredWindow = (g.MovingWindow && !(g.MovingWindow->Flags & ImGuiWindowFlags_NoInputs)) ? g.MovingWindow : FindHoveredWindow(g.IO.MousePos); g.HoveredRootWindow = g.HoveredWindow ? g.HoveredWindow->RootWindow : NULL; - if (ImGuiWindow* modal_window = GetFrontMostModalRootWindow()) + ImGuiWindow* modal_window = GetFrontMostModalRootWindow(); + if (modal_window != NULL) { g.ModalWindowDarkeningRatio = ImMin(g.ModalWindowDarkeningRatio + g.IO.DeltaTime * 6.0f, 1.0f); if (g.HoveredRootWindow && !IsWindowChildOf(g.HoveredRootWindow, modal_window)) @@ -2435,7 +2436,10 @@ void ImGui::NewFrame() g.IO.WantCaptureMouse = (g.WantCaptureMouseNextFrame != 0); else g.IO.WantCaptureMouse = (mouse_avail_to_imgui && (g.HoveredWindow != NULL || mouse_any_down)) || (!g.OpenPopupStack.empty()); - g.IO.WantCaptureKeyboard = (g.WantCaptureKeyboardNextFrame != -1) ? (g.WantCaptureKeyboardNextFrame != 0) : (g.ActiveId != 0); + if (g.WantCaptureKeyboardNextFrame != -1) + g.IO.WantCaptureKeyboard = (g.WantCaptureKeyboardNextFrame != 0); + else + g.IO.WantCaptureKeyboard = (g.ActiveId != 0) || (modal_window != NULL); g.IO.WantTextInput = (g.WantTextInputNextFrame != -1) ? (g.WantTextInputNextFrame != 0) : 0; g.MouseCursor = ImGuiMouseCursor_Arrow; g.WantCaptureMouseNextFrame = g.WantCaptureKeyboardNextFrame = g.WantTextInputNextFrame = -1; From 230f826ef560eddecf86c47eec0eac04d1cbf249 Mon Sep 17 00:00:00 2001 From: omar Date: Thu, 21 Dec 2017 14:50:58 +0100 Subject: [PATCH 322/823] ImDrawList: Comments --- imgui.cpp | 2 +- imgui.h | 9 ++++----- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 3c9c1997caa7..5fcd9ee5f9c6 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -735,7 +735,7 @@ ImGuiStyle::ImGuiStyle() DisplaySafeAreaPadding = ImVec2(4,4); // If you cannot see the edge of your screen (e.g. on a TV) increase the safe area padding. Covers popups/tooltips as well regular windows. AntiAliasedLines = true; // Enable anti-aliasing on lines/borders. Disable if you are really short on CPU/GPU. AntiAliasedShapes = true; // Enable anti-aliasing on filled shapes (rounded rectangles, circles, etc.) - CurveTessellationTol = 1.25f; // Tessellation tolerance. Decrease for highly tessellated curves (higher quality, more polygons), increase to reduce quality. + CurveTessellationTol = 1.25f; // Tessellation tolerance when using PathBezierCurveTo() without a specific number of segments. Decrease for highly tessellated curves (higher quality, more polygons), increase to reduce quality. ImGui::StyleColorsClassic(this); } diff --git a/imgui.h b/imgui.h index 4e5203e214f1..55ac7b2082cf 100644 --- a/imgui.h +++ b/imgui.h @@ -854,7 +854,7 @@ struct ImGuiStyle ImVec2 DisplaySafeAreaPadding; // If you cannot see the edge of your screen (e.g. on a TV) increase the safe area padding. Covers popups/tooltips as well regular windows. bool AntiAliasedLines; // Enable anti-aliasing on lines/borders. Disable if you are really tight on CPU/GPU. bool AntiAliasedShapes; // Enable anti-aliasing on filled shapes (rounded rectangles, circles, etc.) - float CurveTessellationTol; // Tessellation tolerance. Decrease for highly tessellated curves (higher quality, more polygons), increase to reduce quality. + float CurveTessellationTol; // Tessellation tolerance when using PathBezierCurveTo() without a specific number of segments. Decrease for highly tessellated curves (higher quality, more polygons), increase to reduce quality. ImVec4 Colors[ImGuiCol_COUNT]; IMGUI_API ImGuiStyle(); @@ -1372,15 +1372,14 @@ enum ImDrawCornerFlags_ // Draw command list // This is the low-level list of polygons that ImGui functions are filling. At the end of the frame, all command lists are passed to your ImGuiIO::RenderDrawListFn function for rendering. -// At the moment, each ImGui window contains its own ImDrawList but they could potentially be merged in the future. -// If you want to add custom rendering within a window, you can use ImGui::GetWindowDrawList() to access the current draw list and add your own primitives. +// Each ImGui window contains its own ImDrawList. You can use ImGui::GetWindowDrawList() to access the current window draw list and draw custom primitives. // You can interleave normal ImGui:: calls and adding primitives to the current draw list. // All positions are generally in pixel coordinates (top-left at (0,0), bottom-right at io.DisplaySize), however you are totally free to apply whatever transformation matrix to want to the data (if you apply such transformation you'll want to apply it to ClipRect as well) -// Primitives are always added to the list and not culled (culling is done at higher-level by ImGui:: functions). +// Important: Primitives are always added to the list and not culled (culling is done at higher-level by ImGui:: functions), if you use this API a lot consider coarse culling your drawn objects. struct ImDrawList { // This is what you have to render - ImVector CmdBuffer; // Commands. Typically 1 command = 1 GPU draw call. + ImVector CmdBuffer; // Draw commands. Typically 1 command = 1 GPU draw call, unless the command is a callback. ImVector IdxBuffer; // Index buffer. Each command consume ImDrawCmd::ElemCount of those ImVector VtxBuffer; // Vertex buffer. From 531c11d5c72890f324c9734ef5c860408b8a7f3d Mon Sep 17 00:00:00 2001 From: omar Date: Thu, 21 Dec 2017 18:50:27 +0100 Subject: [PATCH 323/823] ImDrawList: Small refactor toward removing dependency on GImGui + PushClipRectFullscreen now correctly uses data provided by imgui which can takes account of DisplaySize + Removed static variable in PathArcToFast() which caused linking issues to some. --- imgui.cpp | 25 +++++++++++++------- imgui.h | 7 ++++-- imgui_draw.cpp | 59 ++++++++++++++++++++++++------------------------ imgui_internal.h | 23 +++++++++++++++---- 4 files changed, 71 insertions(+), 43 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 5fcd9ee5f9c6..dbed5341c697 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1818,7 +1818,7 @@ bool ImGuiListClipper::Step() // ImGuiWindow //----------------------------------------------------------------------------- -ImGuiWindow::ImGuiWindow(const char* name) +ImGuiWindow::ImGuiWindow(ImGuiContext* context, const char* name) { Name = ImStrdup(name); ID = ImHash(name, 0); @@ -1859,7 +1859,7 @@ ImGuiWindow::ImGuiWindow(const char* name) FontWindowScale = 1.0f; DrawList = (ImDrawList*)ImGui::MemAlloc(sizeof(ImDrawList)); - IM_PLACEMENT_NEW(DrawList) ImDrawList(); + IM_PLACEMENT_NEW(DrawList) ImDrawList(&context->DrawListSharedData); DrawList->_OwnerName = Name; ParentWindow = NULL; RootWindow = NULL; @@ -2254,6 +2254,11 @@ ImDrawList* ImGui::GetOverlayDrawList() return &GImGui->OverlayDrawList; } +ImDrawListSharedData* ImGui::GetDrawListSharedData() +{ + return &GImGui->DrawListSharedData; +} + void ImGui::NewFrame() { ImGuiContext& g = *GImGui; @@ -2274,6 +2279,8 @@ void ImGui::NewFrame() SetCurrentFont(GetDefaultFont()); IM_ASSERT(g.Font->IsLoaded()); + g.DrawListSharedData.ClipRectFullscreen = ImVec4(0.0f, 0.0f, g.IO.DisplaySize.x, g.IO.DisplaySize.y); + g.DrawListSharedData.CurveTessellationTol = g.Style.CurveTessellationTol; g.Time += g.IO.DeltaTime; g.FrameCount += 1; @@ -4145,7 +4152,7 @@ static ImGuiWindow* CreateNewWindow(const char* name, ImVec2 size, ImGuiWindowFl // Create window the first time ImGuiWindow* window = (ImGuiWindow*)ImGui::MemAlloc(sizeof(ImGuiWindow)); - IM_PLACEMENT_NEW(window) ImGuiWindow(name); + IM_PLACEMENT_NEW(window) ImGuiWindow(&g, name); window->Flags = flags; g.WindowsById.SetVoidPtr(window->ID, window); @@ -5243,7 +5250,11 @@ static void SetCurrentFont(ImFont* font) g.Font = font; g.FontBaseSize = g.IO.FontGlobalScale * g.Font->FontSize * g.Font->Scale; g.FontSize = g.CurrentWindow ? g.CurrentWindow->CalcFontSize() : 0.0f; - g.FontTexUvWhitePixel = g.Font->ContainerAtlas->TexUvWhitePixel; + + ImFontAtlas* atlas = g.Font->ContainerAtlas; + g.DrawListSharedData.TexUvWhitePixel = atlas->TexUvWhitePixel; + g.DrawListSharedData.Font = g.Font; + g.DrawListSharedData.FontSize = g.FontSize; } void ImGui::PushFont(ImFont* font) @@ -5820,7 +5831,7 @@ float ImGui::GetFontSize() ImVec2 ImGui::GetFontTexUvWhitePixel() { - return GImGui->FontTexUvWhitePixel; + return GImGui->DrawListSharedData.TexUvWhitePixel; } void ImGui::SetWindowFontScale(float scale) @@ -10489,7 +10500,7 @@ bool ImGui::ColorPicker4(const char* label, float col[4], ImGuiColorEditFlags fl ImVec2 tra = wheel_center + ImRotate(triangle_pa, cos_hue_angle, sin_hue_angle); ImVec2 trb = wheel_center + ImRotate(triangle_pb, cos_hue_angle, sin_hue_angle); ImVec2 trc = wheel_center + ImRotate(triangle_pc, cos_hue_angle, sin_hue_angle); - ImVec2 uv_white = g.FontTexUvWhitePixel; + ImVec2 uv_white = GetFontTexUvWhitePixel(); draw_list->PrimReserve(6, 6); draw_list->PrimVtx(tra, uv_white, hue_color32); draw_list->PrimVtx(trb, uv_white, hue_color32); @@ -11609,7 +11620,6 @@ void ImGui::ShowMetricsWindow(bool* p_open) return; ImDrawList* overlay_draw_list = &GImGui->OverlayDrawList; // Render additional visuals into the top-most draw list - overlay_draw_list->PushClipRectFullScreen(); int elem_offset = 0; for (const ImDrawCmd* pcmd = draw_list->CmdBuffer.begin(); pcmd < draw_list->CmdBuffer.end(); elem_offset += pcmd->ElemCount, pcmd++) { @@ -11652,7 +11662,6 @@ void ImGui::ShowMetricsWindow(bool* p_open) } ImGui::TreePop(); } - overlay_draw_list->PopClipRect(); ImGui::TreePop(); } diff --git a/imgui.h b/imgui.h index 55ac7b2082cf..c24a860359d4 100644 --- a/imgui.h +++ b/imgui.h @@ -50,6 +50,7 @@ struct ImDrawChannel; // Temporary storage for outputting drawing struct ImDrawCmd; // A single draw command within a parent ImDrawList (generally maps to 1 GPU draw call) struct ImDrawData; // All draw command lists required to render the frame struct ImDrawList; // A single draw command list (generally one per window) +struct ImDrawListSharedData; // Data shared among multiple draw lists (typically owned by parent ImGui context, but you may create one yourself) struct ImDrawVert; // A single vertex (20 bytes by default, override layout with IMGUI_OVERRIDE_DRAWVERT_STRUCT_LAYOUT) struct ImFont; // Runtime data for a single font within a parent ImFontAtlas struct ImFontAtlas; // Runtime data for multiple fonts, bake multiple fonts into a single texture, TTF/OTF font loader @@ -466,6 +467,7 @@ namespace ImGui IMGUI_API float GetTime(); IMGUI_API int GetFrameCount(); IMGUI_API ImDrawList* GetOverlayDrawList(); // this draw list will be the last rendered one, useful to quickly draw overlays shapes/text + IMGUI_API ImDrawListSharedData* GetDrawListSharedData(); IMGUI_API const char* GetStyleColorName(ImGuiCol idx); IMGUI_API ImVec2 CalcItemRectClosestPoint(const ImVec2& pos, bool on_edge = false, float outward = +0.0f); // utility to find the closest point the last item bounding rectangle edge. useful to visually link items IMGUI_API ImVec2 CalcTextSize(const char* text, const char* text_end = NULL, bool hide_text_after_double_hash = false, float wrap_width = -1.0f); @@ -1325,7 +1327,7 @@ struct ImDrawCmd ImDrawCallback UserCallback; // If != NULL, call the function instead of rendering the vertices. clip_rect and texture_id will be set normally. void* UserCallbackData; // The draw callback code can access this. - ImDrawCmd() { ElemCount = 0; ClipRect.x = ClipRect.y = -8192.0f; ClipRect.z = ClipRect.w = +8192.0f; TextureId = NULL; UserCallback = NULL; UserCallbackData = NULL; } + ImDrawCmd() { ElemCount = 0; ClipRect.x = ClipRect.y = ClipRect.z = ClipRect.w = 0.0f; TextureId = NULL; UserCallback = NULL; UserCallbackData = NULL; } }; // Vertex index (override with '#define ImDrawIdx unsigned int' inside in imconfig.h) @@ -1384,6 +1386,7 @@ struct ImDrawList ImVector VtxBuffer; // Vertex buffer. // [Internal, used while building lists] + const ImDrawListSharedData* _Data; // Pointer to shared draw data (you can use ImGui::GetDrawListSharedData() to get the one from current ImGui context) const char* _OwnerName; // Pointer to owner window's name for debugging unsigned int _VtxCurrentIdx; // [Internal] == VtxBuffer.Size ImDrawVert* _VtxWritePtr; // [Internal] point within VtxBuffer.Data after each add command (to avoid using the ImVector<> operators too much) @@ -1395,7 +1398,7 @@ struct ImDrawList int _ChannelsCount; // [Internal] number of active channels (1+) ImVector _Channels; // [Internal] draw channels for columns API (not resized down so _ChannelsCount may be smaller than _Channels.Size) - ImDrawList() { _OwnerName = NULL; Clear(); } + ImDrawList(const ImDrawListSharedData* shared_data) { _Data = shared_data; _OwnerName = NULL; Clear(); } ~ImDrawList() { ClearFreeMemory(); } IMGUI_API void PushClipRect(ImVec2 clip_rect_min, ImVec2 clip_rect_max, bool intersect_with_current_clip_rect = false); // Render-level scissoring. This is passed down to your render function but not used for CPU-side coarse clipping. Prefer using higher-level ImGui::PushClipRect() to affect logic (hit-testing and widget culling) IMGUI_API void PushClipRectFullScreen(); diff --git a/imgui_draw.cpp b/imgui_draw.cpp index 69e93689ff65..03ff863c3388 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -277,10 +277,27 @@ void ImGui::StyleColorsLight(ImGuiStyle* dst) } //----------------------------------------------------------------------------- -// ImDrawList +// ImDrawListData //----------------------------------------------------------------------------- -static const ImVec4 GNullClipRect(-8192.0f, -8192.0f, +8192.0f, +8192.0f); // Large values that are easy to encode in a few bits+shift +ImDrawListSharedData::ImDrawListSharedData() +{ + Font = NULL; + FontSize = 0.0f; + CurveTessellationTol = 0.0f; + ClipRectFullscreen = ImVec4(-8192.0f, -8192.0f, +8192.0f, +8192.0f); + + // Const data + for (int i = 0; i < IM_ARRAYSIZE(CircleVtx12); i++) + { + const float a = ((float)i * 2 * IM_PI) / (float)IM_ARRAYSIZE(CircleVtx12); + CircleVtx12[i] = ImVec2(cosf(a), sinf(a)); + } +} + +//----------------------------------------------------------------------------- +// ImDrawList +//----------------------------------------------------------------------------- void ImDrawList::Clear() { @@ -321,7 +338,7 @@ void ImDrawList::ClearFreeMemory() } // Using macros because C++ is a terrible language, we want guaranteed inline, no code in header, and no overhead in Debug builds -#define GetCurrentClipRect() (_ClipRectStack.Size ? _ClipRectStack.Data[_ClipRectStack.Size-1] : GNullClipRect) +#define GetCurrentClipRect() (_ClipRectStack.Size ? _ClipRectStack.Data[_ClipRectStack.Size-1] : _Data->ClipRectFullscreen) #define GetCurrentTextureId() (_TextureIdStack.Size ? _TextureIdStack.Data[_TextureIdStack.Size-1] : NULL) void ImDrawList::AddDrawCmd() @@ -412,8 +429,7 @@ void ImDrawList::PushClipRect(ImVec2 cr_min, ImVec2 cr_max, bool intersect_with_ void ImDrawList::PushClipRectFullScreen() { - PushClipRect(ImVec2(GNullClipRect.x, GNullClipRect.y), ImVec2(GNullClipRect.z, GNullClipRect.w)); - //PushClipRect(GetVisibleRect()); // FIXME-OPT: This would be more correct but we're not supposed to access ImGuiContext from here? + PushClipRect(ImVec2(_Data->ClipRectFullscreen.x, _Data->ClipRectFullscreen.y), ImVec2(_Data->ClipRectFullscreen.z, _Data->ClipRectFullscreen.w)); } void ImDrawList::PopClipRect() @@ -533,7 +549,7 @@ void ImDrawList::PrimReserve(int idx_count, int vtx_count) // Fully unrolled with inline call to keep our debug builds decently fast. void ImDrawList::PrimRect(const ImVec2& a, const ImVec2& c, ImU32 col) { - ImVec2 b(c.x, a.y), d(a.x, c.y), uv(GImGui->FontTexUvWhitePixel); + ImVec2 b(c.x, a.y), d(a.x, c.y), uv(_Data->TexUvWhitePixel); ImDrawIdx idx = (ImDrawIdx)_VtxCurrentIdx; _IdxWritePtr[0] = idx; _IdxWritePtr[1] = (ImDrawIdx)(idx+1); _IdxWritePtr[2] = (ImDrawIdx)(idx+2); _IdxWritePtr[3] = idx; _IdxWritePtr[4] = (ImDrawIdx)(idx+2); _IdxWritePtr[5] = (ImDrawIdx)(idx+3); @@ -581,7 +597,7 @@ void ImDrawList::AddPolyline(const ImVec2* points, const int points_count, ImU32 if (points_count < 2) return; - const ImVec2 uv = GImGui->FontTexUvWhitePixel; + const ImVec2 uv = _Data->TexUvWhitePixel; anti_aliased &= GImGui->Style.AntiAliasedLines; //if (ImGui::GetIO().KeyCtrl) anti_aliased = false; // Debug @@ -759,7 +775,7 @@ void ImDrawList::AddPolyline(const ImVec2* points, const int points_count, ImU32 void ImDrawList::AddConvexPolyFilled(const ImVec2* points, const int points_count, ImU32 col, bool anti_aliased) { - const ImVec2 uv = GImGui->FontTexUvWhitePixel; + const ImVec2 uv = _Data->TexUvWhitePixel; anti_aliased &= GImGui->Style.AntiAliasedShapes; //if (ImGui::GetIO().KeyCtrl) anti_aliased = false; // Debug @@ -842,20 +858,6 @@ void ImDrawList::AddConvexPolyFilled(const ImVec2* points, const int points_coun void ImDrawList::PathArcToFast(const ImVec2& centre, float radius, int a_min_of_12, int a_max_of_12) { - static ImVec2 circle_vtx[12]; - static bool circle_vtx_builds = false; - const int circle_vtx_count = IM_ARRAYSIZE(circle_vtx); - if (!circle_vtx_builds) - { - for (int i = 0; i < circle_vtx_count; i++) - { - const float a = ((float)i / (float)circle_vtx_count) * 2*IM_PI; - circle_vtx[i].x = cosf(a); - circle_vtx[i].y = sinf(a); - } - circle_vtx_builds = true; - } - if (radius == 0.0f || a_min_of_12 > a_max_of_12) { _Path.push_back(centre); @@ -864,7 +866,7 @@ void ImDrawList::PathArcToFast(const ImVec2& centre, float radius, int a_min_of_ _Path.reserve(_Path.Size + (a_max_of_12 - a_min_of_12 + 1)); for (int a = a_min_of_12; a <= a_max_of_12; a++) { - const ImVec2& c = circle_vtx[a % circle_vtx_count]; + const ImVec2& c = _Data->CircleVtx12[a % IM_ARRAYSIZE(_Data->CircleVtx12)]; _Path.push_back(ImVec2(centre.x + c.x * radius, centre.y + c.y * radius)); } } @@ -916,7 +918,7 @@ void ImDrawList::PathBezierCurveTo(const ImVec2& p2, const ImVec2& p3, const ImV if (num_segments == 0) { // Auto-tessellated - PathBezierToCasteljau(&_Path, p1.x, p1.y, p2.x, p2.y, p3.x, p3.y, p4.x, p4.y, GImGui->Style.CurveTessellationTol, 0); + PathBezierToCasteljau(&_Path, p1.x, p1.y, p2.x, p2.y, p3.x, p3.y, p4.x, p4.y, _Data->CurveTessellationTol, 0); } else { @@ -998,7 +1000,7 @@ void ImDrawList::AddRectFilledMultiColor(const ImVec2& a, const ImVec2& c, ImU32 if (((col_upr_left | col_upr_right | col_bot_right | col_bot_left) & IM_COL32_A_MASK) == 0) return; - const ImVec2 uv = GImGui->FontTexUvWhitePixel; + const ImVec2 uv = _Data->TexUvWhitePixel; PrimReserve(6, 4); PrimWriteIdx((ImDrawIdx)(_VtxCurrentIdx)); PrimWriteIdx((ImDrawIdx)(_VtxCurrentIdx+1)); PrimWriteIdx((ImDrawIdx)(_VtxCurrentIdx+2)); PrimWriteIdx((ImDrawIdx)(_VtxCurrentIdx)); PrimWriteIdx((ImDrawIdx)(_VtxCurrentIdx+2)); PrimWriteIdx((ImDrawIdx)(_VtxCurrentIdx+3)); @@ -1094,12 +1096,11 @@ void ImDrawList::AddText(const ImFont* font, float font_size, const ImVec2& pos, if (text_begin == text_end) return; - // IMPORTANT: This is one of the few instance of breaking the encapsulation of ImDrawList, as we pull this from ImGui state, but it is just SO useful. - // Might just move Font/FontSize to ImDrawList? + // Pull default font/size from the shared ImDrawListSharedData instance if (font == NULL) - font = GImGui->Font; + font = _Data->Font; if (font_size == 0.0f) - font_size = GImGui->FontSize; + font_size = _Data->FontSize; IM_ASSERT(font->ContainerAtlas->TexID == _TextureIdStack.back()); // Use high-level ImGui::PushFont() or low-level ImDrawList::PushTextureId() to change font. diff --git a/imgui_internal.h b/imgui_internal.h index ed19ba664434..ca15636719e1 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -453,6 +453,21 @@ struct ImGuiColumnsSet } }; +struct ImDrawListSharedData +{ + ImVec2 TexUvWhitePixel; // UV of white pixel in the atlas + ImFont* Font; // Current/default font (optional, for simplified AddText overload) + float FontSize; // Current/default font size (optional, for simplified AddText overload) + float CurveTessellationTol; + ImVec4 ClipRectFullscreen; // Value for PushClipRectFullscreen() + + // Const data + // FIXME: Bake rounded corners fill/borders in atlas + ImVec2 CircleVtx12[12]; + + ImDrawListSharedData(); +}; + // Main state for ImGui struct ImGuiContext { @@ -462,7 +477,7 @@ struct ImGuiContext ImFont* Font; // (Shortcut) == FontStack.empty() ? IO.Font : FontStack.back() float FontSize; // (Shortcut) == FontBaseSize * g.CurrentWindow->FontWindowScale == window->FontSize(). Text height for current window. float FontBaseSize; // (Shortcut) == IO.FontGlobalScale * Font->Scale * Font->FontSize. Base text height. - ImVec2 FontTexUvWhitePixel; // (Shortcut) == Font->TexUvWhitePixel + ImDrawListSharedData DrawListSharedData; float Time; int FrameCount; @@ -574,12 +589,11 @@ struct ImGuiContext int WantTextInputNextFrame; char TempBuffer[1024*3+1]; // temporary text buffer - ImGuiContext() + ImGuiContext() : OverlayDrawList(NULL) { Initialized = false; Font = NULL; FontSize = FontBaseSize = 0.0f; - FontTexUvWhitePixel = ImVec2(0.0f, 0.0f); Time = 0.0f; FrameCount = 0; @@ -639,6 +653,7 @@ struct ImGuiContext OsImePosRequest = OsImePosSet = ImVec2(-1.0f, -1.0f); ModalWindowDarkeningRatio = 0.0f; + OverlayDrawList._Data = &DrawListSharedData; OverlayDrawList._OwnerName = "##Overlay"; // Give it a name for debugging MouseCursor = ImGuiMouseCursor_Arrow; memset(MouseCursorData, 0, sizeof(MouseCursorData)); @@ -805,7 +820,7 @@ struct IMGUI_API ImGuiWindow int FocusIdxTabRequestNext; // " public: - ImGuiWindow(const char* name); + ImGuiWindow(ImGuiContext* context, const char* name); ~ImGuiWindow(); ImGuiID GetID(const char* str, const char* str_end = NULL); From 14cb8177d0939fcdf59252192e7cd68162213c43 Mon Sep 17 00:00:00 2001 From: omar Date: Thu, 21 Dec 2017 19:01:53 +0100 Subject: [PATCH 324/823] ImDrawList: Removed 'bool anti_aliased = true' final parameter of ImDrawList::AddPolyline() and ImDrawList::AddConvexPolyFilled(). Anti-aliasing is controlled via the regular style.AntiAliased flags. --- imgui.cpp | 9 ++++++++- imgui.h | 8 ++++---- imgui_draw.cpp | 8 ++++---- 3 files changed, 16 insertions(+), 9 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index dbed5341c697..e3000c92923e 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -213,6 +213,7 @@ Here is a change-log of API breaking changes, if you are using one of the functions listed, expect to have to fix some code. Also read releases logs https://github.com/ocornut/imgui/releases for more details. + - 2017/12/21 (1.53) - removed 'bool anti_aliased = true' final parameter of ImDrawList::AddPolyline() and ImDrawList::AddConvexPolyFilled(). Anti-aliasing is controlled via the regular style.AntiAliased flags. - 2017/12/14 (1.53) - using the ImGuiWindowFlags_NoScrollWithMouse flag on a child window forwards the mouse wheel event to the parent window, unless either ImGuiWindowFlags_NoInputs or ImGuiWindowFlags_NoScrollbar are also set. - 2017/12/13 (1.53) - renamed GetItemsLineHeightWithSpacing() to GetFrameHeightWithSpacing(). Kept redirection function (will obsolete). - 2017/12/13 (1.53) - obsoleted IsRootWindowFocused() in favor of using IsWindowFocused(ImGuiFocusedFlags_RootWindow). Kept redirection function (will obsolete). @@ -11658,7 +11659,13 @@ void ImGui::ShowMetricsWindow(bool* p_open) } ImGui::Selectable(buf, false); if (ImGui::IsItemHovered()) - overlay_draw_list->AddPolyline(triangles_pos, 3, IM_COL32(255,255,0,255), true, 1.0f, false); // Add triangle without AA, more readable for large-thin triangle + { + ImGuiStyle& style = ImGui::GetStyle(); + bool backup_aa_lines = style.AntiAliasedLines; + style.AntiAliasedLines = false; // Disable AA on triangle outlines at is more readable for very large and thin triangles. + overlay_draw_list->AddPolyline(triangles_pos, 3, IM_COL32(255,255,0,255), true, 1.0f); + style.AntiAliasedLines = backup_aa_lines; + } } ImGui::TreePop(); } diff --git a/imgui.h b/imgui.h index c24a860359d4..2185d0665a63 100644 --- a/imgui.h +++ b/imgui.h @@ -1424,16 +1424,16 @@ struct ImDrawList IMGUI_API void AddImage(ImTextureID user_texture_id, const ImVec2& a, const ImVec2& b, const ImVec2& uv_a = ImVec2(0,0), const ImVec2& uv_b = ImVec2(1,1), ImU32 col = 0xFFFFFFFF); IMGUI_API void AddImageQuad(ImTextureID user_texture_id, const ImVec2& a, const ImVec2& b, const ImVec2& c, const ImVec2& d, const ImVec2& uv_a = ImVec2(0,0), const ImVec2& uv_b = ImVec2(1,0), const ImVec2& uv_c = ImVec2(1,1), const ImVec2& uv_d = ImVec2(0,1), ImU32 col = 0xFFFFFFFF); IMGUI_API void AddImageRounded(ImTextureID user_texture_id, const ImVec2& a, const ImVec2& b, const ImVec2& uv_a, const ImVec2& uv_b, ImU32 col, float rounding, int rounding_corners = ImDrawCornerFlags_All); - IMGUI_API void AddPolyline(const ImVec2* points, const int num_points, ImU32 col, bool closed, float thickness, bool anti_aliased); - IMGUI_API void AddConvexPolyFilled(const ImVec2* points, const int num_points, ImU32 col, bool anti_aliased); + IMGUI_API void AddPolyline(const ImVec2* points, const int num_points, ImU32 col, bool closed, float thickness); + IMGUI_API void AddConvexPolyFilled(const ImVec2* points, const int num_points, ImU32 col); IMGUI_API void AddBezierCurve(const ImVec2& pos0, const ImVec2& cp0, const ImVec2& cp1, const ImVec2& pos1, ImU32 col, float thickness, int num_segments = 0); // Stateful path API, add points then finish with PathFill() or PathStroke() inline void PathClear() { _Path.resize(0); } inline void PathLineTo(const ImVec2& pos) { _Path.push_back(pos); } inline void PathLineToMergeDuplicate(const ImVec2& pos) { if (_Path.Size == 0 || memcmp(&_Path[_Path.Size-1], &pos, 8) != 0) _Path.push_back(pos); } - inline void PathFillConvex(ImU32 col) { AddConvexPolyFilled(_Path.Data, _Path.Size, col, true); PathClear(); } - inline void PathStroke(ImU32 col, bool closed, float thickness = 1.0f) { AddPolyline(_Path.Data, _Path.Size, col, closed, thickness, true); PathClear(); } + inline void PathFillConvex(ImU32 col) { AddConvexPolyFilled(_Path.Data, _Path.Size, col); PathClear(); } + inline void PathStroke(ImU32 col, bool closed, float thickness = 1.0f) { AddPolyline(_Path.Data, _Path.Size, col, closed, thickness); PathClear(); } IMGUI_API void PathArcTo(const ImVec2& centre, float radius, float a_min, float a_max, int num_segments = 10); IMGUI_API void PathArcToFast(const ImVec2& centre, float radius, int a_min_of_12, int a_max_of_12); // Use precomputed angles for a 12 steps circle IMGUI_API void PathBezierCurveTo(const ImVec2& p1, const ImVec2& p2, const ImVec2& p3, int num_segments = 0); diff --git a/imgui_draw.cpp b/imgui_draw.cpp index 03ff863c3388..1136e274a66b 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -592,13 +592,13 @@ void ImDrawList::PrimQuadUV(const ImVec2& a, const ImVec2& b, const ImVec2& c, c } // TODO: Thickness anti-aliased lines cap are missing their AA fringe. -void ImDrawList::AddPolyline(const ImVec2* points, const int points_count, ImU32 col, bool closed, float thickness, bool anti_aliased) +void ImDrawList::AddPolyline(const ImVec2* points, const int points_count, ImU32 col, bool closed, float thickness) { if (points_count < 2) return; const ImVec2 uv = _Data->TexUvWhitePixel; - anti_aliased &= GImGui->Style.AntiAliasedLines; + bool anti_aliased = GImGui->Style.AntiAliasedLines; //if (ImGui::GetIO().KeyCtrl) anti_aliased = false; // Debug int count = points_count; @@ -773,10 +773,10 @@ void ImDrawList::AddPolyline(const ImVec2* points, const int points_count, ImU32 } } -void ImDrawList::AddConvexPolyFilled(const ImVec2* points, const int points_count, ImU32 col, bool anti_aliased) +void ImDrawList::AddConvexPolyFilled(const ImVec2* points, const int points_count, ImU32 col) { const ImVec2 uv = _Data->TexUvWhitePixel; - anti_aliased &= GImGui->Style.AntiAliasedShapes; + bool anti_aliased = GImGui->Style.AntiAliasedShapes; //if (ImGui::GetIO().KeyCtrl) anti_aliased = false; // Debug if (anti_aliased) From d139bd088df3547377b2ad5e788547447fe18299 Mon Sep 17 00:00:00 2001 From: omar Date: Thu, 21 Dec 2017 19:27:06 +0100 Subject: [PATCH 325/823] Begin: Moved modal darkening draw block --- imgui.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index e3000c92923e..1490d042d640 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -4661,16 +4661,16 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) window->Scroll = CalcNextScrollFromScrollTargetAndClamp(window); window->ScrollTarget = ImVec2(FLT_MAX, FLT_MAX); - // Modal window darkens what is behind them - if ((flags & ImGuiWindowFlags_Modal) != 0 && window == GetFrontMostModalRootWindow()) - window->DrawList->AddRectFilled(fullscreen_rect.Min, fullscreen_rect.Max, GetColorU32(ImGuiCol_ModalWindowDarkening, g.ModalWindowDarkeningRatio)); - // Apply focus, new windows appears in front bool want_focus = false; if (window_just_activated_by_user && !(flags & ImGuiWindowFlags_NoFocusOnAppearing)) if (!(flags & (ImGuiWindowFlags_ChildWindow | ImGuiWindowFlags_Tooltip)) || (flags & ImGuiWindowFlags_Popup)) want_focus = true; + // Draw modal window background (darkens what is behind them) + if ((flags & ImGuiWindowFlags_Modal) != 0 && window == GetFrontMostModalRootWindow()) + window->DrawList->AddRectFilled(fullscreen_rect.Min, fullscreen_rect.Max, GetColorU32(ImGuiCol_ModalWindowDarkening, g.ModalWindowDarkeningRatio)); + // Draw window + handle manual resize ImRect title_bar_rect = window->TitleBarRect(); if (window->Collapsed) @@ -11644,6 +11644,8 @@ void ImGui::ShowMetricsWindow(bool* p_open) } if (!pcmd_node_open) continue; + + // Display individual triangles/vertices. Hover on to get the corresponding triangle highlighted. ImGuiListClipper clipper(pcmd->ElemCount/3); // Manually coarse clip our print out of individual vertices to save CPU, only items that may be visible. while (clipper.Step()) for (int prim = clipper.DisplayStart, vtx_i = elem_offset + clipper.DisplayStart*3; prim < clipper.DisplayEnd; prim++) From 996dfb21cf0a2be4b2e09356dc4df9c1ff47ce6c Mon Sep 17 00:00:00 2001 From: omar Date: Thu, 21 Dec 2017 19:48:51 +0100 Subject: [PATCH 326/823] ImDrawList: Added ImDrawListFlags for AA settings. ImDrawList doesn't directly depends on GImGui anymore. --- TODO.txt | 4 +--- imgui.cpp | 16 +++++++++------- imgui.h | 10 +++++++++- imgui_demo.cpp | 2 +- imgui_draw.cpp | 9 +++------ 5 files changed, 23 insertions(+), 18 deletions(-) diff --git a/TODO.txt b/TODO.txt index 41270c4d9cf8..c052aeb5c09c 100644 --- a/TODO.txt +++ b/TODO.txt @@ -30,12 +30,10 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i !- scrolling: allow immediately effective change of scroll after Begin() if we haven't appended items yet. - scrolling/clipping: separator on the initial position of a window is not visible (cursorpos.y <= clippos.y). (2017-08-20: can't repro) - - drawlist: move Font, FontSize, FontTexUvWhitePixel inside ImDrawList and make it self-contained (apart from drawing settings?) - - drawlist: make it easier to toggle AA per primitive, so we can use e.g. non-AA fill + AA borders more naturally - drawlist: end-user probably can't call Clear() directly because we expect a texture to be pushed in the stack. - drawlist: maintaining bounding box per command would allow to merge draw command when clipping isn't relied on (typical non-scrolling window or non-overflowing column would merge with previous command). - - drawlist: avoid passing null (-9999,+9999) rectangle to end-user, instead perhaps pass rectangle based on io.DisplaySize? - drawlist: primtiives/helpers to manipulate vertices post submission, so e.g. a quad/rect can be resized to fit later submitted content, _without_ using the ChannelSplit api + - drawlist: make it easier to toggle AA per primitive, so we can use e.g. non-AA fill + AA borders more naturally - drawlist: non-AA strokes have gaps between points (#593, #288), especially RenderCheckmark(). - drawlist: would be good to be able to deep copy a draw list (ImVector= op?). - drawlist/opt: AddRect() axis aligned pixel aligned (no-aa) could use 8 triangles instead of 16 and no normal calculation. diff --git a/imgui.cpp b/imgui.cpp index 1490d042d640..ce3c09c039bb 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -213,7 +213,8 @@ Here is a change-log of API breaking changes, if you are using one of the functions listed, expect to have to fix some code. Also read releases logs https://github.com/ocornut/imgui/releases for more details. - - 2017/12/21 (1.53) - removed 'bool anti_aliased = true' final parameter of ImDrawList::AddPolyline() and ImDrawList::AddConvexPolyFilled(). Anti-aliasing is controlled via the regular style.AntiAliased flags. + - 2017/12/21 (1.53) - renamed style.AntiAliasedShapes to style.AntiAliasedFill for consistency and as a way to explicitly break code that manipulate those flag at runtime. You can now manipulate ImDrawList::Flags + - 2017/12/21 (1.53) - removed 'bool anti_aliased = true' final parameter of ImDrawList::AddPolyline() and ImDrawList::AddConvexPolyFilled(). Prefer manipulating ImDrawList::Flags. - 2017/12/14 (1.53) - using the ImGuiWindowFlags_NoScrollWithMouse flag on a child window forwards the mouse wheel event to the parent window, unless either ImGuiWindowFlags_NoInputs or ImGuiWindowFlags_NoScrollbar are also set. - 2017/12/13 (1.53) - renamed GetItemsLineHeightWithSpacing() to GetFrameHeightWithSpacing(). Kept redirection function (will obsolete). - 2017/12/13 (1.53) - obsoleted IsRootWindowFocused() in favor of using IsWindowFocused(ImGuiFocusedFlags_RootWindow). Kept redirection function (will obsolete). @@ -735,7 +736,7 @@ ImGuiStyle::ImGuiStyle() DisplayWindowPadding = ImVec2(22,22); // Window positions are clamped to be visible within the display area by at least this amount. Only covers regular windows. DisplaySafeAreaPadding = ImVec2(4,4); // If you cannot see the edge of your screen (e.g. on a TV) increase the safe area padding. Covers popups/tooltips as well regular windows. AntiAliasedLines = true; // Enable anti-aliasing on lines/borders. Disable if you are really short on CPU/GPU. - AntiAliasedShapes = true; // Enable anti-aliasing on filled shapes (rounded rectangles, circles, etc.) + AntiAliasedFill = true; // Enable anti-aliasing on filled shapes (rounded rectangles, circles, etc.) CurveTessellationTol = 1.25f; // Tessellation tolerance when using PathBezierCurveTo() without a specific number of segments. Decrease for highly tessellated curves (higher quality, more polygons), increase to reduce quality. ImGui::StyleColorsClassic(this); @@ -2290,6 +2291,7 @@ void ImGui::NewFrame() g.OverlayDrawList.Clear(); g.OverlayDrawList.PushTextureID(g.IO.Fonts->TexID); g.OverlayDrawList.PushClipRectFullScreen(); + g.OverlayDrawList.Flags = (g.Style.AntiAliasedLines ? ImDrawListFlags_AntiAliasedLines : 0) | (g.Style.AntiAliasedFill ? ImDrawListFlags_AntiAliasedFill : 0); // Mark rendering data as invalid to prevent user who may have a handle on it to use it g.RenderDrawData.Valid = false; @@ -4475,8 +4477,9 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) window->LastFrameActive = current_frame; window->IDStack.resize(1); - // Clear draw list, setup texture, outer clipping rectangle + // Setup draw list and outer clipping rectangle window->DrawList->Clear(); + window->DrawList->Flags = (g.Style.AntiAliasedLines ? ImDrawListFlags_AntiAliasedLines : 0) | (g.Style.AntiAliasedFill ? ImDrawListFlags_AntiAliasedFill : 0); window->DrawList->PushTextureID(g.Font->ContainerAtlas->TexID); ImRect fullscreen_rect(GetVisibleRect()); if ((flags & ImGuiWindowFlags_ChildWindow) && !(flags & ImGuiWindowFlags_Popup)) @@ -11662,11 +11665,10 @@ void ImGui::ShowMetricsWindow(bool* p_open) ImGui::Selectable(buf, false); if (ImGui::IsItemHovered()) { - ImGuiStyle& style = ImGui::GetStyle(); - bool backup_aa_lines = style.AntiAliasedLines; - style.AntiAliasedLines = false; // Disable AA on triangle outlines at is more readable for very large and thin triangles. + ImDrawListFlags backup_flags = overlay_draw_list->Flags; + overlay_draw_list->Flags &= ~ImDrawListFlags_AntiAliasedLines; // Disable AA on triangle outlines at is more readable for very large and thin triangles. overlay_draw_list->AddPolyline(triangles_pos, 3, IM_COL32(255,255,0,255), true, 1.0f); - style.AntiAliasedLines = backup_aa_lines; + overlay_draw_list->Flags = backup_flags; } } ImGui::TreePop(); diff --git a/imgui.h b/imgui.h index 2185d0665a63..c313080ad669 100644 --- a/imgui.h +++ b/imgui.h @@ -79,6 +79,7 @@ typedef int ImGuiKey; // enum: a key identifier (ImGui-side enum) typedef int ImGuiMouseCursor; // enum: a mouse cursor identifier // enum ImGuiMouseCursor_ typedef int ImGuiStyleVar; // enum: a variable identifier for styling // enum ImGuiStyleVar_ typedef int ImDrawCornerFlags; // flags: for ImDrawList::AddRect*() etc. // enum ImDrawCornerFlags_ +typedef int ImDrawListFlags; // flags: for ImDrawList // enum ImDrawListFlags_ typedef int ImGuiColorEditFlags; // flags: for ColorEdit*(), ColorPicker*() // enum ImGuiColorEditFlags_ typedef int ImGuiColumnsFlags; // flags: for *Columns*() // enum ImGuiColumnsFlags_ typedef int ImGuiDragDropFlags; // flags: for *DragDrop*() // enum ImGuiDragDropFlags_ @@ -855,7 +856,7 @@ struct ImGuiStyle ImVec2 DisplayWindowPadding; // Window positions are clamped to be visible within the display area by at least this amount. Only covers regular windows. ImVec2 DisplaySafeAreaPadding; // If you cannot see the edge of your screen (e.g. on a TV) increase the safe area padding. Covers popups/tooltips as well regular windows. bool AntiAliasedLines; // Enable anti-aliasing on lines/borders. Disable if you are really tight on CPU/GPU. - bool AntiAliasedShapes; // Enable anti-aliasing on filled shapes (rounded rectangles, circles, etc.) + bool AntiAliasedFill; // Enable anti-aliasing on filled shapes (rounded rectangles, circles, etc.) float CurveTessellationTol; // Tessellation tolerance when using PathBezierCurveTo() without a specific number of segments. Decrease for highly tessellated curves (higher quality, more polygons), increase to reduce quality. ImVec4 Colors[ImGuiCol_COUNT]; @@ -1372,6 +1373,12 @@ enum ImDrawCornerFlags_ ImDrawCornerFlags_All = 0xF // In your function calls you may use ~0 (= all bits sets) instead of ImDrawCornerFlags_All, as a convenience }; +enum ImDrawListFlags_ +{ + ImDrawListFlags_AntiAliasedLines = 1 << 0, + ImDrawListFlags_AntiAliasedFill = 1 << 1 +}; + // Draw command list // This is the low-level list of polygons that ImGui functions are filling. At the end of the frame, all command lists are passed to your ImGuiIO::RenderDrawListFn function for rendering. // Each ImGui window contains its own ImDrawList. You can use ImGui::GetWindowDrawList() to access the current window draw list and draw custom primitives. @@ -1386,6 +1393,7 @@ struct ImDrawList ImVector VtxBuffer; // Vertex buffer. // [Internal, used while building lists] + ImDrawListFlags Flags; // Flags, you may poke into these to adjust anti-aliasing settings per-primitive. const ImDrawListSharedData* _Data; // Pointer to shared draw data (you can use ImGui::GetDrawListSharedData() to get the one from current ImGui context) const char* _OwnerName; // Pointer to owner window's name for debugging unsigned int _VtxCurrentIdx; // [Internal] == VtxBuffer.Size diff --git a/imgui_demo.cpp b/imgui_demo.cpp index a2bf1be563e6..4f2705db1163 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -1983,7 +1983,7 @@ void ImGui::ShowStyleEditor(ImGuiStyle* ref) if (ImGui::TreeNode("Rendering")) { ImGui::Checkbox("Anti-aliased lines", &style.AntiAliasedLines); ImGui::SameLine(); ShowHelpMarker("When disabling anti-aliasing lines, you'll probably want to disable borders in your style as well."); - ImGui::Checkbox("Anti-aliased shapes", &style.AntiAliasedShapes); + ImGui::Checkbox("Anti-aliased fill", &style.AntiAliasedFill); ImGui::PushItemWidth(100); ImGui::DragFloat("Curve Tessellation Tolerance", &style.CurveTessellationTol, 0.02f, 0.10f, FLT_MAX, NULL, 2.0f); if (style.CurveTessellationTol < 0.0f) style.CurveTessellationTol = 0.10f; diff --git a/imgui_draw.cpp b/imgui_draw.cpp index 1136e274a66b..2ce3c0bdc3fb 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -304,6 +304,7 @@ void ImDrawList::Clear() CmdBuffer.resize(0); IdxBuffer.resize(0); VtxBuffer.resize(0); + Flags = ImDrawListFlags_AntiAliasedLines | ImDrawListFlags_AntiAliasedFill; _VtxCurrentIdx = 0; _VtxWritePtr = NULL; _IdxWritePtr = NULL; @@ -598,15 +599,13 @@ void ImDrawList::AddPolyline(const ImVec2* points, const int points_count, ImU32 return; const ImVec2 uv = _Data->TexUvWhitePixel; - bool anti_aliased = GImGui->Style.AntiAliasedLines; - //if (ImGui::GetIO().KeyCtrl) anti_aliased = false; // Debug int count = points_count; if (!closed) count = points_count-1; const bool thick_line = thickness > 1.0f; - if (anti_aliased) + if (Flags & ImDrawListFlags_AntiAliasedLines) { // Anti-aliased stroke const float AA_SIZE = 1.0f; @@ -776,10 +775,8 @@ void ImDrawList::AddPolyline(const ImVec2* points, const int points_count, ImU32 void ImDrawList::AddConvexPolyFilled(const ImVec2* points, const int points_count, ImU32 col) { const ImVec2 uv = _Data->TexUvWhitePixel; - bool anti_aliased = GImGui->Style.AntiAliasedShapes; - //if (ImGui::GetIO().KeyCtrl) anti_aliased = false; // Debug - if (anti_aliased) + if (Flags & ImDrawListFlags_AntiAliasedFill) { // Anti-aliased Fill const float AA_SIZE = 1.0f; From c8c872c75380f4094665bbebd22089c445fcf9ee Mon Sep 17 00:00:00 2001 From: omar Date: Thu, 21 Dec 2017 13:43:09 +0100 Subject: [PATCH 327/823] Internals: String functions uses size_t in their signature --- imgui.cpp | 18 +++++++++--------- imgui_internal.h | 8 ++++---- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index ce3c09c039bb..272859c32357 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -911,17 +911,17 @@ int ImStricmp(const char* str1, const char* str2) return d; } -int ImStrnicmp(const char* str1, const char* str2, int count) +int ImStrnicmp(const char* str1, const char* str2, size_t count) { int d = 0; while (count > 0 && (d = toupper(*str2) - toupper(*str1)) == 0 && *str1) { str1++; str2++; count--; } return d; } -void ImStrncpy(char* dst, const char* src, int count) +void ImStrncpy(char* dst, const char* src, size_t count) { if (count < 1) return; - strncpy(dst, src, (size_t)count); + strncpy(dst, src, count); dst[count-1] = 0; } @@ -992,7 +992,7 @@ static const char* ImAtoi(const char* src, int* output) // Ideally we would test for only one of those limits at runtime depending on the behavior the vsnprintf(), but trying to deduct it at compile time sounds like a pandora can of worm. // B) When buf==NULL vsnprintf() will return the output size. #ifndef IMGUI_DISABLE_FORMAT_STRING_FUNCTIONS -int ImFormatString(char* buf, int buf_size, const char* fmt, ...) +int ImFormatString(char* buf, size_t buf_size, const char* fmt, ...) { va_list args; va_start(args, fmt); @@ -1000,19 +1000,19 @@ int ImFormatString(char* buf, int buf_size, const char* fmt, ...) va_end(args); if (buf == NULL) return w; - if (w == -1 || w >= buf_size) - w = buf_size - 1; + if (w == -1 || w >= (int)buf_size) + w = (int)buf_size - 1; buf[w] = 0; return w; } -int ImFormatStringV(char* buf, int buf_size, const char* fmt, va_list args) +int ImFormatStringV(char* buf, size_t buf_size, const char* fmt, va_list args) { int w = vsnprintf(buf, buf_size, fmt, args); if (buf == NULL) return w; - if (w == -1 || w >= buf_size) - w = buf_size - 1; + if (w == -1 || w >= (int)buf_size) + w = (int)buf_size - 1; buf[w] = 0; return w; } diff --git a/imgui_internal.h b/imgui_internal.h index ca15636719e1..060b200415b0 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -103,15 +103,15 @@ IMGUI_API void ImTriangleBarycentricCoords(const ImVec2& a, const ImVec // Helpers: String IMGUI_API int ImStricmp(const char* str1, const char* str2); -IMGUI_API int ImStrnicmp(const char* str1, const char* str2, int count); -IMGUI_API void ImStrncpy(char* dst, const char* src, int count); +IMGUI_API int ImStrnicmp(const char* str1, const char* str2, size_t count); +IMGUI_API void ImStrncpy(char* dst, const char* src, size_t count); IMGUI_API char* ImStrdup(const char* str); IMGUI_API char* ImStrchrRange(const char* str_begin, const char* str_end, char c); IMGUI_API int ImStrlenW(const ImWchar* str); IMGUI_API const ImWchar*ImStrbolW(const ImWchar* buf_mid_line, const ImWchar* buf_begin); // Find beginning-of-line IMGUI_API const char* ImStristr(const char* haystack, const char* haystack_end, const char* needle, const char* needle_end); -IMGUI_API int ImFormatString(char* buf, int buf_size, const char* fmt, ...) IM_FMTARGS(3); -IMGUI_API int ImFormatStringV(char* buf, int buf_size, const char* fmt, va_list args) IM_FMTLIST(3); +IMGUI_API int ImFormatString(char* buf, size_t buf_size, const char* fmt, ...) IM_FMTARGS(3); +IMGUI_API int ImFormatStringV(char* buf, size_t buf_size, const char* fmt, va_list args) IM_FMTLIST(3); // Helpers: Math // We are keeping those not leaking to the user by default, in the case the user has implicit cast operators between ImVec2 and its own types (when IM_VEC2_CLASS_EXTRA is defined) From 8d21ee56d2a4ae50a5ca4c84442280251d945e84 Mon Sep 17 00:00:00 2001 From: omar Date: Fri, 22 Dec 2017 20:19:48 +0100 Subject: [PATCH 328/823] ImDrawList, Font: Fixed bug introduced in 531c11d5c72890f324c9734ef5c860408b8a7f3d (#1519) --- imgui.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 272859c32357..943b63eccca4 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1922,7 +1922,7 @@ static void SetCurrentWindow(ImGuiWindow* window) ImGuiContext& g = *GImGui; g.CurrentWindow = window; if (window) - g.FontSize = window->CalcFontSize(); + g.FontSize = g.DrawListSharedData.FontSize = window->CalcFontSize(); } void ImGui::SetActiveID(ImGuiID id, ImGuiWindow* window) @@ -5843,7 +5843,7 @@ void ImGui::SetWindowFontScale(float scale) ImGuiContext& g = *GImGui; ImGuiWindow* window = GetCurrentWindow(); window->FontWindowScale = scale; - g.FontSize = window->CalcFontSize(); + g.FontSize = g.DrawListSharedData.FontSize = window->CalcFontSize(); } // User generally sees positions in window coordinates. Internally we store CursorPos in absolute screen coordinates because it is more convenient. From e1a103b251f219d567c60f8cffda100a057523c1 Mon Sep 17 00:00:00 2001 From: omar Date: Fri, 22 Dec 2017 13:41:41 +0100 Subject: [PATCH 329/823] Drag and Drop: Disable tracking mouse button ownership when an external drag source is active, to make it easier to achieve drag and drop over multiple OS windows. (#143) --- imgui.cpp | 5 +++-- imgui_demo.cpp | 5 ++++- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 943b63eccca4..81a37d7adca9 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2456,8 +2456,9 @@ void ImGui::NewFrame() g.OsImePosRequest = ImVec2(1.0f, 1.0f); // OS Input Method Editor showing on top-left of our window by default // If mouse was first clicked outside of ImGui bounds we also cancel out hovering. - // FIXME: For patterns of drag and drop between "application" and "imgui" we may need to rework/remove this test (first committed 311c0ca9 on 2015/02) - if (!mouse_avail_to_imgui) + // FIXME: For patterns of drag and drop across OS windows, we may need to rework/remove this test (first committed 311c0ca9 on 2015/02) + bool mouse_dragging_extern_payload = g.DragDropActive && (g.DragDropSourceFlags & ImGuiDragDropFlags_SourceExtern) != 0; + if (!mouse_avail_to_imgui && !mouse_dragging_extern_payload) g.HoveredWindow = g.HoveredRootWindow = NULL; // Scale & Scrolling diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 4f2705db1163..fb0cff59fb52 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -1734,7 +1734,10 @@ void ImGui::ShowTestWindow(bool* p_open) if (ImGui::TreeNode("Keyboard & Mouse State")) { - ImGui::Text("Mouse pos: (%g, %g)", io.MousePos.x, io.MousePos.y); + if (ImGui::IsMousePosValid()) + ImGui::Text("Mouse pos: (%g, %g)", io.MousePos.x, io.MousePos.y); + else + ImGui::Text("Mouse pos: "); ImGui::Text("Mouse down:"); for (int i = 0; i < IM_ARRAYSIZE(io.MouseDown); i++) if (io.MouseDownDuration[i] >= 0.0f) { ImGui::SameLine(); ImGui::Text("b%d (%.02f secs)", i, io.MouseDownDuration[i]); } ImGui::Text("Mouse clicked:"); for (int i = 0; i < IM_ARRAYSIZE(io.MouseDown); i++) if (ImGui::IsMouseClicked(i)) { ImGui::SameLine(); ImGui::Text("b%d", i); } ImGui::Text("Mouse dbl-clicked:"); for (int i = 0; i < IM_ARRAYSIZE(io.MouseDown); i++) if (ImGui::IsMouseDoubleClicked(i)) { ImGui::SameLine(); ImGui::Text("b%d", i); } From 471bcf8b5e5caa341293fb0b0e79daf19357189b Mon Sep 17 00:00:00 2001 From: omar Date: Fri, 22 Dec 2017 19:35:58 +0100 Subject: [PATCH 330/823] Columns: Fixed dragging when using a same of columns multiple times in the frame. (#125) --- imgui.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 81a37d7adca9..2a1f5e8f8dc2 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -10867,6 +10867,8 @@ static float PixelsToOffsetNorm(const ImGuiColumnsSet* columns, float offset) return (offset - columns->MinX) / (columns->MaxX - columns->MinX); } +static inline float GetColumnsRectHalfWidth() { return 4.0f; } + static float GetDraggedColumnOffset(ImGuiColumnsSet* columns, int column_index) { // Active (dragged) column always follow mouse. The reason we need this is that dragging a column to the right edge of an auto-resizing @@ -10876,7 +10878,7 @@ static float GetDraggedColumnOffset(ImGuiColumnsSet* columns, int column_index) IM_ASSERT(column_index > 0); // We cannot drag column 0. If you get this assert you may have a conflict between the ID of your columns and another widgets. IM_ASSERT(g.ActiveId == columns->ID + ImGuiID(column_index)); - float x = g.IO.MousePos.x - g.ActiveIdClickOffset.x - window->Pos.x; + float x = g.IO.MousePos.x - g.ActiveIdClickOffset.x + GetColumnsRectHalfWidth() - window->Pos.x; x = ImMax(x, ImGui::GetColumnOffset(column_index - 1) + g.Style.ColumnsMinSpacing); if ((columns->Flags & ImGuiColumnsFlags_NoPreserveWidths)) x = ImMin(x, ImGui::GetColumnOffset(column_index + 1) - g.Style.ColumnsMinSpacing); @@ -11086,7 +11088,7 @@ void ImGui::EndColumns() { float x = window->Pos.x + GetColumnOffset(n); const ImGuiID column_id = columns->ID + ImGuiID(n); - const float column_hw = 4.0f; // Half-width for interaction + const float column_hw = GetColumnsRectHalfWidth(); // Half-width for interaction const ImRect column_rect(ImVec2(x - column_hw, y1), ImVec2(x + column_hw, y2)); KeepAliveID(column_id); if (IsClippedEx(column_rect, column_id, false)) @@ -11098,8 +11100,6 @@ void ImGui::EndColumns() ButtonBehavior(column_rect, column_id, &hovered, &held); if (hovered || held) g.MouseCursor = ImGuiMouseCursor_ResizeEW; - if (held && g.ActiveIdIsJustActivated) - g.ActiveIdClickOffset.x -= column_hw; // Store from center of column line (we used a 8 wide rect for columns clicking). This is used by GetDraggedColumnOffset(). if (held && !(columns->Columns[n].Flags & ImGuiColumnsFlags_NoResize)) dragging_column = n; } From 46dcd9aa50148a0904f084713f38a0c53b1980d0 Mon Sep 17 00:00:00 2001 From: omar Date: Fri, 22 Dec 2017 19:45:15 +0100 Subject: [PATCH 331/823] Columns: Made PixelsToOffsetNorm() properly symetrical to OffsetNormToPixels() (#125) --- imgui.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 2a1f5e8f8dc2..dd580538cf2f 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -10864,7 +10864,7 @@ static float OffsetNormToPixels(const ImGuiColumnsSet* columns, float offset_nor static float PixelsToOffsetNorm(const ImGuiColumnsSet* columns, float offset) { - return (offset - columns->MinX) / (columns->MaxX - columns->MinX); + return offset / (columns->MaxX - columns->MinX); } static inline float GetColumnsRectHalfWidth() { return 4.0f; } @@ -10951,7 +10951,7 @@ void ImGui::SetColumnOffset(int column_index, float offset) if (!(columns->Flags & ImGuiColumnsFlags_NoForceWithinWindow)) offset = ImMin(offset, columns->MaxX - g.Style.ColumnsMinSpacing * (columns->Count - column_index)); - columns->Columns[column_index].OffsetNorm = PixelsToOffsetNorm(columns, offset); + columns->Columns[column_index].OffsetNorm = PixelsToOffsetNorm(columns, offset - columns->MinX); if (preserve_width) SetColumnOffset(column_index + 1, offset + ImMax(g.Style.ColumnsMinSpacing, width)); @@ -11015,7 +11015,7 @@ void ImGui::BeginColumns(const char* str_id, int columns_count, ImGuiColumnsFlag // Set state for first column const float content_region_width = (window->SizeContentsExplicit.x != 0.0f) ? (window->SizeContentsExplicit.x) : (window->Size.x -window->ScrollbarSizes.x); columns->MinX = window->DC.IndentX - g.Style.ItemSpacing.x; // Lock our horizontal range - //column->ColumnsMaxX = content_region_width - window->Scroll.x -((window->Flags & ImGuiWindowFlags_NoScrollbar) ? 0 : g.Style.ScrollbarSize);// - window->WindowPadding().x; + //column->MaxX = content_region_width - window->Scroll.x - ((window->Flags & ImGuiWindowFlags_NoScrollbar) ? 0 : g.Style.ScrollbarSize);// - window->WindowPadding().x; columns->MaxX = content_region_width - window->Scroll.x; columns->StartPosY = window->DC.CursorPos.y; columns->StartMaxPosX = window->DC.CursorMaxPos.x; @@ -11043,7 +11043,7 @@ void ImGui::BeginColumns(const char* str_id, int columns_count, ImGuiColumnsFlag ImGuiColumnData* column = &columns->Columns[n]; float t = column->OffsetNorm; if (!(columns->Flags & ImGuiColumnsFlags_NoForceWithinWindow)) - t = ImMin(t, PixelsToOffsetNorm(columns, columns->MaxX - g.Style.ColumnsMinSpacing * (columns->Count - n))); + t = ImMin(t, PixelsToOffsetNorm(columns, (columns->MaxX - columns->MinX) - g.Style.ColumnsMinSpacing * (columns->Count - n))); column->OffsetNorm = t; if (n == columns_count) From cf9b893841ba8e9e380332825605735423d3cab0 Mon Sep 17 00:00:00 2001 From: omar Date: Sat, 23 Dec 2017 13:40:01 +0100 Subject: [PATCH 332/823] Examples: Added null_example/ which is helpful for quick testing on multiple compilers/settings without relyong on graphics library. --- examples/null_example/build_win32.bat | 3 +++ examples/null_example/main.cpp | 33 +++++++++++++++++++++++++++ 2 files changed, 36 insertions(+) create mode 100644 examples/null_example/build_win32.bat create mode 100644 examples/null_example/main.cpp diff --git a/examples/null_example/build_win32.bat b/examples/null_example/build_win32.bat new file mode 100644 index 000000000000..7bb78232af62 --- /dev/null +++ b/examples/null_example/build_win32.bat @@ -0,0 +1,3 @@ +@REM Build for Visual Studio compiler. Run your copy of vcvars32.bat or vcvarsall.bat to setup command-line compiler. +mkdir Debug +cl /nologo /Zi /MD /I ..\.. *.cpp ..\..\*.cpp /FeDebug/null_example.exe /FoDebug/ /link gdi32.lib shell32.lib diff --git a/examples/null_example/main.cpp b/examples/null_example/main.cpp new file mode 100644 index 000000000000..b12f75c960d2 --- /dev/null +++ b/examples/null_example/main.cpp @@ -0,0 +1,33 @@ +// ImGui - null/dummy example application (compile and link imgui with no inputs, no outputs) +#include +#include + +int main(int, char**) +{ + ImGuiIO& io = ImGui::GetIO(); + + // Build atlas + unsigned char* tex_pixels = NULL; + int tex_w, tex_h; + io.Fonts->GetTexDataAsRGBA32(&tex_pixels, &tex_w, &tex_h); + + for (int n = 0; n < 50; n++) + { + printf("NewFrame() %d\n", n); + io.DisplaySize = ImVec2(1920, 1080); + io.DeltaTime = 1.0f / 60.0f; + ImGui::NewFrame(); + + static float f = 0.0f; + ImGui::Text("Hello, world!"); + ImGui::SliderFloat("float", &f, 0.0f, 1.0f); + ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / io.Framerate, io.Framerate); + ImGui::ShowTestWindow(NULL); + + ImGui::Render(); + } + + printf("Shutdown()\n"); + ImGui::Shutdown(); + return 0; +} From 1f26652944d0a04dc9716578dcddef6ed3b67de1 Mon Sep 17 00:00:00 2001 From: omar Date: Sat, 23 Dec 2017 14:07:03 +0100 Subject: [PATCH 333/823] Various zealous warning fixes (thanks Clang). --- imgui.cpp | 9 ++++----- imgui.h | 2 +- imgui_draw.cpp | 5 ++--- imgui_internal.h | 2 +- 4 files changed, 8 insertions(+), 10 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index dd580538cf2f..26c3b698e6e4 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -586,7 +586,6 @@ #include "imgui.h" #define IMGUI_DEFINE_MATH_OPERATORS -#define IMGUI_DEFINE_PLACEMENT_NEW #include "imgui_internal.h" #include // toupper, isprint @@ -3272,16 +3271,16 @@ void ImGui::RenderTriangle(ImVec2 p_min, ImGuiDir dir, float scale) switch (dir) { case ImGuiDir_Up: - r = -r; // ...fall through, no break! case ImGuiDir_Down: + if (dir == ImGuiDir_Up) r = -r; center.y -= r * 0.25f; a = ImVec2(0,1) * r; b = ImVec2(-0.866f,-0.5f) * r; c = ImVec2(+0.866f,-0.5f) * r; break; case ImGuiDir_Left: - r = -r; // ...fall through, no break! case ImGuiDir_Right: + if (dir == ImGuiDir_Left) r = -r; center.x -= r * 0.25f; a = ImVec2(1,0) * r; b = ImVec2(-0.500f,+0.866f) * r; @@ -10254,7 +10253,7 @@ static void RenderArrow(ImDrawList* draw_list, ImVec2 pos, ImVec2 half_sz, ImGui case ImGuiDir_Right: draw_list->AddTriangleFilled(ImVec2(pos.x - half_sz.x, pos.y + half_sz.y), ImVec2(pos.x - half_sz.x, pos.y - half_sz.y), pos, col); return; case ImGuiDir_Up: draw_list->AddTriangleFilled(ImVec2(pos.x + half_sz.x, pos.y + half_sz.y), ImVec2(pos.x - half_sz.x, pos.y + half_sz.y), pos, col); return; case ImGuiDir_Down: draw_list->AddTriangleFilled(ImVec2(pos.x - half_sz.x, pos.y - half_sz.y), ImVec2(pos.x + half_sz.x, pos.y - half_sz.y), pos, col); return; - default: return; // Fix warning for ImGuiDir_None + default: break; // Fix warning for ImGuiDir_None } } @@ -11491,7 +11490,7 @@ void ImGui::EndDragDropTarget() #if defined(_WIN32) && !defined(_WINDOWS_) && (!defined(IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCTIONS) || !defined(IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS)) #undef WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN -#include +#include #endif // Win32 API clipboard implementation diff --git a/imgui.h b/imgui.h index c313080ad669..11213d69cd66 100644 --- a/imgui.h +++ b/imgui.h @@ -622,7 +622,7 @@ enum ImGuiFocusedFlags_ { ImGuiFocusedFlags_ChildWindows = 1 << 0, // IsWindowFocused(): Return true if any children of the window is focused ImGuiFocusedFlags_RootWindow = 1 << 1, // IsWindowFocused(): Test from root window (top most parent of the current hierarchy) - ImGuiFocusedFlags_RootAndChildWindows = ImGuiFocusedFlags_RootWindow | ImGuiFocusedFlags_ChildWindows, + ImGuiFocusedFlags_RootAndChildWindows = ImGuiFocusedFlags_RootWindow | ImGuiFocusedFlags_ChildWindows }; // Flags for ImGui::IsItemHovered(), ImGui::IsWindowHovered() diff --git a/imgui_draw.cpp b/imgui_draw.cpp index 2ce3c0bdc3fb..48500c7ce9c9 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -15,7 +15,6 @@ #include "imgui.h" #define IMGUI_DEFINE_MATH_OPERATORS -#define IMGUI_DEFINE_PLACEMENT_NEW #include "imgui_internal.h" #include // vsnprintf, sscanf, printf @@ -1254,8 +1253,8 @@ void ImGui::ShadeVertsLinearUV(ImDrawVert* vert_start, ImDrawVert* vert_end, con const ImVec2 size = b - a; const ImVec2 uv_size = uv_b - uv_a; const ImVec2 scale = ImVec2( - size.x ? (uv_size.x / size.x) : 0.0f, - size.y ? (uv_size.y / size.y) : 0.0f); + size.x != 0.0f ? (uv_size.x / size.x) : 0.0f, + size.y != 0.0f ? (uv_size.y / size.y) : 0.0f); if (clamp) { diff --git a/imgui_internal.h b/imgui_internal.h index 060b200415b0..1e0f8ae1f5d9 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -230,7 +230,7 @@ enum ImGuiAxis { ImGuiAxis_None = -1, ImGuiAxis_X = 0, - ImGuiAxis_Y = 1, + ImGuiAxis_Y = 1 }; enum ImGuiPlotType From b263bc568931b7065926a06e6a293fc05279c6e5 Mon Sep 17 00:00:00 2001 From: omar Date: Sat, 23 Dec 2017 14:07:27 +0100 Subject: [PATCH 334/823] Examples: DirectX: Using IM_ARRAYSIZE() --- examples/directx10_example/imgui_impl_dx10.cpp | 2 +- examples/directx11_example/imgui_impl_dx11.cpp | 2 +- examples/directx9_example/imgui_impl_dx9.cpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/directx10_example/imgui_impl_dx10.cpp b/examples/directx10_example/imgui_impl_dx10.cpp index 4670f053792b..59152673b261 100644 --- a/examples/directx10_example/imgui_impl_dx10.cpp +++ b/examples/directx10_example/imgui_impl_dx10.cpp @@ -228,7 +228,7 @@ void ImGui_ImplDX10_RenderDrawLists(ImDrawData* draw_data) static bool IsAnyMouseButtonDown() { ImGuiIO& io = ImGui::GetIO(); - for (int n = 0; n < ARRAYSIZE(io.MouseDown); n++) + for (int n = 0; n < IM_ARRAYSIZE(io.MouseDown); n++) if (io.MouseDown[n]) return true; return false; diff --git a/examples/directx11_example/imgui_impl_dx11.cpp b/examples/directx11_example/imgui_impl_dx11.cpp index df02577bb334..af6e54f49601 100644 --- a/examples/directx11_example/imgui_impl_dx11.cpp +++ b/examples/directx11_example/imgui_impl_dx11.cpp @@ -235,7 +235,7 @@ void ImGui_ImplDX11_RenderDrawLists(ImDrawData* draw_data) static bool IsAnyMouseButtonDown() { ImGuiIO& io = ImGui::GetIO(); - for (int n = 0; n < ARRAYSIZE(io.MouseDown); n++) + for (int n = 0; n < IM_ARRAYSIZE(io.MouseDown); n++) if (io.MouseDown[n]) return true; return false; diff --git a/examples/directx9_example/imgui_impl_dx9.cpp b/examples/directx9_example/imgui_impl_dx9.cpp index 24f53ba3a598..484e84cde023 100644 --- a/examples/directx9_example/imgui_impl_dx9.cpp +++ b/examples/directx9_example/imgui_impl_dx9.cpp @@ -174,7 +174,7 @@ void ImGui_ImplDX9_RenderDrawLists(ImDrawData* draw_data) static bool IsAnyMouseButtonDown() { ImGuiIO& io = ImGui::GetIO(); - for (int n = 0; n < ARRAYSIZE(io.MouseDown); n++) + for (int n = 0; n < IM_ARRAYSIZE(io.MouseDown); n++) if (io.MouseDown[n]) return true; return false; From 6172e932728a0fa629d910c1a1534d66a59e386a Mon Sep 17 00:00:00 2001 From: omar Date: Sat, 23 Dec 2017 14:49:23 +0100 Subject: [PATCH 335/823] ImVector: Added assignments and = operators + comments. --- imgui.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/imgui.h b/imgui.h index 11213d69cd66..25c8721a72dc 100644 --- a/imgui.h +++ b/imgui.h @@ -1005,7 +1005,7 @@ namespace ImGui //----------------------------------------------------------------------------- // 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). -// 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! +// Our implementation does NOT call C++ constructors/destructors. This is intentional and we do not require it. Do not use this class as a straight std::vector replacement in your code! template class ImVector { @@ -1020,6 +1020,8 @@ class ImVector ImVector() { Size = Capacity = 0; Data = NULL; } ~ImVector() { if (Data) ImGui::MemFree(Data); } + ImVector(const ImVector& rhs) { Size = Capacity = 0; Data = NULL; if (rhs.Size) { resize(rhs.Size); memcpy(Data, rhs.Data, (size_t)rhs.Size * sizeof(T)); } } + ImVector& operator=(const ImVector& rhs) { resize(rhs.Size); if (rhs.Size) memcpy(Data, rhs.Data, (size_t)rhs.Size * sizeof(T)); return *this; } inline bool empty() const { return Size == 0; } inline int size() const { return Size; } From 8e8b5498f74715cf2caa2feaf28657c438ff7b36 Mon Sep 17 00:00:00 2001 From: omar Date: Sat, 23 Dec 2017 14:51:28 +0100 Subject: [PATCH 336/823] ImVector: insert() uses grow_capacity() - had inconsistent resize policy --- imgui.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/imgui.h b/imgui.h index 25c8721a72dc..35bfb60e2c7b 100644 --- a/imgui.h +++ b/imgui.h @@ -1061,7 +1061,7 @@ class ImVector inline void push_front(const value_type& v) { if (Size == 0) push_back(v); else insert(Data, v); } inline iterator erase(const_iterator it) { IM_ASSERT(it >= Data && it < Data+Size); const ptrdiff_t off = it - Data; memmove(Data + off, Data + off + 1, ((size_t)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 >= Data && it <= Data+Size); const ptrdiff_t off = it - Data; if (Size == Capacity) reserve(Capacity ? Capacity * 2 : 4); if (off < (int)Size) memmove(Data + off + 1, Data + off, ((size_t)Size - (size_t)off) * sizeof(value_type)); Data[off] = v; Size++; return Data + off; } + inline iterator insert(const_iterator it, const value_type& v) { IM_ASSERT(it >= Data && it <= Data+Size); const ptrdiff_t off = it - Data; if (Size == Capacity) reserve(_grow_capacity(Size + 1)); if (off < (int)Size) memmove(Data + off + 1, Data + off, ((size_t)Size - (size_t)off) * sizeof(value_type)); Data[off] = v; Size++; return Data + off; } inline bool contains(const value_type& v) const { const T* data = Data; const T* data_end = Data + Size; while (data < data_end) if (*data++ == v) return true; return false; } }; From 69879dd4f3e25c2d64dff233ef4bda32e6514237 Mon Sep 17 00:00:00 2001 From: omar Date: Sat, 23 Dec 2017 14:51:36 +0100 Subject: [PATCH 337/823] ImVector: Spacing. --- imgui.h | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/imgui.h b/imgui.h index 35bfb60e2c7b..a644337dccfc 100644 --- a/imgui.h +++ b/imgui.h @@ -1018,10 +1018,10 @@ class ImVector typedef value_type* iterator; typedef const value_type* const_iterator; - ImVector() { Size = Capacity = 0; Data = NULL; } - ~ImVector() { if (Data) ImGui::MemFree(Data); } - ImVector(const ImVector& rhs) { Size = Capacity = 0; Data = NULL; if (rhs.Size) { resize(rhs.Size); memcpy(Data, rhs.Data, (size_t)rhs.Size * sizeof(T)); } } - ImVector& operator=(const ImVector& rhs) { resize(rhs.Size); if (rhs.Size) memcpy(Data, rhs.Data, (size_t)rhs.Size * sizeof(T)); return *this; } + inline ImVector() { Size = Capacity = 0; Data = NULL; } + inline ~ImVector() { if (Data) ImGui::MemFree(Data); } + inline ImVector(const ImVector& rhs) { Size = Capacity = 0; Data = NULL; if (rhs.Size) { resize(rhs.Size); memcpy(Data, rhs.Data, (size_t)rhs.Size * sizeof(T)); } } + inline ImVector& operator=(const ImVector& rhs) { resize(rhs.Size); if (rhs.Size) memcpy(Data, rhs.Data, (size_t)rhs.Size * sizeof(T)); return *this; } inline bool empty() const { return Size == 0; } inline int size() const { return Size; } @@ -1037,8 +1037,8 @@ class ImVector 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 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) { int rhs_size = rhs.Size; rhs.Size = Size; Size = rhs_size; int rhs_cap = rhs.Capacity; rhs.Capacity = Capacity; Capacity = rhs_cap; value_type* rhs_data = rhs.Data; rhs.Data = Data; Data = rhs_data; } inline int _grow_capacity(int size) const { int new_capacity = Capacity ? (Capacity + Capacity/2) : 8; return new_capacity > size ? new_capacity : size; } @@ -1047,7 +1047,8 @@ class ImVector inline void resize(int new_size, const T& v){ if (new_size > Capacity) reserve(_grow_capacity(new_size)); if (new_size > Size) for (int n = Size; n < new_size; n++) Data[n] = v; Size = new_size; } inline void reserve(int new_capacity) { - if (new_capacity <= Capacity) return; + if (new_capacity <= Capacity) + return; T* new_data = (value_type*)ImGui::MemAlloc((size_t)new_capacity * sizeof(T)); if (Data) memcpy(new_data, Data, (size_t)Size * sizeof(T)); @@ -1056,7 +1057,7 @@ class ImVector Capacity = new_capacity; } - inline void push_back(const value_type& v) { if (Size == Capacity) reserve(_grow_capacity(Size+1)); Data[Size++] = v; } + 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 void push_front(const value_type& v) { if (Size == 0) push_back(v); else insert(Data, v); } From 53b24ff79afd2b39d67580c77a68fb7a004def66 Mon Sep 17 00:00:00 2001 From: omar Date: Sat, 23 Dec 2017 15:02:36 +0100 Subject: [PATCH 338/823] Removed reliance on ImU64 type for the ImDrawList assert. (#1184) --- imgui.cpp | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 26c3b698e6e4..147db31d45a7 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2846,15 +2846,17 @@ static void AddDrawListToRenderList(ImVector& out_render_list, ImDr IM_ASSERT(draw_list->IdxBuffer.Size == 0 || draw_list->_IdxWritePtr == draw_list->IdxBuffer.Data + draw_list->IdxBuffer.Size); IM_ASSERT((int)draw_list->_VtxCurrentIdx == draw_list->VtxBuffer.Size); - // Check that draw_list doesn't use more vertices than indexable in a single draw call (default ImDrawIdx = unsigned short = 2 bytes = 64K vertices per window) - // If this assert triggers because you are drawing lots of stuff manually, you can: - // A) Add '#define ImDrawIdx unsigned int' in imconfig.h to set the index size to 4 bytes. You'll need to handle the 4-bytes indices to your renderer. - // For example, the OpenGL example code detect index size at compile-time by doing: - // 'glDrawElements(GL_TRIANGLES, (GLsizei)pcmd->ElemCount, sizeof(ImDrawIdx) == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, idx_buffer_offset);' + // Check that draw_list doesn't use more vertices than indexable in a single draw call (default ImDrawIdx = unsigned short = 2 bytes = 64K vertices per ImDrawList = per window) + // If this assert triggers because you are drawing lots of stuff manually: + // A) Make sure you are coarse clipping, because ImDrawList let all your vertices pass. You can use thre Metrics window to inspect draw list contents. + // B) If you need/want meshes with more than 64K vertices, uncomment the '#define ImDrawIdx unsigned int' line in imconfig.h to set the index size to 4 bytes. + // You'll need to handle the 4-bytes indices to your renderer. For example, the OpenGL example code detect index size at compile-time by doing: + // glDrawElements(GL_TRIANGLES, (GLsizei)pcmd->ElemCount, sizeof(ImDrawIdx) == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, idx_buffer_offset); // Your own engine or render API may use different parameters or function calls to specify index sizes. 2 and 4 bytes indices are generally supported by most API. - // B) If for some reason you cannot use 4 bytes indices or don't want to, a workaround is to call BeginChild()/EndChild() before reaching the 64K limit to split your draw commands in multiple draw lists. - IM_ASSERT(((ImU64)draw_list->_VtxCurrentIdx >> (sizeof(ImDrawIdx)*8)) == 0); // Too many vertices in same ImDrawList. See comment above. - + // C) If for some reason you cannot use 4 bytes indices or don't want to, a workaround is to call BeginChild()/EndChild() before reaching the 64K limit to split your draw commands in multiple draw lists. + if (sizeof(ImDrawIdx) == 2) + IM_ASSERT(draw_list->_VtxCurrentIdx < (1 << 16) && "Too many vertices in ImDrawList using 16-bit indices. Read comment above"); + out_render_list.push_back(draw_list); GImGui->IO.MetricsRenderVertices += draw_list->VtxBuffer.Size; GImGui->IO.MetricsRenderIndices += draw_list->IdxBuffer.Size; From 983d8f5f8ea6c8deac1f8f60389d4b1c8549e9c7 Mon Sep 17 00:00:00 2001 From: omar Date: Sat, 23 Dec 2017 15:15:27 +0100 Subject: [PATCH 339/823] Various zealous warning fixes (Clang). --- imgui.cpp | 5 +++-- imgui_demo.cpp | 3 ++- imgui_draw.cpp | 2 ++ 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 147db31d45a7..649d2e765373 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -3288,7 +3288,8 @@ void ImGui::RenderTriangle(ImVec2 p_min, ImGuiDir dir, float scale) b = ImVec2(-0.500f,+0.866f) * r; c = ImVec2(-0.500f,-0.866f) * r; break; - default: + case ImGuiDir_None: + case ImGuiDir_Count_: IM_ASSERT(0); break; } @@ -10255,7 +10256,7 @@ static void RenderArrow(ImDrawList* draw_list, ImVec2 pos, ImVec2 half_sz, ImGui case ImGuiDir_Right: draw_list->AddTriangleFilled(ImVec2(pos.x - half_sz.x, pos.y + half_sz.y), ImVec2(pos.x - half_sz.x, pos.y - half_sz.y), pos, col); return; case ImGuiDir_Up: draw_list->AddTriangleFilled(ImVec2(pos.x + half_sz.x, pos.y + half_sz.y), ImVec2(pos.x - half_sz.x, pos.y + half_sz.y), pos, col); return; case ImGuiDir_Down: draw_list->AddTriangleFilled(ImVec2(pos.x - half_sz.x, pos.y - half_sz.y), ImVec2(pos.x + half_sz.x, pos.y - half_sz.y), pos, col); return; - default: break; // Fix warning for ImGuiDir_None + case ImGuiDir_None: case ImGuiDir_Count_: break; // Fix warnings } } diff --git a/imgui_demo.cpp b/imgui_demo.cpp index fb0cff59fb52..0624bdd3e6ea 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -1304,7 +1304,8 @@ void ImGui::ShowTestWindow(bool* p_open) if (n > 0) ImGui::SameLine(); ImGui::PushID(n + line * 1000); char num_buf[16]; - const char* label = (!(n%15)) ? "FizzBuzz" : (!(n%3)) ? "Fizz" : (!(n%5)) ? "Buzz" : (sprintf(num_buf, "%d", n), num_buf); + sprintf(num_buf, "%d", n); + const char* label = (!(n%15)) ? "FizzBuzz" : (!(n%3)) ? "Fizz" : (!(n%5)) ? "Buzz" : num_buf; float hue = n*0.05f; ImGui::PushStyleColor(ImGuiCol_Button, (ImVec4)ImColor::HSV(hue, 0.6f, 0.6f)); ImGui::PushStyleColor(ImGuiCol_ButtonHovered, (ImVec4)ImColor::HSV(hue, 0.7f, 0.7f)); diff --git a/imgui_draw.cpp b/imgui_draw.cpp index 48500c7ce9c9..02cf42cca520 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -42,6 +42,7 @@ #pragma clang diagnostic ignored "-Wfloat-equal" // warning : comparing floating point with == or != is unsafe // storing and comparing against same constants ok. #pragma clang diagnostic ignored "-Wglobal-constructors" // warning : declaration requires a global destructor // similar to above, not sure what the exact difference it. #pragma clang diagnostic ignored "-Wsign-conversion" // warning : implicit conversion changes signedness // +#pragma clang diagnostic ignored "-Wcomma" // warning : possible misuse of comma operator here // #if __has_warning("-Wreserved-id-macro") #pragma clang diagnostic ignored "-Wreserved-id-macro" // warning : macro name is a reserved identifier // #endif @@ -77,6 +78,7 @@ namespace IMGUI_STB_NAMESPACE #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wunused-function" #pragma clang diagnostic ignored "-Wmissing-prototypes" +#pragma clang diagnostic ignored "-Wimplicit-fallthrough" #endif #ifdef __GNUC__ From a5739a0aa30f35271213157b994a0fcb0cd773b9 Mon Sep 17 00:00:00 2001 From: omar Date: Sat, 23 Dec 2017 15:19:48 +0100 Subject: [PATCH 340/823] Fixed warning with Clang+MSVC using __int64 to define the helper ImU64 type (#1184) --- imgui.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/imgui.h b/imgui.h index a644337dccfc..de9177c94138 100644 --- a/imgui.h +++ b/imgui.h @@ -92,7 +92,7 @@ typedef int ImGuiTreeNodeFlags; // flags: for TreeNode*(),CollapsingHeader() typedef int ImGuiWindowFlags; // flags: for Begin*() // enum ImGuiWindowFlags_ typedef int (*ImGuiTextEditCallback)(ImGuiTextEditCallbackData *data); typedef void (*ImGuiSizeConstraintCallback)(ImGuiSizeConstraintCallbackData* data); -#ifdef _MSC_VER +#if defined(_MSC_VER) && !defined(__clang__) typedef unsigned __int64 ImU64; // 64-bit unsigned integer #else typedef unsigned long long ImU64; // 64-bit unsigned integer From 9cda86d55a80c9f032af84f657b9fe8e6c7f3f52 Mon Sep 17 00:00:00 2001 From: omar Date: Sat, 23 Dec 2017 16:24:33 +0100 Subject: [PATCH 341/823] Internals: Added IM_NEW, IM_DELETE helper macros (#1517, #484, #504) --- imgui.cpp | 28 ++++++++-------------------- imgui_draw.cpp | 8 +------- imgui_internal.h | 12 ++++++++---- 3 files changed, 17 insertions(+), 31 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 649d2e765373..6173f7121298 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1859,8 +1859,7 @@ ImGuiWindow::ImGuiWindow(ImGuiContext* context, const char* name) ItemWidthDefault = 0.0f; FontWindowScale = 1.0f; - DrawList = (ImDrawList*)ImGui::MemAlloc(sizeof(ImDrawList)); - IM_PLACEMENT_NEW(DrawList) ImDrawList(&context->DrawListSharedData); + DrawList = IM_NEW(ImDrawList)(&context->DrawListSharedData); DrawList->_OwnerName = Name; ParentWindow = NULL; RootWindow = NULL; @@ -1873,11 +1872,8 @@ ImGuiWindow::ImGuiWindow(ImGuiContext* context, const char* name) ImGuiWindow::~ImGuiWindow() { - DrawList->~ImDrawList(); - ImGui::MemFree(DrawList); - DrawList = NULL; - ImGui::MemFree(Name); - Name = NULL; + IM_DELETE(DrawList); + IM_DELETE(Name); } ImGuiID ImGuiWindow::GetID(const char* str, const char* str_end) @@ -2579,8 +2575,7 @@ static void SettingsHandlerWindow_WriteAll(ImGuiContext& g, ImGuiTextBuffer* buf void ImGui::Initialize() { ImGuiContext& g = *GImGui; - g.LogClipboard = (ImGuiTextBuffer*)ImGui::MemAlloc(sizeof(ImGuiTextBuffer)); - IM_PLACEMENT_NEW(g.LogClipboard) ImGuiTextBuffer(); + g.LogClipboard = IM_NEW(ImGuiTextBuffer)(); // Add .ini handle for ImGuiWindow type ImGuiSettingsHandler ini_handler; @@ -2613,10 +2608,7 @@ void ImGui::Shutdown() SaveIniSettingsToDisk(g.IO.IniFilename); for (int i = 0; i < g.Windows.Size; i++) - { - g.Windows[i]->~ImGuiWindow(); - ImGui::MemFree(g.Windows[i]); - } + IM_DELETE(g.Windows[i]); g.Windows.clear(); g.WindowsSortBuffer.clear(); g.CurrentWindow = NULL; @@ -2628,7 +2620,7 @@ void ImGui::Shutdown() g.ActiveIdWindow = NULL; g.MovingWindow = NULL; for (int i = 0; i < g.SettingsWindows.Size; i++) - ImGui::MemFree(g.SettingsWindows[i].Name); + IM_DELETE(g.SettingsWindows[i].Name); g.ColorModifiers.clear(); g.StyleModifiers.clear(); g.FontStack.clear(); @@ -2653,10 +2645,7 @@ void ImGui::Shutdown() g.LogFile = NULL; } if (g.LogClipboard) - { - g.LogClipboard->~ImGuiTextBuffer(); - ImGui::MemFree(g.LogClipboard); - } + IM_DELETE(g.LogClipboard); g.Initialized = false; } @@ -4157,8 +4146,7 @@ static ImGuiWindow* CreateNewWindow(const char* name, ImVec2 size, ImGuiWindowFl ImGuiContext& g = *GImGui; // Create window the first time - ImGuiWindow* window = (ImGuiWindow*)ImGui::MemAlloc(sizeof(ImGuiWindow)); - IM_PLACEMENT_NEW(window) ImGuiWindow(&g, name); + ImGuiWindow* window = IM_NEW(ImGuiWindow)(&g, name); window->Flags = flags; g.WindowsById.SetVoidPtr(window->ID, window); diff --git a/imgui_draw.cpp b/imgui_draw.cpp index 02cf42cca520..793aeffbcbc4 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -1461,15 +1461,9 @@ ImFont* ImFontAtlas::AddFont(const ImFontConfig* font_cfg) // Create new font if (!font_cfg->MergeMode) - { - ImFont* font = (ImFont*)ImGui::MemAlloc(sizeof(ImFont)); - IM_PLACEMENT_NEW(font) ImFont(); - Fonts.push_back(font); - } + Fonts.push_back(IM_NEW(ImFont)); else - { IM_ASSERT(!Fonts.empty()); // When using MergeMode make sure that a font has already been added before. You can use ImGui::GetIO().Fonts->AddFontDefault() to add the default imgui font. - } ConfigData.push_back(*font_cfg); ImFontConfig& new_font_cfg = ConfigData.back(); diff --git a/imgui_internal.h b/imgui_internal.h index 1e0f8ae1f5d9..c08f5082cea9 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -160,10 +160,14 @@ static inline ImVec2 ImMul(const ImVec2& lhs, const ImVec2& rhs) // We call C++ constructor on own allocated memory via the placement "new(ptr) Type()" syntax. // Defining a custom placement new() with a dummy parameter allows us to bypass including which on some platforms complains when user has disabled exceptions. -struct ImPlacementNewDummy {}; -inline void* operator new(size_t, ImPlacementNewDummy, void* ptr) { return ptr; } -inline void operator delete(void*, ImPlacementNewDummy, void*) {} -#define IM_PLACEMENT_NEW(_PTR) new(ImPlacementNewDummy(), _PTR) +struct ImNewAllocDummy {}; +struct ImNewPlacementDummy {}; +inline void* operator new(size_t, ImNewPlacementDummy, void* ptr) { return ptr; } +inline void operator delete(void*, ImNewPlacementDummy, void*) {} // This is only required so we can use the symetrical new() +inline void operator delete(void* p, ImNewAllocDummy) { ImGui::MemFree(p); } +#define IM_PLACEMENT_NEW(_PTR) new(ImNewPlacementDummy(), _PTR) +#define IM_NEW(_TYPE) new(ImNewPlacementDummy(), ImGui::MemAlloc(sizeof(_TYPE))) _TYPE +#define IM_DELETE(_PTR) delete(ImNewAllocDummy(), _PTR), _PTR = NULL //----------------------------------------------------------------------------- // Types From d976e4ea23d389a757800cef79261ad3296fb2c5 Mon Sep 17 00:00:00 2001 From: omar Date: Sat, 23 Dec 2017 16:27:16 +0100 Subject: [PATCH 342/823] Internals: Missing IM_DELETE usage (#1517) --- imgui_draw.cpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/imgui_draw.cpp b/imgui_draw.cpp index 793aeffbcbc4..2ffdf4be30cb 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -1403,10 +1403,7 @@ void ImFontAtlas::ClearTexData() void ImFontAtlas::ClearFonts() { for (int i = 0; i < Fonts.Size; i++) - { - Fonts[i]->~ImFont(); - ImGui::MemFree(Fonts[i]); - } + IM_DELETE(Fonts[i]); Fonts.clear(); } From 6c63c7a8b16fdabbb79f7e7f9c75b9a25f17c631 Mon Sep 17 00:00:00 2001 From: omar Date: Sat, 23 Dec 2017 16:40:12 +0100 Subject: [PATCH 343/823] Various zealous warning fixes (thanks Clang). (Navigation branch) --- imgui.cpp | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index f48eaa91dbc2..6db14ae681d4 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2149,7 +2149,7 @@ static bool NavScoreItem(ImRect cand) // FIXME-NAVIGATION: Introducing biases for vertical navigation, needs to be removed. float dbx = NavScoreItemDistInterval(cand.Min.x, cand.Max.x, curr.Min.x, curr.Max.x); float dby = NavScoreItemDistInterval(ImLerp(cand.Min.y, cand.Max.y, 0.2f), ImLerp(cand.Min.y, cand.Max.y, 0.8f), ImLerp(curr.Min.y, curr.Max.y, 0.2f), ImLerp(curr.Min.y, curr.Max.y, 0.8f)); // Scale down on Y to keep using box-distance for vertically touching items - if (dby && dbx) + if (dby != 0.0f && dbx != 0.0f) dbx = (dbx/1000.0f) + ((dbx > 0.0f) ? +1.0f : -1.0f); float dist_box = fabsf(dbx) + fabsf(dby); @@ -2161,7 +2161,7 @@ static bool NavScoreItem(ImRect cand) // Determine which quadrant of 'curr' our candidate item 'cand' lies in based on distance ImGuiDir quadrant; float dax = 0.0f, day = 0.0f, dist_axial = 0.0f; - if (dbx || dby) + if (dbx != 0.0f || dby != 0.0f) { // For non-overlapping boxes, use distance between boxes dax = dbx; @@ -2169,7 +2169,7 @@ static bool NavScoreItem(ImRect cand) dist_axial = dist_box; quadrant = NavScoreItemGetQuadrant(dbx, dby); } - else if (dcx || dcy) + else if (dcx != 0.0f || dcy != 0.0f) { // For overlapping boxes with different centers, use distance between centers dax = dcx; @@ -2232,7 +2232,10 @@ static bool NavScoreItem(ImRect cand) if (g.NavMoveResultDistBox == FLT_MAX && dist_axial < g.NavMoveResultDistAxial) // Check axial match if (g.NavLayer == 1 && !(g.NavWindow->Flags & ImGuiWindowFlags_ChildMenu)) if ((g.NavMoveDir == ImGuiDir_Left && dax < 0.0f) || (g.NavMoveDir == ImGuiDir_Right && dax > 0.0f) || (g.NavMoveDir == ImGuiDir_Up && day < 0.0f) || (g.NavMoveDir == ImGuiDir_Down && day > 0.0f)) - g.NavMoveResultDistAxial = dist_axial, new_best = true; + { + g.NavMoveResultDistAxial = dist_axial; + new_best = true; + } return new_best; } @@ -8329,7 +8332,8 @@ bool ImGui::SliderBehavior(const ImRect& frame_bb, ImGuiID id, float* v, float v else if (g.ActiveIdSource == ImGuiInputSource_Nav && g.NavActivateDownId == id) { const ImVec2 delta2 = GetNavInputAmount2d(0, ImGuiNavReadMode_RepeatFast, 0.0f, 0.0f); - if (float delta = is_horizontal ? delta2.x : -delta2.y) + float delta = is_horizontal ? delta2.x : -delta2.y; + if (delta != 0.0f) { clicked_t = SliderBehaviorCalcRatioFromValue(*v, v_min, v_max, power, linear_zero_pos); if (decimal_precision == 0 && !is_non_linear) From e9ceef4762a801737ead8f4d3d492f4f8c153306 Mon Sep 17 00:00:00 2001 From: omar Date: Sat, 23 Dec 2017 20:37:36 +0100 Subject: [PATCH 344/823] ImVector: Revert 6172e932728a0fa629d910c1a1534d66a59e386a actually problematic with our current use (because we don't construct the instances). --- imgui.h | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/imgui.h b/imgui.h index de9177c94138..33580dc2ae7d 100644 --- a/imgui.h +++ b/imgui.h @@ -1018,10 +1018,8 @@ class ImVector typedef value_type* iterator; typedef const value_type* const_iterator; - inline ImVector() { Size = Capacity = 0; Data = NULL; } - inline ~ImVector() { if (Data) ImGui::MemFree(Data); } - inline ImVector(const ImVector& rhs) { Size = Capacity = 0; Data = NULL; if (rhs.Size) { resize(rhs.Size); memcpy(Data, rhs.Data, (size_t)rhs.Size * sizeof(T)); } } - inline ImVector& operator=(const ImVector& rhs) { resize(rhs.Size); if (rhs.Size) memcpy(Data, rhs.Data, (size_t)rhs.Size * sizeof(T)); return *this; } + inline ImVector() { Size = Capacity = 0; Data = NULL; } + inline ~ImVector() { if (Data) ImGui::MemFree(Data); } inline bool empty() const { return Size == 0; } inline int size() const { return Size; } From bb8dfe4a3432a6e705a26c21cc5a3e859b93350f Mon Sep 17 00:00:00 2001 From: omar Date: Sat, 23 Dec 2017 23:10:26 +0100 Subject: [PATCH 345/823] Fixed incorrect IM_DELETE macro (9cda86d55a80c9f032af84f657b9fe8e6c7f3f52) (#1517, #484, #504) --- imgui_internal.h | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/imgui_internal.h b/imgui_internal.h index c08f5082cea9..e161a6f14c55 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -160,14 +160,12 @@ static inline ImVec2 ImMul(const ImVec2& lhs, const ImVec2& rhs) // We call C++ constructor on own allocated memory via the placement "new(ptr) Type()" syntax. // Defining a custom placement new() with a dummy parameter allows us to bypass including which on some platforms complains when user has disabled exceptions. -struct ImNewAllocDummy {}; struct ImNewPlacementDummy {}; inline void* operator new(size_t, ImNewPlacementDummy, void* ptr) { return ptr; } inline void operator delete(void*, ImNewPlacementDummy, void*) {} // This is only required so we can use the symetrical new() -inline void operator delete(void* p, ImNewAllocDummy) { ImGui::MemFree(p); } -#define IM_PLACEMENT_NEW(_PTR) new(ImNewPlacementDummy(), _PTR) -#define IM_NEW(_TYPE) new(ImNewPlacementDummy(), ImGui::MemAlloc(sizeof(_TYPE))) _TYPE -#define IM_DELETE(_PTR) delete(ImNewAllocDummy(), _PTR), _PTR = NULL +#define IM_PLACEMENT_NEW(_PTR) new(ImNewPlacementDummy(), _PTR) +#define IM_NEW(_TYPE) new(ImNewPlacementDummy(), ImGui::MemAlloc(sizeof(_TYPE))) _TYPE +template void IM_DELETE(T*& p) { if (p) { p->~T(); ImGui::MemFree(p); p = NULL; } } //----------------------------------------------------------------------------- // Types From cead20753580ad503f028afb46401f2e982af1c2 Mon Sep 17 00:00:00 2001 From: omar Date: Sun, 24 Dec 2017 17:58:41 +0100 Subject: [PATCH 346/823] Comments --- imgui.cpp | 4 ++-- imgui_demo.cpp | 4 ++++ imgui_draw.cpp | 1 + 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 6173f7121298..393b4e503948 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -213,8 +213,8 @@ Here is a change-log of API breaking changes, if you are using one of the functions listed, expect to have to fix some code. Also read releases logs https://github.com/ocornut/imgui/releases for more details. - - 2017/12/21 (1.53) - renamed style.AntiAliasedShapes to style.AntiAliasedFill for consistency and as a way to explicitly break code that manipulate those flag at runtime. You can now manipulate ImDrawList::Flags - - 2017/12/21 (1.53) - removed 'bool anti_aliased = true' final parameter of ImDrawList::AddPolyline() and ImDrawList::AddConvexPolyFilled(). Prefer manipulating ImDrawList::Flags. + - 2017/12/21 (1.53) - ImDrawList: renamed style.AntiAliasedShapes to style.AntiAliasedFill for consistency and as a way to explicitly break code that manipulate those flag at runtime. You can now manipulate ImDrawList::Flags + - 2017/12/21 (1.53) - ImDrawList: removed 'bool anti_aliased = true' final parameter of ImDrawList::AddPolyline() and ImDrawList::AddConvexPolyFilled(). Prefer manipulating ImDrawList::Flags if you need to toggle them during the frame. - 2017/12/14 (1.53) - using the ImGuiWindowFlags_NoScrollWithMouse flag on a child window forwards the mouse wheel event to the parent window, unless either ImGuiWindowFlags_NoInputs or ImGuiWindowFlags_NoScrollbar are also set. - 2017/12/13 (1.53) - renamed GetItemsLineHeightWithSpacing() to GetFrameHeightWithSpacing(). Kept redirection function (will obsolete). - 2017/12/13 (1.53) - obsoleted IsRootWindowFocused() in favor of using IsWindowFocused(ImGuiFocusedFlags_RootWindow). Kept redirection function (will obsolete). diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 0624bdd3e6ea..0b329edc298b 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -1911,6 +1911,8 @@ void ImGui::ShowTestWindow(bool* p_open) ImGui::End(); } +// Demo helper function to select among default colors. See ShowStyleEditor() for more advanced options. +// Here we use the simplified Combo() api that packs items into a single literal string. Useful for quick combo boxes where the choices are known locally. bool ImGui::ShowStyleSelector(const char* label) { static int style_idx = 0; @@ -1927,6 +1929,8 @@ bool ImGui::ShowStyleSelector(const char* label) return false; } +// Demo helper function to select among loaded fonts. +// Here we use the regular BeginCombo()/EndCombo() api which is more the more flexible one. void ImGui::ShowFontSelector(const char* label) { ImGuiIO& io = ImGui::GetIO(); diff --git a/imgui_draw.cpp b/imgui_draw.cpp index 2ffdf4be30cb..bba523a380ae 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -225,6 +225,7 @@ void ImGui::StyleColorsDark(ImGuiStyle* dst) colors[ImGuiCol_DragDropTarget] = ImVec4(1.00f, 1.00f, 0.00f, 0.90f); } +// Those light colors are better suited with a thicker font than the default one + FrameBorder void ImGui::StyleColorsLight(ImGuiStyle* dst) { ImGuiStyle* style = dst ? dst : &ImGui::GetStyle(); From 1b86e7343fea755e8a948fd1102d549665c4c134 Mon Sep 17 00:00:00 2001 From: omar Date: Sun, 24 Dec 2017 18:16:22 +0100 Subject: [PATCH 347/823] Renamed the emblematic ShowTestWindow() function to ShowDemoWindow(). Kept redirection function (will obsolete). --- README.md | 2 +- examples/allegro5_example/main.cpp | 10 +++++----- .../apple_example/imguiex-ios/debug_hud.cpp | 6 +++--- .../apple_example/imguiex-ios/debug_hud.h | 2 +- examples/directx10_example/main.cpp | 10 +++++----- examples/directx11_example/main.cpp | 10 +++++----- examples/directx9_example/main.cpp | 10 +++++----- examples/marmalade_example/main.cpp | 10 +++++----- examples/null_example/main.cpp | 2 +- examples/opengl2_example/main.cpp | 10 +++++----- examples/opengl3_example/main.cpp | 10 +++++----- examples/sdl_opengl2_example/main.cpp | 10 +++++----- examples/sdl_opengl3_example/main.cpp | 10 +++++----- examples/vulkan_example/main.cpp | 10 +++++----- imconfig.h | 6 +++--- imgui.cpp | 7 ++++--- imgui.h | 5 +++-- imgui_demo.cpp | 20 +++++++++++-------- 18 files changed, 78 insertions(+), 72 deletions(-) diff --git a/README.md b/README.md index 29fcab16ebb2..6ababf5b300d 100644 --- a/README.md +++ b/README.md @@ -140,7 +140,7 @@ Frequently Asked Question (FAQ) Where is the documentation? - The documentation is at the top of imgui.cpp + effectively imgui.h. -- Example code is in imgui_demo.cpp and particularly the ImGui::ShowTestWindow() function. It covers most features of ImGui so you can read the code and call the function itself to see its output. +- Example code is in imgui_demo.cpp and particularly the ImGui::ShowDemoWindow() function. It covers most features of ImGui so you can read the code and call the function itself to see its output. - Standalone example applications using e.g. OpenGL/DirectX are provided in the examples/ folder. - We obviously needs better documentation! Consider contributing or becoming a [Patron](http://www.patreon.com/imgui) to promote this effort. diff --git a/examples/allegro5_example/main.cpp b/examples/allegro5_example/main.cpp index 4eb9a4aa9149..f9abe756e24a 100644 --- a/examples/allegro5_example/main.cpp +++ b/examples/allegro5_example/main.cpp @@ -41,7 +41,7 @@ int main(int, char**) //ImFont* font = io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf", 18.0f, NULL, io.Fonts->GetGlyphRangesJapanese()); //IM_ASSERT(font != NULL); - bool show_test_window = true; + bool show_demo_window = true; bool show_another_window = false; ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f); @@ -75,7 +75,7 @@ int main(int, char**) ImGui::Text("Hello, world!"); ImGui::SliderFloat("float", &f, 0.0f, 1.0f); ImGui::ColorEdit3("clear color", (float*)&clear_color); - if (ImGui::Button("Test Window")) show_test_window ^= 1; + if (ImGui::Button("Demo Window")) show_demo_window ^= 1; if (ImGui::Button("Another Window")) show_another_window ^= 1; ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f/ImGui::GetIO().Framerate, ImGui::GetIO().Framerate); } @@ -88,11 +88,11 @@ int main(int, char**) ImGui::End(); } - // 3. Show the ImGui test window. Most of the sample code is in ImGui::ShowTestWindow(). - if (show_test_window) + // 3. Show the ImGui demo window. Most of the sample code is in ImGui::ShowDemoWindow(). + if (show_demo_window) { ImGui::SetNextWindowPos(ImVec2(650, 20), ImGuiCond_FirstUseEver); - ImGui::ShowTestWindow(&show_test_window); + ImGui::ShowDemoWindow(&show_demo_window); } // Rendering diff --git a/examples/apple_example/imguiex-ios/debug_hud.cpp b/examples/apple_example/imguiex-ios/debug_hud.cpp index fff26eee9aea..c451322a280c 100644 --- a/examples/apple_example/imguiex-ios/debug_hud.cpp +++ b/examples/apple_example/imguiex-ios/debug_hud.cpp @@ -9,7 +9,7 @@ void DebugHUD_InitDefaults( DebugHUD *hud ) { - hud->show_test_window = true; + hud->show_demo_window = true; hud->show_example_window = true; hud->rotation_speed = 15.0f; @@ -26,10 +26,10 @@ void DebugHUD_InitDefaults( DebugHUD *hud ) void DebugHUD_DoInterface(DebugHUD *hud) { - if (hud->show_test_window) + if (hud->show_demo_window) { ImGui::SetNextWindowPos(ImVec2(650, 20), ImGuiCond_FirstUseEver); - ImGui::ShowTestWindow(&hud->show_test_window ); + ImGui::ShowDemoWindow(&hud->show_demo_window ); } if (hud->show_example_window) diff --git a/examples/apple_example/imguiex-ios/debug_hud.h b/examples/apple_example/imguiex-ios/debug_hud.h index 17122f5e3428..601376c3e160 100644 --- a/examples/apple_example/imguiex-ios/debug_hud.h +++ b/examples/apple_example/imguiex-ios/debug_hud.h @@ -6,7 +6,7 @@ typedef struct DebugHUD { - bool show_test_window; + bool show_demo_window; bool show_example_window; float rotation_speed; float cubeColor1[4]; diff --git a/examples/directx10_example/main.cpp b/examples/directx10_example/main.cpp index 3ece69f909d2..1d7da4b0618e 100644 --- a/examples/directx10_example/main.cpp +++ b/examples/directx10_example/main.cpp @@ -141,7 +141,7 @@ int main(int, char**) //ImFont* font = io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf", 18.0f, NULL, io.Fonts->GetGlyphRangesJapanese()); //IM_ASSERT(font != NULL); - bool show_test_window = true; + bool show_demo_window = true; bool show_another_window = false; ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f); @@ -169,7 +169,7 @@ int main(int, char**) ImGui::Text("Hello, world!"); ImGui::SliderFloat("float", &f, 0.0f, 1.0f); ImGui::ColorEdit3("clear color", (float*)&clear_color); - if (ImGui::Button("Test Window")) show_test_window ^= 1; + if (ImGui::Button("Demo Window")) show_demo_window ^= 1; if (ImGui::Button("Another Window")) show_another_window ^= 1; ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate); } @@ -182,11 +182,11 @@ int main(int, char**) ImGui::End(); } - // 3. Show the ImGui test window. Most of the sample code is in ImGui::ShowTestWindow(). - if (show_test_window) + // 3. Show the ImGui demo window. Most of the sample code is in ImGui::ShowDemoWindow(). + if (show_demo_window) { ImGui::SetNextWindowPos(ImVec2(650, 20), ImGuiCond_FirstUseEver); // 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::ShowDemoWindow(&show_demo_window); } // Rendering diff --git a/examples/directx11_example/main.cpp b/examples/directx11_example/main.cpp index 9bd8637cf0ab..1c6f84a20a22 100644 --- a/examples/directx11_example/main.cpp +++ b/examples/directx11_example/main.cpp @@ -144,7 +144,7 @@ int main(int, char**) //ImFont* font = io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf", 18.0f, NULL, io.Fonts->GetGlyphRangesJapanese()); //IM_ASSERT(font != NULL); - bool show_test_window = true; + bool show_demo_window = true; bool show_another_window = false; ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f); @@ -172,7 +172,7 @@ int main(int, char**) ImGui::Text("Hello, world!"); ImGui::SliderFloat("float", &f, 0.0f, 1.0f); ImGui::ColorEdit3("clear color", (float*)&clear_color); - if (ImGui::Button("Test Window")) show_test_window ^= 1; + if (ImGui::Button("Demo Window")) show_demo_window ^= 1; if (ImGui::Button("Another Window")) show_another_window ^= 1; ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate); } @@ -185,11 +185,11 @@ int main(int, char**) ImGui::End(); } - // 3. Show the ImGui test window. Most of the sample code is in ImGui::ShowTestWindow(). - if (show_test_window) + // 3. Show the ImGui demo window. Most of the sample code is in ImGui::ShowDemoWindow(). + if (show_demo_window) { ImGui::SetNextWindowPos(ImVec2(650, 20), ImGuiCond_FirstUseEver); // 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::ShowDemoWindow(&show_demo_window); } // Rendering diff --git a/examples/directx9_example/main.cpp b/examples/directx9_example/main.cpp index af53ddb30cf5..7ada228dd480 100644 --- a/examples/directx9_example/main.cpp +++ b/examples/directx9_example/main.cpp @@ -93,7 +93,7 @@ int main(int, char**) //ImFont* font = io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf", 18.0f, NULL, io.Fonts->GetGlyphRangesJapanese()); //IM_ASSERT(font != NULL); - bool show_test_window = true; + bool show_demo_window = true; bool show_another_window = false; ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f); @@ -123,7 +123,7 @@ int main(int, char**) ImGui::Text("Hello, world!"); ImGui::SliderFloat("float", &f, 0.0f, 1.0f); ImGui::ColorEdit3("clear color", (float*)&clear_color); - if (ImGui::Button("Test Window")) show_test_window ^= 1; + if (ImGui::Button("Demo Window")) show_demo_window ^= 1; if (ImGui::Button("Another Window")) show_another_window ^= 1; ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate); } @@ -136,11 +136,11 @@ int main(int, char**) ImGui::End(); } - // 3. Show the ImGui test window. Most of the sample code is in ImGui::ShowTestWindow(). - if (show_test_window) + // 3. Show the ImGui demo window. Most of the sample code is in ImGui::ShowDemoWindow(). + if (show_demo_window) { ImGui::SetNextWindowPos(ImVec2(650, 20), ImGuiCond_FirstUseEver); - ImGui::ShowTestWindow(&show_test_window); + ImGui::ShowDemoWindow(&show_demo_window); } // Rendering diff --git a/examples/marmalade_example/main.cpp b/examples/marmalade_example/main.cpp index f87b3bc51154..032e419812b7 100644 --- a/examples/marmalade_example/main.cpp +++ b/examples/marmalade_example/main.cpp @@ -33,7 +33,7 @@ int main(int, char**) //ImFont* font = io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf", 18.0f, NULL, io.Fonts->GetGlyphRangesJapanese()); //IM_ASSERT(font != NULL); - bool show_test_window = true; + bool show_demo_window = true; bool show_another_window = false; ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f); @@ -58,7 +58,7 @@ int main(int, char**) ImGui::Text("Hello, world!"); ImGui::SliderFloat("float", &f, 0.0f, 1.0f); ImGui::ColorEdit3("clear color", (float*)&clear_color); - if (ImGui::Button("Test Window")) show_test_window ^= 1; + if (ImGui::Button("Demo Window")) show_demo_window ^= 1; if (ImGui::Button("Another Window")) show_another_window ^= 1; ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate); } @@ -71,11 +71,11 @@ int main(int, char**) ImGui::End(); } - // 3. Show the ImGui test window. Most of the sample code is in ImGui::ShowTestWindow(). - if (show_test_window) + // 3. Show the ImGui demo window. Most of the sample code is in ImGui::ShowDemoWindow(). + if (show_demo_window) { ImGui::SetNextWindowPos(ImVec2(650, 20), ImGuiCond_FirstUseEver); - ImGui::ShowTestWindow(&show_test_window); + ImGui::ShowDemoWindow(&show_demo_window); } // Rendering diff --git a/examples/null_example/main.cpp b/examples/null_example/main.cpp index b12f75c960d2..04c1bda40702 100644 --- a/examples/null_example/main.cpp +++ b/examples/null_example/main.cpp @@ -22,7 +22,7 @@ int main(int, char**) ImGui::Text("Hello, world!"); ImGui::SliderFloat("float", &f, 0.0f, 1.0f); ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / io.Framerate, io.Framerate); - ImGui::ShowTestWindow(NULL); + ImGui::ShowDemoWindow(NULL); ImGui::Render(); } diff --git a/examples/opengl2_example/main.cpp b/examples/opengl2_example/main.cpp index ed8f1a7b662d..35c8d19c7ec9 100644 --- a/examples/opengl2_example/main.cpp +++ b/examples/opengl2_example/main.cpp @@ -45,7 +45,7 @@ int main(int, char**) //ImFont* font = io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf", 18.0f, NULL, io.Fonts->GetGlyphRangesJapanese()); //IM_ASSERT(font != NULL); - bool show_test_window = true; + bool show_demo_window = true; bool show_another_window = false; ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f); @@ -66,7 +66,7 @@ int main(int, char**) ImGui::Text("Hello, world!"); ImGui::SliderFloat("float", &f, 0.0f, 1.0f); ImGui::ColorEdit3("clear color", (float*)&clear_color); - if (ImGui::Button("Test Window")) show_test_window ^= 1; + if (ImGui::Button("Demo Window")) show_demo_window ^= 1; if (ImGui::Button("Another Window")) show_another_window ^= 1; ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate); } @@ -79,11 +79,11 @@ int main(int, char**) ImGui::End(); } - // 3. Show the ImGui test window. Most of the sample code is in ImGui::ShowTestWindow(). - if (show_test_window) + // 3. Show the ImGui demo window. Most of the sample code is in ImGui::ShowDemoWindow(). + if (show_demo_window) { ImGui::SetNextWindowPos(ImVec2(650, 20), ImGuiCond_FirstUseEver); - ImGui::ShowTestWindow(&show_test_window); + ImGui::ShowDemoWindow(&show_demo_window); } // Rendering diff --git a/examples/opengl3_example/main.cpp b/examples/opengl3_example/main.cpp index 062843d6b5f6..d10d5830552e 100644 --- a/examples/opengl3_example/main.cpp +++ b/examples/opengl3_example/main.cpp @@ -50,7 +50,7 @@ int main(int, char**) //ImFont* font = io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf", 18.0f, NULL, io.Fonts->GetGlyphRangesJapanese()); //IM_ASSERT(font != NULL); - bool show_test_window = true; + bool show_demo_window = true; bool show_another_window = false; ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f); @@ -71,7 +71,7 @@ int main(int, char**) ImGui::Text("Hello, world!"); ImGui::SliderFloat("float", &f, 0.0f, 1.0f); ImGui::ColorEdit3("clear color", (float*)&clear_color); - if (ImGui::Button("Test Window")) show_test_window ^= 1; + if (ImGui::Button("Demo Window")) show_demo_window ^= 1; if (ImGui::Button("Another Window")) show_another_window ^= 1; ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate); } @@ -84,11 +84,11 @@ int main(int, char**) ImGui::End(); } - // 3. Show the ImGui test window. Most of the sample code is in ImGui::ShowTestWindow(). - if (show_test_window) + // 3. Show the ImGui demo window. Most of the sample code is in ImGui::ShowDemoWindow(). + if (show_demo_window) { ImGui::SetNextWindowPos(ImVec2(650, 20), ImGuiCond_FirstUseEver); - ImGui::ShowTestWindow(&show_test_window); + ImGui::ShowDemoWindow(&show_demo_window); } // Rendering diff --git a/examples/sdl_opengl2_example/main.cpp b/examples/sdl_opengl2_example/main.cpp index 77241a5baf91..cc7c5fb7bbfe 100644 --- a/examples/sdl_opengl2_example/main.cpp +++ b/examples/sdl_opengl2_example/main.cpp @@ -51,7 +51,7 @@ int main(int, char**) //ImFont* font = io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf", 18.0f, NULL, io.Fonts->GetGlyphRangesJapanese()); //IM_ASSERT(font != NULL); - bool show_test_window = true; + bool show_demo_window = true; bool show_another_window = false; ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f); @@ -79,7 +79,7 @@ int main(int, char**) ImGui::Text("Hello, world!"); ImGui::SliderFloat("float", &f, 0.0f, 1.0f); ImGui::ColorEdit3("clear color", (float*)&clear_color); - if (ImGui::Button("Test Window")) show_test_window ^= 1; + if (ImGui::Button("Demo Window")) show_demo_window ^= 1; if (ImGui::Button("Another Window")) show_another_window ^= 1; ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate); } @@ -92,11 +92,11 @@ int main(int, char**) ImGui::End(); } - // 3. Show the ImGui test window. Most of the sample code is in ImGui::ShowTestWindow(). - if (show_test_window) + // 3. Show the ImGui demo window. Most of the sample code is in ImGui::ShowDemoWindow(). + if (show_demo_window) { ImGui::SetNextWindowPos(ImVec2(650, 20), ImGuiCond_FirstUseEver); - ImGui::ShowTestWindow(&show_test_window); + ImGui::ShowDemoWindow(&show_demo_window); } // Rendering diff --git a/examples/sdl_opengl3_example/main.cpp b/examples/sdl_opengl3_example/main.cpp index e51b32089383..a9e75fd4c036 100644 --- a/examples/sdl_opengl3_example/main.cpp +++ b/examples/sdl_opengl3_example/main.cpp @@ -51,7 +51,7 @@ int main(int, char**) //ImFont* font = io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf", 18.0f, NULL, io.Fonts->GetGlyphRangesJapanese()); //IM_ASSERT(font != NULL); - bool show_test_window = true; + bool show_demo_window = true; bool show_another_window = false; ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f); @@ -79,7 +79,7 @@ int main(int, char**) ImGui::Text("Hello, world!"); ImGui::SliderFloat("float", &f, 0.0f, 1.0f); ImGui::ColorEdit3("clear color", (float*)&clear_color); - if (ImGui::Button("Test Window")) show_test_window ^= 1; + if (ImGui::Button("Demo Window")) show_demo_window ^= 1; if (ImGui::Button("Another Window")) show_another_window ^= 1; ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate); } @@ -92,11 +92,11 @@ int main(int, char**) ImGui::End(); } - // 3. Show the ImGui test window. Most of the sample code is in ImGui::ShowTestWindow(). - if (show_test_window) + // 3. Show the ImGui demo window. Most of the sample code is in ImGui::ShowDemoWindow(). + if (show_demo_window) { ImGui::SetNextWindowPos(ImVec2(650, 20), ImGuiCond_FirstUseEver); - ImGui::ShowTestWindow(&show_test_window); + ImGui::ShowDemoWindow(&show_demo_window); } // Rendering diff --git a/examples/vulkan_example/main.cpp b/examples/vulkan_example/main.cpp index 9d54976a3571..ec83035f9c18 100644 --- a/examples/vulkan_example/main.cpp +++ b/examples/vulkan_example/main.cpp @@ -668,7 +668,7 @@ int main(int, char**) ImGui_ImplGlfwVulkan_InvalidateFontUploadObjects(); } - bool show_test_window = true; + bool show_demo_window = true; bool show_another_window = false; ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f); @@ -700,7 +700,7 @@ int main(int, char**) ImGui::Text("Hello, world!"); ImGui::SliderFloat("float", &f, 0.0f, 1.0f); ImGui::ColorEdit3("clear color", (float*)&clear_color); - if (ImGui::Button("Test Window")) show_test_window ^= 1; + if (ImGui::Button("Demo Window")) show_demo_window ^= 1; if (ImGui::Button("Another Window")) show_another_window ^= 1; ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate); } @@ -713,11 +713,11 @@ int main(int, char**) ImGui::End(); } - // 3. Show the ImGui test window. Most of the sample code is in ImGui::ShowTestWindow(). - if (show_test_window) + // 3. Show the ImGui demo window. Most of the sample code is in ImGui::ShowDemoWindow(). + if (show_demo_window) { ImGui::SetNextWindowPos(ImVec2(650, 20), ImGuiCond_FirstUseEver); - ImGui::ShowTestWindow(&show_test_window); + ImGui::ShowDemoWindow(&show_demo_window); } g_ClearValue.color.float32[0] = clear_color.x; diff --git a/imconfig.h b/imconfig.h index 85eff5fd42af..824a81afeb03 100644 --- a/imconfig.h +++ b/imconfig.h @@ -23,9 +23,9 @@ //#define IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCTIONS //#define IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS -//---- Don't implement test window functionality (ShowTestWindow()/ShowStyleEditor()/ShowUserGuide() methods will be empty) -//---- It is very strongly recommended to NOT disable the test windows. Please read the comment at the top of imgui_demo.cpp to learn why. -//#define IMGUI_DISABLE_TEST_WINDOWS +//---- Don't implement demo windows functionality (ShowDemoWindow()/ShowStyleEditor()/ShowUserGuide() methods will be empty) +//---- It is very strongly recommended to NOT disable the demo windows. Please read the comment at the top of imgui_demo.cpp to learn why. +//#define IMGUI_DISABLE_DEMO_WINDOWS //---- Don't implement ImFormatString(), ImFormatStringV() so you can reimplement them yourself. //#define IMGUI_DISABLE_FORMAT_STRING_FUNCTIONS diff --git a/imgui.cpp b/imgui.cpp index 393b4e503948..14b2bd8c3b1e 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1,7 +1,7 @@ // dear imgui, v1.53 WIP // (main code and documentation) -// See ImGui::ShowTestWindow() in imgui_demo.cpp for demo code. +// Call and read ImGui::ShowDemoWindow() in imgui_demo.cpp for demo code. // Newcomers, read 'Programmer guide' below for notes on how to setup Dear ImGui in your codebase. // Get latest version at https://github.com/ocornut/imgui // Releases change-log at https://github.com/ocornut/imgui/releases @@ -86,7 +86,7 @@ - Read the FAQ below this section! - Your code creates the UI, if your code doesn't run the UI is gone! == very dynamic UI, no construction/destructions steps, less data retention on your side, no state duplication, less sync, less bugs. - - Call and read ImGui::ShowTestWindow() for demo code demonstrating most features. + - Call and read ImGui::ShowDemoWindow() for demo code demonstrating most features. - You can learn about immediate-mode gui principles at http://www.johno.se/book/imgui.html or watch http://mollyrocket.com/861 HOW TO UPDATE TO A NEWER VERSION OF DEAR IMGUI @@ -213,6 +213,7 @@ Here is a change-log of API breaking changes, if you are using one of the functions listed, expect to have to fix some code. Also read releases logs https://github.com/ocornut/imgui/releases for more details. + - 2017/12/24 (1.53) - renamed the emblematic ShowTestWindow() function to ShowDemoWindow(). Kept redirection function (will obsolete). - 2017/12/21 (1.53) - ImDrawList: renamed style.AntiAliasedShapes to style.AntiAliasedFill for consistency and as a way to explicitly break code that manipulate those flag at runtime. You can now manipulate ImDrawList::Flags - 2017/12/21 (1.53) - ImDrawList: removed 'bool anti_aliased = true' final parameter of ImDrawList::AddPolyline() and ImDrawList::AddConvexPolyFilled(). Prefer manipulating ImDrawList::Flags if you need to toggle them during the frame. - 2017/12/14 (1.53) - using the ImGuiWindowFlags_NoScrollWithMouse flag on a child window forwards the mouse wheel event to the parent window, unless either ImGuiWindowFlags_NoInputs or ImGuiWindowFlags_NoScrollbar are also set. @@ -576,7 +577,7 @@ - tip: the ImGuiOnceUponAFrame helper will allow run the block of code only once a frame. You can use it to quickly add custom UI in the middle of a deep nested inner loop in your code. - tip: you can call Render() multiple times (e.g for VR renders). - - tip: call and read the ShowTestWindow() code in imgui_demo.cpp for more example of how to use ImGui! + - tip: call and read the ShowDemoWindow() code in imgui_demo.cpp for more example of how to use ImGui! */ diff --git a/imgui.h b/imgui.h index 33580dc2ae7d..10d46ab05d83 100644 --- a/imgui.h +++ b/imgui.h @@ -2,7 +2,7 @@ // (headers) // See imgui.cpp file for documentation. -// See ImGui::ShowTestWindow() in imgui_demo.cpp for demo code. +// Call and read ImGui::ShowDemoWindow() in imgui_demo.cpp for demo code. // Read 'Programmer guide' in imgui.cpp for notes on how to setup ImGui in your codebase. // Get latest version at https://github.com/ocornut/imgui @@ -136,7 +136,7 @@ namespace ImGui IMGUI_API void Shutdown(); // Demo, Debug, Informations - IMGUI_API void ShowTestWindow(bool* p_open = NULL); // create demo/test window. demonstrate most ImGui features. call this to learn about the library! try to make it always available in your application! + IMGUI_API void ShowDemoWindow(bool* p_open = NULL); // create demo/test window (previously called ShowTestWindow). demonstrate most ImGui features. call this to learn about the library! try to make it always available in your application! IMGUI_API void ShowMetricsWindow(bool* p_open = NULL); // create metrics window. display ImGui internals: draw commands (with individual draw calls and vertices), window list, basic internal state, etc. IMGUI_API void ShowStyleEditor(ImGuiStyle* ref = NULL); // add style editor block (not a window). you can pass in a reference ImGuiStyle structure to compare to, revert to and save to (else it uses the default style) IMGUI_API bool ShowStyleSelector(const char* label); @@ -985,6 +985,7 @@ struct ImGuiIO #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS namespace ImGui { + static inline void ShowTestWindow() { return ShowDemoWindow(); } // OBSOLETE 1.53+ static inline bool IsRootWindowFocused() { return IsWindowFocused(ImGuiFocusedFlags_RootWindow); } // OBSOLETE 1.53+ static inline bool IsRootWindowOrAnyChildFocused() { return IsWindowFocused(ImGuiFocusedFlags_RootAndChildWindows); } // OBSOLETE 1.53+ static inline void SetNextWindowContentWidth(float width) { SetNextWindowContentSize(ImVec2(width, 0.0f)); } // OBSOLETE 1.53+ (nb: original version preserved last Y value set by SetNextWindowContentSize()) diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 0b329edc298b..204a17220d70 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -3,11 +3,11 @@ // Message to the person tempted to delete this file when integrating ImGui into their code base: // Don't do it! Do NOT remove this file from your project! It is useful reference code that you and other users will want to refer to. -// Everything in this file will be stripped out by the linker if you don't call ImGui::ShowTestWindow(). -// During development, you can call ImGui::ShowTestWindow() in your code to learn about various features of ImGui. Have it wired in a debug menu! +// Everything in this file will be stripped out by the linker if you don't call ImGui::ShowDemoWindow(). +// During development, you can call ImGui::ShowDemoWindow() in your code to learn about various features of ImGui. Have it wired in a debug menu! // Removing this file from your project is hindering access to documentation for everyone in your team, likely leading you to poorer usage of the library. -// Note that you can #define IMGUI_DISABLE_TEST_WINDOWS in imconfig.h for the same effect. -// If you want to link core ImGui in your public builds but not those test windows, #define IMGUI_DISABLE_TEST_WINDOWS in imconfig.h and those functions will be empty. +// Note that you can #define IMGUI_DISABLE_DEMO_WINDOWS in imconfig.h for the same effect. +// If you want to link core ImGui in your public builds but not those demo windows, #define IMGUI_DISABLE_DEMO_WINDOWS in imconfig.h and those functions will be empty. // For any other case, if you have ImGui available you probably want this to be available for reference and execution. // Thank you, // -Your beloved friend, imgui_demo.cpp (that you won't delete) @@ -70,7 +70,11 @@ // DEMO CODE //----------------------------------------------------------------------------- -#ifndef IMGUI_DISABLE_TEST_WINDOWS +#if !defined(IMGUI_DISABLE_OBSOLETE_FUNCTIONS) && defined(IMGUI_DISABLE_TEST_WINDOWS) && !defined(IMGUI_DISABLE_DEMO_WINDOWS) // Obsolete name since 1.53, TEST->DEMO +#define IMGUI_DISABLE_DEMO_WINDOWS +#endif + +#if !defined(IMGUI_DISABLE_DEMO_WINDOWS) static void ShowExampleAppConsole(bool* p_open); static void ShowExampleAppLog(bool* p_open); @@ -121,7 +125,7 @@ void ImGui::ShowUserGuide() } // Demonstrate most ImGui features (big function!) -void ImGui::ShowTestWindow(bool* p_open) +void ImGui::ShowDemoWindow(bool* p_open) { // Examples apps static bool show_app_main_menu_bar = false; @@ -231,7 +235,7 @@ void ImGui::ShowTestWindow(bool* p_open) ImGui::Spacing(); if (ImGui::CollapsingHeader("Help")) { - ImGui::TextWrapped("This window is being created by the ShowTestWindow() function. Please refer to the code in imgui_demo.cpp for reference.\n\n"); + ImGui::TextWrapped("This window is being created by the ShowDemoWindow() function. Please refer to the code in imgui_demo.cpp for reference.\n\n"); ImGui::Text("USER GUIDE:"); ImGui::ShowUserGuide(); } @@ -3041,7 +3045,7 @@ static void ShowExampleAppLongText(bool* p_open) // End of Demo code #else -void ImGui::ShowTestWindow(bool*) {} +void ImGui::ShowDemoWindow(bool*) {} void ImGui::ShowUserGuide() {} void ImGui::ShowStyleEditor(ImGuiStyle*) {} From ce13426a1adefa70c8614e7b34f78c867ed19cc8 Mon Sep 17 00:00:00 2001 From: omar Date: Sun, 24 Dec 2017 18:45:11 +0100 Subject: [PATCH 348/823] Examples: Comments, synched some minor drift between examples + stronger suggestion to use StyleColorsDark(). --- examples/allegro5_example/main.cpp | 24 ++++++----- .../apple_example/imguiex-ios/debug_hud.cpp | 2 +- examples/directx10_example/main.cpp | 20 ++++++---- examples/directx11_example/main.cpp | 20 ++++++---- examples/directx9_example/main.cpp | 20 ++++++---- examples/marmalade_example/main.cpp | 40 +++++++++++-------- examples/opengl2_example/main.cpp | 20 ++++++---- examples/opengl3_example/main.cpp | 20 ++++++---- examples/sdl_opengl2_example/main.cpp | 20 ++++++---- examples/sdl_opengl3_example/main.cpp | 20 ++++++---- examples/vulkan_example/main.cpp | 20 ++++++---- 11 files changed, 143 insertions(+), 83 deletions(-) diff --git a/examples/allegro5_example/main.cpp b/examples/allegro5_example/main.cpp index f9abe756e24a..3c9c9770eb1c 100644 --- a/examples/allegro5_example/main.cpp +++ b/examples/allegro5_example/main.cpp @@ -25,6 +25,10 @@ int main(int, char**) // Setup ImGui binding ImGui_ImplA5_Init(display); + // Setup style + ImGui::StyleColorsClassic(); + //ImGui::StyleColorsDark(); + // Load Fonts // - If no fonts are loaded, dear imgui will use the default font. You can also load multiple fonts and use ImGui::PushFont()/PopFont() to select them. // - AddFontFromFileTTF() will return the ImFont* so you can store it if you need to select the font among multiple. @@ -69,15 +73,17 @@ int main(int, char**) ImGui_ImplA5_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". + // Tip: if we don't call ImGui::Begin()/ImGui::End() the widgets automatically appears in a window called "Debug". { - static float f; - ImGui::Text("Hello, world!"); - ImGui::SliderFloat("float", &f, 0.0f, 1.0f); - ImGui::ColorEdit3("clear color", (float*)&clear_color); - if (ImGui::Button("Demo Window")) show_demo_window ^= 1; - if (ImGui::Button("Another Window")) show_another_window ^= 1; - ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f/ImGui::GetIO().Framerate, ImGui::GetIO().Framerate); + static float f = 0.0f; + ImGui::Text("Hello, world!"); // Some text (you can use a format string too) + ImGui::SliderFloat("float", &f, 0.0f, 1.0f); // Edit 1 float as a slider from 0.0f to 1.0f + ImGui::ColorEdit3("clear color", (float*)&clear_color); // Edit 3 floats as a color + if (ImGui::Button("Demo Window")) // Use buttons to toggle our bools. We could use Checkbox() as well. + show_demo_window ^= 1; + if (ImGui::Button("Another Window")) + show_another_window ^= 1; + ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate); } // 2. Show another simple window. In most cases you will use an explicit Begin/End pair to name the window. @@ -91,7 +97,7 @@ int main(int, char**) // 3. Show the ImGui demo window. Most of the sample code is in ImGui::ShowDemoWindow(). if (show_demo_window) { - ImGui::SetNextWindowPos(ImVec2(650, 20), ImGuiCond_FirstUseEver); + ImGui::SetNextWindowPos(ImVec2(650, 20), ImGuiCond_FirstUseEver); // Normally user code doesn't need/want to call this because positions are saved in .ini file anyway. Here we just want to make the demo initial state a bit more friendly! ImGui::ShowDemoWindow(&show_demo_window); } diff --git a/examples/apple_example/imguiex-ios/debug_hud.cpp b/examples/apple_example/imguiex-ios/debug_hud.cpp index c451322a280c..c81f273d187c 100644 --- a/examples/apple_example/imguiex-ios/debug_hud.cpp +++ b/examples/apple_example/imguiex-ios/debug_hud.cpp @@ -28,7 +28,7 @@ void DebugHUD_DoInterface(DebugHUD *hud) { if (hud->show_demo_window) { - ImGui::SetNextWindowPos(ImVec2(650, 20), ImGuiCond_FirstUseEver); + ImGui::SetNextWindowPos(ImVec2(650, 20), ImGuiCond_FirstUseEver); // Normally user code doesn't need/want to call this because positions are saved in .ini file anyway. Here we just want to make the demo initial state a bit more friendly! ImGui::ShowDemoWindow(&hud->show_demo_window ); } diff --git a/examples/directx10_example/main.cpp b/examples/directx10_example/main.cpp index 1d7da4b0618e..ecfc156a5e42 100644 --- a/examples/directx10_example/main.cpp +++ b/examples/directx10_example/main.cpp @@ -125,6 +125,10 @@ int main(int, char**) // Setup ImGui binding ImGui_ImplDX10_Init(hwnd, g_pd3dDevice); + // Setup style + ImGui::StyleColorsClassic(); + //ImGui::StyleColorsDark(); + // Load Fonts // - If no fonts are loaded, dear imgui will use the default font. You can also load multiple fonts and use ImGui::PushFont()/PopFont() to select them. // - AddFontFromFileTTF() will return the ImFont* so you can store it if you need to select the font among multiple. @@ -163,14 +167,16 @@ int main(int, char**) ImGui_ImplDX10_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". + // Tip: if we don't call ImGui::Begin()/ImGui::End() the widgets automatically appears in a window called "Debug". { static float f = 0.0f; - ImGui::Text("Hello, world!"); - ImGui::SliderFloat("float", &f, 0.0f, 1.0f); - ImGui::ColorEdit3("clear color", (float*)&clear_color); - if (ImGui::Button("Demo Window")) show_demo_window ^= 1; - if (ImGui::Button("Another Window")) show_another_window ^= 1; + ImGui::Text("Hello, world!"); // Some text (you can use a format string too) + ImGui::SliderFloat("float", &f, 0.0f, 1.0f); // Edit 1 float as a slider from 0.0f to 1.0f + ImGui::ColorEdit3("clear color", (float*)&clear_color); // Edit 3 floats as a color + if (ImGui::Button("Demo Window")) // Use buttons to toggle our bools. We could use Checkbox() as well. + show_demo_window ^= 1; + if (ImGui::Button("Another Window")) + show_another_window ^= 1; ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate); } @@ -185,7 +191,7 @@ int main(int, char**) // 3. Show the ImGui demo window. Most of the sample code is in ImGui::ShowDemoWindow(). if (show_demo_window) { - ImGui::SetNextWindowPos(ImVec2(650, 20), ImGuiCond_FirstUseEver); // 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::SetNextWindowPos(ImVec2(650, 20), ImGuiCond_FirstUseEver); // Normally user code doesn't need/want to call this because positions are saved in .ini file anyway. Here we just want to make the demo initial state a bit more friendly! ImGui::ShowDemoWindow(&show_demo_window); } diff --git a/examples/directx11_example/main.cpp b/examples/directx11_example/main.cpp index 1c6f84a20a22..d7eb1df24ece 100644 --- a/examples/directx11_example/main.cpp +++ b/examples/directx11_example/main.cpp @@ -128,6 +128,10 @@ int main(int, char**) // Setup ImGui binding ImGui_ImplDX11_Init(hwnd, g_pd3dDevice, g_pd3dDeviceContext); + // Setup style + ImGui::StyleColorsClassic(); + //ImGui::StyleColorsDark(); + // Load Fonts // - If no fonts are loaded, dear imgui will use the default font. You can also load multiple fonts and use ImGui::PushFont()/PopFont() to select them. // - AddFontFromFileTTF() will return the ImFont* so you can store it if you need to select the font among multiple. @@ -166,14 +170,16 @@ int main(int, char**) ImGui_ImplDX11_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". + // Tip: if we don't call ImGui::Begin()/ImGui::End() the widgets automatically appears in a window called "Debug". { static float f = 0.0f; - ImGui::Text("Hello, world!"); - ImGui::SliderFloat("float", &f, 0.0f, 1.0f); - ImGui::ColorEdit3("clear color", (float*)&clear_color); - if (ImGui::Button("Demo Window")) show_demo_window ^= 1; - if (ImGui::Button("Another Window")) show_another_window ^= 1; + ImGui::Text("Hello, world!"); // Some text (you can use a format string too) + ImGui::SliderFloat("float", &f, 0.0f, 1.0f); // Edit 1 float as a slider from 0.0f to 1.0f + ImGui::ColorEdit3("clear color", (float*)&clear_color); // Edit 3 floats as a color + if (ImGui::Button("Demo Window")) // Use buttons to toggle our bools. We could use Checkbox() as well. + show_demo_window ^= 1; + if (ImGui::Button("Another Window")) + show_another_window ^= 1; ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate); } @@ -188,7 +194,7 @@ int main(int, char**) // 3. Show the ImGui demo window. Most of the sample code is in ImGui::ShowDemoWindow(). if (show_demo_window) { - ImGui::SetNextWindowPos(ImVec2(650, 20), ImGuiCond_FirstUseEver); // 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::SetNextWindowPos(ImVec2(650, 20), ImGuiCond_FirstUseEver); // Normally user code doesn't need/want to call this because positions are saved in .ini file anyway. Here we just want to make the demo initial state a bit more friendly! ImGui::ShowDemoWindow(&show_demo_window); } diff --git a/examples/directx9_example/main.cpp b/examples/directx9_example/main.cpp index 7ada228dd480..09a109d981bc 100644 --- a/examples/directx9_example/main.cpp +++ b/examples/directx9_example/main.cpp @@ -77,6 +77,10 @@ int main(int, char**) // Setup ImGui binding ImGui_ImplDX9_Init(hwnd, g_pd3dDevice); + // Setup style + ImGui::StyleColorsClassic(); + //ImGui::StyleColorsDark(); + // Load Fonts // - If no fonts are loaded, dear imgui will use the default font. You can also load multiple fonts and use ImGui::PushFont()/PopFont() to select them. // - AddFontFromFileTTF() will return the ImFont* so you can store it if you need to select the font among multiple. @@ -117,14 +121,16 @@ int main(int, char**) 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". + // Tip: if we don't call ImGui::Begin()/ImGui::End() the widgets automatically appears in a window called "Debug". { static float f = 0.0f; - ImGui::Text("Hello, world!"); - ImGui::SliderFloat("float", &f, 0.0f, 1.0f); - ImGui::ColorEdit3("clear color", (float*)&clear_color); - if (ImGui::Button("Demo Window")) show_demo_window ^= 1; - if (ImGui::Button("Another Window")) show_another_window ^= 1; + ImGui::Text("Hello, world!"); // Some text (you can use a format string too) + ImGui::SliderFloat("float", &f, 0.0f, 1.0f); // Edit 1 float as a slider from 0.0f to 1.0f + ImGui::ColorEdit3("clear color", (float*)&clear_color); // Edit 3 floats as a color + if (ImGui::Button("Demo Window")) // Use buttons to toggle our bools. We could use Checkbox() as well. + show_demo_window ^= 1; + if (ImGui::Button("Another Window")) + show_another_window ^= 1; ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate); } @@ -139,7 +145,7 @@ int main(int, char**) // 3. Show the ImGui demo window. Most of the sample code is in ImGui::ShowDemoWindow(). if (show_demo_window) { - ImGui::SetNextWindowPos(ImVec2(650, 20), ImGuiCond_FirstUseEver); + ImGui::SetNextWindowPos(ImVec2(650, 20), ImGuiCond_FirstUseEver); // Normally user code doesn't need/want to call this because positions are saved in .ini file anyway. Here we just want to make the demo initial state a bit more friendly! ImGui::ShowDemoWindow(&show_demo_window); } diff --git a/examples/marmalade_example/main.cpp b/examples/marmalade_example/main.cpp index 032e419812b7..2b5edb77f78d 100644 --- a/examples/marmalade_example/main.cpp +++ b/examples/marmalade_example/main.cpp @@ -17,6 +17,10 @@ int main(int, char**) // Setup ImGui binding ImGui_Marmalade_Init(true); + // Setup style + ImGui::StyleColorsClassic(); + //ImGui::StyleColorsDark(); + // Load Fonts // - If no fonts are loaded, dear imgui will use the default font. You can also load multiple fonts and use ImGui::PushFont()/PopFont() to select them. // - AddFontFromFileTTF() will return the ImFont* so you can store it if you need to select the font among multiple. @@ -40,26 +44,28 @@ int main(int, char**) // Main loop while (true) { - if (s3eDeviceCheckQuitRequest()) - break; + if (s3eDeviceCheckQuitRequest()) + break; - // You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs. - // - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application. - // - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application. - // Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags. - s3eKeyboardUpdate(); - s3ePointerUpdate(); - ImGui_Marmalade_NewFrame(); + // You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs. + // - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application. + // - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application. + // Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags. + s3eKeyboardUpdate(); + s3ePointerUpdate(); + ImGui_Marmalade_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". + // Tip: if we don't call ImGui::Begin()/ImGui::End() the widgets automatically appears in a window called "Debug". { static float f = 0.0f; - ImGui::Text("Hello, world!"); - ImGui::SliderFloat("float", &f, 0.0f, 1.0f); - ImGui::ColorEdit3("clear color", (float*)&clear_color); - if (ImGui::Button("Demo Window")) show_demo_window ^= 1; - if (ImGui::Button("Another Window")) show_another_window ^= 1; + ImGui::Text("Hello, world!"); // Some text (you can use a format string too) + ImGui::SliderFloat("float", &f, 0.0f, 1.0f); // Edit 1 float as a slider from 0.0f to 1.0f + ImGui::ColorEdit3("clear color", (float*)&clear_color); // Edit 3 floats as a color + if (ImGui::Button("Demo Window")) // Use buttons to toggle our bools. We could use Checkbox() as well. + show_demo_window ^= 1; + if (ImGui::Button("Another Window")) + show_another_window ^= 1; ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate); } @@ -74,12 +80,12 @@ int main(int, char**) // 3. Show the ImGui demo window. Most of the sample code is in ImGui::ShowDemoWindow(). if (show_demo_window) { - ImGui::SetNextWindowPos(ImVec2(650, 20), ImGuiCond_FirstUseEver); + ImGui::SetNextWindowPos(ImVec2(650, 20), ImGuiCond_FirstUseEver); // Normally user code doesn't need/want to call this because positions are saved in .ini file anyway. Here we just want to make the demo initial state a bit more friendly! ImGui::ShowDemoWindow(&show_demo_window); } // Rendering - IwGxSetColClear(clear_color.x*255,clear_color.y*255,clear_color.z*255,clear_color.w*255) ; + IwGxSetColClear(clear_color.x * 255, clear_color.y * 255, clear_color.z * 255, clear_color.w * 255); IwGxClear(); ImGui::Render(); IwGxSwapBuffers(); diff --git a/examples/opengl2_example/main.cpp b/examples/opengl2_example/main.cpp index 35c8d19c7ec9..ef098e54ae8f 100644 --- a/examples/opengl2_example/main.cpp +++ b/examples/opengl2_example/main.cpp @@ -29,6 +29,10 @@ int main(int, char**) // Setup ImGui binding ImGui_ImplGlfwGL2_Init(window, true); + // Setup style + ImGui::StyleColorsClassic(); + //ImGui::StyleColorsDark(); + // Load Fonts // - If no fonts are loaded, dear imgui will use the default font. You can also load multiple fonts and use ImGui::PushFont()/PopFont() to select them. // - AddFontFromFileTTF() will return the ImFont* so you can store it if you need to select the font among multiple. @@ -60,14 +64,16 @@ int main(int, char**) ImGui_ImplGlfwGL2_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". + // Tip: if we don't call ImGui::Begin()/ImGui::End() the widgets automatically appears in a window called "Debug". { static float f = 0.0f; - ImGui::Text("Hello, world!"); - ImGui::SliderFloat("float", &f, 0.0f, 1.0f); - ImGui::ColorEdit3("clear color", (float*)&clear_color); - if (ImGui::Button("Demo Window")) show_demo_window ^= 1; - if (ImGui::Button("Another Window")) show_another_window ^= 1; + ImGui::Text("Hello, world!"); // Some text (you can use a format string too) + ImGui::SliderFloat("float", &f, 0.0f, 1.0f); // Edit 1 float as a slider from 0.0f to 1.0f + ImGui::ColorEdit3("clear color", (float*)&clear_color); // Edit 3 floats as a color + if (ImGui::Button("Demo Window")) // Use buttons to toggle our bools. We could use Checkbox() as well. + show_demo_window ^= 1; + if (ImGui::Button("Another Window")) + show_another_window ^= 1; ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate); } @@ -82,7 +88,7 @@ int main(int, char**) // 3. Show the ImGui demo window. Most of the sample code is in ImGui::ShowDemoWindow(). if (show_demo_window) { - ImGui::SetNextWindowPos(ImVec2(650, 20), ImGuiCond_FirstUseEver); + ImGui::SetNextWindowPos(ImVec2(650, 20), ImGuiCond_FirstUseEver); // Normally user code doesn't need/want to call this because positions are saved in .ini file anyway. Here we just want to make the demo initial state a bit more friendly! ImGui::ShowDemoWindow(&show_demo_window); } diff --git a/examples/opengl3_example/main.cpp b/examples/opengl3_example/main.cpp index d10d5830552e..9e9a3fb6c8d6 100644 --- a/examples/opengl3_example/main.cpp +++ b/examples/opengl3_example/main.cpp @@ -34,6 +34,10 @@ int main(int, char**) // Setup ImGui binding ImGui_ImplGlfwGL3_Init(window, true); + // Setup style + ImGui::StyleColorsClassic(); + //ImGui::StyleColorsDark(); + // Load Fonts // - If no fonts are loaded, dear imgui will use the default font. You can also load multiple fonts and use ImGui::PushFont()/PopFont() to select them. // - AddFontFromFileTTF() will return the ImFont* so you can store it if you need to select the font among multiple. @@ -65,14 +69,16 @@ int main(int, char**) ImGui_ImplGlfwGL3_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". + // Tip: if we don't call ImGui::Begin()/ImGui::End() the widgets automatically appears in a window called "Debug". { static float f = 0.0f; - ImGui::Text("Hello, world!"); - ImGui::SliderFloat("float", &f, 0.0f, 1.0f); - ImGui::ColorEdit3("clear color", (float*)&clear_color); - if (ImGui::Button("Demo Window")) show_demo_window ^= 1; - if (ImGui::Button("Another Window")) show_another_window ^= 1; + ImGui::Text("Hello, world!"); // Some text (you can use a format string too) + ImGui::SliderFloat("float", &f, 0.0f, 1.0f); // Edit 1 float as a slider from 0.0f to 1.0f + ImGui::ColorEdit3("clear color", (float*)&clear_color); // Edit 3 floats as a color + if (ImGui::Button("Demo Window")) // Use buttons to toggle our bools. We could use Checkbox() as well. + show_demo_window ^= 1; + if (ImGui::Button("Another Window")) + show_another_window ^= 1; ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate); } @@ -87,7 +93,7 @@ int main(int, char**) // 3. Show the ImGui demo window. Most of the sample code is in ImGui::ShowDemoWindow(). if (show_demo_window) { - ImGui::SetNextWindowPos(ImVec2(650, 20), ImGuiCond_FirstUseEver); + ImGui::SetNextWindowPos(ImVec2(650, 20), ImGuiCond_FirstUseEver); // Normally user code doesn't need/want to call this because positions are saved in .ini file anyway. Here we just want to make the demo initial state a bit more friendly! ImGui::ShowDemoWindow(&show_demo_window); } diff --git a/examples/sdl_opengl2_example/main.cpp b/examples/sdl_opengl2_example/main.cpp index cc7c5fb7bbfe..1396fcca023a 100644 --- a/examples/sdl_opengl2_example/main.cpp +++ b/examples/sdl_opengl2_example/main.cpp @@ -35,6 +35,10 @@ int main(int, char**) // Setup ImGui binding ImGui_ImplSdlGL2_Init(window); + // Setup style + ImGui::StyleColorsClassic(); + //ImGui::StyleColorsDark(); + // Load Fonts // - If no fonts are loaded, dear imgui will use the default font. You can also load multiple fonts and use ImGui::PushFont()/PopFont() to select them. // - AddFontFromFileTTF() will return the ImFont* so you can store it if you need to select the font among multiple. @@ -73,14 +77,16 @@ int main(int, char**) ImGui_ImplSdlGL2_NewFrame(window); // 1. Show a simple window - // Tip: if we don't call ImGui::Begin()/ImGui::End() the widgets appears in a window automatically called "Debug". + // Tip: if we don't call ImGui::Begin()/ImGui::End() the widgets automatically appears in a window called "Debug". { static float f = 0.0f; - ImGui::Text("Hello, world!"); - ImGui::SliderFloat("float", &f, 0.0f, 1.0f); - ImGui::ColorEdit3("clear color", (float*)&clear_color); - if (ImGui::Button("Demo Window")) show_demo_window ^= 1; - if (ImGui::Button("Another Window")) show_another_window ^= 1; + ImGui::Text("Hello, world!"); // Some text (you can use a format string too) + ImGui::SliderFloat("float", &f, 0.0f, 1.0f); // Edit 1 float as a slider from 0.0f to 1.0f + ImGui::ColorEdit3("clear color", (float*)&clear_color); // Edit 3 floats as a color + if (ImGui::Button("Demo Window")) // Use buttons to toggle our bools. We could use Checkbox() as well. + show_demo_window ^= 1; + if (ImGui::Button("Another Window")) + show_another_window ^= 1; ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate); } @@ -95,7 +101,7 @@ int main(int, char**) // 3. Show the ImGui demo window. Most of the sample code is in ImGui::ShowDemoWindow(). if (show_demo_window) { - ImGui::SetNextWindowPos(ImVec2(650, 20), ImGuiCond_FirstUseEver); + ImGui::SetNextWindowPos(ImVec2(650, 20), ImGuiCond_FirstUseEver); // Normally user code doesn't need/want to call this because positions are saved in .ini file anyway. Here we just want to make the demo initial state a bit more friendly! ImGui::ShowDemoWindow(&show_demo_window); } diff --git a/examples/sdl_opengl3_example/main.cpp b/examples/sdl_opengl3_example/main.cpp index a9e75fd4c036..7ee60389c417 100644 --- a/examples/sdl_opengl3_example/main.cpp +++ b/examples/sdl_opengl3_example/main.cpp @@ -35,6 +35,10 @@ int main(int, char**) // Setup ImGui binding ImGui_ImplSdlGL3_Init(window); + // Setup style + ImGui::StyleColorsClassic(); + //ImGui::StyleColorsDark(); + // Load Fonts // - If no fonts are loaded, dear imgui will use the default font. You can also load multiple fonts and use ImGui::PushFont()/PopFont() to select them. // - AddFontFromFileTTF() will return the ImFont* so you can store it if you need to select the font among multiple. @@ -73,14 +77,16 @@ int main(int, char**) ImGui_ImplSdlGL3_NewFrame(window); // 1. Show a simple window. - // Tip: if we don't call ImGui::Begin()/ImGui::End() the widgets appears in a window automatically called "Debug". + // Tip: if we don't call ImGui::Begin()/ImGui::End() the widgets automatically appears in a window called "Debug". { static float f = 0.0f; - ImGui::Text("Hello, world!"); - ImGui::SliderFloat("float", &f, 0.0f, 1.0f); - ImGui::ColorEdit3("clear color", (float*)&clear_color); - if (ImGui::Button("Demo Window")) show_demo_window ^= 1; - if (ImGui::Button("Another Window")) show_another_window ^= 1; + ImGui::Text("Hello, world!"); // Some text (you can use a format string too) + ImGui::SliderFloat("float", &f, 0.0f, 1.0f); // Edit 1 float as a slider from 0.0f to 1.0f + ImGui::ColorEdit3("clear color", (float*)&clear_color); // Edit 3 floats as a color + if (ImGui::Button("Demo Window")) // Use buttons to toggle our bools. We could use Checkbox() as well. + show_demo_window ^= 1; + if (ImGui::Button("Another Window")) + show_another_window ^= 1; ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate); } @@ -95,7 +101,7 @@ int main(int, char**) // 3. Show the ImGui demo window. Most of the sample code is in ImGui::ShowDemoWindow(). if (show_demo_window) { - ImGui::SetNextWindowPos(ImVec2(650, 20), ImGuiCond_FirstUseEver); + ImGui::SetNextWindowPos(ImVec2(650, 20), ImGuiCond_FirstUseEver); // Normally user code doesn't need/want to call this because positions are saved in .ini file anyway. Here we just want to make the demo initial state a bit more friendly! ImGui::ShowDemoWindow(&show_demo_window); } diff --git a/examples/vulkan_example/main.cpp b/examples/vulkan_example/main.cpp index ec83035f9c18..81f420a01696 100644 --- a/examples/vulkan_example/main.cpp +++ b/examples/vulkan_example/main.cpp @@ -625,6 +625,10 @@ int main(int, char**) init_data.check_vk_result = check_vk_result; ImGui_ImplGlfwVulkan_Init(window, true, &init_data); + // Setup style + ImGui::StyleColorsClassic(); + //ImGui::StyleColorsDark(); + // Load Fonts // - If no fonts are loaded, dear imgui will use the default font. You can also load multiple fonts and use ImGui::PushFont()/PopFont() to select them. // - AddFontFromFileTTF() will return the ImFont* so you can store it if you need to select the font among multiple. @@ -694,14 +698,16 @@ int main(int, char**) ImGui_ImplGlfwVulkan_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". + // Tip: if we don't call ImGui::Begin()/ImGui::End() the widgets automatically appears in a window called "Debug". { static float f = 0.0f; - ImGui::Text("Hello, world!"); - ImGui::SliderFloat("float", &f, 0.0f, 1.0f); - ImGui::ColorEdit3("clear color", (float*)&clear_color); - if (ImGui::Button("Demo Window")) show_demo_window ^= 1; - if (ImGui::Button("Another Window")) show_another_window ^= 1; + ImGui::Text("Hello, world!"); // Some text (you can use a format string too) + ImGui::SliderFloat("float", &f, 0.0f, 1.0f); // Edit 1 float as a slider from 0.0f to 1.0f + ImGui::ColorEdit3("clear color", (float*)&clear_color); // Edit 3 floats as a color + if (ImGui::Button("Demo Window")) // Use buttons to toggle our bools. We could use Checkbox() as well. + show_demo_window ^= 1; + if (ImGui::Button("Another Window")) + show_another_window ^= 1; ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate); } @@ -716,7 +722,7 @@ int main(int, char**) // 3. Show the ImGui demo window. Most of the sample code is in ImGui::ShowDemoWindow(). if (show_demo_window) { - ImGui::SetNextWindowPos(ImVec2(650, 20), ImGuiCond_FirstUseEver); + ImGui::SetNextWindowPos(ImVec2(650, 20), ImGuiCond_FirstUseEver); // Normally user code doesn't need/want to call this because positions are saved in .ini file anyway. Here we just want to make the demo initial state a bit more friendly! ImGui::ShowDemoWindow(&show_demo_window); } From 3a4a2bb27c0f893843c23f4eb033b57e421fb745 Mon Sep 17 00:00:00 2001 From: omar Date: Sun, 24 Dec 2017 18:49:19 +0100 Subject: [PATCH 349/823] Examples: Vulkan: Tweak --- examples/vulkan_example/main.cpp | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/examples/vulkan_example/main.cpp b/examples/vulkan_example/main.cpp index 81f420a01696..6c4ef33fe28b 100644 --- a/examples/vulkan_example/main.cpp +++ b/examples/vulkan_example/main.cpp @@ -726,11 +726,7 @@ int main(int, char**) ImGui::ShowDemoWindow(&show_demo_window); } - g_ClearValue.color.float32[0] = clear_color.x; - g_ClearValue.color.float32[1] = clear_color.y; - g_ClearValue.color.float32[2] = clear_color.z; - g_ClearValue.color.float32[3] = clear_color.w; - + memcpy(&g_ClearValue.color.float32[0], &clear_color, 4 * sizeof(float)); frame_begin(); ImGui_ImplGlfwVulkan_Render(g_CommandBuffer[g_FrameIndex]); frame_end(); From 8d54b1b7aff34111b6f64c0e076eb0b7a981ad9a Mon Sep 17 00:00:00 2001 From: omar Date: Sun, 24 Dec 2017 18:59:14 +0100 Subject: [PATCH 350/823] Misc comments, removed duplicated IM_ARRAYSIZE macro in imgui_demo.cpp (it is now declared in imgui.h) --- imgui.cpp | 2 +- imgui_demo.cpp | 17 ++++++++--------- 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 14b2bd8c3b1e..a2214220bbf4 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -8,7 +8,7 @@ // Gallery (please post your screenshots/video there!): https://github.com/ocornut/imgui/issues/1269 // Developed by Omar Cornut and every direct or indirect contributors to the GitHub. // This library is free but I need your support to sustain development and maintenance. -// If you work for a company, please consider financial support, e.g: https://www.patreon.com/imgui +// If you work for a company, please consider financial support, see Readme. For individuals: https://www.patreon.com/imgui /* diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 204a17220d70..7a6a0fa21b84 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -7,16 +7,16 @@ // During development, you can call ImGui::ShowDemoWindow() in your code to learn about various features of ImGui. Have it wired in a debug menu! // Removing this file from your project is hindering access to documentation for everyone in your team, likely leading you to poorer usage of the library. // Note that you can #define IMGUI_DISABLE_DEMO_WINDOWS in imconfig.h for the same effect. -// If you want to link core ImGui in your public builds but not those demo windows, #define IMGUI_DISABLE_DEMO_WINDOWS in imconfig.h and those functions will be empty. -// For any other case, if you have ImGui available you probably want this to be available for reference and execution. +// If you want to link core ImGui in your final builds but not those demo windows, #define IMGUI_DISABLE_DEMO_WINDOWS in imconfig.h and those functions will be empty. +// In other situation, when you have ImGui available you probably want this to be available for reference and execution. // Thank you, // -Your beloved friend, imgui_demo.cpp (that you won't delete) -// Message to beginner C/C++ programmer about the meaning of 'static': in this demo code, we frequently we use 'static' variables inside functions. -// We do this as a way to gather code and data in the same place, make the demo code faster to read, faster to write, and smaller. A static variable persist across calls, -// so it is essentially like a global variable but declared inside the scope of the function. +// Message to beginner C/C++ programmers. About the meaning of 'static': in this demo code, we frequently we use 'static' variables inside functions. +// We do this as a way to gather code and data in the same place, just to make the demo code faster to read, faster to write, and use less code. +// A static variable persist across calls, so it is essentially like a global variable but declared inside the scope of the function. // It also happens to be a convenient way of storing simple UI related information as long as your function doesn't need to be reentrant or used in threads. -// This may be a pattern you want to use in your code (simple is beautiful!), but most of the real data you would be editing is likely to be stored outside your function. +// This might be a pattern you occasionally want to use in your code, but most of the real data you would be editing is likely to be stored outside your function. #if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_WARNINGS) #define _CRT_SECURE_NO_WARNINGS @@ -52,18 +52,17 @@ #pragma GCC diagnostic ignored "-Wdouble-promotion" // warning: implicit conversion from 'float' to 'double' when passing argument to function #pragma GCC diagnostic ignored "-Wconversion" // warning: conversion to 'xxxx' from 'xxxx' may alter its value #if (__GNUC__ >= 6) -#pragma GCC diagnostic ignored "-Wmisleading-indentation" // warning: this 'if' clause does not guard this statement // GCC 6.0+ only. See #883 on github. +#pragma GCC diagnostic ignored "-Wmisleading-indentation" // warning: this 'if' clause does not guard this statement // GCC 6.0+ only. See #883 on GitHub. #endif #endif -// Play it nice with Windows users. Notepad in 2015 still doesn't display text data with Unix-style \n. +// Play it nice with Windows users. Notepad in 2017 still doesn't display text data with Unix-style \n. #ifdef _WIN32 #define IM_NEWLINE "\r\n" #else #define IM_NEWLINE "\n" #endif -#define IM_ARRAYSIZE(_ARR) ((int)(sizeof(_ARR)/sizeof(*_ARR))) #define IM_MAX(_A,_B) (((_A) >= (_B)) ? (_A) : (_B)) //----------------------------------------------------------------------------- From 78f48bb795e5ea54ec2f8e232dc1f06315af340b Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 25 Dec 2017 14:54:54 +0100 Subject: [PATCH 351/823] Examples: DirectX10,DirectX11: Moved call to OMSetRenderTargets() in main loop so example code can integrate more nicely with other code. --- examples/directx10_example/main.cpp | 2 +- examples/directx11_example/main.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/directx10_example/main.cpp b/examples/directx10_example/main.cpp index ecfc156a5e42..38f4054eada3 100644 --- a/examples/directx10_example/main.cpp +++ b/examples/directx10_example/main.cpp @@ -27,7 +27,6 @@ void CreateRenderTarget() render_target_view_desc.ViewDimension = D3D10_RTV_DIMENSION_TEXTURE2D; g_pSwapChain->GetBuffer(0, __uuidof(ID3D10Texture2D), (LPVOID*)&pBackBuffer); g_pd3dDevice->CreateRenderTargetView(pBackBuffer, &render_target_view_desc, &g_mainRenderTargetView); - g_pd3dDevice->OMSetRenderTargets(1, &g_mainRenderTargetView, NULL); pBackBuffer->Release(); } @@ -196,6 +195,7 @@ int main(int, char**) } // Rendering + g_pd3dDevice->OMSetRenderTargets(1, &g_mainRenderTargetView, NULL); g_pd3dDevice->ClearRenderTargetView(g_mainRenderTargetView, (float*)&clear_color); ImGui::Render(); diff --git a/examples/directx11_example/main.cpp b/examples/directx11_example/main.cpp index d7eb1df24ece..79e7bb169ddc 100644 --- a/examples/directx11_example/main.cpp +++ b/examples/directx11_example/main.cpp @@ -27,7 +27,6 @@ void CreateRenderTarget() render_target_view_desc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D; g_pSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&pBackBuffer); g_pd3dDevice->CreateRenderTargetView(pBackBuffer, &render_target_view_desc, &g_mainRenderTargetView); - g_pd3dDeviceContext->OMSetRenderTargets(1, &g_mainRenderTargetView, NULL); pBackBuffer->Release(); } @@ -199,6 +198,7 @@ int main(int, char**) } // Rendering + g_pd3dDeviceContext->OMSetRenderTargets(1, &g_mainRenderTargetView, NULL); g_pd3dDeviceContext->ClearRenderTargetView(g_mainRenderTargetView, (float*)&clear_color); ImGui::Render(); From 3849bb4470aebb4ff276113170f26cc82f990f49 Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 25 Dec 2017 16:03:58 +0100 Subject: [PATCH 352/823] Moving window doesn't use accumulating MouseDelta so straying out of boundaries keeps moved window at the same spot. --- imgui.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index a2214220bbf4..d8eba7a596f4 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2379,9 +2379,10 @@ void ImGui::NewFrame() IM_ASSERT(g.MovingWindow->MoveId == g.MovingWindowMoveId); if (g.IO.MouseDown[0]) { - g.MovingWindow->RootWindow->PosFloat += g.IO.MouseDelta; - if (g.IO.MouseDelta.x != 0.0f || g.IO.MouseDelta.y != 0.0f) + ImVec2 pos = g.IO.MousePos - g.ActiveIdClickOffset; + if (g.MovingWindow->RootWindow->PosFloat.x != pos.x || g.MovingWindow->RootWindow->PosFloat.y != pos.y) MarkIniSettingsDirty(g.MovingWindow->RootWindow); + g.MovingWindow->RootWindow->PosFloat = pos; FocusWindow(g.MovingWindow); } else @@ -2930,6 +2931,7 @@ void ImGui::EndFrame() g.MovingWindow = g.HoveredWindow; g.MovingWindowMoveId = g.MovingWindow->MoveId; SetActiveID(g.MovingWindowMoveId, g.HoveredRootWindow); + g.ActiveIdClickOffset = g.IO.MousePos - g.MovingWindow->RootWindow->Pos; } } else if (g.NavWindow != NULL && GetFrontMostModalRootWindow() == NULL) From 3d48f5b8c296aba88c5df6b76dfc23f5f32fe581 Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 25 Dec 2017 17:40:47 +0100 Subject: [PATCH 353/823] Demo: BeginCombo() demo code --- imgui.h | 1 + imgui_demo.cpp | 28 ++++++++++++++++++++++------ 2 files changed, 23 insertions(+), 6 deletions(-) diff --git a/imgui.h b/imgui.h index 10d46ab05d83..bd9571cfb10e 100644 --- a/imgui.h +++ b/imgui.h @@ -300,6 +300,7 @@ namespace ImGui // Widgets: Combo Box // The new BeginCombo()/EndCombo() api allows you to manage your contents and selection state however you want it. + // The old Combo() api are helpers over BeginCombo()/EndCombo() which are kept available for convenience purpose. IMGUI_API bool BeginCombo(const char* label, const char* preview_value, ImGuiComboFlags flags = 0); IMGUI_API void EndCombo(); IMGUI_API bool Combo(const char* label, int* current_item, const char* const items[], int items_count, int popup_max_height_in_items = -1); diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 7a6a0fa21b84..966d80c52c4f 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -322,12 +322,28 @@ void ImGui::ShowDemoWindow(bool* p_open) ImGui::LabelText("label", "Value"); - static int item = 1; - ImGui::Combo("combo", &item, "aaaa\0bbbb\0cccc\0dddd\0eeee\0\0"); // Combo using values packed in a single constant string (for really quick combo) - - const char* items[] = { "AAAA", "BBBB", "CCCC", "DDDD", "EEEE", "FFFF", "GGGG", "HHHH", "IIII", "JJJJ", "KKKK", "LLLLLLL", "MMMM", "OOOOOOO", "PPPP", "QQQQQQQQQQ", "RRR", "SSSS" }; - static int item2 = -1; - ImGui::Combo("combo scroll", &item2, items, IM_ARRAYSIZE(items)); // Combo using proper array. You can also pass a callback to retrieve array value, no need to create/copy an array just for that. + { + // Simplified one-liner Combo() API, using values packed in a single constant string + static int current_item_1 = 1; + ImGui::Combo("combo", ¤t_item_1, "aaaa\0bbbb\0cccc\0dddd\0eeee\0\0"); + //ImGui::Combo("combo w/ array of char*", ¤t_item_2_idx, items, IM_ARRAYSIZE(items)); // Combo using proper array. You can also pass a callback to retrieve array value, no need to create/copy an array just for that. + + // General BeginCombo() API, you have full control over your selection data and display type + const char* items[] = { "AAAA", "BBBB", "CCCC", "DDDD", "EEEE", "FFFF", "GGGG", "HHHH", "IIII", "JJJJ", "KKKK", "LLLLLLL", "MMMM", "OOOOOOO", "PPPP", "QQQQQQQQQQ", "RRR", "SSSS" }; + static const char* current_item_2 = NULL; + if (ImGui::BeginCombo("combo 2", current_item_2)) // The second parameter is the label previewed before opening the combo. + { + for (int n = 0; n < IM_ARRAYSIZE(items); n++) + { + bool is_selected = (current_item_2 == items[n]); // You can store your selection however you want, outside or inside your objects + if (ImGui::Selectable(items[n], is_selected)) + current_item_2 = items[n]; + if (is_selected) + ImGui::SetItemDefaultFocus(); // Set the initial focus when opening the combo (scrolling + for keyboard navigation support in the upcoming navigation branch) + } + ImGui::EndCombo(); + } + } { static char str0[128] = "Hello, world!"; From e916310b2e1f9cacbb2b9ce192a3dfb359e4b509 Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 25 Dec 2017 17:41:41 +0100 Subject: [PATCH 354/823] Version 1.53 --- imgui.cpp | 2 +- imgui.h | 4 ++-- imgui_demo.cpp | 2 +- imgui_draw.cpp | 2 +- imgui_internal.h | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index d8eba7a596f4..075fb8c46004 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.53 WIP +// dear imgui, v1.53 // (main code and documentation) // Call and read ImGui::ShowDemoWindow() in imgui_demo.cpp for demo code. diff --git a/imgui.h b/imgui.h index bd9571cfb10e..22e213985790 100644 --- a/imgui.h +++ b/imgui.h @@ -1,4 +1,4 @@ -// dear imgui, v1.53 WIP +// dear imgui, v1.53 // (headers) // See imgui.cpp file for documentation. @@ -16,7 +16,7 @@ #include // ptrdiff_t, NULL #include // memset, memmove, memcpy, strlen, strchr, strcpy, strcmp -#define IMGUI_VERSION "1.53 WIP" +#define IMGUI_VERSION "1.53" // Define attributes of all API symbols declarations, e.g. for DLL under Windows. #ifndef IMGUI_API diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 966d80c52c4f..d739dfa4e5d8 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.53 WIP +// dear imgui, v1.53 // (demo code) // Message to the person tempted to delete this file when integrating ImGui into their code base: diff --git a/imgui_draw.cpp b/imgui_draw.cpp index bba523a380ae..6efb6bc62cc6 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.53 WIP +// dear imgui, v1.53 // (drawing and font code) // Contains implementation for diff --git a/imgui_internal.h b/imgui_internal.h index e161a6f14c55..8043539020b5 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -1,4 +1,4 @@ -// dear imgui, v1.53 WIP +// dear imgui, v1.53 // (internals) // You may use this file to debug, understand or extend ImGui features but we don't provide any guarantee of forward compatibility! From 9511f22e8b07d8f2456c256c742c6048c585aba4 Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 25 Dec 2017 18:47:44 +0100 Subject: [PATCH 355/823] Demo: Console: More friendly to text color changes. --- imgui_demo.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/imgui_demo.cpp b/imgui_demo.cpp index d739dfa4e5d8..a5864fefbde5 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -2616,12 +2616,13 @@ struct ExampleAppConsole ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(4,1)); // Tighten spacing if (copy_to_clipboard) ImGui::LogToClipboard(); + ImVec4 col_default_text = ImGui::GetStyleColorVec4(ImGuiCol_Text); for (int i = 0; i < Items.Size; i++) { const char* item = Items[i]; if (!filter.PassFilter(item)) continue; - ImVec4 col = ImVec4(1.0f,1.0f,1.0f,1.0f); // A better implementation may store a type per-item. For the sample let's just parse the text. + ImVec4 col = col_default_text; if (strstr(item, "[error]")) col = ImColor(1.0f,0.4f,0.4f,1.0f); else if (strncmp(item, "# ", 2) == 0) col = ImColor(1.0f,0.78f,0.58f,1.0f); ImGui::PushStyleColor(ImGuiCol_Text, col); From 149523a10185a0e4f7e6832198277cf35b27d7e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Branimir=20Karad=C5=BEi=C4=87?= Date: Mon, 25 Dec 2017 12:31:23 -0800 Subject: [PATCH 356/823] =?UTF-8?q?Fixing=20error:=20declaration=20of=20?= =?UTF-8?q?=E2=80=98size=E2=80=99=20shadows=20a=20member=20of=20'this'=20[?= =?UTF-8?q?-Werror=3Dshadow]?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- imgui.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/imgui.h b/imgui.h index 22e213985790..2304dad10c3c 100644 --- a/imgui.h +++ b/imgui.h @@ -1041,7 +1041,7 @@ class ImVector inline const value_type& back() const { IM_ASSERT(Size > 0); return Data[Size - 1]; } inline void swap(ImVector& rhs) { int rhs_size = rhs.Size; rhs.Size = Size; Size = rhs_size; int rhs_cap = rhs.Capacity; rhs.Capacity = Capacity; Capacity = rhs_cap; value_type* rhs_data = rhs.Data; rhs.Data = Data; Data = rhs_data; } - inline int _grow_capacity(int size) const { int new_capacity = Capacity ? (Capacity + Capacity/2) : 8; return new_capacity > size ? new_capacity : size; } + inline int _grow_capacity(int sz) const { int new_capacity = Capacity ? (Capacity + Capacity/2) : 8; return new_capacity > sz ? new_capacity : sz; } inline void resize(int new_size) { if (new_size > Capacity) reserve(_grow_capacity(new_size)); Size = new_size; } inline void resize(int new_size, const T& v){ if (new_size > Capacity) reserve(_grow_capacity(new_size)); if (new_size > Size) for (int n = Size; n < new_size; n++) Data[n] = v; Size = new_size; } From d9034bf2d81f72b283b108abde5b3118b5ace1a6 Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 26 Dec 2017 15:36:55 +0100 Subject: [PATCH 357/823] ListBox() changed signature of ListBox() to match Combo(). Still not very happy about not using const char** anymore. (#931) --- imgui.cpp | 2 +- imgui.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 075fb8c46004..dee18b4eab99 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -9502,7 +9502,7 @@ void ImGui::ListBoxFooter() EndGroup(); } -bool ImGui::ListBox(const char* label, int* current_item, const char* const* items, int items_count, int height_items) +bool ImGui::ListBox(const char* label, int* current_item, const char* const items[], int items_count, int height_items) { const bool value_changed = ListBox(label, current_item, Items_ArrayGetter, (void*)items, items_count, height_items); return value_changed; diff --git a/imgui.h b/imgui.h index 2304dad10c3c..1b1e92b354cc 100644 --- a/imgui.h +++ b/imgui.h @@ -377,7 +377,7 @@ namespace ImGui // Widgets: Selectable / Lists IMGUI_API bool Selectable(const char* label, bool selected = false, ImGuiSelectableFlags flags = 0, const ImVec2& size = ImVec2(0,0)); // size.x==0.0: use remaining width, size.x>0.0: specify width. size.y==0.0: use label height, size.y>0.0: specify height IMGUI_API bool Selectable(const char* label, bool* p_selected, ImGuiSelectableFlags flags = 0, const ImVec2& size = ImVec2(0,0)); - IMGUI_API bool ListBox(const char* label, int* current_item, const char* const* items, int items_count, int height_in_items = -1); + IMGUI_API bool ListBox(const char* label, int* current_item, const char* const items[], int items_count, int height_in_items = -1); IMGUI_API bool ListBox(const char* label, int* current_item, bool (*items_getter)(void* data, int idx, const char** out_text), void* data, int items_count, int height_in_items = -1); IMGUI_API bool ListBoxHeader(const char* label, const ImVec2& size = ImVec2(0,0)); // use if you want to reimplement ListBox() will custom data or interactions. make sure to call ListBoxFooter() afterwards. IMGUI_API bool ListBoxHeader(const char* label, int items_count, int height_in_items = -1); // " From 7fd805497a5291c7adb6a77fc7fb564422e34344 Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 26 Dec 2017 20:30:22 +0100 Subject: [PATCH 358/823] Update README.md --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 6ababf5b300d..608468329796 100644 --- a/README.md +++ b/README.md @@ -60,6 +60,7 @@ Languages: - ChaiScript: https://github.com/JuJuBoSc/imgui-chaiscript - D (DerelictImgui): https://github.com/Extrawurst/DerelictImgui - Go (go-imgui): https://github.com/Armored-Dragon/go-imgui +- Haxe/hxcpp (linc_imgui): https://github.com/Aidan63/linc_imgui - Lua: https://github.com/patrickriordan/imgui_lua_bindings - Odin: https://github.com/ThisDrunkDane/odin-dear_imgui - Pascal (imgui-pas): https://github.com/dpethes/imgui-pas From 6e30c33642f06e77f6f38c8f15e4447a745c6645 Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 26 Dec 2017 21:04:17 +0100 Subject: [PATCH 359/823] Demo dinaries update --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 608468329796..bf30994601fd 100644 --- a/README.md +++ b/README.md @@ -45,7 +45,7 @@ Binaries/Demo ------------- You should be able to build the examples from sources (tested on Windows/Mac/Linux). If you don't, let me know! If you want to have a quick look at some Dear ImGui features, you can download Windows binaries of the demo app here: -- [imgui-demo-binaries-20171013.zip](http://www.miracleworld.net/imgui/binaries/imgui-demo-binaries-20171013.zip) (Windows binaries, Dear ImGui 1.52 WIP built 2017/10/13, 5 executables) +- [imgui-demo-binaries-20171226.zip](http://www.miracleworld.net/imgui/binaries/imgui-demo-binaries-20171226.zip) (Windows binaries, Dear ImGui 1.53 built 2017/12/26, 5 executables) Bindings -------- From 49eed6e2d132e8fb27af3760061b8558e8bbb654 Mon Sep 17 00:00:00 2001 From: omar Date: Thu, 28 Dec 2017 15:17:35 +0100 Subject: [PATCH 360/823] Version 1.54 WIP --- imgui.cpp | 2 +- imgui.h | 4 ++-- imgui_demo.cpp | 2 +- imgui_draw.cpp | 2 +- imgui_internal.h | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index dee18b4eab99..e0f1af4b9b78 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.53 +// dear imgui, v1.54 WIP // (main code and documentation) // Call and read ImGui::ShowDemoWindow() in imgui_demo.cpp for demo code. diff --git a/imgui.h b/imgui.h index 1b1e92b354cc..711e0271f299 100644 --- a/imgui.h +++ b/imgui.h @@ -1,4 +1,4 @@ -// dear imgui, v1.53 +// dear imgui, v1.54 WIP // (headers) // See imgui.cpp file for documentation. @@ -16,7 +16,7 @@ #include // ptrdiff_t, NULL #include // memset, memmove, memcpy, strlen, strchr, strcpy, strcmp -#define IMGUI_VERSION "1.53" +#define IMGUI_VERSION "1.54 WIP" // Define attributes of all API symbols declarations, e.g. for DLL under Windows. #ifndef IMGUI_API diff --git a/imgui_demo.cpp b/imgui_demo.cpp index a5864fefbde5..94531a1077cd 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.53 +// dear imgui, v1.54 WIP // (demo code) // Message to the person tempted to delete this file when integrating ImGui into their code base: diff --git a/imgui_draw.cpp b/imgui_draw.cpp index 6efb6bc62cc6..b56d90cfcdf7 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.53 +// dear imgui, v1.54 WIP // (drawing and font code) // Contains implementation for diff --git a/imgui_internal.h b/imgui_internal.h index 8043539020b5..797d66d62061 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -1,4 +1,4 @@ -// dear imgui, v1.53 +// dear imgui, v1.54 WIP // (internals) // You may use this file to debug, understand or extend ImGui features but we don't provide any guarantee of forward compatibility! From 563d04fdb118c72a9add2d2f8e98639eae6d1feb Mon Sep 17 00:00:00 2001 From: omar Date: Thu, 28 Dec 2017 15:29:06 +0100 Subject: [PATCH 361/823] TreeNode: node with the ImGuiTreeNodeFlags_Leaf flag correctly disable highlight when DragDrop is active. (#143, #581) --- imgui.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/imgui.cpp b/imgui.cpp index e0f1af4b9b78..50059632e824 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -6702,7 +6702,8 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l // - OpenOnArrow .................... single-click on arrow to open // - OpenOnDoubleClick|OpenOnArrow .. single-click on arrow or double-click anywhere to open ImGuiButtonFlags button_flags = ImGuiButtonFlags_NoKeyModifiers | ((flags & ImGuiTreeNodeFlags_AllowItemOverlap) ? ImGuiButtonFlags_AllowItemOverlap : 0); - button_flags |= ImGuiButtonFlags_PressedOnDragDropHold; + if (!(flags & ImGuiTreeNodeFlags_Leaf)) + button_flags |= ImGuiButtonFlags_PressedOnDragDropHold; if (flags & ImGuiTreeNodeFlags_OpenOnDoubleClick) button_flags |= ImGuiButtonFlags_PressedOnDoubleClick | ((flags & ImGuiTreeNodeFlags_OpenOnArrow) ? ImGuiButtonFlags_PressedOnClickRelease : 0); From 06bea369c0ce977c1cb71e085d860a6644330297 Mon Sep 17 00:00:00 2001 From: omar Date: Thu, 28 Dec 2017 16:54:16 +0100 Subject: [PATCH 362/823] DragDrop: Added IsDragDropActive() helper which is useful for binding to decide how to handle mouse inputs. --- imgui.cpp | 6 ++++++ imgui.h | 1 + 2 files changed, 7 insertions(+) diff --git a/imgui.cpp b/imgui.cpp index 50059632e824..45ed8ad8d8a3 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -11478,6 +11478,12 @@ void ImGui::EndDragDropTarget() IM_ASSERT(g.DragDropActive); } +bool ImGui::IsDragDropActive() +{ + ImGuiContext& g = *GImGui; + return g.DragDropActive; +} + //----------------------------------------------------------------------------- // PLATFORM DEPENDENT HELPERS //----------------------------------------------------------------------------- diff --git a/imgui.h b/imgui.h index 711e0271f299..4972443a2d98 100644 --- a/imgui.h +++ b/imgui.h @@ -433,6 +433,7 @@ namespace ImGui IMGUI_API bool BeginDragDropTarget(); // call after submitting an item that may receive an item. If this returns true, you can call AcceptDragDropPayload() + EndDragDropTarget() IMGUI_API const ImGuiPayload* AcceptDragDropPayload(const char* type, ImGuiDragDropFlags flags = 0); // accept contents of a given type. If ImGuiDragDropFlags_AcceptBeforeDelivery is set you can peek into the payload before the mouse button is released. IMGUI_API void EndDragDropTarget(); + IMGUI_API bool IsDragDropActive(); // Clipping IMGUI_API void PushClipRect(const ImVec2& clip_rect_min, const ImVec2& clip_rect_max, bool intersect_with_current_clip_rect); From e985baa35ddda960b48d87e9d384cdc77a691913 Mon Sep 17 00:00:00 2001 From: omar Date: Thu, 28 Dec 2017 17:05:52 +0100 Subject: [PATCH 363/823] Combo: When peeking into the popup window for alignment we check if the window was active, which is more correct. (no known issue in current codebase, but we'll need that change for later) --- imgui.cpp | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 45ed8ad8d8a3..3c6df7011736 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -9230,14 +9230,15 @@ bool ImGui::BeginCombo(const char* label, const char* preview_value, ImGuiComboF // Peak into expected window size so we can position it if (ImGuiWindow* popup_window = FindWindowByName(name)) - { - ImVec2 size_contents = CalcSizeContents(popup_window); - ImVec2 size_expected = CalcSizeAfterConstraint(popup_window, CalcSizeAutoFit(popup_window, size_contents)); - if (flags & ImGuiComboFlags_PopupAlignLeft) - popup_window->AutoPosLastDirection = ImGuiDir_Left; - ImVec2 pos = FindBestWindowPosForPopup(frame_bb.GetBL(), size_expected, &popup_window->AutoPosLastDirection, frame_bb, ImGuiPopupPositionPolicy_ComboBox); - SetNextWindowPos(pos); - } + if (popup_window->WasActive) + { + ImVec2 size_contents = CalcSizeContents(popup_window); + ImVec2 size_expected = CalcSizeAfterConstraint(popup_window, CalcSizeAutoFit(popup_window, size_contents)); + if (flags & ImGuiComboFlags_PopupAlignLeft) + popup_window->AutoPosLastDirection = ImGuiDir_Left; + ImVec2 pos = FindBestWindowPosForPopup(frame_bb.GetBL(), size_expected, &popup_window->AutoPosLastDirection, frame_bb, ImGuiPopupPositionPolicy_ComboBox); + SetNextWindowPos(pos); + } ImGuiWindowFlags window_flags = ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_Popup | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoSavedSettings; if (!Begin(name, NULL, window_flags)) From 90ff4ae5d16c2200cf6fdad2825ebb473d906899 Mon Sep 17 00:00:00 2001 From: omar Date: Thu, 28 Dec 2017 23:08:48 +0100 Subject: [PATCH 364/823] BeginPopupModal(): the conditional test for SetNextWindowPos() was polling the wrong window, which in practice made the test succeed all the time. --- imgui.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/imgui.cpp b/imgui.cpp index 3c6df7011736..10ef65be3839 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -3885,7 +3885,7 @@ bool ImGui::BeginPopupModal(const char* name, bool* p_open, ImGuiWindowFlags ext } // Center modal windows by default - if ((window->SetWindowPosAllowFlags & g.SetNextWindowPosCond) == 0) + if (g.SetNextWindowPosCond == 0) SetNextWindowPos(g.IO.DisplaySize * 0.5f, ImGuiCond_Appearing, ImVec2(0.5f, 0.5f)); ImGuiWindowFlags flags = extra_flags|ImGuiWindowFlags_Popup|ImGuiWindowFlags_Modal|ImGuiWindowFlags_NoCollapse|ImGuiWindowFlags_NoSavedSettings; From 4ba2e8574433b049ce643eb13fc2fbfb3d222d33 Mon Sep 17 00:00:00 2001 From: omar Date: Thu, 28 Dec 2017 23:50:37 +0100 Subject: [PATCH 365/823] Demo: Tweak. Comments. Metrics: Added some Drag and Drop info. --- imgui.cpp | 9 +++++---- imgui_demo.cpp | 1 + 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 10ef65be3839..2e16fb3f21d3 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2914,7 +2914,7 @@ void ImGui::EndFrame() IM_ASSERT(g.CurrentWindowStack.Size == 1); // Mismatched Begin()/End() calls if (g.CurrentWindow && !g.CurrentWindow->WriteAccessed) g.CurrentWindow->Active = false; - ImGui::End(); + End(); if (g.ActiveId == 0 && g.HoveredId == 0) { @@ -3715,7 +3715,7 @@ void ImGui::BeginTooltip() void ImGui::EndTooltip() { IM_ASSERT(GetCurrentWindowRead()->Flags & ImGuiWindowFlags_Tooltip); // Mismatched BeginTooltip()/EndTooltip() calls - ImGui::End(); + End(); } // Mark popup as open (toggle toward open state). @@ -4011,7 +4011,7 @@ void ImGui::EndChild() IM_ASSERT(window->Flags & ImGuiWindowFlags_ChildWindow); // Mismatched BeginChild()/EndChild() callss if (window->BeginCount > 1) { - ImGui::End(); + End(); } else { @@ -4021,7 +4021,7 @@ void ImGui::EndChild() sz.x = ImMax(4.0f, sz.x); if (window->AutoFitChildAxises & (1 << ImGuiAxis_Y)) sz.y = ImMax(4.0f, sz.y); - ImGui::End(); + End(); ImGuiWindow* parent_window = GetCurrentWindow(); ImRect bb(parent_window->DC.CursorPos, parent_window->DC.CursorPos + sz); @@ -11730,6 +11730,7 @@ void ImGui::ShowMetricsWindow(bool* p_open) ImGui::Text("ActiveId: 0x%08X/0x%08X (%.2f sec)", g.ActiveId, g.ActiveIdPreviousFrame, g.ActiveIdTimer); ImGui::Text("ActiveIdWindow: '%s'", g.ActiveIdWindow ? g.ActiveIdWindow->Name : "NULL"); ImGui::Text("NavWindow: '%s'", g.NavWindow ? g.NavWindow->Name : "NULL"); + ImGui::Text("DragDrop: %d, SourceId = 0x%08X, Payload \"%s\" (%d bytes)", g.DragDropActive, g.DragDropPayload.SourceId, g.DragDropPayload.DataType, g.DragDropPayload.DataSize); ImGui::TreePop(); } } diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 94531a1077cd..1ccc2990eb28 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -2365,6 +2365,7 @@ static void ShowExampleAppFixedOverlay(bool* p_open) if (ImGui::MenuItem("Top-right", NULL, corner == 1)) corner = 1; if (ImGui::MenuItem("Bottom-left", NULL, corner == 2)) corner = 2; if (ImGui::MenuItem("Bottom-right", NULL, corner == 3)) corner = 3; + if (p_open && ImGui::MenuItem("Close")) *p_open = false; ImGui::EndPopup(); } ImGui::End(); From 4fbdb50dca435741531d775f2ea6239ccf13e151 Mon Sep 17 00:00:00 2001 From: omar Date: Thu, 28 Dec 2017 23:51:58 +0100 Subject: [PATCH 366/823] MenuBar: Fixed menu bar pushing a clipping rect outside of its allocated bound (usually unnoticeable). --- imgui.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/imgui.cpp b/imgui.cpp index 2e16fb3f21d3..479e8eaf0058 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -9632,7 +9632,7 @@ bool ImGui::BeginMenuBar() // We remove 1 worth of rounding to Max.x to that text in long menus don't tend to display over the lower-right rounded area, which looks particularly glitchy. ImRect bar_rect = window->MenuBarRect(); ImRect clip_rect(ImFloor(bar_rect.Min.x + 0.5f), ImFloor(bar_rect.Min.y + window->WindowBorderSize + 0.5f), ImFloor(ImMax(bar_rect.Min.x, bar_rect.Max.x - window->WindowRounding) + 0.5f), ImFloor(bar_rect.Max.y + 0.5f)); - clip_rect.ClipWith(window->Rect()); + clip_rect.ClipWith(window->WindowRectClipped); PushClipRect(clip_rect.Min, clip_rect.Max, false); window->DC.CursorPos = ImVec2(bar_rect.Min.x + window->DC.MenuBarOffsetX, bar_rect.Min.y);// + g.Style.FramePadding.y); From 9f8632b131e1bd282f733ab31301dd8c49515e4a Mon Sep 17 00:00:00 2001 From: omar Date: Fri, 29 Dec 2017 15:03:36 +0100 Subject: [PATCH 367/823] Examples: Comments about invalid mouse pos. --- examples/marmalade_example/imgui_impl_marmalade.cpp | 2 +- examples/opengl2_example/imgui_impl_glfw.cpp | 2 +- examples/opengl3_example/imgui_impl_glfw_gl3.cpp | 2 +- examples/sdl_opengl2_example/imgui_impl_sdl.cpp | 2 +- examples/sdl_opengl3_example/imgui_impl_sdl_gl3.cpp | 2 +- examples/vulkan_example/imgui_impl_glfw_vulkan.cpp | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/examples/marmalade_example/imgui_impl_marmalade.cpp b/examples/marmalade_example/imgui_impl_marmalade.cpp index 6ecffa7365fa..cae1be1856d5 100644 --- a/examples/marmalade_example/imgui_impl_marmalade.cpp +++ b/examples/marmalade_example/imgui_impl_marmalade.cpp @@ -273,7 +273,7 @@ void ImGui_Marmalade_NewFrame() double mouse_x, mouse_y; mouse_x = s3ePointerGetX(); mouse_y = s3ePointerGetY(); - io.MousePos = ImVec2((float)mouse_x/g_scale.x, (float)mouse_y/g_scale.y); // Mouse position in screen coordinates (set to -1,-1 if no mouse / on another screen, etc.) + io.MousePos = ImVec2((float)mouse_x/g_scale.x, (float)mouse_y/g_scale.y); // Mouse position (set to -FLT_MAX,-FLT_MAX if no mouse / on another screen, etc.) for (int i = 0; i < 3; i++) { diff --git a/examples/opengl2_example/imgui_impl_glfw.cpp b/examples/opengl2_example/imgui_impl_glfw.cpp index 364d92889576..33df611e7677 100644 --- a/examples/opengl2_example/imgui_impl_glfw.cpp +++ b/examples/opengl2_example/imgui_impl_glfw.cpp @@ -281,7 +281,7 @@ void ImGui_ImplGlfwGL2_NewFrame() { double mouse_x, mouse_y; glfwGetCursorPos(g_Window, &mouse_x, &mouse_y); - io.MousePos = ImVec2((float)mouse_x, (float)mouse_y); // Get mouse position in screen coordinates (set to -1,-1 if no mouse / on another screen, etc.) + io.MousePos = ImVec2((float)mouse_x, (float)mouse_y); } } else diff --git a/examples/opengl3_example/imgui_impl_glfw_gl3.cpp b/examples/opengl3_example/imgui_impl_glfw_gl3.cpp index 7d924fcf1887..6c439fa186d2 100644 --- a/examples/opengl3_example/imgui_impl_glfw_gl3.cpp +++ b/examples/opengl3_example/imgui_impl_glfw_gl3.cpp @@ -393,7 +393,7 @@ void ImGui_ImplGlfwGL3_NewFrame() { double mouse_x, mouse_y; glfwGetCursorPos(g_Window, &mouse_x, &mouse_y); - io.MousePos = ImVec2((float)mouse_x, (float)mouse_y); // Get mouse position in screen coordinates (set to -1,-1 if no mouse / on another screen, etc.) + io.MousePos = ImVec2((float)mouse_x, (float)mouse_y); } } else diff --git a/examples/sdl_opengl2_example/imgui_impl_sdl.cpp b/examples/sdl_opengl2_example/imgui_impl_sdl.cpp index 66f3ed5a8472..baf5c0176844 100644 --- a/examples/sdl_opengl2_example/imgui_impl_sdl.cpp +++ b/examples/sdl_opengl2_example/imgui_impl_sdl.cpp @@ -276,7 +276,7 @@ void ImGui_ImplSdlGL2_NewFrame(SDL_Window *window) int mx, my; Uint32 mouseMask = SDL_GetMouseState(&mx, &my); if (SDL_GetWindowFlags(window) & SDL_WINDOW_MOUSE_FOCUS) - io.MousePos = ImVec2((float)mx, (float)my); // Mouse position, in pixels (set to -1,-1 if no mouse / on another screen, etc.) + io.MousePos = ImVec2((float)mx, (float)my); else io.MousePos = ImVec2(-FLT_MAX,-FLT_MAX); diff --git a/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.cpp b/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.cpp index 68e27a68c645..93849cf8b372 100644 --- a/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.cpp +++ b/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.cpp @@ -387,7 +387,7 @@ void ImGui_ImplSdlGL3_NewFrame(SDL_Window* window) int mx, my; Uint32 mouseMask = SDL_GetMouseState(&mx, &my); if (SDL_GetWindowFlags(window) & SDL_WINDOW_MOUSE_FOCUS) - io.MousePos = ImVec2((float)mx, (float)my); // Mouse position, in pixels (set to -1,-1 if no mouse / on another screen, etc.) + io.MousePos = ImVec2((float)mx, (float)my); else io.MousePos = ImVec2(-FLT_MAX, -FLT_MAX); diff --git a/examples/vulkan_example/imgui_impl_glfw_vulkan.cpp b/examples/vulkan_example/imgui_impl_glfw_vulkan.cpp index 1d12e3f774a6..8eb35ec3c708 100644 --- a/examples/vulkan_example/imgui_impl_glfw_vulkan.cpp +++ b/examples/vulkan_example/imgui_impl_glfw_vulkan.cpp @@ -811,7 +811,7 @@ void ImGui_ImplGlfwVulkan_NewFrame() { double mouse_x, mouse_y; glfwGetCursorPos(g_Window, &mouse_x, &mouse_y); - io.MousePos = ImVec2((float)mouse_x, (float)mouse_y); // Mouse position in screen coordinates (set to -1,-1 if no mouse / on another screen, etc.) + io.MousePos = ImVec2((float)mouse_x, (float)mouse_y); } else { From 2dd2ca0096767721fa5b845f5dc733bbf2e10822 Mon Sep 17 00:00:00 2001 From: omar Date: Fri, 29 Dec 2017 17:59:13 +0100 Subject: [PATCH 368/823] Removed CalcItemRectClosestPoint() which was weird and not really used by anyone except demo code. If you need it it's easy to replicate on your side. Removed internal corresponding ImRect::GetClosestPoint() for now. Essentially revert dcaafffe0ed21c9b03530a911785ded80e14358f. --- imgui.cpp | 9 +-------- imgui.h | 2 +- imgui_demo.cpp | 2 +- imgui_internal.h | 10 ---------- 4 files changed, 3 insertions(+), 20 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 479e8eaf0058..4b8f8aa474ca 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -213,6 +213,7 @@ Here is a change-log of API breaking changes, if you are using one of the functions listed, expect to have to fix some code. Also read releases logs https://github.com/ocornut/imgui/releases for more details. + - 2017/12/29 (1.54) - removed CalcItemRectClosestPoint() which was weird and not really used by anyone except demo code. If you need it it's easy to replicate on your side. - 2017/12/24 (1.53) - renamed the emblematic ShowTestWindow() function to ShowDemoWindow(). Kept redirection function (will obsolete). - 2017/12/21 (1.53) - ImDrawList: renamed style.AntiAliasedShapes to style.AntiAliasedFill for consistency and as a way to explicitly break code that manipulate those flag at runtime. You can now manipulate ImDrawList::Flags - 2017/12/21 (1.53) - ImDrawList: removed 'bool anti_aliased = true' final parameter of ImDrawList::AddPolyline() and ImDrawList::AddConvexPolyFilled(). Prefer manipulating ImDrawList::Flags if you need to toggle them during the frame. @@ -3658,14 +3659,6 @@ ImVec2 ImGui::GetItemRectSize() return window->DC.LastItemRect.GetSize(); } -ImVec2 ImGui::CalcItemRectClosestPoint(const ImVec2& pos, bool on_edge, float outward) -{ - ImGuiWindow* window = GetCurrentWindowRead(); - ImRect rect = window->DC.LastItemRect; - rect.Expand(outward); - return rect.GetClosestPoint(pos, on_edge); -} - static ImRect GetVisibleRect() { ImGuiContext& g = *GImGui; diff --git a/imgui.h b/imgui.h index 4972443a2d98..79ce272c7bbe 100644 --- a/imgui.h +++ b/imgui.h @@ -472,7 +472,6 @@ namespace ImGui IMGUI_API ImDrawList* GetOverlayDrawList(); // this draw list will be the last rendered one, useful to quickly draw overlays shapes/text IMGUI_API ImDrawListSharedData* GetDrawListSharedData(); IMGUI_API const char* GetStyleColorName(ImGuiCol idx); - IMGUI_API ImVec2 CalcItemRectClosestPoint(const ImVec2& pos, bool on_edge = false, float outward = +0.0f); // utility to find the closest point the last item bounding rectangle edge. useful to visually link items IMGUI_API ImVec2 CalcTextSize(const char* text, const char* text_end = NULL, bool hide_text_after_double_hash = false, float wrap_width = -1.0f); IMGUI_API void CalcListClipping(int items_count, float items_height, int* out_items_display_start, int* out_items_display_end); // calculate coarse clipping for large list of evenly sized items. Prefer using the ImGuiListClipper higher-level helper if you can. @@ -987,6 +986,7 @@ struct ImGuiIO #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS namespace ImGui { + static inline ImVec2 CalcItemRectClosestPoint(const ImVec2& pos, bool on_edge = false, float outward = +0.0f) { (void)on_edge; (void)outward; return pos; } // OBSOLETE 1.54+ static inline void ShowTestWindow() { return ShowDemoWindow(); } // OBSOLETE 1.53+ static inline bool IsRootWindowFocused() { return IsWindowFocused(ImGuiFocusedFlags_RootWindow); } // OBSOLETE 1.53+ static inline bool IsRootWindowOrAnyChildFocused() { return IsWindowFocused(ImGuiFocusedFlags_RootAndChildWindows); } // OBSOLETE 1.53+ diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 1ccc2990eb28..c9d47d4dfbf3 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -1894,7 +1894,7 @@ void ImGui::ShowDemoWindow(bool* p_open) // Draw a line between the button and the mouse cursor ImDrawList* draw_list = ImGui::GetWindowDrawList(); draw_list->PushClipRectFullScreen(); - draw_list->AddLine(ImGui::CalcItemRectClosestPoint(io.MousePos, true, -2.0f), io.MousePos, ImColor(ImGui::GetStyle().Colors[ImGuiCol_Button]), 4.0f); + draw_list->AddLine(io.MouseClickedPos[0], io.MousePos, ImGui::GetColorU32(ImGuiCol_Button), 4.0f); draw_list->PopClipRect(); // Drag operations gets "unlocked" when the mouse has moved past a certain threshold (the default threshold is stored in io.MouseDragThreshold) diff --git a/imgui_internal.h b/imgui_internal.h index 797d66d62061..fc0ef6029883 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -290,16 +290,6 @@ struct IMGUI_API ImRect void Floor() { Min.x = (float)(int)Min.x; Min.y = (float)(int)Min.y; Max.x = (float)(int)Max.x; Max.y = (float)(int)Max.y; } void FixInverted() { if (Min.x > Max.x) ImSwap(Min.x, Max.x); if (Min.y > Max.y) ImSwap(Min.y, Max.y); } bool IsFinite() const { return Min.x != FLT_MAX; } - ImVec2 GetClosestPoint(ImVec2 p, bool on_edge) const - { - if (!on_edge && Contains(p)) - return p; - if (p.x > Max.x) p.x = Max.x; - else if (p.x < Min.x) p.x = Min.x; - if (p.y > Max.y) p.y = Max.y; - else if (p.y < Min.y) p.y = Min.y; - return p; - } }; // Stacked color modifier, backup of modified data so we can restore it From eef9120e07331f251b53eb9ef8387dbd7c70bf8e Mon Sep 17 00:00:00 2001 From: omar Date: Fri, 29 Dec 2017 18:14:36 +0100 Subject: [PATCH 369/823] Reorganized comments in the IMGUI_DISABLE_OBSOLETE_FUNCTIONS function. Added an IM_ASSERT(0). --- imgui.h | 35 ++++++++++++++++++++--------------- 1 file changed, 20 insertions(+), 15 deletions(-) diff --git a/imgui.h b/imgui.h index 79ce272c7bbe..f5ac95f89636 100644 --- a/imgui.h +++ b/imgui.h @@ -980,26 +980,31 @@ struct ImGuiIO }; //----------------------------------------------------------------------------- -// Obsolete functions (Will be removed! Also see 'API BREAKING CHANGES' section in imgui.cpp) +// Obsolete functions (Will be removed! Read 'API BREAKING CHANGES' section in imgui.cpp for details) //----------------------------------------------------------------------------- #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS namespace ImGui { - static inline ImVec2 CalcItemRectClosestPoint(const ImVec2& pos, bool on_edge = false, float outward = +0.0f) { (void)on_edge; (void)outward; return pos; } // OBSOLETE 1.54+ - static inline void ShowTestWindow() { return ShowDemoWindow(); } // OBSOLETE 1.53+ - static inline bool IsRootWindowFocused() { return IsWindowFocused(ImGuiFocusedFlags_RootWindow); } // OBSOLETE 1.53+ - static inline bool IsRootWindowOrAnyChildFocused() { return IsWindowFocused(ImGuiFocusedFlags_RootAndChildWindows); } // OBSOLETE 1.53+ - static inline void SetNextWindowContentWidth(float width) { SetNextWindowContentSize(ImVec2(width, 0.0f)); } // OBSOLETE 1.53+ (nb: original version preserved last Y value set by SetNextWindowContentSize()) - static inline bool IsRootWindowOrAnyChildHovered(ImGuiHoveredFlags flags = 0) { return IsItemHovered(flags | ImGuiHoveredFlags_RootWindow | ImGuiHoveredFlags_ChildWindows); } // OBSOLETE 1.53+ use flags directly - bool Begin(const char* name, bool* p_open, const ImVec2& size_on_first_use, float bg_alpha_override = -1.0f, ImGuiWindowFlags flags = 0); // OBSOLETE 1.52+. use SetNextWindowSize() instead if you want to set a window size. - static inline void AlignFirstTextHeightToWidgets() { AlignTextToFramePadding(); } // OBSOLETE 1.52+ - static inline void SetNextWindowPosCenter(ImGuiCond cond = 0) { SetNextWindowPos(ImVec2(GetIO().DisplaySize.x * 0.5f, GetIO().DisplaySize.y * 0.5f), cond, ImVec2(0.5f, 0.5f)); } // OBSOLETE 1.52+ - static inline bool IsItemHoveredRect() { return IsItemHovered(ImGuiHoveredFlags_RectOnly); } // OBSOLETE 1.51+ - static inline bool IsPosHoveringAnyWindow(const ImVec2&) { IM_ASSERT(0); return false; } // OBSOLETE 1.51+. This was partly broken. You probably wanted to use ImGui::GetIO().WantCaptureMouse instead. - static inline bool IsMouseHoveringAnyWindow() { return IsAnyWindowHovered(); } // OBSOLETE 1.51+ - static inline bool IsMouseHoveringWindow() { return IsWindowHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup | ImGuiHoveredFlags_AllowWhenBlockedByActiveItem); } // OBSOLETE 1.51+ - static inline bool CollapsingHeader(const char* label, const char* str_id, bool framed = true, bool default_open = false) { (void)str_id; (void)framed; ImGuiTreeNodeFlags default_open_flags = 1 << 5; return CollapsingHeader(label, (default_open ? default_open_flags : 0)); } // OBSOLETE 1.49+ + // OBSOLETED in 1.54 (from Dec 2017) + static inline ImVec2 CalcItemRectClosestPoint(const ImVec2& pos, bool on_edge = false, float outward = 0.f) { (void)on_edge; (void)outward; IM_ASSERT(0); return pos; } + // OBSOLETED in 1.53 (between Oct 2017 and Dec 2017) + static inline void ShowTestWindow() { return ShowDemoWindow(); } + static inline bool IsRootWindowFocused() { return IsWindowFocused(ImGuiFocusedFlags_RootWindow); } + static inline bool IsRootWindowOrAnyChildFocused() { return IsWindowFocused(ImGuiFocusedFlags_RootAndChildWindows); } + static inline void SetNextWindowContentWidth(float w) { SetNextWindowContentSize(ImVec2(w, 0.0f)); } + // OBSOLETED in 1.52 (between Aug 2017 and Oct 2017) + bool Begin(const char* name, bool* p_open, const ImVec2& size_on_first_use, float bg_alpha_override = -1.0f, ImGuiWindowFlags flags = 0); // Use SetNextWindowSize() instead if you want to set a window size. + static inline bool IsRootWindowOrAnyChildHovered() { return IsItemHovered(ImGuiHoveredFlags_RootAndChildWindows); } // Use flags directly! + static inline void AlignFirstTextHeightToWidgets() { AlignTextToFramePadding(); } + static inline void SetNextWindowPosCenter(ImGuiCond c=0) { ImGuiIO& io = GetIO(); SetNextWindowPos(ImVec2(io.DisplaySize.x * 0.5f, io.DisplaySize.y * 0.5f), c, ImVec2(0.5f, 0.5f)); } + // OBSOLETED in 1.51 (between Jun 2017 and Aug 2017) + static inline bool IsItemHoveredRect() { return IsItemHovered(ImGuiHoveredFlags_RectOnly); } + static inline bool IsPosHoveringAnyWindow(const ImVec2&) { IM_ASSERT(0); return false; } // This was misleading and partly broken. You probably want to use the ImGui::GetIO().WantCaptureMouse flag instead. + static inline bool IsMouseHoveringAnyWindow() { return IsAnyWindowHovered(); } + static inline bool IsMouseHoveringWindow() { return IsWindowHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup | ImGuiHoveredFlags_AllowWhenBlockedByActiveItem); } + // OBSOLETED IN 1.49 (between Apr 2016 and May 2016) + static inline bool CollapsingHeader(const char* label, const char* str_id, bool framed = true, bool default_open = false) { (void)str_id; (void)framed; ImGuiTreeNodeFlags default_open_flags = 1 << 5; return CollapsingHeader(label, (default_open ? default_open_flags : 0)); } } #endif From fbf2435f38725d2f9e38faf83cd72d2540af0b5d Mon Sep 17 00:00:00 2001 From: omar Date: Fri, 29 Dec 2017 17:18:31 +0100 Subject: [PATCH 370/823] Exposed IM_OFFSETOF() helper in imgui.h --- imgui.h | 1 + imgui_internal.h | 3 +-- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/imgui.h b/imgui.h index f5ac95f89636..a8dd3435bcb4 100644 --- a/imgui.h +++ b/imgui.h @@ -39,6 +39,7 @@ #define IM_FMTLIST(FMT) #endif #define IM_ARRAYSIZE(_ARR) ((int)(sizeof(_ARR)/sizeof(*_ARR))) +#define IM_OFFSETOF(_TYPE,_ELM) ((size_t)&(((_TYPE*)0)->_ELM)) #if defined(__clang__) #pragma clang diagnostic push diff --git a/imgui_internal.h b/imgui_internal.h index fc0ef6029883..49e1e012b76d 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -77,8 +77,7 @@ extern IMGUI_API ImGuiContext* GImGui; // Current implicit ImGui context pointe // Helpers //----------------------------------------------------------------------------- -#define IM_PI 3.14159265358979323846f -#define IM_OFFSETOF(_TYPE,_ELM) ((size_t)&(((_TYPE*)0)->_ELM)) +#define IM_PI 3.14159265358979323846f // Helpers: UTF-8 <> wchar IMGUI_API int ImTextStrToUtf8(char* buf, int buf_size, const ImWchar* in_text, const ImWchar* in_text_end); // return output UTF-8 bytes count From 6ec00a366a59ad91781d4743238ebae18142f0b2 Mon Sep 17 00:00:00 2001 From: omar Date: Fri, 29 Dec 2017 18:28:04 +0100 Subject: [PATCH 371/823] Internals: ImRect: Minor formatting tweaks. --- imgui_internal.h | 40 ++++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/imgui_internal.h b/imgui_internal.h index 49e1e012b76d..7f538adec700 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -269,26 +269,26 @@ struct IMGUI_API ImRect ImRect(const ImVec4& v) : Min(v.x, v.y), Max(v.z, v.w) {} ImRect(float x1, float y1, float x2, float y2) : Min(x1, y1), Max(x2, y2) {} - ImVec2 GetCenter() const { return ImVec2((Min.x+Max.x)*0.5f, (Min.y+Max.y)*0.5f); } - ImVec2 GetSize() const { return ImVec2(Max.x-Min.x, Max.y-Min.y); } - float GetWidth() const { return Max.x-Min.x; } - float GetHeight() const { return Max.y-Min.y; } - ImVec2 GetTL() const { return Min; } // Top-left - ImVec2 GetTR() const { return ImVec2(Max.x, Min.y); } // Top-right - ImVec2 GetBL() const { return ImVec2(Min.x, Max.y); } // Bottom-left - ImVec2 GetBR() const { return Max; } // Bottom-right - bool Contains(const ImVec2& p) const { return p.x >= Min.x && p.y >= Min.y && p.x < Max.x && p.y < Max.y; } - bool Contains(const ImRect& r) const { return r.Min.x >= Min.x && r.Min.y >= Min.y && r.Max.x < Max.x && r.Max.y < Max.y; } - bool Overlaps(const ImRect& r) const { return r.Min.y < Max.y && r.Max.y > Min.y && r.Min.x < Max.x && r.Max.x > Min.x; } - void Add(const ImVec2& rhs) { if (Min.x > rhs.x) Min.x = rhs.x; if (Min.y > rhs.y) Min.y = rhs.y; if (Max.x < rhs.x) Max.x = rhs.x; if (Max.y < rhs.y) Max.y = rhs.y; } - void Add(const ImRect& rhs) { if (Min.x > rhs.Min.x) Min.x = rhs.Min.x; if (Min.y > rhs.Min.y) Min.y = rhs.Min.y; if (Max.x < rhs.Max.x) Max.x = rhs.Max.x; if (Max.y < rhs.Max.y) Max.y = rhs.Max.y; } - void Expand(const float amount) { Min.x -= amount; Min.y -= amount; Max.x += amount; Max.y += amount; } - void Expand(const ImVec2& amount) { Min.x -= amount.x; Min.y -= amount.y; Max.x += amount.x; Max.y += amount.y; } - void Translate(const ImVec2& v) { Min.x += v.x; Min.y += v.y; Max.x += v.x; Max.y += v.y; } - void ClipWith(const ImRect& clip) { if (Min.x < clip.Min.x) Min.x = clip.Min.x; if (Min.y < clip.Min.y) Min.y = clip.Min.y; if (Max.x > clip.Max.x) Max.x = clip.Max.x; if (Max.y > clip.Max.y) Max.y = clip.Max.y; } - void Floor() { Min.x = (float)(int)Min.x; Min.y = (float)(int)Min.y; Max.x = (float)(int)Max.x; Max.y = (float)(int)Max.y; } - void FixInverted() { if (Min.x > Max.x) ImSwap(Min.x, Max.x); if (Min.y > Max.y) ImSwap(Min.y, Max.y); } - bool IsFinite() const { return Min.x != FLT_MAX; } + ImVec2 GetCenter() const { return ImVec2((Min.x + Max.x) * 0.5f, (Min.y + Max.y) * 0.5f); } + ImVec2 GetSize() const { return ImVec2(Max.x - Min.x, Max.y - Min.y); } + float GetWidth() const { return Max.x - Min.x; } + float GetHeight() const { return Max.y - Min.y; } + ImVec2 GetTL() const { return Min; } // Top-left + ImVec2 GetTR() const { return ImVec2(Max.x, Min.y); } // Top-right + ImVec2 GetBL() const { return ImVec2(Min.x, Max.y); } // Bottom-left + ImVec2 GetBR() const { return Max; } // Bottom-right + bool Contains(const ImVec2& p) const { return p.x >= Min.x && p.y >= Min.y && p.x < Max.x && p.y < Max.y; } + bool Contains(const ImRect& r) const { return r.Min.x >= Min.x && r.Min.y >= Min.y && r.Max.x < Max.x && r.Max.y < Max.y; } + bool Overlaps(const ImRect& r) const { return r.Min.y < Max.y && r.Max.y > Min.y && r.Min.x < Max.x && r.Max.x > Min.x; } + void Add(const ImVec2& p) { if (Min.x > p.x) Min.x = p.x; if (Min.y > p.y) Min.y = p.y; if (Max.x < p.x) Max.x = p.x; if (Max.y < p.y) Max.y = p.y; } + void Add(const ImRect& r) { if (Min.x > r.Min.x) Min.x = r.Min.x; if (Min.y > r.Min.y) Min.y = r.Min.y; if (Max.x < r.Max.x) Max.x = r.Max.x; if (Max.y < r.Max.y) Max.y = r.Max.y; } + void Expand(const float amount) { Min.x -= amount; Min.y -= amount; Max.x += amount; Max.y += amount; } + void Expand(const ImVec2& amount) { Min.x -= amount.x; Min.y -= amount.y; Max.x += amount.x; Max.y += amount.y; } + void Translate(const ImVec2& v) { Min.x += v.x; Min.y += v.y; Max.x += v.x; Max.y += v.y; } + void ClipWith(const ImRect& r) { if (Min.x < r.Min.x) Min.x = r.Min.x; if (Min.y < r.Min.y) Min.y = r.Min.y; if (Max.x > r.Max.x) Max.x = r.Max.x; if (Max.y > r.Max.y) Max.y = r.Max.y; } + void Floor() { Min.x = (float)(int)Min.x; Min.y = (float)(int)Min.y; Max.x = (float)(int)Max.x; Max.y = (float)(int)Max.y; } + void FixInverted() { if (Min.x > Max.x) ImSwap(Min.x, Max.x); if (Min.y > Max.y) ImSwap(Min.y, Max.y); } + bool IsFinite() const { return Min.x != FLT_MAX; } }; // Stacked color modifier, backup of modified data so we can restore it From 4af84ac781bff28ca063fae6bc3d2683e502517f Mon Sep 17 00:00:00 2001 From: omar Date: Sat, 30 Dec 2017 23:10:11 +0100 Subject: [PATCH 372/823] ImFontAtlas: Handle stb_truetype failure more gracefully, GetTexDataAsRGBA32() won't crash during conversion. (#1527) --- imgui_draw.cpp | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/imgui_draw.cpp b/imgui_draw.cpp index b56d90cfcdf7..3de85da86605 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -1439,11 +1439,14 @@ void ImFontAtlas::GetTexDataAsRGBA32(unsigned char** out_pixels, int* out_wid { unsigned char* pixels; GetTexDataAsAlpha8(&pixels, NULL, NULL); - TexPixelsRGBA32 = (unsigned int*)ImGui::MemAlloc((size_t)(TexWidth * TexHeight * 4)); - const unsigned char* src = pixels; - unsigned int* dst = TexPixelsRGBA32; - for (int n = TexWidth * TexHeight; n > 0; n--) - *dst++ = IM_COL32(255, 255, 255, (unsigned int)(*src++)); + if (pixels) + { + TexPixelsRGBA32 = (unsigned int*)ImGui::MemAlloc((size_t)(TexWidth * TexHeight * 4)); + const unsigned char* src = pixels; + unsigned int* dst = TexPixelsRGBA32; + for (int n = TexWidth * TexHeight; n > 0; n--) + *dst++ = IM_COL32(255, 255, 255, (unsigned int)(*src++)); + } } *out_pixels = (unsigned char*)TexPixelsRGBA32; @@ -1683,6 +1686,7 @@ bool ImFontAtlasBuildWithStbTruetype(ImFontAtlas* atlas) IM_ASSERT(font_offset >= 0); if (!stbtt_InitFont(&tmp.FontInfo, (unsigned char*)cfg.FontData, font_offset)) { + atlas->TexWidth = atlas->TexHeight = 0; // Reset output on failure ImGui::MemFree(tmp_array); return false; } From 170bcb2d7c247595761bfb07b36755aa6541f4cf Mon Sep 17 00:00:00 2001 From: omar Date: Fri, 29 Dec 2017 20:56:52 +0100 Subject: [PATCH 373/823] Internals: NewFrame: Shuffled some code around (to minimize upcoming patches) --- imgui.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 4b8f8aa474ca..b9ceb11df9ab 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2276,15 +2276,16 @@ void ImGui::NewFrame() if (!g.Initialized) Initialize(); + g.Time += g.IO.DeltaTime; + g.FrameCount += 1; + g.TooltipOverrideCount = 0; + g.WindowsActiveCount = 0; + SetCurrentFont(GetDefaultFont()); IM_ASSERT(g.Font->IsLoaded()); g.DrawListSharedData.ClipRectFullscreen = ImVec4(0.0f, 0.0f, g.IO.DisplaySize.x, g.IO.DisplaySize.y); g.DrawListSharedData.CurveTessellationTol = g.Style.CurveTessellationTol; - g.Time += g.IO.DeltaTime; - g.FrameCount += 1; - g.TooltipOverrideCount = 0; - g.WindowsActiveCount = 0; g.OverlayDrawList.Clear(); g.OverlayDrawList.PushTextureID(g.IO.Fonts->TexID); g.OverlayDrawList.PushClipRectFullScreen(); From 561e9f286eee47f3a651f2bb3a1f6d021179e7ee Mon Sep 17 00:00:00 2001 From: Cory McWilliams Date: Tue, 2 Jan 2018 10:46:20 -0500 Subject: [PATCH 374/823] Fix a memory leak of ImGuiColumnsSet's Columns vector. ImVector doesn't call destructors. --- imgui.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/imgui.cpp b/imgui.cpp index b9ceb11df9ab..2b6b699a7157 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1876,6 +1876,8 @@ ImGuiWindow::~ImGuiWindow() { IM_DELETE(DrawList); IM_DELETE(Name); + for (int i = 0; i != ColumnsStorage.Size; i++) + ColumnsStorage[i].~ImGuiColumnsSet(); } ImGuiID ImGuiWindow::GetID(const char* str, const char* str_end) From 856ee17ed8f73023701cb9642bfe02902be1777a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Branimir=20Karad=C5=BEi=C4=87?= Date: Tue, 2 Jan 2018 16:20:51 -0800 Subject: [PATCH 375/823] Fixed Android clang warning. --- imgui_draw.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/imgui_draw.cpp b/imgui_draw.cpp index 3de85da86605..c7232af8fedc 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -42,7 +42,9 @@ #pragma clang diagnostic ignored "-Wfloat-equal" // warning : comparing floating point with == or != is unsafe // storing and comparing against same constants ok. #pragma clang diagnostic ignored "-Wglobal-constructors" // warning : declaration requires a global destructor // similar to above, not sure what the exact difference it. #pragma clang diagnostic ignored "-Wsign-conversion" // warning : implicit conversion changes signedness // +#if __has_warning("-Wcomma") #pragma clang diagnostic ignored "-Wcomma" // warning : possible misuse of comma operator here // +#endif #if __has_warning("-Wreserved-id-macro") #pragma clang diagnostic ignored "-Wreserved-id-macro" // warning : macro name is a reserved identifier // #endif From 04b44398eb2602d40c5688c1f092b7340bf30f82 Mon Sep 17 00:00:00 2001 From: omar Date: Wed, 3 Jan 2018 12:12:41 +0100 Subject: [PATCH 376/823] Internals: refactored g.SetNextWindow fields into g.NextWindow. structure (so it can be more easily transported/copied) --- imgui.cpp | 116 +++++++++++++++++++++++------------------------ imgui_internal.h | 69 +++++++++++++++------------- 2 files changed, 95 insertions(+), 90 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 2b6b699a7157..1e257e0dacb9 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2632,8 +2632,8 @@ void ImGui::Shutdown() g.FontStack.clear(); g.OpenPopupStack.clear(); g.CurrentPopupStack.clear(); - g.SetNextWindowSizeConstraintCallback = NULL; - g.SetNextWindowSizeConstraintCallbackUserData = NULL; + g.NextWindow.SizeConstraintCallback = NULL; + g.NextWindow.SizeConstraintCallbackUserData = NULL; for (int i = 0; i < IM_ARRAYSIZE(g.RenderDrawLists); i++) g.RenderDrawLists[i].clear(); g.OverlayDrawList.ClearFreeMemory(); @@ -3820,8 +3820,8 @@ static inline void ClearSetNextWindowData() { // FIXME-OPT ImGuiContext& g = *GImGui; - g.SetNextWindowPosCond = g.SetNextWindowSizeCond = g.SetNextWindowContentSizeCond = g.SetNextWindowCollapsedCond = 0; - g.SetNextWindowSizeConstraint = g.SetNextWindowFocus = false; + g.NextWindow.PosCond = g.NextWindow.SizeCond = g.NextWindow.ContentSizeCond = g.NextWindow.CollapsedCond = 0; + g.NextWindow.SizeConstraint = g.NextWindow.Focus = false; } bool ImGui::BeginPopupEx(ImGuiID id, ImGuiWindowFlags extra_flags) @@ -3881,7 +3881,7 @@ bool ImGui::BeginPopupModal(const char* name, bool* p_open, ImGuiWindowFlags ext } // Center modal windows by default - if (g.SetNextWindowPosCond == 0) + if (g.NextWindow.PosCond == 0) SetNextWindowPos(g.IO.DisplaySize * 0.5f, ImGuiCond_Appearing, ImVec2(0.5f, 0.5f)); ImGuiWindowFlags flags = extra_flags|ImGuiWindowFlags_Popup|ImGuiWindowFlags_Modal|ImGuiWindowFlags_NoCollapse|ImGuiWindowFlags_NoSavedSettings; @@ -4193,20 +4193,20 @@ static ImGuiWindow* CreateNewWindow(const char* name, ImVec2 size, ImGuiWindowFl static ImVec2 CalcSizeAfterConstraint(ImGuiWindow* window, ImVec2 new_size) { ImGuiContext& g = *GImGui; - if (g.SetNextWindowSizeConstraint) + if (g.NextWindow.SizeConstraint) { // Using -1,-1 on either X/Y axis to preserve the current size. - ImRect cr = g.SetNextWindowSizeConstraintRect; + ImRect cr = g.NextWindow.SizeConstraintRect; new_size.x = (cr.Min.x >= 0 && cr.Max.x >= 0) ? ImClamp(new_size.x, cr.Min.x, cr.Max.x) : window->SizeFull.x; new_size.y = (cr.Min.y >= 0 && cr.Max.y >= 0) ? ImClamp(new_size.y, cr.Min.y, cr.Max.y) : window->SizeFull.y; - if (g.SetNextWindowSizeConstraintCallback) + if (g.NextWindow.SizeConstraintCallback) { ImGuiSizeConstraintCallbackData data; - data.UserData = g.SetNextWindowSizeConstraintCallbackUserData; + data.UserData = g.NextWindow.SizeConstraintCallbackUserData; data.Pos = window->Pos; data.CurrentSize = window->SizeFull; data.DesiredSize = new_size; - g.SetNextWindowSizeConstraintCallback(&data); + g.NextWindow.SizeConstraintCallback(&data); new_size = data.DesiredSize; } } @@ -4352,7 +4352,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) ImGuiWindow* window = FindWindowByName(name); if (!window) { - ImVec2 size_on_first_use = (g.SetNextWindowSizeCond != 0) ? g.SetNextWindowSizeVal : ImVec2(0.0f, 0.0f); // Any condition flag will do since we are creating a new window here. + ImVec2 size_on_first_use = (g.NextWindow.SizeCond != 0) ? g.NextWindow.SizeVal : ImVec2(0.0f, 0.0f); // Any condition flag will do since we are creating a new window here. window = CreateNewWindow(name, size_on_first_use, flags); } @@ -4397,50 +4397,50 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) // Process SetNextWindow***() calls bool window_pos_set_by_api = false; bool window_size_x_set_by_api = false, window_size_y_set_by_api = false; - if (g.SetNextWindowPosCond) + if (g.NextWindow.PosCond) { - window_pos_set_by_api = (window->SetWindowPosAllowFlags & g.SetNextWindowPosCond) != 0; - if (window_pos_set_by_api && ImLengthSqr(g.SetNextWindowPosPivot) > 0.00001f) + window_pos_set_by_api = (window->SetWindowPosAllowFlags & g.NextWindow.PosCond) != 0; + if (window_pos_set_by_api && ImLengthSqr(g.NextWindow.PosPivotVal) > 0.00001f) { // May be processed on the next frame if this is our first frame and we are measuring size // FIXME: Look into removing the branch so everything can go through this same code path for consistency. - window->SetWindowPosVal = g.SetNextWindowPosVal; - window->SetWindowPosPivot = g.SetNextWindowPosPivot; + window->SetWindowPosVal = g.NextWindow.PosVal; + window->SetWindowPosPivot = g.NextWindow.PosPivotVal; window->SetWindowPosAllowFlags &= ~(ImGuiCond_Once | ImGuiCond_FirstUseEver | ImGuiCond_Appearing); } else { - SetWindowPos(window, g.SetNextWindowPosVal, g.SetNextWindowPosCond); + SetWindowPos(window, g.NextWindow.PosVal, g.NextWindow.PosCond); } - g.SetNextWindowPosCond = 0; + g.NextWindow.PosCond = 0; } - if (g.SetNextWindowSizeCond) + if (g.NextWindow.SizeCond) { - window_size_x_set_by_api = (window->SetWindowSizeAllowFlags & g.SetNextWindowSizeCond) != 0 && (g.SetNextWindowSizeVal.x > 0.0f); - window_size_y_set_by_api = (window->SetWindowSizeAllowFlags & g.SetNextWindowSizeCond) != 0 && (g.SetNextWindowSizeVal.y > 0.0f); - SetWindowSize(window, g.SetNextWindowSizeVal, g.SetNextWindowSizeCond); - g.SetNextWindowSizeCond = 0; + window_size_x_set_by_api = (window->SetWindowSizeAllowFlags & g.NextWindow.SizeCond) != 0 && (g.NextWindow.SizeVal.x > 0.0f); + window_size_y_set_by_api = (window->SetWindowSizeAllowFlags & g.NextWindow.SizeCond) != 0 && (g.NextWindow.SizeVal.y > 0.0f); + SetWindowSize(window, g.NextWindow.SizeVal, g.NextWindow.SizeCond); + g.NextWindow.SizeCond = 0; } - if (g.SetNextWindowContentSizeCond) + if (g.NextWindow.ContentSizeCond) { // Adjust passed "client size" to become a "window size" - window->SizeContentsExplicit = g.SetNextWindowContentSizeVal; + window->SizeContentsExplicit = g.NextWindow.ContentSizeVal; window->SizeContentsExplicit.y += window->TitleBarHeight() + window->MenuBarHeight(); - g.SetNextWindowContentSizeCond = 0; + g.NextWindow.ContentSizeCond = 0; } else if (first_begin_of_the_frame) { window->SizeContentsExplicit = ImVec2(0.0f, 0.0f); } - if (g.SetNextWindowCollapsedCond) + if (g.NextWindow.CollapsedCond) { - SetWindowCollapsed(window, g.SetNextWindowCollapsedVal, g.SetNextWindowCollapsedCond); - g.SetNextWindowCollapsedCond = 0; + SetWindowCollapsed(window, g.NextWindow.CollapsedVal, g.NextWindow.CollapsedCond); + g.NextWindow.CollapsedCond = 0; } - if (g.SetNextWindowFocus) + if (g.NextWindow.Focus) { SetWindowFocus(); - g.SetNextWindowFocus = false; + g.NextWindow.Focus = false; } if (window->Appearing) SetWindowConditionAllowFlags(window, ImGuiCond_Appearing, false); @@ -4940,7 +4940,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) window->WriteAccessed = false; window->BeginCount++; - g.SetNextWindowSizeConstraint = false; + g.NextWindow.SizeConstraint = false; // Child window can be out of sight and have "negative" clip windows. // Mark them as collapsed so commands are skipped earlier (we can't manually collapse because they have no title bar). @@ -5702,45 +5702,45 @@ void ImGui::SetWindowFocus(const char* name) void ImGui::SetNextWindowPos(const ImVec2& pos, ImGuiCond cond, const ImVec2& pivot) { ImGuiContext& g = *GImGui; - g.SetNextWindowPosVal = pos; - g.SetNextWindowPosPivot = pivot; - g.SetNextWindowPosCond = cond ? cond : ImGuiCond_Always; + g.NextWindow.PosVal = pos; + g.NextWindow.PosPivotVal = pivot; + g.NextWindow.PosCond = cond ? cond : ImGuiCond_Always; } void ImGui::SetNextWindowSize(const ImVec2& size, ImGuiCond cond) { ImGuiContext& g = *GImGui; - g.SetNextWindowSizeVal = size; - g.SetNextWindowSizeCond = cond ? cond : ImGuiCond_Always; + g.NextWindow.SizeVal = size; + g.NextWindow.SizeCond = cond ? cond : ImGuiCond_Always; } void ImGui::SetNextWindowSizeConstraints(const ImVec2& size_min, const ImVec2& size_max, ImGuiSizeConstraintCallback custom_callback, void* custom_callback_user_data) { ImGuiContext& g = *GImGui; - g.SetNextWindowSizeConstraint = true; - g.SetNextWindowSizeConstraintRect = ImRect(size_min, size_max); - g.SetNextWindowSizeConstraintCallback = custom_callback; - g.SetNextWindowSizeConstraintCallbackUserData = custom_callback_user_data; + g.NextWindow.SizeConstraint = true; + g.NextWindow.SizeConstraintRect = ImRect(size_min, size_max); + g.NextWindow.SizeConstraintCallback = custom_callback; + g.NextWindow.SizeConstraintCallbackUserData = custom_callback_user_data; } void ImGui::SetNextWindowContentSize(const ImVec2& size) { ImGuiContext& g = *GImGui; - g.SetNextWindowContentSizeVal = size; // In Begin() we will add the size of window decorations (title bar, menu etc.) to that to form a SizeContents value. - g.SetNextWindowContentSizeCond = ImGuiCond_Always; + g.NextWindow.ContentSizeVal = size; // In Begin() we will add the size of window decorations (title bar, menu etc.) to that to form a SizeContents value. + g.NextWindow.ContentSizeCond = ImGuiCond_Always; } void ImGui::SetNextWindowCollapsed(bool collapsed, ImGuiCond cond) { ImGuiContext& g = *GImGui; - g.SetNextWindowCollapsedVal = collapsed; - g.SetNextWindowCollapsedCond = cond ? cond : ImGuiCond_Always; + g.NextWindow.CollapsedVal = collapsed; + g.NextWindow.CollapsedCond = cond ? cond : ImGuiCond_Always; } void ImGui::SetNextWindowFocus() { ImGuiContext& g = *GImGui; - g.SetNextWindowFocus = true; + g.NextWindow.Focus = true; } // In window space (not screen space!) @@ -6615,11 +6615,11 @@ bool ImGui::TreeNodeBehaviorIsOpen(ImGuiID id, ImGuiTreeNodeFlags flags) ImGuiStorage* storage = window->DC.StateStorage; bool is_open; - if (g.SetNextTreeNodeOpenCond != 0) + if (g.NextTreeNodeOpenCond != 0) { - if (g.SetNextTreeNodeOpenCond & ImGuiCond_Always) + if (g.NextTreeNodeOpenCond & ImGuiCond_Always) { - is_open = g.SetNextTreeNodeOpenVal; + is_open = g.NextTreeNodeOpenVal; storage->SetInt(id, is_open); } else @@ -6628,7 +6628,7 @@ bool ImGui::TreeNodeBehaviorIsOpen(ImGuiID id, ImGuiTreeNodeFlags flags) const int stored_value = storage->GetInt(id, -1); if (stored_value == -1) { - is_open = g.SetNextTreeNodeOpenVal; + is_open = g.NextTreeNodeOpenVal; storage->SetInt(id, is_open); } else @@ -6636,7 +6636,7 @@ bool ImGui::TreeNodeBehaviorIsOpen(ImGuiID id, ImGuiTreeNodeFlags flags) is_open = stored_value != 0; } } - g.SetNextTreeNodeOpenCond = 0; + g.NextTreeNodeOpenCond = 0; } else { @@ -6903,8 +6903,8 @@ void ImGui::SetNextTreeNodeOpen(bool is_open, ImGuiCond cond) ImGuiContext& g = *GImGui; if (g.CurrentWindow->SkipItems) return; - g.SetNextTreeNodeOpenVal = is_open; - g.SetNextTreeNodeOpenCond = cond ? cond : ImGuiCond_Always; + g.NextTreeNodeOpenVal = is_open; + g.NextTreeNodeOpenCond = cond ? cond : ImGuiCond_Always; } void ImGui::PushID(const char* str_id) @@ -9163,8 +9163,8 @@ bool ImGui::BeginCombo(const char* label, const char* preview_value, ImGuiComboF { // Always consume the SetNextWindowSizeConstraint() call in our early return paths ImGuiContext& g = *GImGui; - bool backup_has_next_window_size_constraint = g.SetNextWindowSizeConstraint; - g.SetNextWindowSizeConstraint = false; + bool backup_has_next_window_size_constraint = g.NextWindow.SizeConstraint; + g.NextWindow.SizeConstraint = false; ImGuiWindow* window = GetCurrentWindow(); if (window->SkipItems) @@ -9206,8 +9206,8 @@ bool ImGui::BeginCombo(const char* label, const char* preview_value, ImGuiComboF if (backup_has_next_window_size_constraint) { - g.SetNextWindowSizeConstraint = true; - g.SetNextWindowSizeConstraintRect.Min.x = ImMax(g.SetNextWindowSizeConstraintRect.Min.x, w); + g.NextWindow.SizeConstraint = true; + g.NextWindow.SizeConstraintRect.Min.x = ImMax(g.NextWindow.SizeConstraintRect.Min.x, w); } else { @@ -9269,7 +9269,7 @@ bool ImGui::Combo(const char* label, int* current_item, bool (*items_getter)(voi items_getter(data, *current_item, &preview_text); // The old Combo() API exposed "popup_max_height_in_items", however the new more general BeginCombo() API doesn't, so we emulate it here. - if (popup_max_height_in_items != -1 && !g.SetNextWindowSizeConstraint) + if (popup_max_height_in_items != -1 && !g.NextWindow.SizeConstraint) { float popup_max_height = CalcMaxPopupHeightFromItemCount(popup_max_height_in_items); SetNextWindowSizeConstraints(ImVec2(0,0), ImVec2(FLT_MAX, popup_max_height)); diff --git a/imgui_internal.h b/imgui_internal.h index 7f538adec700..7877e3ffead6 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -459,6 +459,38 @@ struct ImDrawListSharedData ImDrawListSharedData(); }; +// Storage for SetNexWindow** functions +struct ImGuiNextWindowData +{ + ImGuiCond PosCond; + ImGuiCond SizeCond; + ImGuiCond ContentSizeCond; + ImGuiCond CollapsedCond; + ImVec2 PosVal; + ImVec2 PosPivotVal; + ImVec2 SizeVal; + ImVec2 ContentSizeVal; + bool CollapsedVal; + ImRect SizeConstraintRect; // Valid if 'SetNextWindowSizeConstraint' is true + ImGuiSizeConstraintCallback SizeConstraintCallback; + void* SizeConstraintCallbackUserData; + bool SizeConstraint; + bool Focus; + + ImGuiNextWindowData() + { + PosCond = SizeCond = ContentSizeCond = CollapsedCond = 0; + PosVal = PosPivotVal = SizeVal = ImVec2(0.0f, 0.0f); + ContentSizeVal = ImVec2(0.0f, 0.0f); + CollapsedVal = false; + SizeConstraintRect = ImRect(); + SizeConstraintCallback = NULL; + SizeConstraintCallbackUserData = NULL; + SizeConstraint = false; + Focus = false; + } +}; + // Main state for ImGui struct ImGuiContext { @@ -502,24 +534,9 @@ struct ImGuiContext ImVector FontStack; // Stack for PushFont()/PopFont() ImVector OpenPopupStack; // Which popups are open (persistent) ImVector CurrentPopupStack; // Which level of BeginPopup() we are in (reset every frame) - - // Storage for SetNexWindow** and SetNextTreeNode*** functions - ImVec2 SetNextWindowPosVal; - ImVec2 SetNextWindowPosPivot; - ImVec2 SetNextWindowSizeVal; - ImVec2 SetNextWindowContentSizeVal; - bool SetNextWindowCollapsedVal; - ImGuiCond SetNextWindowPosCond; - ImGuiCond SetNextWindowSizeCond; - ImGuiCond SetNextWindowContentSizeCond; - ImGuiCond SetNextWindowCollapsedCond; - ImRect SetNextWindowSizeConstraintRect; // Valid if 'SetNextWindowSizeConstraint' is true - ImGuiSizeConstraintCallback SetNextWindowSizeConstraintCallback; - void* SetNextWindowSizeConstraintCallbackUserData; - bool SetNextWindowSizeConstraint; - bool SetNextWindowFocus; - bool SetNextTreeNodeOpenVal; - ImGuiCond SetNextTreeNodeOpenCond; + ImGuiNextWindowData NextWindow; // Storage for SetNextWindow** functions + bool NextTreeNodeOpenVal; // Storage for SetNextTreeNode** functions + ImGuiCond NextTreeNodeOpenCond; // Render ImDrawData RenderDrawData; // Main ImDrawData instance to pass render information to the user @@ -609,20 +626,8 @@ struct ImGuiContext MovingWindow = NULL; MovingWindowMoveId = 0; - SetNextWindowPosVal = ImVec2(0.0f, 0.0f); - SetNextWindowSizeVal = ImVec2(0.0f, 0.0f); - SetNextWindowCollapsedVal = false; - SetNextWindowPosCond = 0; - SetNextWindowSizeCond = 0; - SetNextWindowContentSizeCond = 0; - SetNextWindowCollapsedCond = 0; - SetNextWindowSizeConstraintRect = ImRect(); - SetNextWindowSizeConstraintCallback = NULL; - SetNextWindowSizeConstraintCallbackUserData = NULL; - SetNextWindowSizeConstraint = false; - SetNextWindowFocus = false; - SetNextTreeNodeOpenVal = false; - SetNextTreeNodeOpenCond = 0; + NextTreeNodeOpenVal = false; + NextTreeNodeOpenCond = 0; DragDropActive = false; DragDropSourceFlags = 0; From e339949de1c01f3eb2f2d4815f5e8f0f44287229 Mon Sep 17 00:00:00 2001 From: omar Date: Wed, 3 Jan 2018 12:22:02 +0100 Subject: [PATCH 377/823] Internals: NextWindow: Using ImGuiCond for consistency. --- imgui.cpp | 25 ++++++++++++------------- imgui_internal.h | 8 +++----- 2 files changed, 15 insertions(+), 18 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 1e257e0dacb9..b303170e5228 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -3820,8 +3820,7 @@ static inline void ClearSetNextWindowData() { // FIXME-OPT ImGuiContext& g = *GImGui; - g.NextWindow.PosCond = g.NextWindow.SizeCond = g.NextWindow.ContentSizeCond = g.NextWindow.CollapsedCond = 0; - g.NextWindow.SizeConstraint = g.NextWindow.Focus = false; + g.NextWindow.PosCond = g.NextWindow.SizeCond = g.NextWindow.ContentSizeCond = g.NextWindow.CollapsedCond = g.NextWindow.SizeConstraintCond = g.NextWindow.FocusCond = 0; } bool ImGui::BeginPopupEx(ImGuiID id, ImGuiWindowFlags extra_flags) @@ -4193,7 +4192,7 @@ static ImGuiWindow* CreateNewWindow(const char* name, ImVec2 size, ImGuiWindowFl static ImVec2 CalcSizeAfterConstraint(ImGuiWindow* window, ImVec2 new_size) { ImGuiContext& g = *GImGui; - if (g.NextWindow.SizeConstraint) + if (g.NextWindow.SizeConstraintCond != 0) { // Using -1,-1 on either X/Y axis to preserve the current size. ImRect cr = g.NextWindow.SizeConstraintRect; @@ -4437,10 +4436,10 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) SetWindowCollapsed(window, g.NextWindow.CollapsedVal, g.NextWindow.CollapsedCond); g.NextWindow.CollapsedCond = 0; } - if (g.NextWindow.Focus) + if (g.NextWindow.FocusCond) { SetWindowFocus(); - g.NextWindow.Focus = false; + g.NextWindow.FocusCond = 0; } if (window->Appearing) SetWindowConditionAllowFlags(window, ImGuiCond_Appearing, false); @@ -4940,7 +4939,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) window->WriteAccessed = false; window->BeginCount++; - g.NextWindow.SizeConstraint = false; + g.NextWindow.SizeConstraintCond = 0; // Child window can be out of sight and have "negative" clip windows. // Mark them as collapsed so commands are skipped earlier (we can't manually collapse because they have no title bar). @@ -5717,7 +5716,7 @@ void ImGui::SetNextWindowSize(const ImVec2& size, ImGuiCond cond) void ImGui::SetNextWindowSizeConstraints(const ImVec2& size_min, const ImVec2& size_max, ImGuiSizeConstraintCallback custom_callback, void* custom_callback_user_data) { ImGuiContext& g = *GImGui; - g.NextWindow.SizeConstraint = true; + g.NextWindow.SizeConstraintCond = ImGuiCond_Always; g.NextWindow.SizeConstraintRect = ImRect(size_min, size_max); g.NextWindow.SizeConstraintCallback = custom_callback; g.NextWindow.SizeConstraintCallbackUserData = custom_callback_user_data; @@ -5740,7 +5739,7 @@ void ImGui::SetNextWindowCollapsed(bool collapsed, ImGuiCond cond) void ImGui::SetNextWindowFocus() { ImGuiContext& g = *GImGui; - g.NextWindow.Focus = true; + g.NextWindow.FocusCond = ImGuiCond_Always; } // In window space (not screen space!) @@ -9163,8 +9162,8 @@ bool ImGui::BeginCombo(const char* label, const char* preview_value, ImGuiComboF { // Always consume the SetNextWindowSizeConstraint() call in our early return paths ImGuiContext& g = *GImGui; - bool backup_has_next_window_size_constraint = g.NextWindow.SizeConstraint; - g.NextWindow.SizeConstraint = false; + ImGuiCond backup_next_window_size_constraint = g.NextWindow.SizeConstraintCond; + g.NextWindow.SizeConstraintCond = 0; ImGuiWindow* window = GetCurrentWindow(); if (window->SkipItems) @@ -9204,9 +9203,9 @@ bool ImGui::BeginCombo(const char* label, const char* preview_value, ImGuiComboF if (!popup_open) return false; - if (backup_has_next_window_size_constraint) + if (backup_next_window_size_constraint) { - g.NextWindow.SizeConstraint = true; + g.NextWindow.SizeConstraintCond = backup_next_window_size_constraint; g.NextWindow.SizeConstraintRect.Min.x = ImMax(g.NextWindow.SizeConstraintRect.Min.x, w); } else @@ -9269,7 +9268,7 @@ bool ImGui::Combo(const char* label, int* current_item, bool (*items_getter)(voi items_getter(data, *current_item, &preview_text); // The old Combo() API exposed "popup_max_height_in_items", however the new more general BeginCombo() API doesn't, so we emulate it here. - if (popup_max_height_in_items != -1 && !g.NextWindow.SizeConstraint) + if (popup_max_height_in_items != -1 && !g.NextWindow.SizeConstraintCond) { float popup_max_height = CalcMaxPopupHeightFromItemCount(popup_max_height_in_items); SetNextWindowSizeConstraints(ImVec2(0,0), ImVec2(FLT_MAX, popup_max_height)); diff --git a/imgui_internal.h b/imgui_internal.h index 7877e3ffead6..f66e99eb2b68 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -466,6 +466,8 @@ struct ImGuiNextWindowData ImGuiCond SizeCond; ImGuiCond ContentSizeCond; ImGuiCond CollapsedCond; + ImGuiCond SizeConstraintCond; + ImGuiCond FocusCond; ImVec2 PosVal; ImVec2 PosPivotVal; ImVec2 SizeVal; @@ -474,20 +476,16 @@ struct ImGuiNextWindowData ImRect SizeConstraintRect; // Valid if 'SetNextWindowSizeConstraint' is true ImGuiSizeConstraintCallback SizeConstraintCallback; void* SizeConstraintCallbackUserData; - bool SizeConstraint; - bool Focus; ImGuiNextWindowData() { - PosCond = SizeCond = ContentSizeCond = CollapsedCond = 0; + PosCond = SizeCond = ContentSizeCond = CollapsedCond = SizeConstraintCond = FocusCond = 0; PosVal = PosPivotVal = SizeVal = ImVec2(0.0f, 0.0f); ContentSizeVal = ImVec2(0.0f, 0.0f); CollapsedVal = false; SizeConstraintRect = ImRect(); SizeConstraintCallback = NULL; SizeConstraintCallbackUserData = NULL; - SizeConstraint = false; - Focus = false; } }; From 7fcbd4550010d53ec294fc7aa239ea97f76dfdf4 Mon Sep 17 00:00:00 2001 From: omar Date: Wed, 3 Jan 2018 12:28:16 +0100 Subject: [PATCH 378/823] Internals: NextWindow: Renamed, moved functions to member. --- imgui.cpp | 110 +++++++++++++++++++++-------------------------- imgui_internal.h | 7 ++- 2 files changed, 56 insertions(+), 61 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index b303170e5228..ae85abf064dd 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -642,7 +642,6 @@ static void SetWindowSize(ImGuiWindow* window, const ImVec2& size, I static void SetWindowCollapsed(ImGuiWindow* window, bool collapsed, ImGuiCond cond); static ImGuiWindow* FindHoveredWindow(ImVec2 pos); static ImGuiWindow* CreateNewWindow(const char* name, ImVec2 size, ImGuiWindowFlags flags); -static void ClearSetNextWindowData(); static void CheckStacksSize(ImGuiWindow* window, bool write); static ImVec2 CalcNextScrollFromScrollTargetAndClamp(ImGuiWindow* window); @@ -2632,8 +2631,6 @@ void ImGui::Shutdown() g.FontStack.clear(); g.OpenPopupStack.clear(); g.CurrentPopupStack.clear(); - g.NextWindow.SizeConstraintCallback = NULL; - g.NextWindow.SizeConstraintCallbackUserData = NULL; for (int i = 0; i < IM_ARRAYSIZE(g.RenderDrawLists); i++) g.RenderDrawLists[i].clear(); g.OverlayDrawList.ClearFreeMemory(); @@ -3816,19 +3813,12 @@ void ImGui::CloseCurrentPopup() ClosePopupToLevel(popup_idx); } -static inline void ClearSetNextWindowData() -{ - // FIXME-OPT - ImGuiContext& g = *GImGui; - g.NextWindow.PosCond = g.NextWindow.SizeCond = g.NextWindow.ContentSizeCond = g.NextWindow.CollapsedCond = g.NextWindow.SizeConstraintCond = g.NextWindow.FocusCond = 0; -} - bool ImGui::BeginPopupEx(ImGuiID id, ImGuiWindowFlags extra_flags) { ImGuiContext& g = *GImGui; if (!IsPopupOpen(id)) { - ClearSetNextWindowData(); // We behave like Begin() and need to consume those values + g.NextWindowData.Clear(); // We behave like Begin() and need to consume those values return false; } @@ -3850,7 +3840,7 @@ bool ImGui::BeginPopup(const char* str_id) ImGuiContext& g = *GImGui; if (g.OpenPopupStack.Size <= g.CurrentPopupStack.Size) // Early out for performance { - ClearSetNextWindowData(); // We behave like Begin() and need to consume those values + g.NextWindowData.Clear(); // We behave like Begin() and need to consume those values return false; } return BeginPopupEx(g.CurrentWindow->GetID(str_id), ImGuiWindowFlags_AlwaysAutoResize|ImGuiWindowFlags_NoTitleBar|ImGuiWindowFlags_NoSavedSettings); @@ -3875,12 +3865,12 @@ bool ImGui::BeginPopupModal(const char* name, bool* p_open, ImGuiWindowFlags ext const ImGuiID id = window->GetID(name); if (!IsPopupOpen(id)) { - ClearSetNextWindowData(); // We behave like Begin() and need to consume those values + g.NextWindowData.Clear(); // We behave like Begin() and need to consume those values return false; } // Center modal windows by default - if (g.NextWindow.PosCond == 0) + if (g.NextWindowData.PosCond == 0) SetNextWindowPos(g.IO.DisplaySize * 0.5f, ImGuiCond_Appearing, ImVec2(0.5f, 0.5f)); ImGuiWindowFlags flags = extra_flags|ImGuiWindowFlags_Popup|ImGuiWindowFlags_Modal|ImGuiWindowFlags_NoCollapse|ImGuiWindowFlags_NoSavedSettings; @@ -4192,20 +4182,20 @@ static ImGuiWindow* CreateNewWindow(const char* name, ImVec2 size, ImGuiWindowFl static ImVec2 CalcSizeAfterConstraint(ImGuiWindow* window, ImVec2 new_size) { ImGuiContext& g = *GImGui; - if (g.NextWindow.SizeConstraintCond != 0) + if (g.NextWindowData.SizeConstraintCond != 0) { // Using -1,-1 on either X/Y axis to preserve the current size. - ImRect cr = g.NextWindow.SizeConstraintRect; + ImRect cr = g.NextWindowData.SizeConstraintRect; new_size.x = (cr.Min.x >= 0 && cr.Max.x >= 0) ? ImClamp(new_size.x, cr.Min.x, cr.Max.x) : window->SizeFull.x; new_size.y = (cr.Min.y >= 0 && cr.Max.y >= 0) ? ImClamp(new_size.y, cr.Min.y, cr.Max.y) : window->SizeFull.y; - if (g.NextWindow.SizeConstraintCallback) + if (g.NextWindowData.SizeConstraintCallback) { ImGuiSizeConstraintCallbackData data; - data.UserData = g.NextWindow.SizeConstraintCallbackUserData; + data.UserData = g.NextWindowData.SizeConstraintCallbackUserData; data.Pos = window->Pos; data.CurrentSize = window->SizeFull; data.DesiredSize = new_size; - g.NextWindow.SizeConstraintCallback(&data); + g.NextWindowData.SizeConstraintCallback(&data); new_size = data.DesiredSize; } } @@ -4351,7 +4341,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) ImGuiWindow* window = FindWindowByName(name); if (!window) { - ImVec2 size_on_first_use = (g.NextWindow.SizeCond != 0) ? g.NextWindow.SizeVal : ImVec2(0.0f, 0.0f); // Any condition flag will do since we are creating a new window here. + ImVec2 size_on_first_use = (g.NextWindowData.SizeCond != 0) ? g.NextWindowData.SizeVal : ImVec2(0.0f, 0.0f); // Any condition flag will do since we are creating a new window here. window = CreateNewWindow(name, size_on_first_use, flags); } @@ -4396,50 +4386,50 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) // Process SetNextWindow***() calls bool window_pos_set_by_api = false; bool window_size_x_set_by_api = false, window_size_y_set_by_api = false; - if (g.NextWindow.PosCond) + if (g.NextWindowData.PosCond) { - window_pos_set_by_api = (window->SetWindowPosAllowFlags & g.NextWindow.PosCond) != 0; - if (window_pos_set_by_api && ImLengthSqr(g.NextWindow.PosPivotVal) > 0.00001f) + window_pos_set_by_api = (window->SetWindowPosAllowFlags & g.NextWindowData.PosCond) != 0; + if (window_pos_set_by_api && ImLengthSqr(g.NextWindowData.PosPivotVal) > 0.00001f) { // May be processed on the next frame if this is our first frame and we are measuring size // FIXME: Look into removing the branch so everything can go through this same code path for consistency. - window->SetWindowPosVal = g.NextWindow.PosVal; - window->SetWindowPosPivot = g.NextWindow.PosPivotVal; + window->SetWindowPosVal = g.NextWindowData.PosVal; + window->SetWindowPosPivot = g.NextWindowData.PosPivotVal; window->SetWindowPosAllowFlags &= ~(ImGuiCond_Once | ImGuiCond_FirstUseEver | ImGuiCond_Appearing); } else { - SetWindowPos(window, g.NextWindow.PosVal, g.NextWindow.PosCond); + SetWindowPos(window, g.NextWindowData.PosVal, g.NextWindowData.PosCond); } - g.NextWindow.PosCond = 0; + g.NextWindowData.PosCond = 0; } - if (g.NextWindow.SizeCond) + if (g.NextWindowData.SizeCond) { - window_size_x_set_by_api = (window->SetWindowSizeAllowFlags & g.NextWindow.SizeCond) != 0 && (g.NextWindow.SizeVal.x > 0.0f); - window_size_y_set_by_api = (window->SetWindowSizeAllowFlags & g.NextWindow.SizeCond) != 0 && (g.NextWindow.SizeVal.y > 0.0f); - SetWindowSize(window, g.NextWindow.SizeVal, g.NextWindow.SizeCond); - g.NextWindow.SizeCond = 0; + window_size_x_set_by_api = (window->SetWindowSizeAllowFlags & g.NextWindowData.SizeCond) != 0 && (g.NextWindowData.SizeVal.x > 0.0f); + window_size_y_set_by_api = (window->SetWindowSizeAllowFlags & g.NextWindowData.SizeCond) != 0 && (g.NextWindowData.SizeVal.y > 0.0f); + SetWindowSize(window, g.NextWindowData.SizeVal, g.NextWindowData.SizeCond); + g.NextWindowData.SizeCond = 0; } - if (g.NextWindow.ContentSizeCond) + if (g.NextWindowData.ContentSizeCond) { // Adjust passed "client size" to become a "window size" - window->SizeContentsExplicit = g.NextWindow.ContentSizeVal; + window->SizeContentsExplicit = g.NextWindowData.ContentSizeVal; window->SizeContentsExplicit.y += window->TitleBarHeight() + window->MenuBarHeight(); - g.NextWindow.ContentSizeCond = 0; + g.NextWindowData.ContentSizeCond = 0; } else if (first_begin_of_the_frame) { window->SizeContentsExplicit = ImVec2(0.0f, 0.0f); } - if (g.NextWindow.CollapsedCond) + if (g.NextWindowData.CollapsedCond) { - SetWindowCollapsed(window, g.NextWindow.CollapsedVal, g.NextWindow.CollapsedCond); - g.NextWindow.CollapsedCond = 0; + SetWindowCollapsed(window, g.NextWindowData.CollapsedVal, g.NextWindowData.CollapsedCond); + g.NextWindowData.CollapsedCond = 0; } - if (g.NextWindow.FocusCond) + if (g.NextWindowData.FocusCond) { SetWindowFocus(); - g.NextWindow.FocusCond = 0; + g.NextWindowData.FocusCond = 0; } if (window->Appearing) SetWindowConditionAllowFlags(window, ImGuiCond_Appearing, false); @@ -4939,7 +4929,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) window->WriteAccessed = false; window->BeginCount++; - g.NextWindow.SizeConstraintCond = 0; + g.NextWindowData.SizeConstraintCond = 0; // Child window can be out of sight and have "negative" clip windows. // Mark them as collapsed so commands are skipped earlier (we can't manually collapse because they have no title bar). @@ -5701,45 +5691,45 @@ void ImGui::SetWindowFocus(const char* name) void ImGui::SetNextWindowPos(const ImVec2& pos, ImGuiCond cond, const ImVec2& pivot) { ImGuiContext& g = *GImGui; - g.NextWindow.PosVal = pos; - g.NextWindow.PosPivotVal = pivot; - g.NextWindow.PosCond = cond ? cond : ImGuiCond_Always; + g.NextWindowData.PosVal = pos; + g.NextWindowData.PosPivotVal = pivot; + g.NextWindowData.PosCond = cond ? cond : ImGuiCond_Always; } void ImGui::SetNextWindowSize(const ImVec2& size, ImGuiCond cond) { ImGuiContext& g = *GImGui; - g.NextWindow.SizeVal = size; - g.NextWindow.SizeCond = cond ? cond : ImGuiCond_Always; + g.NextWindowData.SizeVal = size; + g.NextWindowData.SizeCond = cond ? cond : ImGuiCond_Always; } void ImGui::SetNextWindowSizeConstraints(const ImVec2& size_min, const ImVec2& size_max, ImGuiSizeConstraintCallback custom_callback, void* custom_callback_user_data) { ImGuiContext& g = *GImGui; - g.NextWindow.SizeConstraintCond = ImGuiCond_Always; - g.NextWindow.SizeConstraintRect = ImRect(size_min, size_max); - g.NextWindow.SizeConstraintCallback = custom_callback; - g.NextWindow.SizeConstraintCallbackUserData = custom_callback_user_data; + g.NextWindowData.SizeConstraintCond = ImGuiCond_Always; + g.NextWindowData.SizeConstraintRect = ImRect(size_min, size_max); + g.NextWindowData.SizeConstraintCallback = custom_callback; + g.NextWindowData.SizeConstraintCallbackUserData = custom_callback_user_data; } void ImGui::SetNextWindowContentSize(const ImVec2& size) { ImGuiContext& g = *GImGui; - g.NextWindow.ContentSizeVal = size; // In Begin() we will add the size of window decorations (title bar, menu etc.) to that to form a SizeContents value. - g.NextWindow.ContentSizeCond = ImGuiCond_Always; + g.NextWindowData.ContentSizeVal = size; // In Begin() we will add the size of window decorations (title bar, menu etc.) to that to form a SizeContents value. + g.NextWindowData.ContentSizeCond = ImGuiCond_Always; } void ImGui::SetNextWindowCollapsed(bool collapsed, ImGuiCond cond) { ImGuiContext& g = *GImGui; - g.NextWindow.CollapsedVal = collapsed; - g.NextWindow.CollapsedCond = cond ? cond : ImGuiCond_Always; + g.NextWindowData.CollapsedVal = collapsed; + g.NextWindowData.CollapsedCond = cond ? cond : ImGuiCond_Always; } void ImGui::SetNextWindowFocus() { ImGuiContext& g = *GImGui; - g.NextWindow.FocusCond = ImGuiCond_Always; + g.NextWindowData.FocusCond = ImGuiCond_Always; } // In window space (not screen space!) @@ -9162,8 +9152,8 @@ bool ImGui::BeginCombo(const char* label, const char* preview_value, ImGuiComboF { // Always consume the SetNextWindowSizeConstraint() call in our early return paths ImGuiContext& g = *GImGui; - ImGuiCond backup_next_window_size_constraint = g.NextWindow.SizeConstraintCond; - g.NextWindow.SizeConstraintCond = 0; + ImGuiCond backup_next_window_size_constraint = g.NextWindowData.SizeConstraintCond; + g.NextWindowData.SizeConstraintCond = 0; ImGuiWindow* window = GetCurrentWindow(); if (window->SkipItems) @@ -9205,8 +9195,8 @@ bool ImGui::BeginCombo(const char* label, const char* preview_value, ImGuiComboF if (backup_next_window_size_constraint) { - g.NextWindow.SizeConstraintCond = backup_next_window_size_constraint; - g.NextWindow.SizeConstraintRect.Min.x = ImMax(g.NextWindow.SizeConstraintRect.Min.x, w); + g.NextWindowData.SizeConstraintCond = backup_next_window_size_constraint; + g.NextWindowData.SizeConstraintRect.Min.x = ImMax(g.NextWindowData.SizeConstraintRect.Min.x, w); } else { @@ -9268,7 +9258,7 @@ bool ImGui::Combo(const char* label, int* current_item, bool (*items_getter)(voi items_getter(data, *current_item, &preview_text); // The old Combo() API exposed "popup_max_height_in_items", however the new more general BeginCombo() API doesn't, so we emulate it here. - if (popup_max_height_in_items != -1 && !g.NextWindow.SizeConstraintCond) + if (popup_max_height_in_items != -1 && !g.NextWindowData.SizeConstraintCond) { float popup_max_height = CalcMaxPopupHeightFromItemCount(popup_max_height_in_items); SetNextWindowSizeConstraints(ImVec2(0,0), ImVec2(FLT_MAX, popup_max_height)); diff --git a/imgui_internal.h b/imgui_internal.h index f66e99eb2b68..9faade5cc500 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -487,6 +487,11 @@ struct ImGuiNextWindowData SizeConstraintCallback = NULL; SizeConstraintCallbackUserData = NULL; } + + void Clear() + { + PosCond = SizeCond = ContentSizeCond = CollapsedCond = SizeConstraintCond = FocusCond = 0; + } }; // Main state for ImGui @@ -532,7 +537,7 @@ struct ImGuiContext ImVector FontStack; // Stack for PushFont()/PopFont() ImVector OpenPopupStack; // Which popups are open (persistent) ImVector CurrentPopupStack; // Which level of BeginPopup() we are in (reset every frame) - ImGuiNextWindowData NextWindow; // Storage for SetNextWindow** functions + ImGuiNextWindowData NextWindowData; // Storage for SetNextWindow** functions bool NextTreeNodeOpenVal; // Storage for SetNextTreeNode** functions ImGuiCond NextTreeNodeOpenCond; From 3c6fbe08491418f367cb8d9a7c6215a3bb3c2f93 Mon Sep 17 00:00:00 2001 From: omar Date: Wed, 3 Jan 2018 12:31:56 +0100 Subject: [PATCH 379/823] Renamed ImGuiSizeConstraintCallback to ImGuiSizeCallback, ImGuiSizeConstraintCallbackData to ImGuiSizeCallbackData. --- imgui.cpp | 15 ++++++++------- imgui.h | 8 ++++---- imgui_demo.cpp | 4 ++-- imgui_internal.h | 8 ++++---- 4 files changed, 18 insertions(+), 17 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index ae85abf064dd..b616af8382a2 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -213,6 +213,7 @@ Here is a change-log of API breaking changes, if you are using one of the functions listed, expect to have to fix some code. Also read releases logs https://github.com/ocornut/imgui/releases for more details. + - 2018/01/03 (1.54) - renamed ImGuiSizeConstraintCallback to ImGuiSizeCallback, ImGuiSizeConstraintCallbackData to ImGuiSizeCallbackData. - 2017/12/29 (1.54) - removed CalcItemRectClosestPoint() which was weird and not really used by anyone except demo code. If you need it it's easy to replicate on your side. - 2017/12/24 (1.53) - renamed the emblematic ShowTestWindow() function to ShowDemoWindow(). Kept redirection function (will obsolete). - 2017/12/21 (1.53) - ImDrawList: renamed style.AntiAliasedShapes to style.AntiAliasedFill for consistency and as a way to explicitly break code that manipulate those flag at runtime. You can now manipulate ImDrawList::Flags @@ -4188,14 +4189,14 @@ static ImVec2 CalcSizeAfterConstraint(ImGuiWindow* window, ImVec2 new_size) ImRect cr = g.NextWindowData.SizeConstraintRect; new_size.x = (cr.Min.x >= 0 && cr.Max.x >= 0) ? ImClamp(new_size.x, cr.Min.x, cr.Max.x) : window->SizeFull.x; new_size.y = (cr.Min.y >= 0 && cr.Max.y >= 0) ? ImClamp(new_size.y, cr.Min.y, cr.Max.y) : window->SizeFull.y; - if (g.NextWindowData.SizeConstraintCallback) + if (g.NextWindowData.SizeCallback) { - ImGuiSizeConstraintCallbackData data; - data.UserData = g.NextWindowData.SizeConstraintCallbackUserData; + ImGuiSizeCallbackData data; + data.UserData = g.NextWindowData.SizeCallbackUserData; data.Pos = window->Pos; data.CurrentSize = window->SizeFull; data.DesiredSize = new_size; - g.NextWindowData.SizeConstraintCallback(&data); + g.NextWindowData.SizeCallback(&data); new_size = data.DesiredSize; } } @@ -5703,13 +5704,13 @@ void ImGui::SetNextWindowSize(const ImVec2& size, ImGuiCond cond) g.NextWindowData.SizeCond = cond ? cond : ImGuiCond_Always; } -void ImGui::SetNextWindowSizeConstraints(const ImVec2& size_min, const ImVec2& size_max, ImGuiSizeConstraintCallback custom_callback, void* custom_callback_user_data) +void ImGui::SetNextWindowSizeConstraints(const ImVec2& size_min, const ImVec2& size_max, ImGuiSizeCallback custom_callback, void* custom_callback_user_data) { ImGuiContext& g = *GImGui; g.NextWindowData.SizeConstraintCond = ImGuiCond_Always; g.NextWindowData.SizeConstraintRect = ImRect(size_min, size_max); - g.NextWindowData.SizeConstraintCallback = custom_callback; - g.NextWindowData.SizeConstraintCallbackUserData = custom_callback_user_data; + g.NextWindowData.SizeCallback = custom_callback; + g.NextWindowData.SizeCallbackUserData = custom_callback_user_data; } void ImGui::SetNextWindowContentSize(const ImVec2& size) diff --git a/imgui.h b/imgui.h index a8dd3435bcb4..4e9b2e79785a 100644 --- a/imgui.h +++ b/imgui.h @@ -64,7 +64,7 @@ struct ImGuiStyle; // Runtime data for styling/colors struct ImGuiTextFilter; // Parse and apply text filters. In format "aaaaa[,bbbb][,ccccc]" struct ImGuiTextBuffer; // Text buffer for logging/accumulating text struct ImGuiTextEditCallbackData; // Shared state of ImGui::InputText() when using custom ImGuiTextEditCallback (rare/advanced use) -struct ImGuiSizeConstraintCallbackData;// Structure used to constraint window size in custom ways when using custom ImGuiSizeConstraintCallback (rare/advanced use) +struct ImGuiSizeCallbackData; // Structure used to constraint window size in custom ways when using custom ImGuiSizeCallback (rare/advanced use) struct ImGuiListClipper; // Helper to manually clip large list of items struct ImGuiPayload; // User data payload for drag and drop operations struct ImGuiContext; // ImGui context (opaque) @@ -92,7 +92,7 @@ typedef int ImGuiSelectableFlags; // flags: for Selectable() typedef int ImGuiTreeNodeFlags; // flags: for TreeNode*(),CollapsingHeader()// enum ImGuiTreeNodeFlags_ typedef int ImGuiWindowFlags; // flags: for Begin*() // enum ImGuiWindowFlags_ typedef int (*ImGuiTextEditCallback)(ImGuiTextEditCallbackData *data); -typedef void (*ImGuiSizeConstraintCallback)(ImGuiSizeConstraintCallbackData* data); +typedef void (*ImGuiSizeCallback)(ImGuiSizeCallbackData* data); #if defined(_MSC_VER) && !defined(__clang__) typedef unsigned __int64 ImU64; // 64-bit unsigned integer #else @@ -167,7 +167,7 @@ namespace ImGui IMGUI_API void SetNextWindowPos(const ImVec2& pos, ImGuiCond cond = 0, const ImVec2& pivot = ImVec2(0,0)); // set next window position. call before Begin(). use pivot=(0.5f,0.5f) to center on given point, etc. IMGUI_API void SetNextWindowSize(const ImVec2& size, ImGuiCond cond = 0); // set next window size. set axis to 0.0f to force an auto-fit on this axis. call before Begin() - IMGUI_API void SetNextWindowSizeConstraints(const ImVec2& size_min, const ImVec2& size_max, ImGuiSizeConstraintCallback custom_callback = NULL, void* custom_callback_data = NULL); // set next window size limits. use -1,-1 on either X/Y axis to preserve the current size. Use callback to apply non-trivial programmatic constraints. + IMGUI_API void SetNextWindowSizeConstraints(const ImVec2& size_min, const ImVec2& size_max, ImGuiSizeCallback custom_callback = NULL, void* custom_callback_data = NULL); // set next window size limits. use -1,-1 on either X/Y axis to preserve the current size. Use callback to apply non-trivial programmatic constraints. IMGUI_API void SetNextWindowContentSize(const ImVec2& size); // set next window content size (~ enforce the range of scrollbars). not including window decorations (title bar, menu bar, etc.). set an axis to 0.0f to leave it automatic. call before Begin() IMGUI_API void SetNextWindowCollapsed(bool collapsed, ImGuiCond cond = 0); // set next window collapsed state. call before Begin() IMGUI_API void SetNextWindowFocus(); // set next window to be focused / front-most. call before Begin() @@ -1218,7 +1218,7 @@ struct ImGuiTextEditCallbackData // Resizing callback data to apply custom constraint. As enabled by SetNextWindowSizeConstraints(). Callback is called during the next Begin(). // NB: For basic min/max size constraint on each axis you don't need to use the callback! The SetNextWindowSizeConstraints() parameters are enough. -struct ImGuiSizeConstraintCallbackData +struct ImGuiSizeCallbackData { void* UserData; // Read-only. What user passed to SetNextWindowSizeConstraints() ImVec2 Pos; // Read-only. Window position, for reference. diff --git a/imgui_demo.cpp b/imgui_demo.cpp index c9d47d4dfbf3..4a5c32dec285 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -2303,8 +2303,8 @@ static void ShowExampleAppConstrainedResize(bool* p_open) { struct CustomConstraints // Helper functions to demonstrate programmatic constraints { - static void Square(ImGuiSizeConstraintCallbackData* data) { data->DesiredSize = ImVec2(IM_MAX(data->DesiredSize.x, data->DesiredSize.y), IM_MAX(data->DesiredSize.x, data->DesiredSize.y)); } - static void Step(ImGuiSizeConstraintCallbackData* data) { float step = (float)(int)(intptr_t)data->UserData; data->DesiredSize = ImVec2((int)(data->DesiredSize.x / step + 0.5f) * step, (int)(data->DesiredSize.y / step + 0.5f) * step); } + static void Square(ImGuiSizeCallbackData* data) { data->DesiredSize = ImVec2(IM_MAX(data->DesiredSize.x, data->DesiredSize.y), IM_MAX(data->DesiredSize.x, data->DesiredSize.y)); } + static void Step(ImGuiSizeCallbackData* data) { float step = (float)(int)(intptr_t)data->UserData; data->DesiredSize = ImVec2((int)(data->DesiredSize.x / step + 0.5f) * step, (int)(data->DesiredSize.y / step + 0.5f) * step); } }; static bool auto_resize = false; diff --git a/imgui_internal.h b/imgui_internal.h index 9faade5cc500..8481f3ac0811 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -474,8 +474,8 @@ struct ImGuiNextWindowData ImVec2 ContentSizeVal; bool CollapsedVal; ImRect SizeConstraintRect; // Valid if 'SetNextWindowSizeConstraint' is true - ImGuiSizeConstraintCallback SizeConstraintCallback; - void* SizeConstraintCallbackUserData; + ImGuiSizeCallback SizeCallback; + void* SizeCallbackUserData; ImGuiNextWindowData() { @@ -484,8 +484,8 @@ struct ImGuiNextWindowData ContentSizeVal = ImVec2(0.0f, 0.0f); CollapsedVal = false; SizeConstraintRect = ImRect(); - SizeConstraintCallback = NULL; - SizeConstraintCallbackUserData = NULL; + SizeCallback = NULL; + SizeCallbackUserData = NULL; } void Clear() From 05ec0b07365b36319ed6ef301c723634c7f8777d Mon Sep 17 00:00:00 2001 From: omar Date: Wed, 3 Jan 2018 14:30:40 +0100 Subject: [PATCH 380/823] Casing tweaks + clarify license copyright (simpler/safer?) (#1346) --- LICENSE.txt | 2 +- imgui.cpp | 2 +- imgui_demo.cpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/LICENSE.txt b/LICENSE.txt index 5a9b98b83d98..24fcd01a72f2 100644 --- a/LICENSE.txt +++ b/LICENSE.txt @@ -1,6 +1,6 @@ The MIT License (MIT) -Copyright (c) 2014-2017 Omar Cornut and ImGui contributors +Copyright (c) 2014-2017 Omar Cornut Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/imgui.cpp b/imgui.cpp index b616af8382a2..6f57bb40e5ab 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -11588,7 +11588,7 @@ void ImGui::ShowMetricsWindow(bool* p_open) { if (ImGui::Begin("ImGui Metrics", p_open)) { - ImGui::Text("ImGui %s", ImGui::GetVersion()); + ImGui::Text("Dear ImGui %s", ImGui::GetVersion()); ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate); ImGui::Text("%d vertices, %d indices (%d triangles)", ImGui::GetIO().MetricsRenderVertices, ImGui::GetIO().MetricsRenderIndices, ImGui::GetIO().MetricsRenderIndices / 3); ImGui::Text("%d allocations", ImGui::GetIO().MetricsAllocs); diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 4a5c32dec285..4bcc516a4364 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -160,7 +160,7 @@ void ImGui::ShowDemoWindow(bool* p_open) if (show_app_about) { ImGui::Begin("About Dear ImGui", &show_app_about, ImGuiWindowFlags_AlwaysAutoResize); - ImGui::Text("dear imgui, %s", ImGui::GetVersion()); + ImGui::Text("Dear ImGui, %s", ImGui::GetVersion()); ImGui::Separator(); ImGui::Text("By Omar Cornut and all dear imgui contributors."); ImGui::Text("Dear ImGui is licensed under the MIT License, see LICENSE for more information."); From 79d38e5aded9c30956cb147cf71e9935f7bb4202 Mon Sep 17 00:00:00 2001 From: omar Date: Wed, 3 Jan 2018 14:31:13 +0100 Subject: [PATCH 381/823] Updated copyright date for 2018 --- LICENSE.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LICENSE.txt b/LICENSE.txt index 24fcd01a72f2..21b6ee7e2a45 100644 --- a/LICENSE.txt +++ b/LICENSE.txt @@ -1,6 +1,6 @@ The MIT License (MIT) -Copyright (c) 2014-2017 Omar Cornut +Copyright (c) 2014-2018 Omar Cornut Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal From f9b2058d5a264c184f8c935eded18926f90d9226 Mon Sep 17 00:00:00 2001 From: omar Date: Wed, 3 Jan 2018 14:35:11 +0100 Subject: [PATCH 382/823] Internals: Renamed ImGuiSimpleColumns to ImGuiMenuColumns to avoid confusion. Reduced internal buffer size (we only use 3 slots). --- imgui.cpp | 8 ++++---- imgui_internal.h | 10 +++++----- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 6f57bb40e5ab..71a40d1fe3d3 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1693,7 +1693,7 @@ void ImGuiTextBuffer::appendf(const char* fmt, ...) // ImGuiSimpleColumns (internal use only) //----------------------------------------------------------------------------- -ImGuiSimpleColumns::ImGuiSimpleColumns() +ImGuiMenuColumns::ImGuiMenuColumns() { Count = 0; Spacing = Width = NextWidth = 0.0f; @@ -1701,7 +1701,7 @@ ImGuiSimpleColumns::ImGuiSimpleColumns() memset(NextWidths, 0, sizeof(NextWidths)); } -void ImGuiSimpleColumns::Update(int count, float spacing, bool clear) +void ImGuiMenuColumns::Update(int count, float spacing, bool clear) { IM_ASSERT(Count <= IM_ARRAYSIZE(Pos)); Count = count; @@ -1718,7 +1718,7 @@ void ImGuiSimpleColumns::Update(int count, float spacing, bool clear) } } -float ImGuiSimpleColumns::DeclColumns(float w0, float w1, float w2) // not using va_arg because they promote float to double +float ImGuiMenuColumns::DeclColumns(float w0, float w1, float w2) // not using va_arg because they promote float to double { NextWidth = 0.0f; NextWidths[0] = ImMax(NextWidths[0], w0); @@ -1729,7 +1729,7 @@ float ImGuiSimpleColumns::DeclColumns(float w0, float w1, float w2) // not using return ImMax(Width, NextWidth); } -float ImGuiSimpleColumns::CalcExtraSpace(float avail_w) +float ImGuiMenuColumns::CalcExtraSpace(float avail_w) { return ImMax(0.0f, avail_w - Width); } diff --git a/imgui_internal.h b/imgui_internal.h index 8481f3ac0811..babda0b5d804 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -35,7 +35,7 @@ struct ImRect; struct ImGuiColMod; struct ImGuiStyleMod; struct ImGuiGroupData; -struct ImGuiSimpleColumns; +struct ImGuiMenuColumns; struct ImGuiDrawContext; struct ImGuiTextEditState; struct ImGuiMouseCursorData; @@ -323,14 +323,14 @@ struct ImGuiGroupData }; // Simple column measurement currently used for MenuItem() only. This is very short-sighted/throw-away code and NOT a generic helper. -struct IMGUI_API ImGuiSimpleColumns +struct IMGUI_API ImGuiMenuColumns { int Count; float Spacing; float Width, NextWidth; - float Pos[8], NextWidths[8]; + float Pos[4], NextWidths[4]; - ImGuiSimpleColumns(); + ImGuiMenuColumns(); void Update(int count, float spacing, bool clear); float DeclColumns(float w0, float w1, float w2); float CalcExtraSpace(float avail_w); @@ -801,7 +801,7 @@ struct IMGUI_API ImGuiWindow ImRect InnerRect; int LastFrameActive; float ItemWidthDefault; - ImGuiSimpleColumns MenuColumns; // Simplified columns storage for menu items + ImGuiMenuColumns MenuColumns; // Simplified columns storage for menu items ImGuiStorage StateStorage; ImVector ColumnsStorage; float FontWindowScale; // Scale multiplier per-window From 33f7769d85fc12c5255919a59d88ec8d540e2589 Mon Sep 17 00:00:00 2001 From: omar Date: Wed, 3 Jan 2018 14:38:01 +0100 Subject: [PATCH 383/823] Columns: Clear offsets data when columns count changed. (#1525) --- imgui.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/imgui.cpp b/imgui.cpp index 71a40d1fe3d3..c4239190cd36 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -11004,6 +11004,10 @@ void ImGui::BeginColumns(const char* str_id, int columns_count, ImGuiColumnsFlag window->DC.ColumnsOffsetX = 0.0f; window->DC.CursorPos.x = (float)(int)(window->Pos.x + window->DC.IndentX + window->DC.ColumnsOffsetX); + // Clear data if columns count changed + if (columns->Columns.Size != 0 && columns->Columns.Size != columns_count + 1) + columns->Columns.resize(0); + // Initialize defaults columns->IsFirstFrame = (columns->Columns.Size == 0); if (columns->Columns.Size == 0) @@ -11016,7 +11020,6 @@ void ImGui::BeginColumns(const char* str_id, int columns_count, ImGuiColumnsFlag columns->Columns.push_back(column); } } - IM_ASSERT(columns->Columns.Size == columns_count + 1); for (int n = 0; n < columns_count + 1; n++) { From 9fbecac87eda2265a6384f9e146493f5750ef0c2 Mon Sep 17 00:00:00 2001 From: omar Date: Wed, 3 Jan 2018 15:11:14 +0100 Subject: [PATCH 384/823] Demo: Improved Selectable() examples. (#1528) --- imgui.h | 4 ++-- imgui_demo.cpp | 52 +++++++++++++++++++++++++++++++++++++++++--------- 2 files changed, 45 insertions(+), 11 deletions(-) diff --git a/imgui.h b/imgui.h index 4e9b2e79785a..87d3ae380c04 100644 --- a/imgui.h +++ b/imgui.h @@ -376,8 +376,8 @@ namespace ImGui IMGUI_API bool CollapsingHeader(const char* label, bool* p_open, ImGuiTreeNodeFlags flags = 0); // when 'p_open' isn't NULL, display an additional small close button on upper right of the header // Widgets: Selectable / Lists - IMGUI_API bool Selectable(const char* label, bool selected = false, ImGuiSelectableFlags flags = 0, const ImVec2& size = ImVec2(0,0)); // size.x==0.0: use remaining width, size.x>0.0: specify width. size.y==0.0: use label height, size.y>0.0: specify height - IMGUI_API bool Selectable(const char* label, bool* p_selected, ImGuiSelectableFlags flags = 0, const ImVec2& size = ImVec2(0,0)); + IMGUI_API bool Selectable(const char* label, bool selected = false, ImGuiSelectableFlags flags = 0, const ImVec2& size = ImVec2(0,0)); // "bool selected" carry the selection state (read-only). Selectable() is clicked is returns true so you can modify your selection state. size.x==0.0: use remaining width, size.x>0.0: specify width. size.y==0.0: use label height, size.y>0.0: specify height + IMGUI_API bool Selectable(const char* label, bool* p_selected, ImGuiSelectableFlags flags = 0, const ImVec2& size = ImVec2(0,0)); // "bool* p_selected" point to the selection state (read-write), as a convenient helper. IMGUI_API bool ListBox(const char* label, int* current_item, const char* const items[], int items_count, int height_in_items = -1); IMGUI_API bool ListBox(const char* label, int* current_item, bool (*items_getter)(void* data, int idx, const char** out_text), void* data, int items_count, int height_in_items = -1); IMGUI_API bool ListBoxHeader(const char* label, const ImVec2& size = ImVec2(0,0)); // use if you want to reimplement ListBox() will custom data or interactions. make sure to call ListBoxFooter() afterwards. diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 4bcc516a4364..9f11de36cd2f 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -609,24 +609,58 @@ void ImGui::ShowDemoWindow(bool* p_open) if (ImGui::TreeNode("Selectables")) { + // Selectable() has 2 overloads: + // - The one taking "bool selected" as a read-only selection information. When Selectable() has been clicked is returns true and you can alter selection state accordingly. + // - The one taking "bool* p_selected" as a read-write selection information (convenient in some cases) + // The earlier is more flexible, as in real application your selection may be stored in a different manner (in flags within objects, as an external list, etc). if (ImGui::TreeNode("Basic")) { - static bool selected[4] = { false, true, false, false }; - ImGui::Selectable("1. I am selectable", &selected[0]); - ImGui::Selectable("2. I am selectable", &selected[1]); + static bool selection[5] = { false, true, false, false, false }; + ImGui::Selectable("1. I am selectable", &selection[0]); + ImGui::Selectable("2. I am selectable", &selection[1]); ImGui::Text("3. I am not selectable"); - ImGui::Selectable("4. I am selectable", &selected[2]); - if (ImGui::Selectable("5. I am double clickable", selected[3], ImGuiSelectableFlags_AllowDoubleClick)) + ImGui::Selectable("4. I am selectable", &selection[3]); + if (ImGui::Selectable("5. I am double clickable", selection[4], ImGuiSelectableFlags_AllowDoubleClick)) if (ImGui::IsMouseDoubleClicked(0)) - selected[3] = !selected[3]; + selection[4] = !selection[4]; ImGui::TreePop(); } - if (ImGui::TreeNode("Rendering more text into the same block")) + if (ImGui::TreeNode("Selection State: Single Selection")) { + static int selected = -1; + for (int n = 0; n < 5; n++) + { + char buf[32]; + sprintf(buf, "Object %d", n); + if (ImGui::Selectable(buf, selected == n)) + selected = n; + } + ImGui::TreePop(); + } + if (ImGui::TreeNode("Selection State: Multiple Selection")) + { + ShowHelpMarker("Hold CTRL and click to select multiple items."); + static bool selection[5] = { false, false, false, false, false }; + for (int n = 0; n < 5; n++) + { + char buf[32]; + sprintf(buf, "Object %d", n); + if (ImGui::Selectable(buf, selection[n])) + { + if (!ImGui::GetIO().KeyCtrl) // Clear selection when CTRL is not held + memset(selection, 0, sizeof(selection)); + selection[n] ^= 1; + } + } + ImGui::TreePop(); + } + if (ImGui::TreeNode("Rendering more text into the same line")) + { + // Using the Selectable() override that takes "bool* p_selected" parameter and toggle your booleans automatically. static bool selected[3] = { false, false, false }; - ImGui::Selectable("main.c", &selected[0]); ImGui::SameLine(300); ImGui::Text(" 2,345 bytes"); + ImGui::Selectable("main.c", &selected[0]); ImGui::SameLine(300); ImGui::Text(" 2,345 bytes"); ImGui::Selectable("Hello.cpp", &selected[1]); ImGui::SameLine(300); ImGui::Text("12,345 bytes"); - ImGui::Selectable("Hello.h", &selected[2]); ImGui::SameLine(300); ImGui::Text(" 2,345 bytes"); + ImGui::Selectable("Hello.h", &selected[2]); ImGui::SameLine(300); ImGui::Text(" 2,345 bytes"); ImGui::TreePop(); } if (ImGui::TreeNode("In columns")) From a7deb3a3943c9fe8b0acb34bc65bc1ec5343d524 Mon Sep 17 00:00:00 2001 From: omar Date: Wed, 3 Jan 2018 15:36:51 +0100 Subject: [PATCH 385/823] Demo: Minor tweaks. --- imgui_demo.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 9f11de36cd2f..76a8fa5515ca 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -413,7 +413,7 @@ void ImGui::ShowDemoWindow(bool* p_open) { ImGui::Text("blah blah"); ImGui::SameLine(); - if (ImGui::SmallButton("print")) printf("Child %d pressed", i); + if (ImGui::SmallButton("button")) { }; ImGui::TreePop(); } ImGui::TreePop(); @@ -807,14 +807,14 @@ void ImGui::ShowDemoWindow(bool* p_open) { static ImVec4 color = ImColor(114, 144, 154, 200); - static bool hdr = false; static bool alpha_preview = true; static bool alpha_half_preview = false; static bool options_menu = true; - ImGui::Checkbox("With HDR", &hdr); ImGui::SameLine(); ShowHelpMarker("Currently all this does is to lift the 0..1 limits on dragging widgets."); + static bool hdr = false; ImGui::Checkbox("With Alpha Preview", &alpha_preview); ImGui::Checkbox("With Half Alpha Preview", &alpha_half_preview); ImGui::Checkbox("With Options Menu", &options_menu); ImGui::SameLine(); ShowHelpMarker("Right-click on the individual color widget to show options."); + ImGui::Checkbox("With HDR", &hdr); ImGui::SameLine(); ShowHelpMarker("Currently all this does is to lift the 0..1 limits on dragging widgets."); int misc_flags = (hdr ? ImGuiColorEditFlags_HDR : 0) | (alpha_half_preview ? ImGuiColorEditFlags_AlphaPreviewHalf : (alpha_preview ? ImGuiColorEditFlags_AlphaPreview : 0)) | (options_menu ? 0 : ImGuiColorEditFlags_NoOptions); ImGui::Text("Color widget:"); From 0a0b252bb6982e8033d9e321dfc75a1ff572bf60 Mon Sep 17 00:00:00 2001 From: omar Date: Wed, 3 Jan 2018 16:56:41 +0100 Subject: [PATCH 386/823] DragDrop: Removed IsDragDropActive() (introduced a few days ago, revert 06bea369c0ce977c1cb71e085d860a6644330297) as our use case doesn't need it anymore. Will add it if there is a real need. --- imgui.cpp | 6 ------ imgui.h | 1 - 2 files changed, 7 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index c4239190cd36..d764d60c91d1 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -11468,12 +11468,6 @@ void ImGui::EndDragDropTarget() IM_ASSERT(g.DragDropActive); } -bool ImGui::IsDragDropActive() -{ - ImGuiContext& g = *GImGui; - return g.DragDropActive; -} - //----------------------------------------------------------------------------- // PLATFORM DEPENDENT HELPERS //----------------------------------------------------------------------------- diff --git a/imgui.h b/imgui.h index 87d3ae380c04..fc9791a74767 100644 --- a/imgui.h +++ b/imgui.h @@ -434,7 +434,6 @@ namespace ImGui IMGUI_API bool BeginDragDropTarget(); // call after submitting an item that may receive an item. If this returns true, you can call AcceptDragDropPayload() + EndDragDropTarget() IMGUI_API const ImGuiPayload* AcceptDragDropPayload(const char* type, ImGuiDragDropFlags flags = 0); // accept contents of a given type. If ImGuiDragDropFlags_AcceptBeforeDelivery is set you can peek into the payload before the mouse button is released. IMGUI_API void EndDragDropTarget(); - IMGUI_API bool IsDragDropActive(); // Clipping IMGUI_API void PushClipRect(const ImVec2& clip_rect_min, const ImVec2& clip_rect_max, bool intersect_with_current_clip_rect); From b2ec0741f101493d76967b2a869a01382a74b72f Mon Sep 17 00:00:00 2001 From: omar Date: Fri, 15 Dec 2017 20:59:00 +0100 Subject: [PATCH 387/823] Internals: Settings api tweaks --- imgui.cpp | 26 +++++++++++++++----------- imgui_internal.h | 11 +++++++---- 2 files changed, 22 insertions(+), 15 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index d764d60c91d1..336c43f7842c 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2525,7 +2525,7 @@ void ImGui::NewFrame() Begin("Debug##Default"); } -static void* SettingsHandlerWindow_ReadOpen(ImGuiContext&, const char* name) +static void* SettingsHandlerWindow_ReadOpen(ImGuiContext*, ImGuiSettingsHandler*, const char* name) { ImGuiWindowSettings* settings = ImGui::FindWindowSettings(ImHash(name, 0)); if (!settings) @@ -2533,7 +2533,7 @@ static void* SettingsHandlerWindow_ReadOpen(ImGuiContext&, const char* name) return (void*)settings; } -static void SettingsHandlerWindow_ReadLine(ImGuiContext&, void* entry, const char* line) +static void SettingsHandlerWindow_ReadLine(ImGuiContext*, ImGuiSettingsHandler*, void* entry, const char* line) { ImGuiWindowSettings* settings = (ImGuiWindowSettings*)entry; float x, y; @@ -2543,9 +2543,10 @@ static void SettingsHandlerWindow_ReadLine(ImGuiContext&, void* entry, const cha else if (sscanf(line, "Collapsed=%d", &i) == 1) settings->Collapsed = (i != 0); } -static void SettingsHandlerWindow_WriteAll(ImGuiContext& g, ImGuiTextBuffer* buf) +static void SettingsHandlerWindow_WriteAll(ImGuiContext* imgui_ctx, ImGuiSettingsHandler* handler, ImGuiTextBuffer* buf) { // Gather data from windows that were active during this session + ImGuiContext& g = *imgui_ctx; for (int i = 0; i != g.Windows.Size; i++) { ImGuiWindow* window = g.Windows[i]; @@ -2570,7 +2571,7 @@ static void SettingsHandlerWindow_WriteAll(ImGuiContext& g, ImGuiTextBuffer* buf const char* name = settings->Name; if (const char* p = strstr(name, "###")) // Skip to the "###" marker if any. We don't skip past to match the behavior of GetID() name = p; - buf->appendf("[Window][%s]\n", name); + buf->appendf("[%s][%s]\n", handler->TypeName, name); buf->appendf("Pos=%d,%d\n", (int)settings->Pos.x, (int)settings->Pos.y); buf->appendf("Size=%d,%d\n", (int)settings->Size.x, (int)settings->Size.y); buf->appendf("Collapsed=%d\n", settings->Collapsed); @@ -2684,9 +2685,10 @@ static void LoadIniSettingsFromDisk(const char* ini_filename) ImGui::MemFree(file_data); } -ImGuiSettingsHandler* ImGui::FindSettingsHandler(ImGuiID type_hash) +ImGuiSettingsHandler* ImGui::FindSettingsHandler(const char* type_name) { ImGuiContext& g = *GImGui; + const ImGuiID type_hash = ImHash(type_name, 0, 0); for (int handler_n = 0; handler_n < g.SettingsHandlers.Size; handler_n++) if (g.SettingsHandlers[handler_n].TypeHash == type_hash) return &g.SettingsHandlers[handler_n]; @@ -2702,7 +2704,7 @@ static void LoadIniSettingsFromMemory(const char* buf_readonly) ImGuiContext& g = *GImGui; void* entry_data = NULL; - const ImGuiSettingsHandler* entry_handler = NULL; + ImGuiSettingsHandler* entry_handler = NULL; char* line_end = NULL; for (char* line = buf; line < buf_end; line = line_end + 1) @@ -2733,14 +2735,13 @@ static void LoadIniSettingsFromMemory(const char* buf_readonly) *type_end = 0; // Overwrite first ']' name_start++; // Skip second '[' } - const ImGuiID type_hash = ImHash(type_start, 0, 0); - entry_handler = ImGui::FindSettingsHandler(type_hash); - entry_data = entry_handler ? entry_handler->ReadOpenFn(g, name_start) : NULL; + entry_handler = ImGui::FindSettingsHandler(type_start); + entry_data = entry_handler ? entry_handler->ReadOpenFn(&g, entry_handler, name_start) : NULL; } else if (entry_handler != NULL && entry_data != NULL) { // Let type handler parse the line - entry_handler->ReadLineFn(g, entry_data, line); + entry_handler->ReadLineFn(&g, entry_handler, entry_data, line); } } ImGui::MemFree(buf); @@ -2770,7 +2771,10 @@ static void SaveIniSettingsToMemory(ImVector& out_buf) ImGuiTextBuffer buf; for (int handler_n = 0; handler_n < g.SettingsHandlers.Size; handler_n++) - g.SettingsHandlers[handler_n].WriteAllFn(g, &buf); + { + ImGuiSettingsHandler* handler = &g.SettingsHandlers[handler_n]; + handler->WriteAllFn(&g, handler, &buf); + } buf.Buf.pop_back(); // Remove extra zero-terminator used by ImGuiTextBuffer out_buf.swap(buf.Buf); diff --git a/imgui_internal.h b/imgui_internal.h index babda0b5d804..6a2513d28b2e 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -376,9 +376,12 @@ struct ImGuiSettingsHandler { const char* TypeName; // Short description stored in .ini file. Disallowed characters: '[' ']' ImGuiID TypeHash; // == ImHash(TypeName, 0, 0) - void* (*ReadOpenFn)(ImGuiContext& ctx, const char* name); - void (*ReadLineFn)(ImGuiContext& ctx, void* entry, const char* line); - void (*WriteAllFn)(ImGuiContext& ctx, ImGuiTextBuffer* out_buf); + void* (*ReadOpenFn)(ImGuiContext* ctx, ImGuiSettingsHandler* handler, const char* name); + void (*ReadLineFn)(ImGuiContext* ctx, ImGuiSettingsHandler* handler, void* entry, const char* line); + void (*WriteAllFn)(ImGuiContext* ctx, ImGuiSettingsHandler* handler, ImGuiTextBuffer* out_buf); + void* UserData; + + ImGuiSettingsHandler() { memset(this, 0, sizeof(*this)); } }; // Mouse cursor data (used when io.MouseDrawCursor is set) @@ -870,7 +873,7 @@ namespace ImGui IMGUI_API void Initialize(); IMGUI_API void MarkIniSettingsDirty(); - IMGUI_API ImGuiSettingsHandler* FindSettingsHandler(ImGuiID type_id); + IMGUI_API ImGuiSettingsHandler* FindSettingsHandler(const char* type_name); IMGUI_API ImGuiWindowSettings* FindWindowSettings(ImGuiID id); IMGUI_API void SetActiveID(ImGuiID id, ImGuiWindow* window); From 4b1240b2e1371ce76de0e6cd30f53bfd88df4ecc Mon Sep 17 00:00:00 2001 From: omar Date: Thu, 23 Nov 2017 18:18:56 +0100 Subject: [PATCH 388/823] Fixed non-popup child windows not honoring the HiddenFrames flag (can't see a reason). Docking relies on this. --- imgui.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/imgui.cpp b/imgui.cpp index 336c43f7842c..b0564cba599f 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2867,7 +2867,7 @@ static void AddWindowToRenderList(ImVector& out_render_list, ImGuiW ImGuiWindow* child = window->DC.ChildWindows[i]; if (!child->Active) // clipped children may have been marked not active continue; - if ((child->Flags & ImGuiWindowFlags_Popup) && child->HiddenFrames > 0) + if (child->HiddenFrames > 0) continue; AddWindowToRenderList(out_render_list, child); } From 4fc9f440732d8a5694550b98cb4030135457c230 Mon Sep 17 00:00:00 2001 From: omar Date: Wed, 3 Jan 2018 20:45:06 +0100 Subject: [PATCH 389/823] Merge of minor left-overs from private work branch to reduce drifts. Should be functionally a no-op. --- imgui.cpp | 25 +++++++++++++------------ imgui_internal.h | 2 +- 2 files changed, 14 insertions(+), 13 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index b0564cba599f..3728a890e860 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -4339,9 +4339,6 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) IM_ASSERT(g.Initialized); // Forgot to call ImGui::NewFrame() IM_ASSERT(g.FrameCountEnded != g.FrameCount); // Called ImGui::Render() or ImGui::EndFrame() and haven't called ImGui::NewFrame() again yet - if (flags & ImGuiWindowFlags_NoInputs) - flags |= ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize; - // Find or create ImGuiWindow* window = FindWindowByName(name); if (!window) @@ -4350,6 +4347,12 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) window = CreateNewWindow(name, size_on_first_use, flags); } + // Automatically disable manual moving/resizing when NoInputs is set + if (flags & ImGuiWindowFlags_NoInputs) + flags |= ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize; + //if (flags & ImGuiWindowFlags_NavFlattened) + // IM_ASSERT(flags & ImGuiWindowFlags_ChildWindow); + const int current_frame = g.FrameCount; const bool first_begin_of_the_frame = (window->LastFrameActive != current_frame); if (first_begin_of_the_frame) @@ -4877,18 +4880,16 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) } // Title text (FIXME: refactor text alignment facilities along with RenderText helpers) - const ImVec2 text_size = CalcTextSize(name, NULL, true); - ImVec2 text_min = window->Pos; - ImVec2 text_max = window->Pos + ImVec2(window->Size.x, style.FramePadding.y*2 + text_size.y); - ImRect clip_rect; - clip_rect.Max = ImVec2(window->Pos.x + window->Size.x - (p_open ? title_bar_rect.GetHeight() - 3 : style.FramePadding.x), text_max.y); // Match the size of CloseWindowButton() + ImVec2 text_size = CalcTextSize(name, NULL, true); + ImRect text_r = title_bar_rect; float pad_left = (flags & ImGuiWindowFlags_NoCollapse) == 0 ? (style.FramePadding.x + g.FontSize + style.ItemInnerSpacing.x) : style.FramePadding.x; float pad_right = (p_open != NULL) ? (style.FramePadding.x + g.FontSize + style.ItemInnerSpacing.x) : style.FramePadding.x; if (style.WindowTitleAlign.x > 0.0f) pad_right = ImLerp(pad_right, pad_left, style.WindowTitleAlign.x); - text_min.x += pad_left; - text_max.x -= pad_right; - clip_rect.Min = ImVec2(text_min.x, window->Pos.y); - RenderTextClipped(text_min, text_max, name, NULL, &text_size, style.WindowTitleAlign, &clip_rect); + text_r.Min.x += pad_left; + text_r.Max.x -= pad_right; + ImRect clip_rect = text_r; + clip_rect.Max.x = window->Pos.x + window->Size.x - (p_open ? title_bar_rect.GetHeight() - 3 : style.FramePadding.x); // Match the size of CloseButton() + RenderTextClipped(text_r.Min, text_r.Max, name, NULL, &text_size, style.WindowTitleAlign, &clip_rect); } // Save clipped aabb so we can access it in constant-time in FindHoveredWindow() diff --git a/imgui_internal.h b/imgui_internal.h index 6a2513d28b2e..c80970250d04 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -775,7 +775,7 @@ struct IMGUI_API ImGuiWindow ImVec2 ScrollTargetCenterRatio; // 0.0f = scroll so that target position is at top, 0.5f = scroll so that target position is centered bool ScrollbarX, ScrollbarY; ImVec2 ScrollbarSizes; - bool Active; // Set to true on Begin() + bool Active; // Set to true on Begin(), unless Collapsed bool WasActive; bool WriteAccessed; // Set to true when any widget access the current window bool Collapsed; // Set when collapsing window to become only title-bar From ecbfdd3143e60802c15d5341f664723ffb273d90 Mon Sep 17 00:00:00 2001 From: omar Date: Thu, 4 Jan 2018 11:06:12 +0100 Subject: [PATCH 390/823] Added extraneous initialization to NULL. (#1527). --- imgui_draw.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/imgui_draw.cpp b/imgui_draw.cpp index c7232af8fedc..0cb7cd82f545 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -1439,7 +1439,7 @@ void ImFontAtlas::GetTexDataAsRGBA32(unsigned char** out_pixels, int* out_wid // Although it is likely to be the most commonly used format, our font rendering is 1 channel / 8 bpp if (!TexPixelsRGBA32) { - unsigned char* pixels; + unsigned char* pixels = NULL; GetTexDataAsAlpha8(&pixels, NULL, NULL); if (pixels) { From 4c90529c62ecb765a8b4315d91f69af157ee12df Mon Sep 17 00:00:00 2001 From: omar Date: Thu, 4 Jan 2018 11:42:05 +0100 Subject: [PATCH 391/823] Examples: Visual Studio projects: Disabled extraneous function-level check in Release build. --- examples/directx10_example/directx10_example.vcxproj | 2 ++ examples/directx11_example/directx11_example.vcxproj | 2 ++ examples/directx9_example/directx9_example.vcxproj | 2 ++ examples/opengl2_example/opengl2_example.vcxproj | 2 ++ examples/opengl3_example/opengl3_example.vcxproj | 2 ++ 5 files changed, 10 insertions(+) diff --git a/examples/directx10_example/directx10_example.vcxproj b/examples/directx10_example/directx10_example.vcxproj index c4f15c569096..8583e1dec836 100644 --- a/examples/directx10_example/directx10_example.vcxproj +++ b/examples/directx10_example/directx10_example.vcxproj @@ -110,6 +110,7 @@ true true ..\..;%(AdditionalIncludeDirectories);$(DXSDK_DIR)Include; + false true @@ -127,6 +128,7 @@ true true ..\..;%(AdditionalIncludeDirectories);$(DXSDK_DIR)Include; + false true diff --git a/examples/directx11_example/directx11_example.vcxproj b/examples/directx11_example/directx11_example.vcxproj index 944c8e86365c..7099a7bd4090 100644 --- a/examples/directx11_example/directx11_example.vcxproj +++ b/examples/directx11_example/directx11_example.vcxproj @@ -110,6 +110,7 @@ true true ..\..;%(AdditionalIncludeDirectories);$(DXSDK_DIR)Include; + false true @@ -127,6 +128,7 @@ true true ..\..;%(AdditionalIncludeDirectories);$(DXSDK_DIR)Include; + false true diff --git a/examples/directx9_example/directx9_example.vcxproj b/examples/directx9_example/directx9_example.vcxproj index c10731deea0a..6fe7c9cecf51 100644 --- a/examples/directx9_example/directx9_example.vcxproj +++ b/examples/directx9_example/directx9_example.vcxproj @@ -110,6 +110,7 @@ true true ..\..;%(AdditionalIncludeDirectories);$(DXSDK_DIR)Include; + false true @@ -127,6 +128,7 @@ true true ..\..;%(AdditionalIncludeDirectories);$(DXSDK_DIR)Include; + false true diff --git a/examples/opengl2_example/opengl2_example.vcxproj b/examples/opengl2_example/opengl2_example.vcxproj index bea2104d1318..a6cbebd637cd 100644 --- a/examples/opengl2_example/opengl2_example.vcxproj +++ b/examples/opengl2_example/opengl2_example.vcxproj @@ -116,6 +116,7 @@ true true $(SolutionDir)\libs\glfw\include;..\..;%(AdditionalIncludeDirectories) + false true @@ -135,6 +136,7 @@ true true $(SolutionDir)\libs\glfw\include;..\..;%(AdditionalIncludeDirectories) + false true diff --git a/examples/opengl3_example/opengl3_example.vcxproj b/examples/opengl3_example/opengl3_example.vcxproj index 8d8bec90f2a6..d481c943adbb 100644 --- a/examples/opengl3_example/opengl3_example.vcxproj +++ b/examples/opengl3_example/opengl3_example.vcxproj @@ -116,6 +116,7 @@ true true $(SolutionDir)\libs\glfw\include;$(SolutionDir)\libs\gl3w;..\..;%(AdditionalIncludeDirectories) + false true @@ -135,6 +136,7 @@ true true $(SolutionDir)\libs\glfw\include;$(SolutionDir)\libs\gl3w;..\..;%(AdditionalIncludeDirectories) + false true From 007f4034c907defdf781a1d34ad1f769b0374436 Mon Sep 17 00:00:00 2001 From: omar Date: Fri, 5 Jan 2018 15:33:24 +0100 Subject: [PATCH 392/823] Internals: Added LastActiveId, LastActiveIdTimer. (#1537) --- imgui.cpp | 8 ++++++++ imgui_internal.h | 4 ++++ 2 files changed, 12 insertions(+) diff --git a/imgui.cpp b/imgui.cpp index 3728a890e860..82dc2d6ef97b 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1929,7 +1929,14 @@ void ImGui::SetActiveID(ImGuiID id, ImGuiWindow* window) ImGuiContext& g = *GImGui; g.ActiveIdIsJustActivated = (g.ActiveId != id); if (g.ActiveIdIsJustActivated) + { g.ActiveIdTimer = 0.0f; + if (id != 0) + { + g.LastActiveId = id; + g.LastActiveIdTimer = 0.0f; + } + } g.ActiveId = id; g.ActiveIdAllowOverlap = false; g.ActiveIdIsAlive |= (id != 0); @@ -2308,6 +2315,7 @@ void ImGui::NewFrame() ClearActiveID(); if (g.ActiveId) g.ActiveIdTimer += g.IO.DeltaTime; + g.LastActiveIdTimer += g.IO.DeltaTime; g.ActiveIdPreviousFrame = g.ActiveId; g.ActiveIdIsAlive = false; g.ActiveIdIsJustActivated = false; diff --git a/imgui_internal.h b/imgui_internal.h index c80970250d04..cfc84437fa6b 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -533,6 +533,8 @@ struct ImGuiContext bool ActiveIdAllowOverlap; // Active widget allows another widget to steal active id (generally for overlapping widgets, but not always) ImVec2 ActiveIdClickOffset; // Clicked offset from upper-left corner, if applicable (currently only set by ButtonBehavior) ImGuiWindow* ActiveIdWindow; + ImGuiID LastActiveId; // Store the last non-zero ActiveID, useful for animation. + float LastActiveIdTimer; ImGuiWindow* MovingWindow; // Track the child window we clicked on to move a window. ImGuiID MovingWindowMoveId; // == MovingWindow->MoveId ImVector ColorModifiers; // Stack for PushStyleColor()/PopStyleColor() @@ -629,6 +631,8 @@ struct ImGuiContext ActiveIdAllowOverlap = false; ActiveIdClickOffset = ImVec2(-1,-1); ActiveIdWindow = NULL; + LastActiveId = 0; + LastActiveIdTimer = 0.0f; MovingWindow = NULL; MovingWindowMoveId = 0; From 95b773370fceeaa5cbfadd6353b08a05381edcbc Mon Sep 17 00:00:00 2001 From: omar Date: Fri, 5 Jan 2018 17:39:53 +0100 Subject: [PATCH 393/823] Revert "Internals: Added LastActiveId, LastActiveIdTimer. (#1537)" Will come up with a better design later. This reverts commit 007f4034c907defdf781a1d34ad1f769b0374436. --- imgui.cpp | 8 -------- imgui_internal.h | 4 ---- 2 files changed, 12 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 82dc2d6ef97b..3728a890e860 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1929,14 +1929,7 @@ void ImGui::SetActiveID(ImGuiID id, ImGuiWindow* window) ImGuiContext& g = *GImGui; g.ActiveIdIsJustActivated = (g.ActiveId != id); if (g.ActiveIdIsJustActivated) - { g.ActiveIdTimer = 0.0f; - if (id != 0) - { - g.LastActiveId = id; - g.LastActiveIdTimer = 0.0f; - } - } g.ActiveId = id; g.ActiveIdAllowOverlap = false; g.ActiveIdIsAlive |= (id != 0); @@ -2315,7 +2308,6 @@ void ImGui::NewFrame() ClearActiveID(); if (g.ActiveId) g.ActiveIdTimer += g.IO.DeltaTime; - g.LastActiveIdTimer += g.IO.DeltaTime; g.ActiveIdPreviousFrame = g.ActiveId; g.ActiveIdIsAlive = false; g.ActiveIdIsJustActivated = false; diff --git a/imgui_internal.h b/imgui_internal.h index cfc84437fa6b..c80970250d04 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -533,8 +533,6 @@ struct ImGuiContext bool ActiveIdAllowOverlap; // Active widget allows another widget to steal active id (generally for overlapping widgets, but not always) ImVec2 ActiveIdClickOffset; // Clicked offset from upper-left corner, if applicable (currently only set by ButtonBehavior) ImGuiWindow* ActiveIdWindow; - ImGuiID LastActiveId; // Store the last non-zero ActiveID, useful for animation. - float LastActiveIdTimer; ImGuiWindow* MovingWindow; // Track the child window we clicked on to move a window. ImGuiID MovingWindowMoveId; // == MovingWindow->MoveId ImVector ColorModifiers; // Stack for PushStyleColor()/PopStyleColor() @@ -631,8 +629,6 @@ struct ImGuiContext ActiveIdAllowOverlap = false; ActiveIdClickOffset = ImVec2(-1,-1); ActiveIdWindow = NULL; - LastActiveId = 0; - LastActiveIdTimer = 0.0f; MovingWindow = NULL; MovingWindowMoveId = 0; From 20ae6439eaf7bee14872fedd07b0188cc0a9afee Mon Sep 17 00:00:00 2001 From: Nick Dandoulakis Date: Fri, 5 Jan 2018 22:16:35 +0200 Subject: [PATCH 394/823] CS_DBLCLKS support for Directx9 --- examples/directx9_example/imgui_impl_dx9.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/examples/directx9_example/imgui_impl_dx9.cpp b/examples/directx9_example/imgui_impl_dx9.cpp index 484e84cde023..de00f88d2142 100644 --- a/examples/directx9_example/imgui_impl_dx9.cpp +++ b/examples/directx9_example/imgui_impl_dx9.cpp @@ -192,13 +192,16 @@ IMGUI_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hwnd, UINT msg, WPARAM wPa switch (msg) { case WM_LBUTTONDOWN: + case WM_LBUTTONDBLCLK: case WM_RBUTTONDOWN: + case WM_RBUTTONDBLCLK: case WM_MBUTTONDOWN: + case WM_MBUTTONDBLCLK: { int button = 0; - if (msg == WM_LBUTTONDOWN) button = 0; - if (msg == WM_RBUTTONDOWN) button = 1; - if (msg == WM_MBUTTONDOWN) button = 2; + if (msg == WM_LBUTTONDOWN || msg == WM_LBUTTONDBLCLK) button = 0; + if (msg == WM_RBUTTONDOWN || msg == WM_RBUTTONDBLCLK) button = 1; + if (msg == WM_MBUTTONDOWN || msg == WM_MBUTTONDBLCLK) button = 2; if (!IsAnyMouseButtonDown() && GetCapture() == NULL) SetCapture(hwnd); io.MouseDown[button] = true; From 583e97b2975989dbe1762ee61a4fd4eb84541f0b Mon Sep 17 00:00:00 2001 From: Nick Dandoulakis Date: Fri, 5 Jan 2018 22:25:30 +0200 Subject: [PATCH 395/823] CS_DBLCLKS support for DirectX 10 --- examples/directx10_example/imgui_impl_dx10.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/examples/directx10_example/imgui_impl_dx10.cpp b/examples/directx10_example/imgui_impl_dx10.cpp index 59152673b261..6338be725b3c 100644 --- a/examples/directx10_example/imgui_impl_dx10.cpp +++ b/examples/directx10_example/imgui_impl_dx10.cpp @@ -246,13 +246,16 @@ IMGUI_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hwnd, UINT msg, WPARAM wPa switch (msg) { case WM_LBUTTONDOWN: + case WM_LBUTTONDBLCLK: case WM_RBUTTONDOWN: + case WM_RBUTTONDBLCLK: case WM_MBUTTONDOWN: + case WM_MBUTTONDBLCLK: { int button = 0; - if (msg == WM_LBUTTONDOWN) button = 0; - if (msg == WM_RBUTTONDOWN) button = 1; - if (msg == WM_MBUTTONDOWN) button = 2; + if (msg == WM_LBUTTONDOWN || msg == WM_LBUTTONDBLCLK) button = 0; + if (msg == WM_RBUTTONDOWN || msg == WM_RBUTTONDBLCLK) button = 1; + if (msg == WM_MBUTTONDOWN || msg == WM_MBUTTONDBLCLK) button = 2; if (!IsAnyMouseButtonDown() && GetCapture() == NULL) SetCapture(hwnd); io.MouseDown[button] = true; From bfc25bc8a3c017084c7fc23c955e0c33e13e0226 Mon Sep 17 00:00:00 2001 From: Nick Dandoulakis Date: Fri, 5 Jan 2018 22:28:27 +0200 Subject: [PATCH 396/823] CS_DBLCLKS support for DirectX 11 --- examples/directx11_example/imgui_impl_dx11.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/examples/directx11_example/imgui_impl_dx11.cpp b/examples/directx11_example/imgui_impl_dx11.cpp index af6e54f49601..7016301b234f 100644 --- a/examples/directx11_example/imgui_impl_dx11.cpp +++ b/examples/directx11_example/imgui_impl_dx11.cpp @@ -253,13 +253,16 @@ IMGUI_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hwnd, UINT msg, WPARAM wPa switch (msg) { case WM_LBUTTONDOWN: + case WM_LBUTTONDBLCLK: case WM_RBUTTONDOWN: + case WM_RBUTTONDBLCLK: case WM_MBUTTONDOWN: + case WM_MBUTTONDBLCLK: { int button = 0; - if (msg == WM_LBUTTONDOWN) button = 0; - if (msg == WM_RBUTTONDOWN) button = 1; - if (msg == WM_MBUTTONDOWN) button = 2; + if (msg == WM_LBUTTONDOWN || msg == WM_LBUTTONDBLCLK) button = 0; + if (msg == WM_RBUTTONDOWN || msg == WM_RBUTTONDBLCLK) button = 1; + if (msg == WM_MBUTTONDOWN || msg == WM_MBUTTONDBLCLK) button = 2; if (!IsAnyMouseButtonDown() && GetCapture() == NULL) SetCapture(hwnd); io.MouseDown[button] = true; From 407955d9fbcfe5391e5f28790f21c15f85d06c90 Mon Sep 17 00:00:00 2001 From: omar Date: Fri, 5 Jan 2018 22:05:02 +0100 Subject: [PATCH 397/823] Examples: Using IM_OFFSETOF macro. + Comments --- examples/allegro5_example/imgui_impl_a5.cpp | 8 +++----- examples/apple_example/imguiex-ios/imgui_impl_ios.mm | 9 ++++----- examples/opengl2_example/imgui_impl_glfw.cpp | 8 +++----- examples/opengl3_example/imgui_impl_glfw_gl3.cpp | 8 +++----- examples/sdl_opengl2_example/imgui_impl_sdl.cpp | 8 +++----- examples/sdl_opengl3_example/imgui_impl_sdl_gl3.cpp | 8 +++----- imgui.h | 2 +- 7 files changed, 20 insertions(+), 31 deletions(-) diff --git a/examples/allegro5_example/imgui_impl_a5.cpp b/examples/allegro5_example/imgui_impl_a5.cpp index 0d385923931d..7a7d4cc1ecd0 100644 --- a/examples/allegro5_example/imgui_impl_a5.cpp +++ b/examples/allegro5_example/imgui_impl_a5.cpp @@ -28,8 +28,6 @@ static double g_Time = 0.0; static ALLEGRO_MOUSE_CURSOR* g_MouseCursorInvisible = NULL; static ALLEGRO_VERTEX_DECL* g_VertexDecl = NULL; -#define OFFSETOF(TYPE, ELEMENT) ((size_t)&(((TYPE *)0)->ELEMENT)) - struct ImDrawVertAllegro { ImVec2 pos; @@ -162,9 +160,9 @@ bool ImGui_ImplA5_Init(ALLEGRO_DISPLAY* display) // We still use a custom declaration to use 'ALLEGRO_PRIM_TEX_COORD' instead of 'ALLEGRO_PRIM_TEX_COORD_PIXEL' else we can't do a reliable conversion. ALLEGRO_VERTEX_ELEMENT elems[] = { - { ALLEGRO_PRIM_POSITION, ALLEGRO_PRIM_FLOAT_2, OFFSETOF(ImDrawVertAllegro, pos) }, - { ALLEGRO_PRIM_TEX_COORD, ALLEGRO_PRIM_FLOAT_2, OFFSETOF(ImDrawVertAllegro, uv) }, - { ALLEGRO_PRIM_COLOR_ATTR, 0, OFFSETOF(ImDrawVertAllegro, col) }, + { ALLEGRO_PRIM_POSITION, ALLEGRO_PRIM_FLOAT_2, IM_OFFSETOF(ImDrawVertAllegro, pos) }, + { ALLEGRO_PRIM_TEX_COORD, ALLEGRO_PRIM_FLOAT_2, IM_OFFSETOF(ImDrawVertAllegro, uv) }, + { ALLEGRO_PRIM_COLOR_ATTR, 0, IM_OFFSETOF(ImDrawVertAllegro, col) }, { 0, 0, 0 } }; g_VertexDecl = al_create_vertex_decl(elems, sizeof(ImDrawVertAllegro)); diff --git a/examples/apple_example/imguiex-ios/imgui_impl_ios.mm b/examples/apple_example/imguiex-ios/imgui_impl_ios.mm index bfcae7cd1d2c..7fd7466c9f83 100644 --- a/examples/apple_example/imguiex-ios/imgui_impl_ios.mm +++ b/examples/apple_example/imguiex-ios/imgui_impl_ios.mm @@ -793,11 +793,10 @@ bool ImGui_ImplIOS_CreateDeviceObjects() glEnableVertexAttribArray(g_AttribLocationUV); glEnableVertexAttribArray(g_AttribLocationColor); -#define OFFSETOF(TYPE, ELEMENT) ((size_t)&(((TYPE *)0)->ELEMENT)) - glVertexAttribPointer(g_AttribLocationPosition, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, pos)); - glVertexAttribPointer(g_AttribLocationUV, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, uv)); - glVertexAttribPointer(g_AttribLocationColor, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, col)); -#undef OFFSETOF + glVertexAttribPointer(g_AttribLocationPosition, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)IM_OFFSETOF(ImDrawVert, pos)); + glVertexAttribPointer(g_AttribLocationUV, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)IM_OFFSETOF(ImDrawVert, uv)); + glVertexAttribPointer(g_AttribLocationColor, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(ImDrawVert), (GLvoid*)IM_OFFSETOF(ImDrawVert, col)); + glBindVertexArray(0); glBindBuffer(GL_ARRAY_BUFFER, 0); diff --git a/examples/opengl2_example/imgui_impl_glfw.cpp b/examples/opengl2_example/imgui_impl_glfw.cpp index 33df611e7677..a635cc9af45f 100644 --- a/examples/opengl2_example/imgui_impl_glfw.cpp +++ b/examples/opengl2_example/imgui_impl_glfw.cpp @@ -77,15 +77,14 @@ void ImGui_ImplGlfwGL2_RenderDrawLists(ImDrawData* draw_data) glLoadIdentity(); // Render command lists - #define OFFSETOF(TYPE, ELEMENT) ((size_t)&(((TYPE *)0)->ELEMENT)) for (int n = 0; n < draw_data->CmdListsCount; n++) { const ImDrawList* cmd_list = draw_data->CmdLists[n]; const ImDrawVert* vtx_buffer = cmd_list->VtxBuffer.Data; const ImDrawIdx* idx_buffer = cmd_list->IdxBuffer.Data; - glVertexPointer(2, GL_FLOAT, sizeof(ImDrawVert), (const GLvoid*)((const char*)vtx_buffer + OFFSETOF(ImDrawVert, pos))); - glTexCoordPointer(2, GL_FLOAT, sizeof(ImDrawVert), (const GLvoid*)((const char*)vtx_buffer + OFFSETOF(ImDrawVert, uv))); - glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(ImDrawVert), (const GLvoid*)((const char*)vtx_buffer + OFFSETOF(ImDrawVert, col))); + glVertexPointer(2, GL_FLOAT, sizeof(ImDrawVert), (const GLvoid*)((const char*)vtx_buffer + IM_OFFSETOF(ImDrawVert, pos))); + glTexCoordPointer(2, GL_FLOAT, sizeof(ImDrawVert), (const GLvoid*)((const char*)vtx_buffer + IM_OFFSETOF(ImDrawVert, uv))); + glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(ImDrawVert), (const GLvoid*)((const char*)vtx_buffer + IM_OFFSETOF(ImDrawVert, col))); for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++) { @@ -103,7 +102,6 @@ void ImGui_ImplGlfwGL2_RenderDrawLists(ImDrawData* draw_data) idx_buffer += pcmd->ElemCount; } } - #undef OFFSETOF // Restore modified state glDisableClientState(GL_COLOR_ARRAY); diff --git a/examples/opengl3_example/imgui_impl_glfw_gl3.cpp b/examples/opengl3_example/imgui_impl_glfw_gl3.cpp index 6c439fa186d2..a608e370b92b 100644 --- a/examples/opengl3_example/imgui_impl_glfw_gl3.cpp +++ b/examples/opengl3_example/imgui_impl_glfw_gl3.cpp @@ -269,11 +269,9 @@ bool ImGui_ImplGlfwGL3_CreateDeviceObjects() glEnableVertexAttribArray(g_AttribLocationUV); glEnableVertexAttribArray(g_AttribLocationColor); -#define OFFSETOF(TYPE, ELEMENT) ((size_t)&(((TYPE *)0)->ELEMENT)) - glVertexAttribPointer(g_AttribLocationPosition, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, pos)); - glVertexAttribPointer(g_AttribLocationUV, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, uv)); - glVertexAttribPointer(g_AttribLocationColor, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, col)); -#undef OFFSETOF + glVertexAttribPointer(g_AttribLocationPosition, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)IM_OFFSETOF(ImDrawVert, pos)); + glVertexAttribPointer(g_AttribLocationUV, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)IM_OFFSETOF(ImDrawVert, uv)); + glVertexAttribPointer(g_AttribLocationColor, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(ImDrawVert), (GLvoid*)IM_OFFSETOF(ImDrawVert, col)); ImGui_ImplGlfwGL3_CreateFontsTexture(); diff --git a/examples/sdl_opengl2_example/imgui_impl_sdl.cpp b/examples/sdl_opengl2_example/imgui_impl_sdl.cpp index baf5c0176844..c997d36de07f 100644 --- a/examples/sdl_opengl2_example/imgui_impl_sdl.cpp +++ b/examples/sdl_opengl2_example/imgui_impl_sdl.cpp @@ -70,15 +70,14 @@ void ImGui_ImplSdl_RenderDrawLists(ImDrawData* draw_data) glLoadIdentity(); // Render command lists - #define OFFSETOF(TYPE, ELEMENT) ((size_t)&(((TYPE *)0)->ELEMENT)) for (int n = 0; n < draw_data->CmdListsCount; n++) { const ImDrawList* cmd_list = draw_data->CmdLists[n]; const ImDrawVert* vtx_buffer = cmd_list->VtxBuffer.Data; const ImDrawIdx* idx_buffer = cmd_list->IdxBuffer.Data; - glVertexPointer(2, GL_FLOAT, sizeof(ImDrawVert), (const GLvoid*)((const char*)vtx_buffer + OFFSETOF(ImDrawVert, pos))); - glTexCoordPointer(2, GL_FLOAT, sizeof(ImDrawVert), (const GLvoid*)((const char*)vtx_buffer + OFFSETOF(ImDrawVert, uv))); - glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(ImDrawVert), (const GLvoid*)((const char*)vtx_buffer + OFFSETOF(ImDrawVert, col))); + glVertexPointer(2, GL_FLOAT, sizeof(ImDrawVert), (const GLvoid*)((const char*)vtx_buffer + IM_OFFSETOF(ImDrawVert, pos))); + glTexCoordPointer(2, GL_FLOAT, sizeof(ImDrawVert), (const GLvoid*)((const char*)vtx_buffer + IM_OFFSETOF(ImDrawVert, uv))); + glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(ImDrawVert), (const GLvoid*)((const char*)vtx_buffer + IM_OFFSETOF(ImDrawVert, col))); for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++) { @@ -96,7 +95,6 @@ void ImGui_ImplSdl_RenderDrawLists(ImDrawData* draw_data) idx_buffer += pcmd->ElemCount; } } - #undef OFFSETOF // Restore modified state glDisableClientState(GL_COLOR_ARRAY); diff --git a/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.cpp b/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.cpp index 93849cf8b372..4cdbe0f1b04b 100644 --- a/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.cpp +++ b/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.cpp @@ -273,11 +273,9 @@ bool ImGui_ImplSdlGL3_CreateDeviceObjects() glEnableVertexAttribArray(g_AttribLocationUV); glEnableVertexAttribArray(g_AttribLocationColor); -#define OFFSETOF(TYPE, ELEMENT) ((size_t)&(((TYPE *)0)->ELEMENT)) - glVertexAttribPointer(g_AttribLocationPosition, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, pos)); - glVertexAttribPointer(g_AttribLocationUV, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, uv)); - glVertexAttribPointer(g_AttribLocationColor, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(ImDrawVert), (GLvoid*)OFFSETOF(ImDrawVert, col)); -#undef OFFSETOF + glVertexAttribPointer(g_AttribLocationPosition, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)IM_OFFSETOF(ImDrawVert, pos)); + glVertexAttribPointer(g_AttribLocationUV, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)IM_OFFSETOF(ImDrawVert, uv)); + glVertexAttribPointer(g_AttribLocationColor, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(ImDrawVert), (GLvoid*)IM_OFFSETOF(ImDrawVert, col)); ImGui_ImplSdlGL3_CreateFontsTexture(); diff --git a/imgui.h b/imgui.h index fc9791a74767..bb717eb4df04 100644 --- a/imgui.h +++ b/imgui.h @@ -39,7 +39,7 @@ #define IM_FMTLIST(FMT) #endif #define IM_ARRAYSIZE(_ARR) ((int)(sizeof(_ARR)/sizeof(*_ARR))) -#define IM_OFFSETOF(_TYPE,_ELM) ((size_t)&(((_TYPE*)0)->_ELM)) +#define IM_OFFSETOF(_TYPE,_MEMBER) ((size_t)&(((_TYPE*)0)->_MEMBER)) // Offset of _MEMBER within _TYPE. Standardized as offsetof() in modern C++. #if defined(__clang__) #pragma clang diagnostic push From 3d24a9eb405f024dd0be17608e9a912b0862efa7 Mon Sep 17 00:00:00 2001 From: omar Date: Fri, 5 Jan 2018 22:32:27 +0100 Subject: [PATCH 398/823] Examples: DirectX9/10/11: Comments about CS_DBLCLKS + formatting tweaks. (#1538) --- examples/directx10_example/imgui_impl_dx10.cpp | 10 ++++------ examples/directx11_example/imgui_impl_dx11.cpp | 10 ++++------ examples/directx9_example/imgui_impl_dx9.cpp | 10 ++++------ 3 files changed, 12 insertions(+), 18 deletions(-) diff --git a/examples/directx10_example/imgui_impl_dx10.cpp b/examples/directx10_example/imgui_impl_dx10.cpp index 6338be725b3c..d181f7a5d377 100644 --- a/examples/directx10_example/imgui_impl_dx10.cpp +++ b/examples/directx10_example/imgui_impl_dx10.cpp @@ -240,17 +240,15 @@ static bool IsAnyMouseButtonDown() // - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application. // Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags. // PS: In this Win32 handler, we use the capture API (GetCapture/SetCapture/ReleaseCapture) to be able to read mouse coordinations when dragging mouse outside of our window bounds. +// PS: We treat DBLCLK messages as regular mouse down messages, so this code will work on windows classes that have the CS_DBLCLKS flag set. Our own example app code doesn't set this flag. IMGUI_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { ImGuiIO& io = ImGui::GetIO(); switch (msg) { - case WM_LBUTTONDOWN: - case WM_LBUTTONDBLCLK: - case WM_RBUTTONDOWN: - case WM_RBUTTONDBLCLK: - case WM_MBUTTONDOWN: - case WM_MBUTTONDBLCLK: + case WM_LBUTTONDOWN: case WM_LBUTTONDBLCLK: + case WM_RBUTTONDOWN: case WM_RBUTTONDBLCLK: + case WM_MBUTTONDOWN: case WM_MBUTTONDBLCLK: { int button = 0; if (msg == WM_LBUTTONDOWN || msg == WM_LBUTTONDBLCLK) button = 0; diff --git a/examples/directx11_example/imgui_impl_dx11.cpp b/examples/directx11_example/imgui_impl_dx11.cpp index 7016301b234f..833a0bb07128 100644 --- a/examples/directx11_example/imgui_impl_dx11.cpp +++ b/examples/directx11_example/imgui_impl_dx11.cpp @@ -247,17 +247,15 @@ static bool IsAnyMouseButtonDown() // - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application. // Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags. // PS: In this Win32 handler, we use the capture API (GetCapture/SetCapture/ReleaseCapture) to be able to read mouse coordinations when dragging mouse outside of our window bounds. +// PS: We treat DBLCLK messages as regular mouse down messages, so this code will work on windows classes that have the CS_DBLCLKS flag set. Our own example app code doesn't set this flag. IMGUI_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { ImGuiIO& io = ImGui::GetIO(); switch (msg) { - case WM_LBUTTONDOWN: - case WM_LBUTTONDBLCLK: - case WM_RBUTTONDOWN: - case WM_RBUTTONDBLCLK: - case WM_MBUTTONDOWN: - case WM_MBUTTONDBLCLK: + case WM_LBUTTONDOWN: case WM_LBUTTONDBLCLK: + case WM_RBUTTONDOWN: case WM_RBUTTONDBLCLK: + case WM_MBUTTONDOWN: case WM_MBUTTONDBLCLK: { int button = 0; if (msg == WM_LBUTTONDOWN || msg == WM_LBUTTONDBLCLK) button = 0; diff --git a/examples/directx9_example/imgui_impl_dx9.cpp b/examples/directx9_example/imgui_impl_dx9.cpp index de00f88d2142..40f675aff1fe 100644 --- a/examples/directx9_example/imgui_impl_dx9.cpp +++ b/examples/directx9_example/imgui_impl_dx9.cpp @@ -186,17 +186,15 @@ static bool IsAnyMouseButtonDown() // - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application. // Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags. // PS: In this Win32 handler, we use the capture API (GetCapture/SetCapture/ReleaseCapture) to be able to read mouse coordinations when dragging mouse outside of our window bounds. +// PS: We treat DBLCLK messages as regular mouse down messages, so this code will work on windows classes that have the CS_DBLCLKS flag set. Our own example app code doesn't set this flag. IMGUI_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { ImGuiIO& io = ImGui::GetIO(); switch (msg) { - case WM_LBUTTONDOWN: - case WM_LBUTTONDBLCLK: - case WM_RBUTTONDOWN: - case WM_RBUTTONDBLCLK: - case WM_MBUTTONDOWN: - case WM_MBUTTONDBLCLK: + case WM_LBUTTONDOWN: case WM_LBUTTONDBLCLK: + case WM_RBUTTONDOWN: case WM_RBUTTONDBLCLK: + case WM_MBUTTONDOWN: case WM_MBUTTONDBLCLK: { int button = 0; if (msg == WM_LBUTTONDOWN || msg == WM_LBUTTONDBLCLK) button = 0; From 2874aabb9305645ff2e2de0615ce067573d80527 Mon Sep 17 00:00:00 2001 From: omar Date: Sun, 7 Jan 2018 12:29:54 +0100 Subject: [PATCH 399/823] Internals: BringWindowToFront() iterate front to back, faster in majority of use cases. --- imgui.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 3728a890e860..fef9e11cd932 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -5123,10 +5123,10 @@ void ImGui::BringWindowToFront(ImGuiWindow* window) ImGuiContext& g = *GImGui; if (g.Windows.back() == window) return; - for (int i = 0; i < g.Windows.Size; i++) + for (int i = g.Windows.Size - 2; i >= 0; i--) // We can ignore the front most window if (g.Windows[i] == window) { - g.Windows.erase(g.Windows.begin() + i); + g.Windows.erase(g.Windows.Data + i); g.Windows.push_back(window); break; } From 5fd19f037fdb4d2054002e787055b910278832fd Mon Sep 17 00:00:00 2001 From: omar Date: Sun, 7 Jan 2018 12:34:52 +0100 Subject: [PATCH 400/823] Internals: renamed FocusPreviousWindow() to FocusfrontMostActiveWindow() --- imgui.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index fef9e11cd932..bf40902b8820 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -675,7 +675,7 @@ static bool DataTypeApplyOpFromText(const char* buf, const char* ini namespace ImGui { -static void FocusPreviousWindow(); +static void FocusFrontMostActiveWindow(); } //----------------------------------------------------------------------------- @@ -2511,7 +2511,7 @@ void ImGui::NewFrame() // Closing the focused window restore focus to the first active root window in descending z-order if (g.NavWindow && !g.NavWindow->WasActive) - FocusPreviousWindow(); + FocusFrontMostActiveWindow(); // No window should be open at the beginning of the frame. // But in order to allow the user to call NewFrame() multiple times without calling Render(), we are doing an explicit clear. @@ -5172,7 +5172,7 @@ void ImGui::FocusWindow(ImGuiWindow* window) BringWindowToFront(window); } -void ImGui::FocusPreviousWindow() +void ImGui::FocusFrontMostActiveWindow() { ImGuiContext& g = *GImGui; for (int i = g.Windows.Size - 1; i >= 0; i--) From a34490239c5f58ddbf47c6c07b95441a9f6db982 Mon Sep 17 00:00:00 2001 From: omar Date: Sun, 7 Jan 2018 13:51:36 +0100 Subject: [PATCH 401/823] Internals: Popup: Separating MousePosOnOpen and PopupPosOnOpen. They are equal in the master branch but different in the navigation branch. --- imgui.cpp | 6 ++++-- imgui_internal.h | 3 ++- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index bf40902b8820..2f2443a21874 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -3725,7 +3725,9 @@ void ImGui::OpenPopupEx(ImGuiID id, bool reopen_existing) ImGuiContext& g = *GImGui; ImGuiWindow* parent_window = g.CurrentWindow; int current_stack_size = g.CurrentPopupStack.Size; - ImGuiPopupRef popup_ref = ImGuiPopupRef(id, parent_window, parent_window->GetID("##Menus"), g.IO.MousePos); // Tagged as new ref because constructor sets Window to NULL. + ImVec2 mouse_pos = g.IO.MousePos; + ImVec2 popup_pos = mouse_pos; // NB: In the Navigation branch popup_pos may not use mouse_pos. + ImGuiPopupRef popup_ref = ImGuiPopupRef(id, parent_window, parent_window->GetID("##Menus"), popup_pos, mouse_pos); // Tagged as new ref because constructor sets Window to NULL. if (g.OpenPopupStack.Size < current_stack_size + 1) g.OpenPopupStack.push_back(popup_ref); else if (reopen_existing || g.OpenPopupStack[current_stack_size].PopupId != id) @@ -4479,7 +4481,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) // Popup first latch mouse position, will position itself when it appears next frame window->AutoPosLastDirection = ImGuiDir_None; if ((flags & ImGuiWindowFlags_Popup) != 0 && !window_pos_set_by_api) - window->PosFloat = g.IO.MousePos; + window->PosFloat = g.CurrentPopupStack.back().PopupPosOnOpen; } // Collapse window by double-clicking on title bar diff --git a/imgui_internal.h b/imgui_internal.h index c80970250d04..bdadc464e0e2 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -401,9 +401,10 @@ struct ImGuiPopupRef ImGuiWindow* Window; // Resolved on BeginPopup() - may stay unresolved if user never calls OpenPopup() ImGuiWindow* ParentWindow; // Set on OpenPopup() ImGuiID ParentMenuSet; // Set on OpenPopup() + ImVec2 PopupPosOnOpen; // Preferred popup position (typically == MousePosOnOpen when using mouse) ImVec2 MousePosOnOpen; // Copy of mouse position at the time of opening popup - ImGuiPopupRef(ImGuiID id, ImGuiWindow* parent_window, ImGuiID parent_menu_set, const ImVec2& mouse_pos) { PopupId = id; Window = NULL; ParentWindow = parent_window; ParentMenuSet = parent_menu_set; MousePosOnOpen = mouse_pos; } + ImGuiPopupRef(ImGuiID id, ImGuiWindow* parent_window, ImGuiID parent_menu_set, const ImVec2& popup_pos, const ImVec2& mouse_pos) { PopupId = id; Window = NULL; ParentWindow = parent_window; ParentMenuSet = parent_menu_set; PopupPosOnOpen = popup_pos; MousePosOnOpen = mouse_pos; } }; struct ImGuiColumnData From d730a763f6d84dd8d235c427295a321d75385bc7 Mon Sep 17 00:00:00 2001 From: omar Date: Sun, 7 Jan 2018 14:32:42 +0100 Subject: [PATCH 402/823] Internal: Reworked FocusFrontMostActiveWindow() so it fits the Nav branch usage as well. --- imgui.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 2f2443a21874..75b6aa40cb96 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -675,7 +675,7 @@ static bool DataTypeApplyOpFromText(const char* buf, const char* ini namespace ImGui { -static void FocusFrontMostActiveWindow(); +static void FocusFrontMostActiveWindow(ImGuiWindow* ignore_window); } //----------------------------------------------------------------------------- @@ -2511,7 +2511,7 @@ void ImGui::NewFrame() // Closing the focused window restore focus to the first active root window in descending z-order if (g.NavWindow && !g.NavWindow->WasActive) - FocusFrontMostActiveWindow(); + FocusFrontMostActiveWindow(NULL); // No window should be open at the beginning of the frame. // But in order to allow the user to call NewFrame() multiple times without calling Render(), we are doing an explicit clear. @@ -5174,11 +5174,11 @@ void ImGui::FocusWindow(ImGuiWindow* window) BringWindowToFront(window); } -void ImGui::FocusFrontMostActiveWindow() +void ImGui::FocusFrontMostActiveWindow(ImGuiWindow* ignore_window) { ImGuiContext& g = *GImGui; for (int i = g.Windows.Size - 1; i >= 0; i--) - if (g.Windows[i]->WasActive && !(g.Windows[i]->Flags & ImGuiWindowFlags_ChildWindow)) + if (g.Windows[i] != ignore_window && g.Windows[i]->WasActive && !(g.Windows[i]->Flags & ImGuiWindowFlags_ChildWindow)) { FocusWindow(g.Windows[i]); return; From c337cdcfd3b153541e685d4ad53b908f2d901f2e Mon Sep 17 00:00:00 2001 From: omar Date: Sun, 7 Jan 2018 15:02:09 +0100 Subject: [PATCH 403/823] Internal: ButtonBehavior: Tweak to update g.ActiveIdClickOffset more consistently --- imgui.cpp | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 75b6aa40cb96..d952e287f91b 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -6253,20 +6253,14 @@ bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool { SetActiveID(id, window); // Hold on ID FocusWindow(window); - g.ActiveIdClickOffset = g.IO.MousePos - bb.Min; } if (((flags & ImGuiButtonFlags_PressedOnClick) && g.IO.MouseClicked[0]) || ((flags & ImGuiButtonFlags_PressedOnDoubleClick) && g.IO.MouseDoubleClicked[0])) { pressed = true; if (flags & ImGuiButtonFlags_NoHoldingActiveID) - { ClearActiveID(); - } else - { SetActiveID(id, window); // Hold on ID - g.ActiveIdClickOffset = g.IO.MousePos - bb.Min; - } FocusWindow(window); } if ((flags & ImGuiButtonFlags_PressedOnRelease) && g.IO.MouseReleased[0]) @@ -6286,6 +6280,8 @@ bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool bool held = false; if (g.ActiveId == id) { + if (g.ActiveIdIsJustActivated) + g.ActiveIdClickOffset = g.IO.MousePos - bb.Min; if (g.IO.MouseDown[0]) { held = true; From 63e4677b8148d67336e9807334a4401a93bf9d82 Mon Sep 17 00:00:00 2001 From: omar Date: Sun, 7 Jan 2018 15:22:54 +0100 Subject: [PATCH 404/823] Popup: BeginPopupContextItem(), BeginPopupContextWindow(), BeginPopupContextVoid(), OpenPopupOnItemClick() all react on mouse release instead of mouse click. Note that they don't use the full ButtonBehavior() or tracking aabb on both click and release. Applications I've tried seems to behave inconsistently there but on-release-without-tracking is both fairly common and doesn't require extra code for the id tracking. (~#439) --- imgui.cpp | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index d952e287f91b..e63341b4168c 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -3904,7 +3904,7 @@ void ImGui::EndPopup() bool ImGui::OpenPopupOnItemClick(const char* str_id, int mouse_button) { ImGuiWindow* window = GImGui->CurrentWindow; - if (IsMouseClicked(mouse_button) && IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup)) + if (IsMouseReleased(mouse_button) && IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup)) { ImGuiID id = str_id ? window->GetID(str_id) : window->DC.LastItemId; // If user hasn't passed an ID, we can use the LastItemID. Using LastItemID as a Popup ID won't conflict! IM_ASSERT(id != 0); // However, you cannot pass a NULL str_id if the last item has no identifier (e.g. a Text() item) @@ -3922,9 +3922,8 @@ bool ImGui::BeginPopupContextItem(const char* str_id, int mouse_button) ImGuiWindow* window = GImGui->CurrentWindow; ImGuiID id = str_id ? window->GetID(str_id) : window->DC.LastItemId; // If user hasn't passed an ID, we can use the LastItemID. Using LastItemID as a Popup ID won't conflict! IM_ASSERT(id != 0); // However, you cannot pass a NULL str_id if the last item has no identifier (e.g. a Text() item) - if (IsMouseClicked(mouse_button)) - if (IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup)) - OpenPopupEx(id, true); + if (IsMouseReleased(mouse_button) && IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup)) + OpenPopupEx(id, true); return BeginPopupEx(id, ImGuiWindowFlags_AlwaysAutoResize|ImGuiWindowFlags_NoTitleBar|ImGuiWindowFlags_NoSavedSettings); } @@ -3933,10 +3932,9 @@ bool ImGui::BeginPopupContextWindow(const char* str_id, int mouse_button, bool a if (!str_id) str_id = "window_context"; ImGuiID id = GImGui->CurrentWindow->GetID(str_id); - if (IsMouseClicked(mouse_button)) - if (IsWindowHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup)) - if (also_over_items || !IsAnyItemHovered()) - OpenPopupEx(id, true); + if (IsMouseReleased(mouse_button) && IsWindowHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup)) + if (also_over_items || !IsAnyItemHovered()) + OpenPopupEx(id, true); return BeginPopupEx(id, ImGuiWindowFlags_AlwaysAutoResize|ImGuiWindowFlags_NoTitleBar|ImGuiWindowFlags_NoSavedSettings); } @@ -3945,7 +3943,7 @@ bool ImGui::BeginPopupContextVoid(const char* str_id, int mouse_button) if (!str_id) str_id = "void_context"; ImGuiID id = GImGui->CurrentWindow->GetID(str_id); - if (!IsAnyWindowHovered() && IsMouseClicked(mouse_button)) + if (IsMouseReleased(mouse_button) && !IsAnyWindowHovered()) OpenPopupEx(id, true); return BeginPopupEx(id, ImGuiWindowFlags_AlwaysAutoResize|ImGuiWindowFlags_NoTitleBar|ImGuiWindowFlags_NoSavedSettings); } From e09852fc49c8aa12f44702f3c9aa85c7c5472003 Mon Sep 17 00:00:00 2001 From: omar Date: Sun, 7 Jan 2018 15:34:15 +0100 Subject: [PATCH 405/823] Popups: Revert aca23fd3f0eb1b6fb109840f5fc942c49312d096 (Oct 20, 2017). Because 1) I can't seem to find a default. 2) The if is definitively faulty and would have been all true. 3) It looks like possibly the following commit 6ab737a4bb288d553f4de3e3841e393ef96d32a0 could have made this unnecessary. Not absolutly certain. (~#439) --- imgui.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index e63341b4168c..7d6c3f9be8bd 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -3737,8 +3737,8 @@ void ImGui::OpenPopupEx(ImGuiID id, bool reopen_existing) // When reopening a popup we first refocus its parent, otherwise if its parent is itself a popup it would get closed by CloseInactivePopups(). // This is equivalent to what ClosePopupToLevel() does. - if (g.OpenPopupStack[current_stack_size].PopupId == id) - FocusWindow(parent_window); + //if (g.OpenPopupStack[current_stack_size].PopupId == id) + // FocusWindow(parent_window); } } From 369189b675c456116a932848d781beeb4b439bd0 Mon Sep 17 00:00:00 2001 From: omar Date: Sun, 7 Jan 2018 15:40:46 +0100 Subject: [PATCH 406/823] Internals: Popup: Explicitely setting up ImGuiPopupRef reduces confusion. --- imgui.cpp | 10 +++++++--- imgui_internal.h | 2 -- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 7d6c3f9be8bd..41d75c6bdf22 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -3725,9 +3725,13 @@ void ImGui::OpenPopupEx(ImGuiID id, bool reopen_existing) ImGuiContext& g = *GImGui; ImGuiWindow* parent_window = g.CurrentWindow; int current_stack_size = g.CurrentPopupStack.Size; - ImVec2 mouse_pos = g.IO.MousePos; - ImVec2 popup_pos = mouse_pos; // NB: In the Navigation branch popup_pos may not use mouse_pos. - ImGuiPopupRef popup_ref = ImGuiPopupRef(id, parent_window, parent_window->GetID("##Menus"), popup_pos, mouse_pos); // Tagged as new ref because constructor sets Window to NULL. + ImGuiPopupRef popup_ref; // Tagged as new ref as Window will be set back to NULL if we write this into OpenPopupStack. + popup_ref.PopupId = id; + popup_ref.Window = NULL; + popup_ref.ParentWindow = parent_window; + popup_ref.ParentMenuSet = parent_window->GetID("##Menus"); + popup_ref.MousePosOnOpen = g.IO.MousePos; + popup_ref.PopupPosOnOpen = g.IO.MousePos; // NB: In the Navigation branch popup_pos may not use mouse_pos. if (g.OpenPopupStack.Size < current_stack_size + 1) g.OpenPopupStack.push_back(popup_ref); else if (reopen_existing || g.OpenPopupStack[current_stack_size].PopupId != id) diff --git a/imgui_internal.h b/imgui_internal.h index bdadc464e0e2..771d4e073280 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -403,8 +403,6 @@ struct ImGuiPopupRef ImGuiID ParentMenuSet; // Set on OpenPopup() ImVec2 PopupPosOnOpen; // Preferred popup position (typically == MousePosOnOpen when using mouse) ImVec2 MousePosOnOpen; // Copy of mouse position at the time of opening popup - - ImGuiPopupRef(ImGuiID id, ImGuiWindow* parent_window, ImGuiID parent_menu_set, const ImVec2& popup_pos, const ImVec2& mouse_pos) { PopupId = id; Window = NULL; ParentWindow = parent_window; ParentMenuSet = parent_menu_set; PopupPosOnOpen = popup_pos; MousePosOnOpen = mouse_pos; } }; struct ImGuiColumnData From 3678307cd953e51913d1d1076f8124a96c34e0a3 Mon Sep 17 00:00:00 2001 From: omar Date: Sun, 7 Jan 2018 15:56:14 +0100 Subject: [PATCH 407/823] Popup, Menus: Tweaks and comments. --- imgui.cpp | 4 ++-- imgui_internal.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 41d75c6bdf22..b3c7a8038f47 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -3729,7 +3729,7 @@ void ImGui::OpenPopupEx(ImGuiID id, bool reopen_existing) popup_ref.PopupId = id; popup_ref.Window = NULL; popup_ref.ParentWindow = parent_window; - popup_ref.ParentMenuSet = parent_window->GetID("##Menus"); + popup_ref.ParentIdOnOpen = parent_window->IDStack.back(); popup_ref.MousePosOnOpen = g.IO.MousePos; popup_ref.PopupPosOnOpen = g.IO.MousePos; // NB: In the Navigation branch popup_pos may not use mouse_pos. if (g.OpenPopupStack.Size < current_stack_size + 1) @@ -9664,7 +9664,7 @@ bool ImGui::BeginMenu(const char* label, bool enabled) bool pressed; bool menu_is_open = IsPopupOpen(id); - bool menuset_is_open = !(window->Flags & ImGuiWindowFlags_Popup) && (g.OpenPopupStack.Size > g.CurrentPopupStack.Size && g.OpenPopupStack[g.CurrentPopupStack.Size].ParentMenuSet == window->GetID("##Menus")); + bool menuset_is_open = !(window->Flags & ImGuiWindowFlags_Popup) && (g.OpenPopupStack.Size > g.CurrentPopupStack.Size && g.OpenPopupStack[g.CurrentPopupStack.Size].ParentIdOnOpen == window->IDStack.back()); ImGuiWindow* backed_nav_window = g.NavWindow; if (menuset_is_open) g.NavWindow = window; // Odd hack to allow hovering across menus of a same menu-set (otherwise we wouldn't be able to hover parent) diff --git a/imgui_internal.h b/imgui_internal.h index 771d4e073280..f355a4922dc6 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -400,7 +400,7 @@ struct ImGuiPopupRef ImGuiID PopupId; // Set on OpenPopup() ImGuiWindow* Window; // Resolved on BeginPopup() - may stay unresolved if user never calls OpenPopup() ImGuiWindow* ParentWindow; // Set on OpenPopup() - ImGuiID ParentMenuSet; // Set on OpenPopup() + ImGuiID ParentIdOnOpen; // Set on OpenPopup(), we need this to differenciate multiple menu sets from each others (e.g. inside menu bar vs loose menu items) ImVec2 PopupPosOnOpen; // Preferred popup position (typically == MousePosOnOpen when using mouse) ImVec2 MousePosOnOpen; // Copy of mouse position at the time of opening popup }; From 69ff65f054eddba4936473be814d58305913479f Mon Sep 17 00:00:00 2001 From: omar Date: Sun, 7 Jan 2018 16:11:25 +0100 Subject: [PATCH 408/823] Internals: Popup: Renaming fields. --- imgui.cpp | 12 ++++++------ imgui_internal.h | 6 +++--- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index b3c7a8038f47..9eef1ba4db60 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -3550,7 +3550,7 @@ ImVec2 ImGui::GetMousePosOnOpeningCurrentPopup() { ImGuiContext& g = *GImGui; if (g.CurrentPopupStack.Size > 0) - return g.OpenPopupStack[g.CurrentPopupStack.Size-1].MousePosOnOpen; + return g.OpenPopupStack[g.CurrentPopupStack.Size-1].OpenMousePos; return g.IO.MousePos; } @@ -3729,9 +3729,9 @@ void ImGui::OpenPopupEx(ImGuiID id, bool reopen_existing) popup_ref.PopupId = id; popup_ref.Window = NULL; popup_ref.ParentWindow = parent_window; - popup_ref.ParentIdOnOpen = parent_window->IDStack.back(); - popup_ref.MousePosOnOpen = g.IO.MousePos; - popup_ref.PopupPosOnOpen = g.IO.MousePos; // NB: In the Navigation branch popup_pos may not use mouse_pos. + popup_ref.OpenParentId = parent_window->IDStack.back(); + popup_ref.OpenMousePos = g.IO.MousePos; + popup_ref.OpenPopupPos = g.IO.MousePos; // NB: In the Navigation branch popup_pos may not use mouse_pos. if (g.OpenPopupStack.Size < current_stack_size + 1) g.OpenPopupStack.push_back(popup_ref); else if (reopen_existing || g.OpenPopupStack[current_stack_size].PopupId != id) @@ -4483,7 +4483,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) // Popup first latch mouse position, will position itself when it appears next frame window->AutoPosLastDirection = ImGuiDir_None; if ((flags & ImGuiWindowFlags_Popup) != 0 && !window_pos_set_by_api) - window->PosFloat = g.CurrentPopupStack.back().PopupPosOnOpen; + window->PosFloat = g.CurrentPopupStack.back().OpenPopupPos; } // Collapse window by double-clicking on title bar @@ -9664,7 +9664,7 @@ bool ImGui::BeginMenu(const char* label, bool enabled) bool pressed; bool menu_is_open = IsPopupOpen(id); - bool menuset_is_open = !(window->Flags & ImGuiWindowFlags_Popup) && (g.OpenPopupStack.Size > g.CurrentPopupStack.Size && g.OpenPopupStack[g.CurrentPopupStack.Size].ParentIdOnOpen == window->IDStack.back()); + bool menuset_is_open = !(window->Flags & ImGuiWindowFlags_Popup) && (g.OpenPopupStack.Size > g.CurrentPopupStack.Size && g.OpenPopupStack[g.CurrentPopupStack.Size].OpenParentId == window->IDStack.back()); ImGuiWindow* backed_nav_window = g.NavWindow; if (menuset_is_open) g.NavWindow = window; // Odd hack to allow hovering across menus of a same menu-set (otherwise we wouldn't be able to hover parent) diff --git a/imgui_internal.h b/imgui_internal.h index f355a4922dc6..4ff50d8f51b5 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -400,9 +400,9 @@ struct ImGuiPopupRef ImGuiID PopupId; // Set on OpenPopup() ImGuiWindow* Window; // Resolved on BeginPopup() - may stay unresolved if user never calls OpenPopup() ImGuiWindow* ParentWindow; // Set on OpenPopup() - ImGuiID ParentIdOnOpen; // Set on OpenPopup(), we need this to differenciate multiple menu sets from each others (e.g. inside menu bar vs loose menu items) - ImVec2 PopupPosOnOpen; // Preferred popup position (typically == MousePosOnOpen when using mouse) - ImVec2 MousePosOnOpen; // Copy of mouse position at the time of opening popup + ImGuiID OpenParentId; // Set on OpenPopup(), we need this to differenciate multiple menu sets from each others (e.g. inside menu bar vs loose menu items) + ImVec2 OpenPopupPos; // Set on OpenPopup(), preferred popup position (typically == OpenMousePos when using mouse) + ImVec2 OpenMousePos; // Set on OpenPopup(), copy of mouse position at the time of opening popup }; struct ImGuiColumnData From deab2ab015c4d66a9cdd51971e616a6ac444bad1 Mon Sep 17 00:00:00 2001 From: omar Date: Sun, 7 Jan 2018 16:15:54 +0100 Subject: [PATCH 409/823] Popups: Gently handle the user mistakenly calling OpenPopup() every frame. (when reopen_existing is true). (#1497) --- imgui.cpp | 18 +++++++++++++++--- imgui_internal.h | 1 + 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 9eef1ba4db60..d735e0266898 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -3729,15 +3729,27 @@ void ImGui::OpenPopupEx(ImGuiID id, bool reopen_existing) popup_ref.PopupId = id; popup_ref.Window = NULL; popup_ref.ParentWindow = parent_window; + popup_ref.OpenFrameCount = g.FrameCount; popup_ref.OpenParentId = parent_window->IDStack.back(); popup_ref.OpenMousePos = g.IO.MousePos; - popup_ref.OpenPopupPos = g.IO.MousePos; // NB: In the Navigation branch popup_pos may not use mouse_pos. + popup_ref.OpenPopupPos = g.IO.MousePos; // NB: In the Navigation branch OpenPopupPos doesn't use the mouse position, hence the separation here. + if (g.OpenPopupStack.Size < current_stack_size + 1) + { g.OpenPopupStack.push_back(popup_ref); + } else if (reopen_existing || g.OpenPopupStack[current_stack_size].PopupId != id) { - g.OpenPopupStack.resize(current_stack_size+1); - g.OpenPopupStack[current_stack_size] = popup_ref; + // Close child popups if any + g.OpenPopupStack.resize(current_stack_size + 1); + + // Gently handle the user mistakenly calling OpenPopup() every frame. It is a programming mistake! However, if we were to run the regular code path, the ui + // would become completely unusable because the popup will always be in hidden-while-calculating-size state _while_ claiming focus. Which would be a very confusing + // situation for the programmer. Instead, we silently allow the popup to proceed, it will keep reappearing and the programming error will be more obvious to understand. + if (g.OpenPopupStack[current_stack_size].PopupId == id && g.OpenPopupStack[current_stack_size].OpenFrameCount == g.FrameCount - 1) + g.OpenPopupStack[current_stack_size].OpenFrameCount = popup_ref.OpenFrameCount; + else + g.OpenPopupStack[current_stack_size] = popup_ref; // When reopening a popup we first refocus its parent, otherwise if its parent is itself a popup it would get closed by CloseInactivePopups(). // This is equivalent to what ClosePopupToLevel() does. diff --git a/imgui_internal.h b/imgui_internal.h index 4ff50d8f51b5..be4284d24a2f 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -400,6 +400,7 @@ struct ImGuiPopupRef ImGuiID PopupId; // Set on OpenPopup() ImGuiWindow* Window; // Resolved on BeginPopup() - may stay unresolved if user never calls OpenPopup() ImGuiWindow* ParentWindow; // Set on OpenPopup() + int OpenFrameCount; // Set on OpenPopup() ImGuiID OpenParentId; // Set on OpenPopup(), we need this to differenciate multiple menu sets from each others (e.g. inside menu bar vs loose menu items) ImVec2 OpenPopupPos; // Set on OpenPopup(), preferred popup position (typically == OpenMousePos when using mouse) ImVec2 OpenMousePos; // Set on OpenPopup(), copy of mouse position at the time of opening popup From 3fc7cf190def6ac51cb5791f3ad8cee7a79c4026 Mon Sep 17 00:00:00 2001 From: omar Date: Sun, 7 Jan 2018 16:20:02 +0100 Subject: [PATCH 410/823] OpenPopup(): Always reopen existing popup. Removed OpenPopupEx() bool reopen_existing which is always true. This also makes the public API on par with OpenPopupEx(). (#1497, #1533) --- imgui.cpp | 16 ++++++++-------- imgui_internal.h | 2 +- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index d735e0266898..4a21fe4de91e 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -3720,7 +3720,7 @@ void ImGui::EndTooltip() // Popups are closed when user click outside, or activate a pressable item, or CloseCurrentPopup() is called within a BeginPopup()/EndPopup() block. // Popup identifiers are relative to the current ID-stack (so OpenPopup and BeginPopup needs to be at the same level). // One open popup per level of the popup hierarchy (NB: when assigning we reset the Window member of ImGuiPopupRef to NULL) -void ImGui::OpenPopupEx(ImGuiID id, bool reopen_existing) +void ImGui::OpenPopupEx(ImGuiID id) { ImGuiContext& g = *GImGui; ImGuiWindow* parent_window = g.CurrentWindow; @@ -3738,7 +3738,7 @@ void ImGui::OpenPopupEx(ImGuiID id, bool reopen_existing) { g.OpenPopupStack.push_back(popup_ref); } - else if (reopen_existing || g.OpenPopupStack[current_stack_size].PopupId != id) + else { // Close child popups if any g.OpenPopupStack.resize(current_stack_size + 1); @@ -3761,7 +3761,7 @@ void ImGui::OpenPopupEx(ImGuiID id, bool reopen_existing) void ImGui::OpenPopup(const char* str_id) { ImGuiContext& g = *GImGui; - OpenPopupEx(g.CurrentWindow->GetID(str_id), false); + OpenPopupEx(g.CurrentWindow->GetID(str_id)); } static void CloseInactivePopups(ImGuiWindow* ref_window) @@ -3924,7 +3924,7 @@ bool ImGui::OpenPopupOnItemClick(const char* str_id, int mouse_button) { ImGuiID id = str_id ? window->GetID(str_id) : window->DC.LastItemId; // If user hasn't passed an ID, we can use the LastItemID. Using LastItemID as a Popup ID won't conflict! IM_ASSERT(id != 0); // However, you cannot pass a NULL str_id if the last item has no identifier (e.g. a Text() item) - OpenPopupEx(id, true); + OpenPopupEx(id); return true; } return false; @@ -3939,7 +3939,7 @@ bool ImGui::BeginPopupContextItem(const char* str_id, int mouse_button) ImGuiID id = str_id ? window->GetID(str_id) : window->DC.LastItemId; // If user hasn't passed an ID, we can use the LastItemID. Using LastItemID as a Popup ID won't conflict! IM_ASSERT(id != 0); // However, you cannot pass a NULL str_id if the last item has no identifier (e.g. a Text() item) if (IsMouseReleased(mouse_button) && IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup)) - OpenPopupEx(id, true); + OpenPopupEx(id); return BeginPopupEx(id, ImGuiWindowFlags_AlwaysAutoResize|ImGuiWindowFlags_NoTitleBar|ImGuiWindowFlags_NoSavedSettings); } @@ -3950,7 +3950,7 @@ bool ImGui::BeginPopupContextWindow(const char* str_id, int mouse_button, bool a ImGuiID id = GImGui->CurrentWindow->GetID(str_id); if (IsMouseReleased(mouse_button) && IsWindowHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup)) if (also_over_items || !IsAnyItemHovered()) - OpenPopupEx(id, true); + OpenPopupEx(id); return BeginPopupEx(id, ImGuiWindowFlags_AlwaysAutoResize|ImGuiWindowFlags_NoTitleBar|ImGuiWindowFlags_NoSavedSettings); } @@ -3960,7 +3960,7 @@ bool ImGui::BeginPopupContextVoid(const char* str_id, int mouse_button) str_id = "void_context"; ImGuiID id = GImGui->CurrentWindow->GetID(str_id); if (IsMouseReleased(mouse_button) && !IsAnyWindowHovered()) - OpenPopupEx(id, true); + OpenPopupEx(id); return BeginPopupEx(id, ImGuiWindowFlags_AlwaysAutoResize|ImGuiWindowFlags_NoTitleBar|ImGuiWindowFlags_NoSavedSettings); } @@ -9204,7 +9204,7 @@ bool ImGui::BeginCombo(const char* label, const char* preview_value, ImGuiComboF if (pressed && !popup_open) { - OpenPopupEx(id, false); + OpenPopupEx(id); popup_open = true; } diff --git a/imgui_internal.h b/imgui_internal.h index be4284d24a2f..9216793b6402 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -894,7 +894,7 @@ namespace ImGui IMGUI_API void PushItemFlag(ImGuiItemFlags option, bool enabled); IMGUI_API void PopItemFlag(); - IMGUI_API void OpenPopupEx(ImGuiID id, bool reopen_existing); + IMGUI_API void OpenPopupEx(ImGuiID id); IMGUI_API void ClosePopup(ImGuiID id); IMGUI_API bool IsPopupOpen(ImGuiID id); IMGUI_API bool BeginPopupEx(ImGuiID id, ImGuiWindowFlags extra_flags); From a8e5542d78a184f06a4a455a0e6914bea59e6a88 Mon Sep 17 00:00:00 2001 From: omar Date: Sun, 7 Jan 2018 18:13:01 +0100 Subject: [PATCH 411/823] BeginPopup: Exposed extra_flags publicly. (#1533) --- imgui.cpp | 4 ++-- imgui.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 4a21fe4de91e..844b63f8c017 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -3858,7 +3858,7 @@ bool ImGui::BeginPopupEx(ImGuiID id, ImGuiWindowFlags extra_flags) return is_open; } -bool ImGui::BeginPopup(const char* str_id) +bool ImGui::BeginPopup(const char* str_id, ImGuiWindowFlags extra_flags) { ImGuiContext& g = *GImGui; if (g.OpenPopupStack.Size <= g.CurrentPopupStack.Size) // Early out for performance @@ -3866,7 +3866,7 @@ bool ImGui::BeginPopup(const char* str_id) g.NextWindowData.Clear(); // We behave like Begin() and need to consume those values return false; } - return BeginPopupEx(g.CurrentWindow->GetID(str_id), ImGuiWindowFlags_AlwaysAutoResize|ImGuiWindowFlags_NoTitleBar|ImGuiWindowFlags_NoSavedSettings); + return BeginPopupEx(g.CurrentWindow->GetID(str_id), extra_flags|ImGuiWindowFlags_AlwaysAutoResize|ImGuiWindowFlags_NoTitleBar|ImGuiWindowFlags_NoSavedSettings); } bool ImGui::IsPopupOpen(ImGuiID id) diff --git a/imgui.h b/imgui.h index bb717eb4df04..215a745e587b 100644 --- a/imgui.h +++ b/imgui.h @@ -409,7 +409,7 @@ namespace ImGui // Popups IMGUI_API void OpenPopup(const char* str_id); // call to mark popup as open (don't call every frame!). popups are closed when user click outside, or if CloseCurrentPopup() is called within a BeginPopup()/EndPopup() block. By default, Selectable()/MenuItem() are calling CloseCurrentPopup(). Popup identifiers are relative to the current ID-stack (so OpenPopup and BeginPopup needs to be at the same level). IMGUI_API bool OpenPopupOnItemClick(const char* str_id = NULL, int mouse_button = 1); // helper to open popup when clicked on last item. return true when just opened. - IMGUI_API bool BeginPopup(const char* str_id); // return true if the popup is open, and you can start outputting to it. only call EndPopup() if BeginPopup() returned true! + IMGUI_API bool BeginPopup(const char* str_id, ImGuiWindowFlags extra_flags = 0); // return true if the popup is open, and you can start outputting to it. only call EndPopup() if BeginPopup() returned true! IMGUI_API bool BeginPopupModal(const char* name, bool* p_open = NULL, ImGuiWindowFlags extra_flags = 0); // modal dialog (block interactions behind the modal window, can't close the modal window by clicking outside) IMGUI_API bool BeginPopupContextItem(const char* str_id = NULL, int mouse_button = 1); // helper to open and begin popup when clicked on last item. if you can pass a NULL str_id only if the previous item had an id. If you want to use that on a non-interactive item such as Text() you need to pass in an explicit ID here. read comments in .cpp! IMGUI_API bool BeginPopupContextWindow(const char* str_id = NULL, int mouse_button = 1, bool also_over_items = true); // helper to open and begin popup when clicked on current window. From 168200f91525bfd440cd30c7dadb2dc0992fd257 Mon Sep 17 00:00:00 2001 From: omar Date: Sun, 7 Jan 2018 18:15:43 +0100 Subject: [PATCH 412/823] Popups: Comments, reorganize bits of the header section, renamed parameters. --- imgui.cpp | 9 ++++----- imgui.h | 6 +++--- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 844b63f8c017..b7057412539b 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -3858,7 +3858,7 @@ bool ImGui::BeginPopupEx(ImGuiID id, ImGuiWindowFlags extra_flags) return is_open; } -bool ImGui::BeginPopup(const char* str_id, ImGuiWindowFlags extra_flags) +bool ImGui::BeginPopup(const char* str_id, ImGuiWindowFlags flags) { ImGuiContext& g = *GImGui; if (g.OpenPopupStack.Size <= g.CurrentPopupStack.Size) // Early out for performance @@ -3866,7 +3866,7 @@ bool ImGui::BeginPopup(const char* str_id, ImGuiWindowFlags extra_flags) g.NextWindowData.Clear(); // We behave like Begin() and need to consume those values return false; } - return BeginPopupEx(g.CurrentWindow->GetID(str_id), extra_flags|ImGuiWindowFlags_AlwaysAutoResize|ImGuiWindowFlags_NoTitleBar|ImGuiWindowFlags_NoSavedSettings); + return BeginPopupEx(g.CurrentWindow->GetID(str_id), flags|ImGuiWindowFlags_AlwaysAutoResize|ImGuiWindowFlags_NoTitleBar|ImGuiWindowFlags_NoSavedSettings); } bool ImGui::IsPopupOpen(ImGuiID id) @@ -3881,7 +3881,7 @@ bool ImGui::IsPopupOpen(const char* str_id) return g.OpenPopupStack.Size > g.CurrentPopupStack.Size && g.OpenPopupStack[g.CurrentPopupStack.Size].PopupId == g.CurrentWindow->GetID(str_id); } -bool ImGui::BeginPopupModal(const char* name, bool* p_open, ImGuiWindowFlags extra_flags) +bool ImGui::BeginPopupModal(const char* name, bool* p_open, ImGuiWindowFlags flags) { ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; @@ -3896,8 +3896,7 @@ bool ImGui::BeginPopupModal(const char* name, bool* p_open, ImGuiWindowFlags ext if (g.NextWindowData.PosCond == 0) SetNextWindowPos(g.IO.DisplaySize * 0.5f, ImGuiCond_Appearing, ImVec2(0.5f, 0.5f)); - ImGuiWindowFlags flags = extra_flags|ImGuiWindowFlags_Popup|ImGuiWindowFlags_Modal|ImGuiWindowFlags_NoCollapse|ImGuiWindowFlags_NoSavedSettings; - bool is_open = Begin(name, p_open, flags); + bool is_open = Begin(name, p_open, flags | ImGuiWindowFlags_Popup | ImGuiWindowFlags_Modal | ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoSavedSettings); if (!is_open || (p_open && !*p_open)) // NB: is_open can be 'false' when the popup is completely clipped (e.g. zero size display) { EndPopup(); diff --git a/imgui.h b/imgui.h index 215a745e587b..d6c5f7b46ff3 100644 --- a/imgui.h +++ b/imgui.h @@ -408,13 +408,13 @@ namespace ImGui // Popups IMGUI_API void OpenPopup(const char* str_id); // call to mark popup as open (don't call every frame!). popups are closed when user click outside, or if CloseCurrentPopup() is called within a BeginPopup()/EndPopup() block. By default, Selectable()/MenuItem() are calling CloseCurrentPopup(). Popup identifiers are relative to the current ID-stack (so OpenPopup and BeginPopup needs to be at the same level). - IMGUI_API bool OpenPopupOnItemClick(const char* str_id = NULL, int mouse_button = 1); // helper to open popup when clicked on last item. return true when just opened. - IMGUI_API bool BeginPopup(const char* str_id, ImGuiWindowFlags extra_flags = 0); // return true if the popup is open, and you can start outputting to it. only call EndPopup() if BeginPopup() returned true! - IMGUI_API bool BeginPopupModal(const char* name, bool* p_open = NULL, ImGuiWindowFlags extra_flags = 0); // modal dialog (block interactions behind the modal window, can't close the modal window by clicking outside) + IMGUI_API bool BeginPopup(const char* str_id, ImGuiWindowFlags flags = 0); // return true if the popup is open, and you can start outputting to it. only call EndPopup() if BeginPopup() returned true! IMGUI_API bool BeginPopupContextItem(const char* str_id = NULL, int mouse_button = 1); // helper to open and begin popup when clicked on last item. if you can pass a NULL str_id only if the previous item had an id. If you want to use that on a non-interactive item such as Text() you need to pass in an explicit ID here. read comments in .cpp! IMGUI_API bool BeginPopupContextWindow(const char* str_id = NULL, int mouse_button = 1, bool also_over_items = true); // helper to open and begin popup when clicked on current window. IMGUI_API bool BeginPopupContextVoid(const char* str_id = NULL, int mouse_button = 1); // helper to open and begin popup when clicked in void (where there are no imgui windows). + IMGUI_API bool BeginPopupModal(const char* name, bool* p_open = NULL, ImGuiWindowFlags flags = 0); // modal dialog (regular window with title bar, block interactions behind the modal window, can't close the modal window by clicking outside) IMGUI_API void EndPopup(); + IMGUI_API bool OpenPopupOnItemClick(const char* str_id = NULL, int mouse_button = 1); // helper to open popup when clicked on last item. return true when just opened. IMGUI_API bool IsPopupOpen(const char* str_id); // return true if the popup is open IMGUI_API void CloseCurrentPopup(); // close the popup we have begin-ed into. clicking on a MenuItem or Selectable automatically close the current popup. From 7484c6344991c91cbec90d439f5e386a4b0dbd2e Mon Sep 17 00:00:00 2001 From: omar Date: Sun, 7 Jan 2018 19:05:42 +0100 Subject: [PATCH 413/823] Examples: OpenGL3+SDL: Changed GLSL shader version to 150 (#1466, #1504) --- examples/sdl_opengl3_example/imgui_impl_sdl_gl3.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.cpp b/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.cpp index 4cdbe0f1b04b..5c0208ac30e1 100644 --- a/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.cpp +++ b/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.cpp @@ -221,7 +221,7 @@ bool ImGui_ImplSdlGL3_CreateDeviceObjects() glGetIntegerv(GL_VERTEX_ARRAY_BINDING, &last_vertex_array); const GLchar *vertex_shader = - "#version 330\n" + "#version 150\n" "uniform mat4 ProjMtx;\n" "in vec2 Position;\n" "in vec2 UV;\n" @@ -236,7 +236,7 @@ bool ImGui_ImplSdlGL3_CreateDeviceObjects() "}\n"; const GLchar* fragment_shader = - "#version 330\n" + "#version 150\n" "uniform sampler2D Texture;\n" "in vec2 Frag_UV;\n" "in vec4 Frag_Color;\n" From 39cb56c39e662a330b278061fb5ab59813c0c911 Mon Sep 17 00:00:00 2001 From: omar Date: Sun, 7 Jan 2018 19:06:20 +0100 Subject: [PATCH 414/823] Examples: OpenGL3+GLFW: Using 3.2 context + GLSL version 150 (#1466) --- examples/opengl3_example/imgui_impl_glfw_gl3.cpp | 4 ++-- examples/opengl3_example/main.cpp | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/opengl3_example/imgui_impl_glfw_gl3.cpp b/examples/opengl3_example/imgui_impl_glfw_gl3.cpp index a608e370b92b..3307d5310915 100644 --- a/examples/opengl3_example/imgui_impl_glfw_gl3.cpp +++ b/examples/opengl3_example/imgui_impl_glfw_gl3.cpp @@ -217,7 +217,7 @@ bool ImGui_ImplGlfwGL3_CreateDeviceObjects() glGetIntegerv(GL_VERTEX_ARRAY_BINDING, &last_vertex_array); const GLchar *vertex_shader = - "#version 330\n" + "#version 150\n" "uniform mat4 ProjMtx;\n" "in vec2 Position;\n" "in vec2 UV;\n" @@ -232,7 +232,7 @@ bool ImGui_ImplGlfwGL3_CreateDeviceObjects() "}\n"; const GLchar* fragment_shader = - "#version 330\n" + "#version 150\n" "uniform sampler2D Texture;\n" "in vec2 Frag_UV;\n" "in vec4 Frag_Color;\n" diff --git a/examples/opengl3_example/main.cpp b/examples/opengl3_example/main.cpp index 9e9a3fb6c8d6..6beb855dc4f0 100644 --- a/examples/opengl3_example/main.cpp +++ b/examples/opengl3_example/main.cpp @@ -21,7 +21,7 @@ int main(int, char**) if (!glfwInit()) return 1; glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); - glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); + glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2); glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); #if __APPLE__ glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); From ce95b848250af5386f099ece3ceec15062f57065 Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 8 Jan 2018 15:30:39 +0100 Subject: [PATCH 415/823] Added ImGuiKey_Insert for future use. Setup in all example bindings. (#1541) --- examples/allegro5_example/imgui_impl_a5.cpp | 1 + examples/apple_example/imguiex-ios/imgui_impl_ios.mm | 1 + examples/directx10_example/imgui_impl_dx10.cpp | 1 + examples/directx11_example/imgui_impl_dx11.cpp | 1 + examples/directx9_example/imgui_impl_dx9.cpp | 1 + examples/marmalade_example/imgui_impl_marmalade.cpp | 1 + examples/opengl2_example/imgui_impl_glfw.cpp | 1 + examples/opengl3_example/imgui_impl_glfw_gl3.cpp | 1 + examples/sdl_opengl2_example/imgui_impl_sdl.cpp | 1 + examples/sdl_opengl3_example/imgui_impl_sdl_gl3.cpp | 1 + examples/vulkan_example/imgui_impl_glfw_vulkan.cpp | 1 + imgui.h | 1 + 12 files changed, 12 insertions(+) diff --git a/examples/allegro5_example/imgui_impl_a5.cpp b/examples/allegro5_example/imgui_impl_a5.cpp index 7a7d4cc1ecd0..d3ccffd23d9c 100644 --- a/examples/allegro5_example/imgui_impl_a5.cpp +++ b/examples/allegro5_example/imgui_impl_a5.cpp @@ -177,6 +177,7 @@ bool ImGui_ImplA5_Init(ALLEGRO_DISPLAY* display) io.KeyMap[ImGuiKey_PageDown] = ALLEGRO_KEY_PGDN; io.KeyMap[ImGuiKey_Home] = ALLEGRO_KEY_HOME; io.KeyMap[ImGuiKey_End] = ALLEGRO_KEY_END; + io.KeyMap[ImGuiKey_Insert] = ALLEGRO_KEY_INSERT; io.KeyMap[ImGuiKey_Delete] = ALLEGRO_KEY_DELETE; io.KeyMap[ImGuiKey_Backspace] = ALLEGRO_KEY_BACKSPACE; io.KeyMap[ImGuiKey_Enter] = ALLEGRO_KEY_ENTER; diff --git a/examples/apple_example/imguiex-ios/imgui_impl_ios.mm b/examples/apple_example/imguiex-ios/imgui_impl_ios.mm index 7fd7466c9f83..9db45d0f29a8 100644 --- a/examples/apple_example/imguiex-ios/imgui_impl_ios.mm +++ b/examples/apple_example/imguiex-ios/imgui_impl_ios.mm @@ -488,6 +488,7 @@ - (void)setupImGuiHooks io.KeyMap[ImGuiKey_DownArrow] = kVK_DownArrow+1; io.KeyMap[ImGuiKey_Home] = kVK_Home+1; io.KeyMap[ImGuiKey_End] = kVK_End+1; + io.KeyMap[ImGuiKey_Insert] = kVK_Help+1; io.KeyMap[ImGuiKey_Delete] = kVK_ForwardDelete+1; io.KeyMap[ImGuiKey_Backspace] = kVK_Delete+1; io.KeyMap[ImGuiKey_Enter] = kVK_Return+1; diff --git a/examples/directx10_example/imgui_impl_dx10.cpp b/examples/directx10_example/imgui_impl_dx10.cpp index d181f7a5d377..4f7117a7bc20 100644 --- a/examples/directx10_example/imgui_impl_dx10.cpp +++ b/examples/directx10_example/imgui_impl_dx10.cpp @@ -545,6 +545,7 @@ bool ImGui_ImplDX10_Init(void* hwnd, ID3D10Device* device) io.KeyMap[ImGuiKey_PageDown] = VK_NEXT; io.KeyMap[ImGuiKey_Home] = VK_HOME; io.KeyMap[ImGuiKey_End] = VK_END; + io.KeyMap[ImGuiKey_Insert] = VK_INSERT; io.KeyMap[ImGuiKey_Delete] = VK_DELETE; io.KeyMap[ImGuiKey_Backspace] = VK_BACK; io.KeyMap[ImGuiKey_Enter] = VK_RETURN; diff --git a/examples/directx11_example/imgui_impl_dx11.cpp b/examples/directx11_example/imgui_impl_dx11.cpp index 833a0bb07128..5df7bf1f04ff 100644 --- a/examples/directx11_example/imgui_impl_dx11.cpp +++ b/examples/directx11_example/imgui_impl_dx11.cpp @@ -547,6 +547,7 @@ bool ImGui_ImplDX11_Init(void* hwnd, ID3D11Device* device, ID3D11DeviceContex io.KeyMap[ImGuiKey_PageDown] = VK_NEXT; io.KeyMap[ImGuiKey_Home] = VK_HOME; io.KeyMap[ImGuiKey_End] = VK_END; + io.KeyMap[ImGuiKey_Insert] = VK_INSERT; io.KeyMap[ImGuiKey_Delete] = VK_DELETE; io.KeyMap[ImGuiKey_Backspace] = VK_BACK; io.KeyMap[ImGuiKey_Enter] = VK_RETURN; diff --git a/examples/directx9_example/imgui_impl_dx9.cpp b/examples/directx9_example/imgui_impl_dx9.cpp index 40f675aff1fe..18ec0d9b5e5f 100644 --- a/examples/directx9_example/imgui_impl_dx9.cpp +++ b/examples/directx9_example/imgui_impl_dx9.cpp @@ -264,6 +264,7 @@ bool ImGui_ImplDX9_Init(void* hwnd, IDirect3DDevice9* device) io.KeyMap[ImGuiKey_PageDown] = VK_NEXT; io.KeyMap[ImGuiKey_Home] = VK_HOME; io.KeyMap[ImGuiKey_End] = VK_END; + io.KeyMap[ImGuiKey_Insert] = VK_INSERT; io.KeyMap[ImGuiKey_Delete] = VK_DELETE; io.KeyMap[ImGuiKey_Backspace] = VK_BACK; io.KeyMap[ImGuiKey_Enter] = VK_RETURN; diff --git a/examples/marmalade_example/imgui_impl_marmalade.cpp b/examples/marmalade_example/imgui_impl_marmalade.cpp index cae1be1856d5..39623cc4d3b6 100644 --- a/examples/marmalade_example/imgui_impl_marmalade.cpp +++ b/examples/marmalade_example/imgui_impl_marmalade.cpp @@ -220,6 +220,7 @@ bool ImGui_Marmalade_Init(bool install_callbacks) io.KeyMap[ImGuiKey_PageDown] = s3eKeyPageDown; io.KeyMap[ImGuiKey_Home] = s3eKeyHome; io.KeyMap[ImGuiKey_End] = s3eKeyEnd; + io.KeyMap[ImGuiKey_Insert] = s3eKeyInsert; io.KeyMap[ImGuiKey_Delete] = s3eKeyDelete; io.KeyMap[ImGuiKey_Backspace] = s3eKeyBackspace; io.KeyMap[ImGuiKey_Enter] = s3eKeyEnter; diff --git a/examples/opengl2_example/imgui_impl_glfw.cpp b/examples/opengl2_example/imgui_impl_glfw.cpp index a635cc9af45f..d2eb657f602e 100644 --- a/examples/opengl2_example/imgui_impl_glfw.cpp +++ b/examples/opengl2_example/imgui_impl_glfw.cpp @@ -211,6 +211,7 @@ bool ImGui_ImplGlfwGL2_Init(GLFWwindow* window, bool install_callbacks) io.KeyMap[ImGuiKey_PageDown] = GLFW_KEY_PAGE_DOWN; io.KeyMap[ImGuiKey_Home] = GLFW_KEY_HOME; io.KeyMap[ImGuiKey_End] = GLFW_KEY_END; + io.KeyMap[ImGuiKey_Insert] = GLFW_KEY_INSERT; io.KeyMap[ImGuiKey_Delete] = GLFW_KEY_DELETE; io.KeyMap[ImGuiKey_Backspace] = GLFW_KEY_BACKSPACE; io.KeyMap[ImGuiKey_Enter] = GLFW_KEY_ENTER; diff --git a/examples/opengl3_example/imgui_impl_glfw_gl3.cpp b/examples/opengl3_example/imgui_impl_glfw_gl3.cpp index 3307d5310915..f35b2654ccca 100644 --- a/examples/opengl3_example/imgui_impl_glfw_gl3.cpp +++ b/examples/opengl3_example/imgui_impl_glfw_gl3.cpp @@ -323,6 +323,7 @@ bool ImGui_ImplGlfwGL3_Init(GLFWwindow* window, bool install_callbacks) io.KeyMap[ImGuiKey_PageDown] = GLFW_KEY_PAGE_DOWN; io.KeyMap[ImGuiKey_Home] = GLFW_KEY_HOME; io.KeyMap[ImGuiKey_End] = GLFW_KEY_END; + io.KeyMap[ImGuiKey_Insert] = GLFW_KEY_INSERT; io.KeyMap[ImGuiKey_Delete] = GLFW_KEY_DELETE; io.KeyMap[ImGuiKey_Backspace] = GLFW_KEY_BACKSPACE; io.KeyMap[ImGuiKey_Enter] = GLFW_KEY_ENTER; diff --git a/examples/sdl_opengl2_example/imgui_impl_sdl.cpp b/examples/sdl_opengl2_example/imgui_impl_sdl.cpp index c997d36de07f..ac9200837e56 100644 --- a/examples/sdl_opengl2_example/imgui_impl_sdl.cpp +++ b/examples/sdl_opengl2_example/imgui_impl_sdl.cpp @@ -214,6 +214,7 @@ bool ImGui_ImplSdlGL2_Init(SDL_Window* window) io.KeyMap[ImGuiKey_PageDown] = SDL_SCANCODE_PAGEDOWN; io.KeyMap[ImGuiKey_Home] = SDL_SCANCODE_HOME; io.KeyMap[ImGuiKey_End] = SDL_SCANCODE_END; + io.KeyMap[ImGuiKey_Insert] = SDLK_INSERT; io.KeyMap[ImGuiKey_Delete] = SDLK_DELETE; io.KeyMap[ImGuiKey_Backspace] = SDLK_BACKSPACE; io.KeyMap[ImGuiKey_Enter] = SDLK_RETURN; diff --git a/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.cpp b/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.cpp index 5c0208ac30e1..f9e970f38daf 100644 --- a/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.cpp +++ b/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.cpp @@ -325,6 +325,7 @@ bool ImGui_ImplSdlGL3_Init(SDL_Window* window) io.KeyMap[ImGuiKey_PageDown] = SDL_SCANCODE_PAGEDOWN; io.KeyMap[ImGuiKey_Home] = SDL_SCANCODE_HOME; io.KeyMap[ImGuiKey_End] = SDL_SCANCODE_END; + io.KeyMap[ImGuiKey_Insert] = SDLK_INSERT; io.KeyMap[ImGuiKey_Delete] = SDLK_DELETE; io.KeyMap[ImGuiKey_Backspace] = SDLK_BACKSPACE; io.KeyMap[ImGuiKey_Enter] = SDLK_RETURN; diff --git a/examples/vulkan_example/imgui_impl_glfw_vulkan.cpp b/examples/vulkan_example/imgui_impl_glfw_vulkan.cpp index 8eb35ec3c708..0af380cc626a 100644 --- a/examples/vulkan_example/imgui_impl_glfw_vulkan.cpp +++ b/examples/vulkan_example/imgui_impl_glfw_vulkan.cpp @@ -750,6 +750,7 @@ bool ImGui_ImplGlfwVulkan_Init(GLFWwindow* window, bool install_callbacks, Im io.KeyMap[ImGuiKey_PageDown] = GLFW_KEY_PAGE_DOWN; io.KeyMap[ImGuiKey_Home] = GLFW_KEY_HOME; io.KeyMap[ImGuiKey_End] = GLFW_KEY_END; + io.KeyMap[ImGuiKey_Insert] = GLFW_KEY_INSERT; io.KeyMap[ImGuiKey_Delete] = GLFW_KEY_DELETE; io.KeyMap[ImGuiKey_Backspace] = GLFW_KEY_BACKSPACE; io.KeyMap[ImGuiKey_Enter] = GLFW_KEY_ENTER; diff --git a/imgui.h b/imgui.h index d6c5f7b46ff3..02832422e969 100644 --- a/imgui.h +++ b/imgui.h @@ -671,6 +671,7 @@ enum ImGuiKey_ ImGuiKey_PageDown, ImGuiKey_Home, // for text edit ImGuiKey_End, // for text edit + ImGuiKey_Insert, // for text edit ImGuiKey_Delete, // for text edit ImGuiKey_Backspace, // for text edit ImGuiKey_Enter, // for text edit From fd4d63a0c5f8ed9004d967b5aa011e31be6ba763 Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 8 Jan 2018 15:54:41 +0100 Subject: [PATCH 416/823] InputText: Moved code for checking clipboard shortcut so we can expand on it. (#1541) --- TODO.txt | 1 + imgui.cpp | 16 +++++++++------- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/TODO.txt b/TODO.txt index c052aeb5c09c..a9bc641e72b8 100644 --- a/TODO.txt +++ b/TODO.txt @@ -64,6 +64,7 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i - input text: add discard flag (e.g. ImGuiInputTextFlags_DiscardActiveBuffer) or make it easier to clear active focus for text replacement during edition (#725) - input text: display bug when clicking a drag/slider after an input text in a different window has all-selected text (order dependant). actually a very old bug but no one appears to have noticed it. - input text multi-line: don't directly call AddText() which does an unnecessary vertex reserve for character count prior to clipping. and/or more line-based clipping to AddText(). and/or reorganize TextUnformatted/RenderText for more efficiency for large text (e.g TextUnformatted could clip and log separately, etc). + - input text multi-line: support for cut/paste without selection (cut/paste the current line) - input text multi-line: line numbers? status bar? (follow up on #200) - input text multi-line: behave better when user changes input buffer while editing is active (even though it is illegal behavior). namely, the change of buffer can create a scrollbar glitch (#725) - input text multi-line: better horizontal scrolling support (#383, #1224) diff --git a/imgui.cpp b/imgui.cpp index b7057412539b..1f3afb5d5e76 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -8610,6 +8610,10 @@ bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2 const bool is_wordmove_key_down = io.OptMacOSXBehaviors ? io.KeyAlt : io.KeyCtrl; // OS X style: Text editing cursor movement using Alt instead of Ctrl const bool is_startend_key_down = io.OptMacOSXBehaviors && io.KeySuper && !io.KeyCtrl && !io.KeyAlt; // OS X style: Line/Text Start and End using Cmd+Arrows instead of Home/End + const bool is_paste = (is_shortcut_key_only && IsKeyPressedMap(ImGuiKey_V)) && is_editable; + const bool is_cut = (is_shortcut_key_only && IsKeyPressedMap(ImGuiKey_X)) && is_editable && !is_password && (!is_multiline || edit_state.HasSelection()); + const bool is_copy = (is_shortcut_key_only && IsKeyPressedMap(ImGuiKey_C)) && !is_password && (!is_multiline || edit_state.HasSelection()); + if (IsKeyPressedMap(ImGuiKey_LeftArrow)) { edit_state.OnKeyPressed((is_startend_key_down ? STB_TEXTEDIT_K_LINESTART : is_wordmove_key_down ? STB_TEXTEDIT_K_WORDLEFT : STB_TEXTEDIT_K_LEFT) | k_mask); } else if (IsKeyPressedMap(ImGuiKey_RightArrow)) { edit_state.OnKeyPressed((is_startend_key_down ? STB_TEXTEDIT_K_LINEEND : is_wordmove_key_down ? STB_TEXTEDIT_K_WORDRIGHT : STB_TEXTEDIT_K_RIGHT) | k_mask); } else if (IsKeyPressedMap(ImGuiKey_UpArrow) && is_multiline) { if (io.KeyCtrl) SetWindowScrollY(draw_window, ImMax(draw_window->Scroll.y - g.FontSize, 0.0f)); else edit_state.OnKeyPressed((is_startend_key_down ? STB_TEXTEDIT_K_TEXTSTART : STB_TEXTEDIT_K_UP) | k_mask); } @@ -8650,13 +8654,9 @@ bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2 else if (is_shortcut_key_only && IsKeyPressedMap(ImGuiKey_Z) && is_editable && is_undoable) { edit_state.OnKeyPressed(STB_TEXTEDIT_K_UNDO); edit_state.ClearSelection(); } else if (is_shortcut_key_only && IsKeyPressedMap(ImGuiKey_Y) && is_editable && is_undoable) { edit_state.OnKeyPressed(STB_TEXTEDIT_K_REDO); edit_state.ClearSelection(); } else if (is_shortcut_key_only && IsKeyPressedMap(ImGuiKey_A)) { edit_state.SelectAll(); edit_state.CursorFollow = true; } - else if (is_shortcut_key_only && !is_password && ((IsKeyPressedMap(ImGuiKey_X) && is_editable) || IsKeyPressedMap(ImGuiKey_C)) && (!is_multiline || edit_state.HasSelection())) + else if (is_cut || is_copy) { // Cut, Copy - const bool cut = IsKeyPressedMap(ImGuiKey_X); - if (cut && !edit_state.HasSelection()) - edit_state.SelectAll(); - if (io.SetClipboardTextFn) { const int ib = edit_state.HasSelection() ? ImMin(edit_state.StbState.select_start, edit_state.StbState.select_end) : 0; @@ -8666,13 +8666,15 @@ bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2 SetClipboardText(edit_state.TempTextBuffer.Data); } - if (cut) + if (is_cut) { + if (!edit_state.HasSelection()) + edit_state.SelectAll(); edit_state.CursorFollow = true; stb_textedit_cut(&edit_state, &edit_state.StbState); } } - else if (is_shortcut_key_only && IsKeyPressedMap(ImGuiKey_V) && is_editable) + else if (is_paste) { // Paste if (const char* clipboard = GetClipboardText()) From 933ee6cd5dac25c9103b6bcb1a4030be38a04aa1 Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 8 Jan 2018 16:01:02 +0100 Subject: [PATCH 417/823] InputText: Added alternative clipboard shortcuts: Shift+Delete (cut), Ctrl+Insert (copy), Shift+Insert (paste). (#1541) --- imgui.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 1f3afb5d5e76..5faa456995c6 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -8609,10 +8609,12 @@ bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2 const bool is_shortcut_key_only = (io.OptMacOSXBehaviors ? (io.KeySuper && !io.KeyCtrl) : (io.KeyCtrl && !io.KeySuper)) && !io.KeyAlt && !io.KeyShift; // OS X style: Shortcuts using Cmd/Super instead of Ctrl const bool is_wordmove_key_down = io.OptMacOSXBehaviors ? io.KeyAlt : io.KeyCtrl; // OS X style: Text editing cursor movement using Alt instead of Ctrl const bool is_startend_key_down = io.OptMacOSXBehaviors && io.KeySuper && !io.KeyCtrl && !io.KeyAlt; // OS X style: Line/Text Start and End using Cmd+Arrows instead of Home/End + const bool is_ctrl_key_only = io.KeyCtrl && !io.KeyShift && !io.KeyAlt && !io.KeySuper; + const bool is_shift_key_only = io.KeyShift && !io.KeyCtrl && !io.KeyAlt && !io.KeySuper; - const bool is_paste = (is_shortcut_key_only && IsKeyPressedMap(ImGuiKey_V)) && is_editable; - const bool is_cut = (is_shortcut_key_only && IsKeyPressedMap(ImGuiKey_X)) && is_editable && !is_password && (!is_multiline || edit_state.HasSelection()); - const bool is_copy = (is_shortcut_key_only && IsKeyPressedMap(ImGuiKey_C)) && !is_password && (!is_multiline || edit_state.HasSelection()); + const bool is_cut = ((is_shortcut_key_only && IsKeyPressedMap(ImGuiKey_X)) || (is_shift_key_only && IsKeyPressedMap(ImGuiKey_Delete))) && is_editable && !is_password && (!is_multiline || edit_state.HasSelection()); + const bool is_copy = ((is_shortcut_key_only && IsKeyPressedMap(ImGuiKey_C)) || (is_ctrl_key_only && IsKeyPressedMap(ImGuiKey_Insert))) && !is_password && (!is_multiline || edit_state.HasSelection()); + const bool is_paste = ((is_shortcut_key_only && IsKeyPressedMap(ImGuiKey_V)) || (is_shift_key_only && IsKeyPressedMap(ImGuiKey_Insert))) && is_editable; if (IsKeyPressedMap(ImGuiKey_LeftArrow)) { edit_state.OnKeyPressed((is_startend_key_down ? STB_TEXTEDIT_K_LINESTART : is_wordmove_key_down ? STB_TEXTEDIT_K_WORDLEFT : STB_TEXTEDIT_K_LEFT) | k_mask); } else if (IsKeyPressedMap(ImGuiKey_RightArrow)) { edit_state.OnKeyPressed((is_startend_key_down ? STB_TEXTEDIT_K_LINEEND : is_wordmove_key_down ? STB_TEXTEDIT_K_WORDRIGHT : STB_TEXTEDIT_K_RIGHT) | k_mask); } From 92d75c44bc3468e2495027652391a6ba928979bb Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 8 Jan 2018 23:59:12 +0100 Subject: [PATCH 418/823] Internals: ImVec2 versions of ImMin, ImMax inline float version for a faster full-on-debug-no-inline experience. --- imgui_internal.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/imgui_internal.h b/imgui_internal.h index 9216793b6402..4e7054870731 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -134,8 +134,8 @@ static inline int ImMin(int lhs, int rhs) static inline int ImMax(int lhs, int rhs) { return lhs >= rhs ? lhs : rhs; } static inline float ImMin(float lhs, float rhs) { return lhs < rhs ? lhs : rhs; } static inline float ImMax(float lhs, float rhs) { return lhs >= rhs ? lhs : rhs; } -static inline ImVec2 ImMin(const ImVec2& lhs, const ImVec2& rhs) { return ImVec2(ImMin(lhs.x,rhs.x), ImMin(lhs.y,rhs.y)); } -static inline ImVec2 ImMax(const ImVec2& lhs, const ImVec2& rhs) { return ImVec2(ImMax(lhs.x,rhs.x), ImMax(lhs.y,rhs.y)); } +static inline ImVec2 ImMin(const ImVec2& lhs, const ImVec2& rhs) { return ImVec2(lhs.x < rhs.x ? lhs.x : rhs.x, lhs.y < rhs.y ? lhs.y : rhs.y); } +static inline ImVec2 ImMax(const ImVec2& lhs, const ImVec2& rhs) { return ImVec2(lhs.x >= rhs.x ? lhs.x : rhs.x, lhs.y >= rhs.y ? lhs.y : rhs.y); } static inline int ImClamp(int v, int mn, int mx) { return (v < mn) ? mn : (v > mx) ? mx : v; } static inline float ImClamp(float v, float mn, float mx) { return (v < mn) ? mn : (v > mx) ? mx : v; } static inline ImVec2 ImClamp(const ImVec2& f, const ImVec2& mn, ImVec2 mx) { return ImVec2(ImClamp(f.x,mn.x,mx.x), ImClamp(f.y,mn.y,mx.y)); } From 0cabd810712938178e8c90baf45ac0b00bb44e63 Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 8 Jan 2018 23:59:51 +0100 Subject: [PATCH 419/823] Internals: Rect: Added ClipWillFull helper + comments on variations. --- imgui_internal.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/imgui_internal.h b/imgui_internal.h index 4e7054870731..4958b5ae3664 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -285,7 +285,8 @@ struct IMGUI_API ImRect void Expand(const float amount) { Min.x -= amount; Min.y -= amount; Max.x += amount; Max.y += amount; } void Expand(const ImVec2& amount) { Min.x -= amount.x; Min.y -= amount.y; Max.x += amount.x; Max.y += amount.y; } void Translate(const ImVec2& v) { Min.x += v.x; Min.y += v.y; Max.x += v.x; Max.y += v.y; } - void ClipWith(const ImRect& r) { if (Min.x < r.Min.x) Min.x = r.Min.x; if (Min.y < r.Min.y) Min.y = r.Min.y; if (Max.x > r.Max.x) Max.x = r.Max.x; if (Max.y > r.Max.y) Max.y = r.Max.y; } + void ClipWith(const ImRect& r) { Min = ImMax(Min, r.Min); Max = ImMin(Max, r.Max); } // Simple version, may lead to an inverted rectangle, which is fine for Contains/Overlaps test but not for display. + void ClipWithFull(const ImRect& r) { Min = ImClamp(Min, r.Min, r.Max); Max = ImClamp(Max, r.Min, r.Max); } // Full version, ensure both points are fully clipped. void Floor() { Min.x = (float)(int)Min.x; Min.y = (float)(int)Min.y; Max.x = (float)(int)Max.x; Max.y = (float)(int)Max.y; } void FixInverted() { if (Min.x > Max.x) ImSwap(Min.x, Max.x); if (Min.y > Max.y) ImSwap(Min.y, Max.y); } bool IsFinite() const { return Min.x != FLT_MAX; } From f610e25682a94d9d593e4691b03d48f7be7ceec1 Mon Sep 17 00:00:00 2001 From: omar Date: Wed, 10 Jan 2018 16:11:29 +0100 Subject: [PATCH 420/823] Internals: Using ImFloor().when appropriate. --- imgui.cpp | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 5faa456995c6..5dd329c3b553 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -4163,14 +4163,13 @@ static ImGuiWindow* CreateNewWindow(const char* name, ImVec2 size, ImGuiWindowFl { // Retrieve settings from .ini file // Use SetWindowPos() or SetNextWindowPos() with the appropriate condition flag to change the initial position of a window. - window->PosFloat = ImVec2(60, 60); - window->Pos = ImVec2((float)(int)window->PosFloat.x, (float)(int)window->PosFloat.y); + window->Pos = window->PosFloat = ImVec2(60, 60); if (ImGuiWindowSettings* settings = ImGui::FindWindowSettings(window->ID)) { SetWindowConditionAllowFlags(window, ImGuiCond_FirstUseEver, false); window->PosFloat = settings->Pos; - window->Pos = ImVec2((float)(int)window->PosFloat.x, (float)(int)window->PosFloat.y); + window->Pos = ImFloor(window->PosFloat); window->Collapsed = settings->Collapsed; if (ImLengthSqr(settings->Size) > 0.00001f) size = settings->Size; @@ -4494,7 +4493,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) // Popup first latch mouse position, will position itself when it appears next frame window->AutoPosLastDirection = ImGuiDir_None; if ((flags & ImGuiWindowFlags_Popup) != 0 && !window_pos_set_by_api) - window->PosFloat = g.CurrentPopupStack.back().OpenPopupPos; + window->Pos = window->PosFloat = g.CurrentPopupStack.back().OpenPopupPos; } // Collapse window by double-clicking on title bar @@ -4648,7 +4647,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) window->PosFloat = ImMin(window->PosFloat, g.IO.DisplaySize - padding); } } - window->Pos = ImVec2((float)(int)window->PosFloat.x, (float)(int)window->PosFloat.y); + window->Pos = ImFloor(window->PosFloat); // Default item width. Make it proportional to window size if window manually resizes if (window->Size.x > 0.0f && !(flags & ImGuiWindowFlags_Tooltip) && !(flags & ImGuiWindowFlags_AlwaysAutoResize)) @@ -4765,7 +4764,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) } if (pos_target.x != FLT_MAX) { - window->Pos = window->PosFloat = ImVec2((float)(int)pos_target.x, (float)(int)pos_target.y); + window->Pos = window->PosFloat = ImFloor(pos_target); MarkIniSettingsDirty(window); } @@ -5593,7 +5592,7 @@ static void SetWindowPos(ImGuiWindow* window, const ImVec2& pos, ImGuiCond cond) // Set const ImVec2 old_pos = window->Pos; window->PosFloat = pos; - window->Pos = ImVec2((float)(int)window->PosFloat.x, (float)(int)window->PosFloat.y); + window->Pos = ImFloor(pos); window->DC.CursorPos += (window->Pos - old_pos); // As we happen to move the window while it is being appended to (which is a bad idea - will smear) let's at least offset the cursor window->DC.CursorMaxPos += (window->Pos - old_pos); // And more importantly we need to adjust this so size calculation doesn't get affected. } From 6c583315e695a8ced6751a0ebb0780f238c1100b Mon Sep 17 00:00:00 2001 From: omar Date: Wed, 10 Jan 2018 18:56:51 +0100 Subject: [PATCH 421/823] Begin: Moving some code around for the benefits of the wip viewport branch. --- imgui.cpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 5dd329c3b553..7c1b9a17f2c8 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -4478,6 +4478,13 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) window->LastFrameActive = current_frame; window->IDStack.resize(1); + // Lock window rounding, border size and rounding so that altering the border sizes for children doesn't have side-effects. + window->WindowRounding = (flags & ImGuiWindowFlags_ChildWindow) ? style.ChildRounding : ((flags & ImGuiWindowFlags_Popup) && !(flags & ImGuiWindowFlags_Modal)) ? style.PopupRounding : style.WindowRounding; + window->WindowBorderSize = (flags & ImGuiWindowFlags_ChildWindow) ? style.ChildBorderSize : ((flags & ImGuiWindowFlags_Popup) && !(flags & ImGuiWindowFlags_Modal)) ? style.PopupBorderSize : style.WindowBorderSize; + window->WindowPadding = style.WindowPadding; + if ((flags & ImGuiWindowFlags_ChildWindow) && !(flags & (ImGuiWindowFlags_AlwaysUseWindowPadding | ImGuiWindowFlags_Popup)) && window->WindowBorderSize == 0.0f) + window->WindowPadding = ImVec2(0.0f, (flags & ImGuiWindowFlags_MenuBar) ? style.WindowPadding.y : 0.0f); + // Setup draw list and outer clipping rectangle window->DrawList->Clear(); window->DrawList->Flags = (g.Style.AntiAliasedLines ? ImDrawListFlags_AntiAliasedLines : 0) | (g.Style.AntiAliasedFill ? ImDrawListFlags_AntiAliasedFill : 0); @@ -4534,15 +4541,6 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) } } - // Lock window rounding, border size and rounding so that altering the border sizes for children doesn't have side-effects. - window->WindowRounding = (flags & ImGuiWindowFlags_ChildWindow) ? style.ChildRounding : ((flags & ImGuiWindowFlags_Popup) && !(flags & ImGuiWindowFlags_Modal)) ? style.PopupRounding : style.WindowRounding; - window->WindowBorderSize = (flags & ImGuiWindowFlags_ChildWindow) ? style.ChildBorderSize : ((flags & ImGuiWindowFlags_Popup) && !(flags & ImGuiWindowFlags_Modal)) ? style.PopupBorderSize : style.WindowBorderSize; - window->WindowPadding = style.WindowPadding; - if ((flags & ImGuiWindowFlags_ChildWindow) && !(flags & (ImGuiWindowFlags_AlwaysUseWindowPadding | ImGuiWindowFlags_Popup)) && window->WindowBorderSize == 0.0f) - window->WindowPadding = ImVec2(0.0f, (flags & ImGuiWindowFlags_MenuBar) ? style.WindowPadding.y : 0.0f); - const float window_rounding = window->WindowRounding; - const float window_border_size = window->WindowBorderSize; - // Calculate auto-fit size, handle automatic resize const ImVec2 size_auto_fit = CalcSizeAutoFit(window, window->SizeContents); ImVec2 size_full_modified(FLT_MAX, FLT_MAX); @@ -4676,6 +4674,8 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) window->DrawList->AddRectFilled(fullscreen_rect.Min, fullscreen_rect.Max, GetColorU32(ImGuiCol_ModalWindowDarkening, g.ModalWindowDarkeningRatio)); // Draw window + handle manual resize + const float window_rounding = window->WindowRounding; + const float window_border_size = window->WindowBorderSize; ImRect title_bar_rect = window->TitleBarRect(); if (window->Collapsed) { From 03f5cd6ca128090f71df7959e0f92c6b40076184 Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 9 Jan 2018 00:05:04 +0100 Subject: [PATCH 422/823] Nav: Fixed RenderNavHighlight() clipping, essentially revert 6ea90af6b76f2b9f7b86c12813bafd6f0408bdc0. (#787) --- imgui.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/imgui.cpp b/imgui.cpp index bd4ffb00a569..6b86867019ca 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -4147,7 +4147,6 @@ void ImGui::RenderNavHighlight(const ImRect& bb, ImGuiID id, ImGuiNavHighlightFl ImGuiWindow* window = ImGui::GetCurrentWindow(); ImRect display_rect = bb; - display_rect.ClipWith(window->ClipRect); if (flags & ImGuiNavHighlightFlags_TypeDefault) { const float THICKNESS = 2.0f; From 483f9b0d07f3688911bd3e0d0500771103e44624 Mon Sep 17 00:00:00 2001 From: omar Date: Wed, 10 Jan 2018 22:55:29 +0100 Subject: [PATCH 423/823] Internals: Begin: Moved DrawList setup code below, the viewport system will need to push the outer clipping rectangle as late as possible. --- imgui.cpp | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 7c1b9a17f2c8..13a12a55284c 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -4485,16 +4485,6 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) if ((flags & ImGuiWindowFlags_ChildWindow) && !(flags & (ImGuiWindowFlags_AlwaysUseWindowPadding | ImGuiWindowFlags_Popup)) && window->WindowBorderSize == 0.0f) window->WindowPadding = ImVec2(0.0f, (flags & ImGuiWindowFlags_MenuBar) ? style.WindowPadding.y : 0.0f); - // Setup draw list and outer clipping rectangle - window->DrawList->Clear(); - window->DrawList->Flags = (g.Style.AntiAliasedLines ? ImDrawListFlags_AntiAliasedLines : 0) | (g.Style.AntiAliasedFill ? ImDrawListFlags_AntiAliasedFill : 0); - window->DrawList->PushTextureID(g.Font->ContainerAtlas->TexID); - ImRect fullscreen_rect(GetVisibleRect()); - if ((flags & ImGuiWindowFlags_ChildWindow) && !(flags & ImGuiWindowFlags_Popup)) - PushClipRect(parent_window->ClipRect.Min, parent_window->ClipRect.Max, true); - else - PushClipRect(fullscreen_rect.Min, fullscreen_rect.Max, true); - if (window_just_activated_by_user) { // Popup first latch mouse position, will position itself when it appears next frame @@ -4669,6 +4659,18 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) if (!(flags & (ImGuiWindowFlags_ChildWindow | ImGuiWindowFlags_Tooltip)) || (flags & ImGuiWindowFlags_Popup)) want_focus = true; + // DRAWING + + // Setup draw list and outer clipping rectangle + window->DrawList->Clear(); + window->DrawList->Flags = (g.Style.AntiAliasedLines ? ImDrawListFlags_AntiAliasedLines : 0) | (g.Style.AntiAliasedFill ? ImDrawListFlags_AntiAliasedFill : 0); + window->DrawList->PushTextureID(g.Font->ContainerAtlas->TexID); + ImRect fullscreen_rect(GetVisibleRect()); + if ((flags & ImGuiWindowFlags_ChildWindow) && !(flags & ImGuiWindowFlags_Popup)) + PushClipRect(parent_window->ClipRect.Min, parent_window->ClipRect.Max, true); + else + PushClipRect(fullscreen_rect.Min, fullscreen_rect.Max, true); + // Draw modal window background (darkens what is behind them) if ((flags & ImGuiWindowFlags_Modal) != 0 && window == GetFrontMostModalRootWindow()) window->DrawList->AddRectFilled(fullscreen_rect.Min, fullscreen_rect.Max, GetColorU32(ImGuiCol_ModalWindowDarkening, g.ModalWindowDarkeningRatio)); From 1eee10778be403a9942727e89eaf22c5c0a7b0c5 Mon Sep 17 00:00:00 2001 From: omar Date: Wed, 10 Jan 2018 23:06:51 +0100 Subject: [PATCH 424/823] Internals: Begin: Refactor some code into an UpdateManualResize() function. --- imgui.cpp | 171 +++++++++++++++++++++++++++++------------------------- 1 file changed, 91 insertions(+), 80 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 13a12a55284c..cf5cfb77c64a 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -675,6 +675,7 @@ static bool DataTypeApplyOpFromText(const char* buf, const char* ini namespace ImGui { +static void UpdateManualResize(ImGuiWindow* window, const ImVec2& size_auto_fit, int* border_held, ImU32 resize_grip_col[4]); static void FocusFrontMostActiveWindow(ImGuiWindow* ignore_window); } @@ -4338,6 +4339,93 @@ static ImRect GetBorderRect(ImGuiWindow* window, int border_n, float perp_paddin return ImRect(); } +// Handle resize for: Resize Grips, Borders, Gamepad +static void ImGui::UpdateManualResize(ImGuiWindow* window, const ImVec2& size_auto_fit, int* border_held, ImU32 resize_grip_col[4]) +{ + ImGuiContext& g = *GImGui; + ImGuiWindowFlags flags = window->Flags; + if ((flags & ImGuiWindowFlags_NoResize) || (flags & ImGuiWindowFlags_AlwaysAutoResize) || window->AutoFitFramesX > 0 || window->AutoFitFramesY > 0) + return; + + const int resize_grip_count = (flags & ImGuiWindowFlags_ResizeFromAnySide) ? 2 : 1; // 4 + const int resize_border_count = (flags & ImGuiWindowFlags_ResizeFromAnySide) ? 4 : 0; + const float grip_draw_size = (float)(int)ImMax(g.FontSize * 1.35f, window->WindowRounding + 1.0f + g.FontSize * 0.2f); + const float grip_hover_size = (float)(int)(grip_draw_size * 0.75f); + + ImVec2 pos_target(FLT_MAX, FLT_MAX); + ImVec2 size_target(FLT_MAX, FLT_MAX); + + // Manual resize grips + PushID("#RESIZE"); + for (int resize_grip_n = 0; resize_grip_n < resize_grip_count; resize_grip_n++) + { + const ImGuiResizeGripDef& grip = resize_grip_def[resize_grip_n]; + const ImVec2 corner = ImLerp(window->Pos, window->Pos + window->Size, grip.CornerPos); + + // Using the FlattenChilds button flag we make the resize button accessible even if we are hovering over a child window + ImRect resize_rect(corner, corner + grip.InnerDir * grip_hover_size); + resize_rect.FixInverted(); + bool hovered, held; + ButtonBehavior(resize_rect, window->GetID((void*)(intptr_t)resize_grip_n), &hovered, &held, ImGuiButtonFlags_FlattenChildren); + if (hovered || held) + g.MouseCursor = (resize_grip_n & 1) ? ImGuiMouseCursor_ResizeNESW : ImGuiMouseCursor_ResizeNWSE; + + if (g.HoveredWindow == window && held && g.IO.MouseDoubleClicked[0] && resize_grip_n == 0) + { + // Manual auto-fit when double-clicking + size_target = CalcSizeAfterConstraint(window, size_auto_fit); + ClearActiveID(); + } + else if (held) + { + // Resize from any of the four corners + // We don't use an incremental MouseDelta but rather compute an absolute target size based on mouse position + ImVec2 corner_target = g.IO.MousePos - g.ActiveIdClickOffset + resize_rect.GetSize() * grip.CornerPos; // Corner of the window corresponding to our corner grip + CalcResizePosSizeFromAnyCorner(window, corner_target, grip.CornerPos, &pos_target, &size_target); + } + if (resize_grip_n == 0 || held || hovered) + resize_grip_col[resize_grip_n] = GetColorU32(held ? ImGuiCol_ResizeGripActive : hovered ? ImGuiCol_ResizeGripHovered : ImGuiCol_ResizeGrip); + } + for (int border_n = 0; border_n < resize_border_count; border_n++) + { + const float BORDER_SIZE = 5.0f; // FIXME: Only works _inside_ window because of HoveredWindow check. + const float BORDER_APPEAR_TIMER = 0.05f; // Reduce visual noise + bool hovered, held; + ImRect border_rect = GetBorderRect(window, border_n, grip_hover_size, BORDER_SIZE); + ButtonBehavior(border_rect, window->GetID((void*)(intptr_t)(border_n + 4)), &hovered, &held, ImGuiButtonFlags_FlattenChildren); + if ((hovered && g.HoveredIdTimer > BORDER_APPEAR_TIMER) || held) + { + g.MouseCursor = (border_n & 1) ? ImGuiMouseCursor_ResizeEW : ImGuiMouseCursor_ResizeNS; + if (held) *border_held = border_n; + } + if (held) + { + ImVec2 border_target = window->Pos; + ImVec2 border_posn; + if (border_n == 0) { border_posn = ImVec2(0, 0); border_target.y = (g.IO.MousePos.y - g.ActiveIdClickOffset.y); } + if (border_n == 1) { border_posn = ImVec2(1, 0); border_target.x = (g.IO.MousePos.x - g.ActiveIdClickOffset.x + BORDER_SIZE); } + if (border_n == 2) { border_posn = ImVec2(0, 1); border_target.y = (g.IO.MousePos.y - g.ActiveIdClickOffset.y + BORDER_SIZE); } + if (border_n == 3) { border_posn = ImVec2(0, 0); border_target.x = (g.IO.MousePos.x - g.ActiveIdClickOffset.x); } + CalcResizePosSizeFromAnyCorner(window, border_target, border_posn, &pos_target, &size_target); + } + } + PopID(); + + // Apply back modified position/size to window + if (size_target.x != FLT_MAX) + { + window->SizeFull = size_target; + MarkIniSettingsDirty(window); + } + if (pos_target.x != FLT_MAX) + { + window->Pos = window->PosFloat = ImFloor(pos_target); + MarkIniSettingsDirty(window); + } + + window->Size = window->SizeFull; +} + // Push a new ImGui window to add widgets to. // - A default window called "Debug" is automatically stacked at the beginning of every frame so you can use widgets without explicitly calling a Begin/End pair. // - Begin/End can be called multiple times during the frame with the same window name to append content. @@ -4693,86 +4781,9 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) int border_held = -1; ImU32 resize_grip_col[4] = { 0 }; const int resize_grip_count = (flags & ImGuiWindowFlags_ResizeFromAnySide) ? 2 : 1; // 4 - const int resize_border_count = (flags & ImGuiWindowFlags_ResizeFromAnySide) ? 4 : 0; - - const float grip_draw_size = (float)(int)ImMax(g.FontSize * 1.35f, window_rounding + 1.0f + g.FontSize * 0.2f); - const float grip_hover_size = (float)(int)(grip_draw_size * 0.75f); - if (!(flags & ImGuiWindowFlags_AlwaysAutoResize) && window->AutoFitFramesX <= 0 && window->AutoFitFramesY <= 0 && !(flags & ImGuiWindowFlags_NoResize)) - { - ImVec2 pos_target(FLT_MAX, FLT_MAX); - ImVec2 size_target(FLT_MAX, FLT_MAX); - - // Manual resize grips - PushID("#RESIZE"); - for (int resize_grip_n = 0; resize_grip_n < resize_grip_count; resize_grip_n++) - { - const ImGuiResizeGripDef& grip = resize_grip_def[resize_grip_n]; - const ImVec2 corner = ImLerp(window->Pos, window->Pos + window->Size, grip.CornerPos); - - // Using the FlattenChilds button flag we make the resize button accessible even if we are hovering over a child window - ImRect resize_rect(corner, corner + grip.InnerDir * grip_hover_size); - resize_rect.FixInverted(); - bool hovered, held; - ButtonBehavior(resize_rect, window->GetID((void*)(intptr_t)resize_grip_n), &hovered, &held, ImGuiButtonFlags_FlattenChildren); - if (hovered || held) - g.MouseCursor = (resize_grip_n & 1) ? ImGuiMouseCursor_ResizeNESW : ImGuiMouseCursor_ResizeNWSE; - - if (g.HoveredWindow == window && held && g.IO.MouseDoubleClicked[0] && resize_grip_n == 0) - { - // Manual auto-fit when double-clicking - size_target = CalcSizeAfterConstraint(window, size_auto_fit); - ClearActiveID(); - } - else if (held) - { - // Resize from any of the four corners - // We don't use an incremental MouseDelta but rather compute an absolute target size based on mouse position - ImVec2 corner_target = g.IO.MousePos - g.ActiveIdClickOffset + resize_rect.GetSize() * grip.CornerPos; // Corner of the window corresponding to our corner grip - CalcResizePosSizeFromAnyCorner(window, corner_target, grip.CornerPos, &pos_target, &size_target); - } - if (resize_grip_n == 0 || held || hovered) - resize_grip_col[resize_grip_n] = GetColorU32(held ? ImGuiCol_ResizeGripActive : hovered ? ImGuiCol_ResizeGripHovered : ImGuiCol_ResizeGrip); - } - for (int border_n = 0; border_n < resize_border_count; border_n++) - { - const float BORDER_SIZE = 5.0f; // FIXME: Only works _inside_ window because of HoveredWindow check. - const float BORDER_APPEAR_TIMER = 0.05f; // Reduce visual noise - bool hovered, held; - ImRect border_rect = GetBorderRect(window, border_n, grip_hover_size, BORDER_SIZE); - ButtonBehavior(border_rect, window->GetID((void*)(intptr_t)(border_n+4)), &hovered, &held, ImGuiButtonFlags_FlattenChildren); - if ((hovered && g.HoveredIdTimer > BORDER_APPEAR_TIMER) || held) - { - g.MouseCursor = (border_n & 1) ? ImGuiMouseCursor_ResizeEW : ImGuiMouseCursor_ResizeNS; - if (held) border_held = border_n; - } - if (held) - { - ImVec2 border_target = window->Pos; - ImVec2 border_posn; - if (border_n == 0) { border_posn = ImVec2(0, 0); border_target.y = (g.IO.MousePos.y - g.ActiveIdClickOffset.y); } - if (border_n == 1) { border_posn = ImVec2(1, 0); border_target.x = (g.IO.MousePos.x - g.ActiveIdClickOffset.x + BORDER_SIZE); } - if (border_n == 2) { border_posn = ImVec2(0, 1); border_target.y = (g.IO.MousePos.y - g.ActiveIdClickOffset.y + BORDER_SIZE); } - if (border_n == 3) { border_posn = ImVec2(0, 0); border_target.x = (g.IO.MousePos.x - g.ActiveIdClickOffset.x); } - CalcResizePosSizeFromAnyCorner(window, border_target, border_posn, &pos_target, &size_target); - } - } - PopID(); - - // Apply back modified position/size to window - if (size_target.x != FLT_MAX) - { - window->SizeFull = size_target; - MarkIniSettingsDirty(window); - } - if (pos_target.x != FLT_MAX) - { - window->Pos = window->PosFloat = ImFloor(pos_target); - MarkIniSettingsDirty(window); - } - - window->Size = window->SizeFull; - title_bar_rect = window->TitleBarRect(); - } + const float grip_draw_size = (float)(int)ImMax(g.FontSize * 1.35f, window->WindowRounding + 1.0f + g.FontSize * 0.2f); + UpdateManualResize(window, size_auto_fit, &border_held, &resize_grip_col[0]); + title_bar_rect = window->TitleBarRect(); // Window background, Default Alpha ImU32 bg_col = GetColorU32(GetWindowBgColorIdxFromFlags(flags)); From a63fbbca8b4340de08afa3360fb768edb0e4ef2d Mon Sep 17 00:00:00 2001 From: omar Date: Thu, 11 Jan 2018 13:49:32 +0100 Subject: [PATCH 425/823] Added ImGuiHoveredFlags_AnyWindow, ImGuiFocusedFlags_AnyWindow. Obsoleted IsAnyWindowHovered()/IsAnyWindowFocused() in favor of IsWindowHovered(ImGuiHoveredFlags_AnyWindow)/IsWindowFocused(ImGuiFocusedFlags_AnyWindow). Added to demo. (#1382) --- imgui.cpp | 66 ++++++++++++++++++++++++++------------------------ imgui.h | 18 ++++++++------ imgui_demo.cpp | 16 +++++++----- 3 files changed, 54 insertions(+), 46 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index cf5cfb77c64a..0a23f73c7a6c 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -213,6 +213,8 @@ Here is a change-log of API breaking changes, if you are using one of the functions listed, expect to have to fix some code. Also read releases logs https://github.com/ocornut/imgui/releases for more details. + - 2018/01/11 (1.54) - obsoleted IsAnyWindowHovered() in favor of IsWindowHovered(ImGuiHoveredFlags_AnyWindow). Kept redirection function (will obsolete). + - 2018/01/11 (1.54) - obsoleted IsAnyWindowFocused() in favor of IsWindowFocused(ImGuiFocusedFlags_AnyWindow). Kept redirection function (will obsolete). - 2018/01/03 (1.54) - renamed ImGuiSizeConstraintCallback to ImGuiSizeCallback, ImGuiSizeConstraintCallbackData to ImGuiSizeCallbackData. - 2017/12/29 (1.54) - removed CalcItemRectClosestPoint() which was weird and not really used by anyone except demo code. If you need it it's easy to replicate on your side. - 2017/12/24 (1.53) - renamed the emblematic ShowTestWindow() function to ShowDemoWindow(). Kept redirection function (will obsolete). @@ -3417,18 +3419,6 @@ bool ImGui::IsMouseHoveringRect(const ImVec2& r_min, const ImVec2& r_max, bool c return rect_for_touch.Contains(g.IO.MousePos); } -bool ImGui::IsAnyWindowHovered() -{ - ImGuiContext& g = *GImGui; - return g.HoveredWindow != NULL; -} - -bool ImGui::IsAnyWindowFocused() -{ - ImGuiContext& g = *GImGui; - return g.NavWindow != NULL; -} - static bool IsKeyPressedMap(ImGuiKey key, bool repeat) { const int key_index = GImGui->IO.KeyMap[key]; @@ -3959,7 +3949,7 @@ bool ImGui::BeginPopupContextVoid(const char* str_id, int mouse_button) if (!str_id) str_id = "void_context"; ImGuiID id = GImGui->CurrentWindow->GetID(str_id); - if (IsMouseReleased(mouse_button) && !IsAnyWindowHovered()) + if (IsMouseReleased(mouse_button) && !IsWindowHovered(ImGuiHoveredFlags_AnyWindow)) OpenPopupEx(id); return BeginPopupEx(id, ImGuiWindowFlags_AlwaysAutoResize|ImGuiWindowFlags_NoTitleBar|ImGuiWindowFlags_NoSavedSettings); } @@ -5522,24 +5512,33 @@ bool ImGui::IsWindowHovered(ImGuiHoveredFlags flags) { IM_ASSERT((flags & ImGuiHoveredFlags_AllowWhenOverlapped) == 0); // Flags not supported by this function ImGuiContext& g = *GImGui; - switch (flags & (ImGuiHoveredFlags_RootWindow | ImGuiHoveredFlags_ChildWindows)) + + if (flags & ImGuiHoveredFlags_AnyWindow) { - case ImGuiHoveredFlags_RootWindow | ImGuiHoveredFlags_ChildWindows: - if (g.HoveredRootWindow != g.CurrentWindow->RootWindow) - return false; - break; - case ImGuiHoveredFlags_RootWindow: - if (g.HoveredWindow != g.CurrentWindow->RootWindow) - return false; - break; - case ImGuiHoveredFlags_ChildWindows: - if (g.HoveredWindow == NULL || !IsWindowChildOf(g.HoveredWindow, g.CurrentWindow)) - return false; - break; - default: - if (g.HoveredWindow != g.CurrentWindow) + if (g.HoveredWindow == NULL) return false; - break; + } + else + { + switch (flags & (ImGuiHoveredFlags_RootWindow | ImGuiHoveredFlags_ChildWindows)) + { + case ImGuiHoveredFlags_RootWindow | ImGuiHoveredFlags_ChildWindows: + if (g.HoveredRootWindow != g.CurrentWindow->RootWindow) + return false; + break; + case ImGuiHoveredFlags_RootWindow: + if (g.HoveredWindow != g.CurrentWindow->RootWindow) + return false; + break; + case ImGuiHoveredFlags_ChildWindows: + if (g.HoveredWindow == NULL || !IsWindowChildOf(g.HoveredWindow, g.CurrentWindow)) + return false; + break; + default: + if (g.HoveredWindow != g.CurrentWindow) + return false; + break; + } } if (!IsWindowContentHoverable(g.HoveredRootWindow, flags)) @@ -5555,16 +5554,19 @@ bool ImGui::IsWindowFocused(ImGuiFocusedFlags flags) ImGuiContext& g = *GImGui; IM_ASSERT(g.CurrentWindow); // Not inside a Begin()/End() + if (flags & ImGuiFocusedFlags_AnyWindow) + return g.NavWindow != NULL; + switch (flags & (ImGuiFocusedFlags_RootWindow | ImGuiFocusedFlags_ChildWindows)) { case ImGuiFocusedFlags_RootWindow | ImGuiFocusedFlags_ChildWindows: - return g.NavWindow && g.CurrentWindow->RootWindow == g.NavWindow->RootWindow; + return g.NavWindow && g.NavWindow->RootWindow == g.CurrentWindow->RootWindow; case ImGuiFocusedFlags_RootWindow: - return g.CurrentWindow->RootWindow == g.NavWindow; + return g.NavWindow == g.CurrentWindow->RootWindow; case ImGuiFocusedFlags_ChildWindows: return g.NavWindow && IsWindowChildOf(g.NavWindow, g.CurrentWindow); default: - return g.CurrentWindow == g.NavWindow; + return g.NavWindow == g.CurrentWindow; } } diff --git a/imgui.h b/imgui.h index 02832422e969..59ce6663c0b9 100644 --- a/imgui.h +++ b/imgui.h @@ -463,8 +463,6 @@ namespace ImGui IMGUI_API void SetItemAllowOverlap(); // allow last item to be overlapped by a subsequent item. sometimes useful with invisible buttons, selectables, etc. to catch unused area. IMGUI_API bool IsWindowFocused(ImGuiFocusedFlags flags = 0); // is current window focused? or its root/child, depending on flags. see flags for options. IMGUI_API bool IsWindowHovered(ImGuiHoveredFlags flags = 0); // is current window hovered (and typically: not blocked by a popup/modal)? see flags for options. - IMGUI_API bool IsAnyWindowFocused(); - IMGUI_API bool IsAnyWindowHovered(); // is mouse hovering any visible window IMGUI_API bool IsRectVisible(const ImVec2& size); // test if rectangle (of given size, starting from cursor position) is visible / not clipped. IMGUI_API bool IsRectVisible(const ImVec2& rect_min, const ImVec2& rect_max); // test if rectangle (in screen space) is visible / not clipped. to perform coarse clipping on user's side. IMGUI_API float GetTime(); @@ -623,6 +621,7 @@ enum ImGuiFocusedFlags_ { ImGuiFocusedFlags_ChildWindows = 1 << 0, // IsWindowFocused(): Return true if any children of the window is focused ImGuiFocusedFlags_RootWindow = 1 << 1, // IsWindowFocused(): Test from root window (top most parent of the current hierarchy) + ImGuiFocusedFlags_AnyWindow = 1 << 2, // IsWindowFocused(): Return true if any window is focused ImGuiFocusedFlags_RootAndChildWindows = ImGuiFocusedFlags_RootWindow | ImGuiFocusedFlags_ChildWindows }; @@ -632,10 +631,11 @@ enum ImGuiHoveredFlags_ ImGuiHoveredFlags_Default = 0, // Return true if directly over the item/window, not obstructed by another window, not obstructed by an active popup or modal blocking inputs under them. ImGuiHoveredFlags_ChildWindows = 1 << 0, // IsWindowHovered() only: Return true if any children of the window is hovered ImGuiHoveredFlags_RootWindow = 1 << 1, // IsWindowHovered() only: Test from root window (top most parent of the current hierarchy) - ImGuiHoveredFlags_AllowWhenBlockedByPopup = 1 << 2, // Return true even if a popup window is normally blocking access to this item/window - //ImGuiHoveredFlags_AllowWhenBlockedByModal = 1 << 3, // Return true even if a modal popup window is normally blocking access to this item/window. FIXME-TODO: Unavailable yet. - ImGuiHoveredFlags_AllowWhenBlockedByActiveItem = 1 << 4, // Return true even if an active item is blocking access to this item/window. Useful for Drag and Drop patterns. - ImGuiHoveredFlags_AllowWhenOverlapped = 1 << 5, // Return true even if the position is overlapped by another window + ImGuiHoveredFlags_AnyWindow = 1 << 2, // IsWindowHovered() only: Return true if any window is hovered + ImGuiHoveredFlags_AllowWhenBlockedByPopup = 1 << 3, // Return true even if a popup window is normally blocking access to this item/window + //ImGuiHoveredFlags_AllowWhenBlockedByModal = 1 << 4, // Return true even if a modal popup window is normally blocking access to this item/window. FIXME-TODO: Unavailable yet. + ImGuiHoveredFlags_AllowWhenBlockedByActiveItem = 1 << 5, // Return true even if an active item is blocking access to this item/window. Useful for Drag and Drop patterns. + ImGuiHoveredFlags_AllowWhenOverlapped = 1 << 6, // Return true even if the position is overlapped by another window ImGuiHoveredFlags_RectOnly = ImGuiHoveredFlags_AllowWhenBlockedByPopup | ImGuiHoveredFlags_AllowWhenBlockedByActiveItem | ImGuiHoveredFlags_AllowWhenOverlapped, ImGuiHoveredFlags_RootAndChildWindows = ImGuiHoveredFlags_RootWindow | ImGuiHoveredFlags_ChildWindows }; @@ -988,6 +988,8 @@ struct ImGuiIO namespace ImGui { // OBSOLETED in 1.54 (from Dec 2017) + static bool IsAnyWindowFocused() { return IsWindowFocused(ImGuiFocusedFlags_AnyWindow); } + static bool IsAnyWindowHovered() { return IsWindowHovered(ImGuiHoveredFlags_AnyWindow); } static inline ImVec2 CalcItemRectClosestPoint(const ImVec2& pos, bool on_edge = false, float outward = 0.f) { (void)on_edge; (void)outward; IM_ASSERT(0); return pos; } // OBSOLETED in 1.53 (between Oct 2017 and Dec 2017) static inline void ShowTestWindow() { return ShowDemoWindow(); } @@ -996,13 +998,13 @@ namespace ImGui static inline void SetNextWindowContentWidth(float w) { SetNextWindowContentSize(ImVec2(w, 0.0f)); } // OBSOLETED in 1.52 (between Aug 2017 and Oct 2017) bool Begin(const char* name, bool* p_open, const ImVec2& size_on_first_use, float bg_alpha_override = -1.0f, ImGuiWindowFlags flags = 0); // Use SetNextWindowSize() instead if you want to set a window size. - static inline bool IsRootWindowOrAnyChildHovered() { return IsItemHovered(ImGuiHoveredFlags_RootAndChildWindows); } // Use flags directly! + static inline bool IsRootWindowOrAnyChildHovered() { return IsItemHovered(ImGuiHoveredFlags_RootAndChildWindows); } static inline void AlignFirstTextHeightToWidgets() { AlignTextToFramePadding(); } static inline void SetNextWindowPosCenter(ImGuiCond c=0) { ImGuiIO& io = GetIO(); SetNextWindowPos(ImVec2(io.DisplaySize.x * 0.5f, io.DisplaySize.y * 0.5f), c, ImVec2(0.5f, 0.5f)); } // OBSOLETED in 1.51 (between Jun 2017 and Aug 2017) static inline bool IsItemHoveredRect() { return IsItemHovered(ImGuiHoveredFlags_RectOnly); } static inline bool IsPosHoveringAnyWindow(const ImVec2&) { IM_ASSERT(0); return false; } // This was misleading and partly broken. You probably want to use the ImGui::GetIO().WantCaptureMouse flag instead. - static inline bool IsMouseHoveringAnyWindow() { return IsAnyWindowHovered(); } + static inline bool IsMouseHoveringAnyWindow() { return IsWindowHovered(ImGuiHoveredFlags_AnyWindow); } static inline bool IsMouseHoveringWindow() { return IsWindowHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup | ImGuiHoveredFlags_AllowWhenBlockedByActiveItem); } // OBSOLETED IN 1.49 (between Apr 2016 and May 2016) static inline bool CollapsingHeader(const char* label, const char* str_id, bool framed = true, bool default_open = false) { (void)str_id; (void)framed; ImGuiTreeNodeFlags default_open_flags = 1 << 5; return CollapsingHeader(label, (default_open ? default_open_flags : 0)); } diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 76a8fa5515ca..11dc87c6b62c 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -1871,11 +1871,13 @@ void ImGui::ShowDemoWindow(bool* p_open) "IsWindowFocused() = %d\n" "IsWindowFocused(_ChildWindows) = %d\n" "IsWindowFocused(_ChildWindows|_RootWindow) = %d\n" - "IsWindowFocused(_RootWindow) = %d\n", + "IsWindowFocused(_RootWindow) = %d\n" + "IsWindowFocused(_AnyWindow) = %d\n", ImGui::IsWindowFocused(), - ImGui::IsWindowFocused(ImGuiHoveredFlags_ChildWindows), - ImGui::IsWindowFocused(ImGuiHoveredFlags_ChildWindows | ImGuiHoveredFlags_RootWindow), - ImGui::IsWindowFocused(ImGuiHoveredFlags_RootWindow)); + ImGui::IsWindowFocused(ImGuiFocusedFlags_ChildWindows), + ImGui::IsWindowFocused(ImGuiFocusedFlags_ChildWindows | ImGuiFocusedFlags_RootWindow), + ImGui::IsWindowFocused(ImGuiFocusedFlags_RootWindow), + ImGui::IsWindowFocused(ImGuiFocusedFlags_AnyWindow)); // Testing IsWindowHovered() function with its various flags (note that the flags can be combined) ImGui::BulletText( @@ -1884,13 +1886,15 @@ void ImGui::ShowDemoWindow(bool* p_open) "IsWindowHovered(_AllowWhenBlockedByActiveItem) = %d\n" "IsWindowHovered(_ChildWindows) = %d\n" "IsWindowHovered(_ChildWindows|_RootWindow) = %d\n" - "IsWindowHovered(_RootWindow) = %d\n", + "IsWindowHovered(_RootWindow) = %d\n" + "IsWindowHovered(_AnyWindow) = %d\n", ImGui::IsWindowHovered(), ImGui::IsWindowHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup), ImGui::IsWindowHovered(ImGuiHoveredFlags_AllowWhenBlockedByActiveItem), ImGui::IsWindowHovered(ImGuiHoveredFlags_ChildWindows), ImGui::IsWindowHovered(ImGuiHoveredFlags_ChildWindows | ImGuiHoveredFlags_RootWindow), - ImGui::IsWindowHovered(ImGuiHoveredFlags_RootWindow)); + ImGui::IsWindowHovered(ImGuiHoveredFlags_RootWindow), + ImGui::IsWindowHovered(ImGuiHoveredFlags_AnyWindow)); // Testing IsItemHovered() function (because BulletText is an item itself and that would affect the output of IsItemHovered, we pass all lines in a single items to shorten the code) ImGui::Button("ITEM"); From 398a4e1865db8225f7e1367dba17223ca57e1291 Mon Sep 17 00:00:00 2001 From: omar Date: Thu, 11 Jan 2018 13:58:25 +0100 Subject: [PATCH 426/823] Made obsolete IsAnyWindowHovered()/IsAnyWindowFocused() static inline. static only tends to trigger warnings. (#1382) --- imgui.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/imgui.h b/imgui.h index 59ce6663c0b9..6742540822b3 100644 --- a/imgui.h +++ b/imgui.h @@ -988,8 +988,8 @@ struct ImGuiIO namespace ImGui { // OBSOLETED in 1.54 (from Dec 2017) - static bool IsAnyWindowFocused() { return IsWindowFocused(ImGuiFocusedFlags_AnyWindow); } - static bool IsAnyWindowHovered() { return IsWindowHovered(ImGuiHoveredFlags_AnyWindow); } + static inline bool IsAnyWindowFocused() { return IsWindowFocused(ImGuiFocusedFlags_AnyWindow); } + static inline bool IsAnyWindowHovered() { return IsWindowHovered(ImGuiHoveredFlags_AnyWindow); } static inline ImVec2 CalcItemRectClosestPoint(const ImVec2& pos, bool on_edge = false, float outward = 0.f) { (void)on_edge; (void)outward; IM_ASSERT(0); return pos; } // OBSOLETED in 1.53 (between Oct 2017 and Dec 2017) static inline void ShowTestWindow() { return ShowDemoWindow(); } From 12aa3cb09ed83aa478a0bfa6afbbb8b0c003bbf6 Mon Sep 17 00:00:00 2001 From: omar Date: Thu, 11 Jan 2018 15:22:33 +0100 Subject: [PATCH 427/823] Demo: Tweaks format. --- imgui_demo.cpp | 44 +++++++++++++++++++++++++------------------- 1 file changed, 25 insertions(+), 19 deletions(-) diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 11dc87c6b62c..1e1421eb15fd 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -1061,33 +1061,39 @@ void ImGui::ShowDemoWindow(bool* p_open) goto_line |= ImGui::InputInt("##Line", &line, 0, 0, ImGuiInputTextFlags_EnterReturnsTrue); ImGui::PopItemWidth(); - ImGui::BeginChild("Sub1", ImVec2(ImGui::GetWindowContentRegionWidth() * 0.5f,300), false, ImGuiWindowFlags_HorizontalScrollbar | (disable_mouse_wheel ? ImGuiWindowFlags_NoScrollWithMouse : 0)); - for (int i = 0; i < 100; i++) + // Child 1: no border, enable horizontal scrollbar { - ImGui::Text("%04d: scrollable region", i); - if (goto_line && line == i) + ImGui::BeginChild("Child1", ImVec2(ImGui::GetWindowContentRegionWidth() * 0.5f, 300), false, ImGuiWindowFlags_HorizontalScrollbar | (disable_mouse_wheel ? ImGuiWindowFlags_NoScrollWithMouse : 0)); + for (int i = 0; i < 100; i++) + { + ImGui::Text("%04d: scrollable region", i); + if (goto_line && line == i) + ImGui::SetScrollHere(); + } + if (goto_line && line >= 100) ImGui::SetScrollHere(); + ImGui::EndChild(); } - if (goto_line && line >= 100) - ImGui::SetScrollHere(); - ImGui::EndChild(); ImGui::SameLine(); - ImGui::PushStyleVar(ImGuiStyleVar_ChildRounding, 5.0f); - ImGui::BeginChild("Sub2", ImVec2(0,300), true, (disable_mouse_wheel ? ImGuiWindowFlags_NoScrollWithMouse : 0)); - ImGui::Text("With border"); - ImGui::Columns(2); - for (int i = 0; i < 100; i++) + // Child 2: rounded border { - if (i == 50) - ImGui::NextColumn(); - char buf[32]; - sprintf(buf, "%08x", i*5731); - ImGui::Button(buf, ImVec2(-1.0f, 0.0f)); + ImGui::PushStyleVar(ImGuiStyleVar_ChildRounding, 5.0f); + ImGui::BeginChild("Child2", ImVec2(0,300), true, (disable_mouse_wheel ? ImGuiWindowFlags_NoScrollWithMouse : 0)); + ImGui::Text("With border"); + ImGui::Columns(2); + for (int i = 0; i < 100; i++) + { + if (i == 50) + ImGui::NextColumn(); + char buf[32]; + sprintf(buf, "%08x", i*5731); + ImGui::Button(buf, ImVec2(-1.0f, 0.0f)); + } + ImGui::EndChild(); + ImGui::PopStyleVar(); } - ImGui::EndChild(); - ImGui::PopStyleVar(); ImGui::TreePop(); } From a8bbb0b7ddc13e71b075f02db069d7a66041abda Mon Sep 17 00:00:00 2001 From: omar Date: Thu, 11 Jan 2018 15:47:07 +0100 Subject: [PATCH 428/823] Demo: Using IM_COL32() instead of ImColor() in ImDrawList centric contexts. --- imgui_demo.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 1e1421eb15fd..9cebf88b3914 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -1401,8 +1401,8 @@ void ImGui::ShowDemoWindow(bool* p_open) ImVec4 clip_rect(pos.x, pos.y, pos.x+size.x, pos.y+size.y); ImGui::InvisibleButton("##dummy", size); if (ImGui::IsItemActive() && ImGui::IsMouseDragging()) { offset.x += ImGui::GetIO().MouseDelta.x; offset.y += ImGui::GetIO().MouseDelta.y; } - ImGui::GetWindowDrawList()->AddRectFilled(pos, ImVec2(pos.x+size.x,pos.y+size.y), ImColor(90,90,120,255)); - ImGui::GetWindowDrawList()->AddText(ImGui::GetFont(), ImGui::GetFontSize()*2.0f, ImVec2(pos.x+offset.x,pos.y+offset.y), ImColor(255,255,255,255), "Line 1 hello\nLine 2 clip me!", NULL, 0.0f, &clip_rect); + ImGui::GetWindowDrawList()->AddRectFilled(pos, ImVec2(pos.x+size.x,pos.y+size.y), IM_COL32(90,90,120,255)); + ImGui::GetWindowDrawList()->AddText(ImGui::GetFont(), ImGui::GetFontSize()*2.0f, ImVec2(pos.x+offset.x,pos.y+offset.y), IM_COL32(255,255,255,255), "Line 1 hello\nLine 2 clip me!", NULL, 0.0f, &clip_rect); ImGui::TreePop(); } } @@ -2490,7 +2490,7 @@ static void ShowExampleAppCustomRendering(bool* p_open) draw_list->AddRectFilled(ImVec2(x, y), ImVec2(x+sz, y+sz), col32, 10.0f); x += sz+spacing; draw_list->AddRectFilled(ImVec2(x, y), ImVec2(x+sz, y+sz), col32, 10.0f, ImDrawCornerFlags_TopLeft|ImDrawCornerFlags_BotRight); x += sz+spacing; draw_list->AddTriangleFilled(ImVec2(x+sz*0.5f, y), ImVec2(x+sz,y+sz-0.5f), ImVec2(x,y+sz-0.5f), col32); x += sz+spacing; - draw_list->AddRectFilledMultiColor(ImVec2(x, y), ImVec2(x+sz, y+sz), ImColor(0,0,0), ImColor(255,0,0), ImColor(255,255,0), ImColor(0,255,0)); + draw_list->AddRectFilledMultiColor(ImVec2(x, y), ImVec2(x+sz, y+sz), IM_COL32(0,0,0,255), IM_COL32(255,0,0,255), IM_COL32(255,255,0,255), IM_COL32(0,255,0,255)); ImGui::Dummy(ImVec2((sz+spacing)*8, (sz+spacing)*3)); } ImGui::Separator(); @@ -2509,8 +2509,8 @@ static void ShowExampleAppCustomRendering(bool* p_open) ImVec2 canvas_size = ImGui::GetContentRegionAvail(); // Resize canvas to what's available if (canvas_size.x < 50.0f) canvas_size.x = 50.0f; if (canvas_size.y < 50.0f) canvas_size.y = 50.0f; - draw_list->AddRectFilledMultiColor(canvas_pos, ImVec2(canvas_pos.x + canvas_size.x, canvas_pos.y + canvas_size.y), ImColor(50,50,50), ImColor(50,50,60), ImColor(60,60,70), ImColor(50,50,60)); - draw_list->AddRect(canvas_pos, ImVec2(canvas_pos.x + canvas_size.x, canvas_pos.y + canvas_size.y), ImColor(255,255,255)); + draw_list->AddRectFilledMultiColor(canvas_pos, ImVec2(canvas_pos.x + canvas_size.x, canvas_pos.y + canvas_size.y), IM_COL32(50,50,50,255), IM_COL32(50,50,60,255), IM_COL32(60,60,70,255), IM_COL32(50,50,60,255)); + draw_list->AddRect(canvas_pos, ImVec2(canvas_pos.x + canvas_size.x, canvas_pos.y + canvas_size.y), IM_COL32(255,255,255,255)); bool adding_preview = false; ImGui::InvisibleButton("canvas", canvas_size); @@ -2519,7 +2519,7 @@ static void ShowExampleAppCustomRendering(bool* p_open) { adding_preview = true; points.push_back(mouse_pos_in_canvas); - if (!ImGui::GetIO().MouseDown[0]) + if (!ImGui::IsMouseDown(0)) adding_line = adding_preview = false; } if (ImGui::IsItemHovered()) From 651538e13bef974e5cc7db3fbd0e78fe78f98f63 Mon Sep 17 00:00:00 2001 From: omar Date: Thu, 11 Jan 2018 16:43:03 +0100 Subject: [PATCH 429/823] Clicking on a window with the ImGuiWIndowFlags_NoMove flags takes an ActiveId so we can't hover something else. (ref #1381, #1337) --- imgui.cpp | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 0a23f73c7a6c..23cded818745 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2386,11 +2386,14 @@ void ImGui::NewFrame() IM_ASSERT(g.MovingWindow->MoveId == g.MovingWindowMoveId); if (g.IO.MouseDown[0]) { - ImVec2 pos = g.IO.MousePos - g.ActiveIdClickOffset; - if (g.MovingWindow->RootWindow->PosFloat.x != pos.x || g.MovingWindow->RootWindow->PosFloat.y != pos.y) - MarkIniSettingsDirty(g.MovingWindow->RootWindow); - g.MovingWindow->RootWindow->PosFloat = pos; - FocusWindow(g.MovingWindow); + if (!(g.MovingWindow->Flags & ImGuiWindowFlags_NoMove) && !(g.MovingWindow->RootWindow->Flags & ImGuiWindowFlags_NoMove)) + { + ImVec2 pos = g.IO.MousePos - g.ActiveIdClickOffset; + if (g.MovingWindow->RootWindow->PosFloat.x != pos.x || g.MovingWindow->RootWindow->PosFloat.y != pos.y) + MarkIniSettingsDirty(g.MovingWindow->RootWindow); + g.MovingWindow->RootWindow->PosFloat = pos; + FocusWindow(g.MovingWindow); + } } else { @@ -2934,14 +2937,13 @@ void ImGui::EndFrame() { if (g.HoveredRootWindow != NULL) { + // Mark for moving even if the _NoMove flag is set (the tests will be done during actual moving) + // Because we always want to set an ActiveId, without it dragging away from a window with _NoMove would activate hover on other windows. FocusWindow(g.HoveredWindow); - if (!(g.HoveredWindow->Flags & ImGuiWindowFlags_NoMove) && !(g.HoveredRootWindow->Flags & ImGuiWindowFlags_NoMove)) - { - g.MovingWindow = g.HoveredWindow; - g.MovingWindowMoveId = g.MovingWindow->MoveId; - SetActiveID(g.MovingWindowMoveId, g.HoveredRootWindow); - g.ActiveIdClickOffset = g.IO.MousePos - g.MovingWindow->RootWindow->Pos; - } + g.MovingWindow = g.HoveredWindow; + g.MovingWindowMoveId = g.MovingWindow->MoveId; + SetActiveID(g.MovingWindowMoveId, g.HoveredRootWindow); + g.ActiveIdClickOffset = g.IO.MousePos - g.HoveredRootWindow->Pos; } else if (g.NavWindow != NULL && GetFrontMostModalRootWindow() == NULL) { From 7d2a068dea877efb6007a183494d20c813971f0f Mon Sep 17 00:00:00 2001 From: omar Date: Thu, 11 Jan 2018 17:33:37 +0100 Subject: [PATCH 430/823] Begin: Shuffling bits of code around. --- imgui.cpp | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 23cded818745..9135add8cfce 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -4565,14 +4565,6 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) if ((flags & ImGuiWindowFlags_ChildWindow) && !(flags & (ImGuiWindowFlags_AlwaysUseWindowPadding | ImGuiWindowFlags_Popup)) && window->WindowBorderSize == 0.0f) window->WindowPadding = ImVec2(0.0f, (flags & ImGuiWindowFlags_MenuBar) ? style.WindowPadding.y : 0.0f); - if (window_just_activated_by_user) - { - // Popup first latch mouse position, will position itself when it appears next frame - window->AutoPosLastDirection = ImGuiDir_None; - if ((flags & ImGuiWindowFlags_Popup) != 0 && !window_pos_set_by_api) - window->Pos = window->PosFloat = g.CurrentPopupStack.back().OpenPopupPos; - } - // Collapse window by double-clicking on title bar // At this point we don't have a clipping rectangle setup yet, so we can use the title bar area for hit detection and drawing if (!(flags & ImGuiWindowFlags_NoTitleBar) && !(flags & ImGuiWindowFlags_NoCollapse)) @@ -4660,14 +4652,23 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) // POSITION + // Popup latch its initial position, will position itself when it appears next frame + if (window_just_activated_by_user) + { + window->AutoPosLastDirection = ImGuiDir_None; + if ((flags & ImGuiWindowFlags_Popup) != 0 && !window_pos_set_by_api) + window->Pos = window->PosFloat = g.CurrentPopupStack.back().OpenPopupPos; + } + // Position child window if (flags & ImGuiWindowFlags_ChildWindow) { window->BeginOrderWithinParent = parent_window->DC.ChildWindows.Size; parent_window->DC.ChildWindows.push_back(window); + + if (!(flags & ImGuiWindowFlags_Popup) && !window_pos_set_by_api) + window->Pos = window->PosFloat = parent_window->DC.CursorPos; } - if ((flags & ImGuiWindowFlags_ChildWindow) && !(flags & ImGuiWindowFlags_Popup) && !window_pos_set_by_api) - window->Pos = window->PosFloat = parent_window->DC.CursorPos; const bool window_pos_with_pivot = (window->SetWindowPosVal.x != FLT_MAX && window->HiddenFrames == 0); if (window_pos_with_pivot) From b74f24c3e5980562e1be99758c239c009b18fcfe Mon Sep 17 00:00:00 2001 From: omar Date: Thu, 11 Jan 2018 18:08:14 +0100 Subject: [PATCH 431/823] Revert "Clicking on a window with the ImGuiWIndowFlags_NoMove flags takes an ActiveId so we can't hover something else. (ref #1381, #1337)" This reverts commit 651538e13bef974e5cc7db3fbd0e78fe78f98f63. --- imgui.cpp | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 9135add8cfce..c869063608ac 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2386,14 +2386,11 @@ void ImGui::NewFrame() IM_ASSERT(g.MovingWindow->MoveId == g.MovingWindowMoveId); if (g.IO.MouseDown[0]) { - if (!(g.MovingWindow->Flags & ImGuiWindowFlags_NoMove) && !(g.MovingWindow->RootWindow->Flags & ImGuiWindowFlags_NoMove)) - { - ImVec2 pos = g.IO.MousePos - g.ActiveIdClickOffset; - if (g.MovingWindow->RootWindow->PosFloat.x != pos.x || g.MovingWindow->RootWindow->PosFloat.y != pos.y) - MarkIniSettingsDirty(g.MovingWindow->RootWindow); - g.MovingWindow->RootWindow->PosFloat = pos; - FocusWindow(g.MovingWindow); - } + ImVec2 pos = g.IO.MousePos - g.ActiveIdClickOffset; + if (g.MovingWindow->RootWindow->PosFloat.x != pos.x || g.MovingWindow->RootWindow->PosFloat.y != pos.y) + MarkIniSettingsDirty(g.MovingWindow->RootWindow); + g.MovingWindow->RootWindow->PosFloat = pos; + FocusWindow(g.MovingWindow); } else { @@ -2937,13 +2934,14 @@ void ImGui::EndFrame() { if (g.HoveredRootWindow != NULL) { - // Mark for moving even if the _NoMove flag is set (the tests will be done during actual moving) - // Because we always want to set an ActiveId, without it dragging away from a window with _NoMove would activate hover on other windows. FocusWindow(g.HoveredWindow); - g.MovingWindow = g.HoveredWindow; - g.MovingWindowMoveId = g.MovingWindow->MoveId; - SetActiveID(g.MovingWindowMoveId, g.HoveredRootWindow); - g.ActiveIdClickOffset = g.IO.MousePos - g.HoveredRootWindow->Pos; + if (!(g.HoveredWindow->Flags & ImGuiWindowFlags_NoMove) && !(g.HoveredRootWindow->Flags & ImGuiWindowFlags_NoMove)) + { + g.MovingWindow = g.HoveredWindow; + g.MovingWindowMoveId = g.MovingWindow->MoveId; + SetActiveID(g.MovingWindowMoveId, g.HoveredRootWindow); + g.ActiveIdClickOffset = g.IO.MousePos - g.MovingWindow->RootWindow->Pos; + } } else if (g.NavWindow != NULL && GetFrontMostModalRootWindow() == NULL) { From 6a1011cf53dfea417e82eee5c84a137b39a7eebd Mon Sep 17 00:00:00 2001 From: omar Date: Thu, 11 Jan 2018 18:16:16 +0100 Subject: [PATCH 432/823] MovingWindow: Proper fix for 651538e attempt, without altering MovingWindow which has side-effects. Clicking on a window with the ImGuiWIndowFlags_NoMove flags takes an ActiveId so we can't hover something else. (ref #1381, #1337) --- imgui.cpp | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index c869063608ac..bd0be86266f8 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2378,10 +2378,10 @@ void ImGui::NewFrame() g.FramerateSecPerFrameIdx = (g.FramerateSecPerFrameIdx + 1) % IM_ARRAYSIZE(g.FramerateSecPerFrame); g.IO.Framerate = 1.0f / (g.FramerateSecPerFrameAccum / (float)IM_ARRAYSIZE(g.FramerateSecPerFrame)); - // Handle user moving window with mouse (at the beginning of the frame to avoid input lag or sheering). Only valid for root windows. + // Handle user moving window with mouse (at the beginning of the frame to avoid input lag or sheering). if (g.MovingWindowMoveId && g.MovingWindowMoveId == g.ActiveId) { - KeepAliveID(g.MovingWindowMoveId); + KeepAliveID(g.ActiveId); IM_ASSERT(g.MovingWindow && g.MovingWindow->RootWindow); IM_ASSERT(g.MovingWindow->MoveId == g.MovingWindowMoveId); if (g.IO.MouseDown[0]) @@ -2401,6 +2401,13 @@ void ImGui::NewFrame() } else { + // When clicking/dragging from a window that has the _NoMove flag, we still set the ActiveId in order to prevent hovering others. + if (g.ActiveIdWindow && g.ActiveIdWindow->MoveId == g.ActiveId) + { + KeepAliveID(g.ActiveId); + if (!g.IO.MouseDown[0]) + ClearActiveID(); + } g.MovingWindow = NULL; g.MovingWindowMoveId = 0; } @@ -2934,13 +2941,14 @@ void ImGui::EndFrame() { if (g.HoveredRootWindow != NULL) { + // Set ActiveId even if the _NoMove flag is set, without it dragging away from a window with _NoMove would activate hover on other windows. FocusWindow(g.HoveredWindow); + SetActiveID(g.HoveredWindow->MoveId, g.HoveredWindow); + g.ActiveIdClickOffset = g.IO.MousePos - g.HoveredRootWindow->Pos; if (!(g.HoveredWindow->Flags & ImGuiWindowFlags_NoMove) && !(g.HoveredRootWindow->Flags & ImGuiWindowFlags_NoMove)) { g.MovingWindow = g.HoveredWindow; g.MovingWindowMoveId = g.MovingWindow->MoveId; - SetActiveID(g.MovingWindowMoveId, g.HoveredRootWindow); - g.ActiveIdClickOffset = g.IO.MousePos - g.MovingWindow->RootWindow->Pos; } } else if (g.NavWindow != NULL && GetFrontMostModalRootWindow() == NULL) From 5e9ae92ae978081ed200ec7914248d5767d66321 Mon Sep 17 00:00:00 2001 From: omar Date: Thu, 11 Jan 2018 23:17:34 +0100 Subject: [PATCH 433/823] Begin: Handle manual resize (grip, border, gamepad) before setting up window DrawList main clipping rectangle. Sane (and required for viewport code). (#822, #1542) --- imgui.cpp | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index bd0be86266f8..4f62a426c892 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -677,7 +677,7 @@ static bool DataTypeApplyOpFromText(const char* buf, const char* ini namespace ImGui { -static void UpdateManualResize(ImGuiWindow* window, const ImVec2& size_auto_fit, int* border_held, ImU32 resize_grip_col[4]); +static void UpdateManualResize(ImGuiWindow* window, const ImVec2& size_auto_fit, int* border_held, int resize_grip_count, ImU32 resize_grip_col[4]); static void FocusFrontMostActiveWindow(ImGuiWindow* ignore_window); } @@ -4338,14 +4338,13 @@ static ImRect GetBorderRect(ImGuiWindow* window, int border_n, float perp_paddin } // Handle resize for: Resize Grips, Borders, Gamepad -static void ImGui::UpdateManualResize(ImGuiWindow* window, const ImVec2& size_auto_fit, int* border_held, ImU32 resize_grip_col[4]) +static void ImGui::UpdateManualResize(ImGuiWindow* window, const ImVec2& size_auto_fit, int* border_held, int resize_grip_count, ImU32 resize_grip_col[4]) { ImGuiContext& g = *GImGui; ImGuiWindowFlags flags = window->Flags; if ((flags & ImGuiWindowFlags_NoResize) || (flags & ImGuiWindowFlags_AlwaysAutoResize) || window->AutoFitFramesX > 0 || window->AutoFitFramesY > 0) return; - const int resize_grip_count = (flags & ImGuiWindowFlags_ResizeFromAnySide) ? 2 : 1; // 4 const int resize_border_count = (flags & ImGuiWindowFlags_ResizeFromAnySide) ? 4 : 0; const float grip_draw_size = (float)(int)ImMax(g.FontSize * 1.35f, window->WindowRounding + 1.0f + g.FontSize * 0.2f); const float grip_hover_size = (float)(int)(grip_draw_size * 0.75f); @@ -4746,6 +4745,13 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) if (!(flags & (ImGuiWindowFlags_ChildWindow | ImGuiWindowFlags_Tooltip)) || (flags & ImGuiWindowFlags_Popup)) want_focus = true; + // Handle manual resize: Resize Grips, Borders, Gamepad + int border_held = -1; + ImU32 resize_grip_col[4] = { 0 }; + const int resize_grip_count = (flags & ImGuiWindowFlags_ResizeFromAnySide) ? 2 : 1; // 4 + const float grip_draw_size = (float)(int)ImMax(g.FontSize * 1.35f, window->WindowRounding + 1.0f + g.FontSize * 0.2f); + UpdateManualResize(window, size_auto_fit, &border_held, resize_grip_count, &resize_grip_col[0]); + // DRAWING // Setup draw list and outer clipping rectangle @@ -4776,14 +4782,6 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) } else { - // Handle resize for: Resize Grips, Borders, Gamepad - int border_held = -1; - ImU32 resize_grip_col[4] = { 0 }; - const int resize_grip_count = (flags & ImGuiWindowFlags_ResizeFromAnySide) ? 2 : 1; // 4 - const float grip_draw_size = (float)(int)ImMax(g.FontSize * 1.35f, window->WindowRounding + 1.0f + g.FontSize * 0.2f); - UpdateManualResize(window, size_auto_fit, &border_held, &resize_grip_col[0]); - title_bar_rect = window->TitleBarRect(); - // Window background, Default Alpha ImU32 bg_col = GetColorU32(GetWindowBgColorIdxFromFlags(flags)); window->DrawList->AddRectFilled(window->Pos+ImVec2(0,window->TitleBarHeight()), window->Pos+window->Size, bg_col, window_rounding, (flags & ImGuiWindowFlags_NoTitleBar) ? ImDrawCornerFlags_All : ImDrawCornerFlags_Bot); From cc173d7619180cfaf211dcc338b02c7938e0d221 Mon Sep 17 00:00:00 2001 From: omar Date: Thu, 11 Jan 2018 23:21:24 +0100 Subject: [PATCH 434/823] Begin: FIx previous commit - no need to call on collapsed window. Handle manual resize (grip, border, gamepad) before setting up window DrawList main clipping rectangle. Sane (and required for viewport code). (#822, #1542) --- imgui.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/imgui.cpp b/imgui.cpp index 4f62a426c892..1a1be794917f 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -4750,7 +4750,8 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) ImU32 resize_grip_col[4] = { 0 }; const int resize_grip_count = (flags & ImGuiWindowFlags_ResizeFromAnySide) ? 2 : 1; // 4 const float grip_draw_size = (float)(int)ImMax(g.FontSize * 1.35f, window->WindowRounding + 1.0f + g.FontSize * 0.2f); - UpdateManualResize(window, size_auto_fit, &border_held, resize_grip_count, &resize_grip_col[0]); + if (!window->Collapsed) + UpdateManualResize(window, size_auto_fit, &border_held, resize_grip_count, &resize_grip_col[0]); // DRAWING From 16285603f272ea565653652e51fb49573054776f Mon Sep 17 00:00:00 2001 From: omar Date: Fri, 12 Jan 2018 19:11:11 +0100 Subject: [PATCH 435/823] Internals: Initializing fields in same order as declaration order + fixed uninitialized DragDropAcceptIdCurrRectSurface (was harmless) --- imgui_internal.h | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/imgui_internal.h b/imgui_internal.h index 4958b5ae3664..51702eab9782 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -632,14 +632,20 @@ struct ImGuiContext ActiveIdWindow = NULL; MovingWindow = NULL; MovingWindowMoveId = 0; - NextTreeNodeOpenVal = false; NextTreeNodeOpenCond = 0; + ModalWindowDarkeningRatio = 0.0f; + OverlayDrawList._Data = &DrawListSharedData; + OverlayDrawList._OwnerName = "##Overlay"; // Give it a name for debugging + MouseCursor = ImGuiMouseCursor_Arrow; + memset(MouseCursorData, 0, sizeof(MouseCursorData)); + DragDropActive = false; DragDropSourceFlags = 0; DragDropMouseButton = -1; DragDropTargetId = 0; + DragDropAcceptIdCurrRectSurface = 0.0f; DragDropAcceptIdPrev = DragDropAcceptIdCurr = 0; DragDropAcceptFrameCount = -1; memset(DragDropPayloadBufLocal, 0, sizeof(DragDropPayloadBufLocal)); @@ -655,12 +661,6 @@ struct ImGuiContext TooltipOverrideCount = 0; OsImePosRequest = OsImePosSet = ImVec2(-1.0f, -1.0f); - ModalWindowDarkeningRatio = 0.0f; - OverlayDrawList._Data = &DrawListSharedData; - OverlayDrawList._OwnerName = "##Overlay"; // Give it a name for debugging - MouseCursor = ImGuiMouseCursor_Arrow; - memset(MouseCursorData, 0, sizeof(MouseCursorData)); - SettingsDirtyTimer = 0.0f; LogEnabled = false; From 0a982027140c01121cf214c18efcd4f5444d364e Mon Sep 17 00:00:00 2001 From: omar Date: Fri, 12 Jan 2018 19:13:15 +0100 Subject: [PATCH 436/823] Nav: Standardized FIXME-NAV marker. --- imgui.cpp | 12 ++++++------ imgui_internal.h | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 9746251d4a54..f09ff856dbc2 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2,7 +2,7 @@ // (main code and documentation) // ** EXPERIMENTAL GAMEPAD/KEYBOARD NAVIGATION BRANCH -// ** Grep for FIXME-NAVIGATION +// ** Grep for FIXME-NAV // Call and read ImGui::ShowDemoWindow() in imgui_demo.cpp for demo code. // Newcomers, read 'Programmer guide' below for notes on how to setup Dear ImGui in your codebase. @@ -2153,7 +2153,7 @@ static bool NavScoreItem(ImRect cand) } // Compute distance between boxes - // FIXME-NAVIGATION: Introducing biases for vertical navigation, needs to be removed. + // FIXME-NAV: Introducing biases for vertical navigation, needs to be removed. float dbx = NavScoreItemDistInterval(cand.Min.x, cand.Max.x, curr.Min.x, curr.Max.x); float dby = NavScoreItemDistInterval(ImLerp(cand.Min.y, cand.Max.y, 0.2f), ImLerp(cand.Min.y, cand.Max.y, 0.8f), ImLerp(curr.Min.y, curr.Max.y, 0.2f), ImLerp(curr.Min.y, curr.Max.y, 0.8f)); // Scale down on Y to keep using box-distance for vertically touching items if (dby != 0.0f && dbx != 0.0f) @@ -2654,7 +2654,7 @@ enum ImGuiNavReadMode ImGuiNavReadMode_RepeatFast }; -// FIXME-NAVIGATION: Expose navigation repeat delay/rate +// FIXME-NAV: Expose navigation repeat delay/rate static float GetNavInputAmount(ImGuiNavInput n, ImGuiNavReadMode mode) { ImGuiContext& g = *GImGui; @@ -5320,7 +5320,7 @@ static void ImGui::UpdateManualResize(ImGuiWindow* window, const ImVec2& size_au resize_grip_col[0] = GetColorU32(ImGuiCol_ResizeGripActive); if (nav_resize_delta.x != 0.0f || nav_resize_delta.y != 0.0f) { - // FIXME-NAVIGATION: Should store and accumulate into a separate size buffer to handle sizing constraints properly, right now a constraint will make us stuck. + // FIXME-NAV: Should store and accumulate into a separate size buffer to handle sizing constraints properly, right now a constraint will make us stuck. g.NavWindowingToggleLayer = false; size_target = CalcSizeAfterConstraint(window, window->SizeFull + nav_resize_delta); } @@ -7278,7 +7278,7 @@ bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool // PressedOnClick | | .. // PressedOnRelease | | .. (NOT on release) // PressedOnDoubleClick | | .. - // FIXME-NAVIGATION: We don't honor those different behaviors. + // FIXME-NAV: We don't honor those different behaviors. if ((flags & ImGuiButtonFlags_PressedOnClickRelease) && g.IO.MouseClicked[0]) { SetActiveID(id, window); @@ -8375,7 +8375,7 @@ bool ImGui::SliderBehavior(const ImRect& frame_bb, ImGuiID id, float* v, float v } if (IsNavInputDown(ImGuiNavInput_PadTweakFast)) delta *= 10.0f; - clicked_t = ImSaturate(clicked_t + delta); // FIXME-NAVIGATION: todo: cancel adjustment if current value already past edge and we are moving in edge direction, to avoid clamping value to edge. + clicked_t = ImSaturate(clicked_t + delta); // FIXME-NAV: todo: cancel adjustment if current value already past edge and we are moving in edge direction, to avoid clamping value to edge. set_new_value = true; } } diff --git a/imgui_internal.h b/imgui_internal.h index 816c56ac88ed..17e264811b92 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -912,7 +912,7 @@ struct IMGUI_API ImGuiWindow ImGuiWindow* RootNavWindow; // Generally point to ourself. If we are a child window with the ImGuiWindowFlags_NavFlattenedChild flag, point to parent. Used to display TitleBgActive color and for selecting which window to use for NavWindowing. // Navigation / Focus - // FIXME-NAVIGATION: Merge all this with the new Nav system, at least the request variables should be moved to ImGuiContext + // FIXME-NAV: Merge all this with the new Nav system, at least the request variables should be moved to ImGuiContext int FocusIdxAllCounter; // Start at -1 and increase as assigned via FocusItemRegister() int FocusIdxTabCounter; // (same, but only count widgets which you can Tab through) int FocusIdxAllRequestCurrent; // Item being requested for focus From c85d7d6e4932f4529059dad3f1b148a66b4ca846 Mon Sep 17 00:00:00 2001 From: omar Date: Fri, 12 Jan 2018 19:28:37 +0100 Subject: [PATCH 437/823] Nav: Remove GetItemID(), hide ActivateItem() before this feature is unfinished and has issue (full feature is on hold). Undo part of 59c6f35bf6b8919000d7deacc0a7b1c1428a2519 (#787) --- imgui.cpp | 6 ------ imgui.h | 2 -- imgui_demo.cpp | 16 ---------------- imgui_internal.h | 1 + 4 files changed, 1 insertion(+), 24 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 4e46158cba46..755d49f8d566 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -6965,12 +6965,6 @@ void ImGui::ActivateItem(ImGuiID id) g.NavNextActivateId = id; } -ImGuiID ImGui::GetItemID() -{ - ImGuiContext& g = *GImGui; - return g.CurrentWindow->DC.LastItemId; -} - void ImGui::SetKeyboardFocusHere(int offset) { IM_ASSERT(offset >= -1); // -1 is allowed but not below diff --git a/imgui.h b/imgui.h index 280a9f5e3fc8..e73a5445e2cb 100644 --- a/imgui.h +++ b/imgui.h @@ -448,8 +448,6 @@ namespace ImGui IMGUI_API void StyleColorsLight(ImGuiStyle* dst = NULL); // Focus, Activation - IMGUI_API void ActivateItem(ImGuiID id); // remotely activate a button, checkbox, tree node etc. given its unique ID. activation is queued and processed on the next frame when the item is encountered again. - IMGUI_API ImGuiID GetItemID(); // get id of previous item, generally ~GetID(label) IMGUI_API void SetItemDefaultFocus(); // make last item the default focused item of a window. Please use instead of "if (IsWindowAppearing()) SetScrollHere()" to signify "default item". IMGUI_API void SetKeyboardFocusHere(int offset = 0); // focus keyboard on the next widget. Use positive 'offset' to access sub components of a multiple component widget. Use -1 to access previous widget. diff --git a/imgui_demo.cpp b/imgui_demo.cpp index d6be264960a1..67be3577580f 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -1887,22 +1887,6 @@ void ImGui::ShowDemoWindow(bool* p_open) ImGui::TreePop(); } -#if 0 - if (ImGui::TreeNode("Remote Activation")) - { - static char label[256]; - ImGui::InputText("Label", label, IM_ARRAYSIZE(label)); - ImGui::PopID(); // We don't yet have an easy way compute ID at other levels of the ID stack so we pop it manually for now (e.g. we'd like something like GetID("../label")) - ImGuiID id = ImGui::GetID(label); - ImGui::PushID("Remote Activation"); - if (ImGui::SmallButton("Activate")) - ImGui::ActivateItem(id); - ImGui::SameLine(); - ImGui::Text("ID = 0x%08X", id); - ImGui::TreePop(); - } -#endif - if (ImGui::TreeNode("Focused & Hovered Test")) { static bool embed_all_inside_a_child_window = false; diff --git a/imgui_internal.h b/imgui_internal.h index cc66758b12ac..8f4ecc206515 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -1003,6 +1003,7 @@ namespace ImGui IMGUI_API void BeginTooltipEx(ImGuiWindowFlags extra_flags, bool override_previous_tooltip = true); IMGUI_API void NavInitWindow(ImGuiWindow* window, bool force_reinit); + IMGUI_API void ActivateItem(ImGuiID id); // Remotely activate a button, checkbox, tree node etc. given its unique ID. activation is queued and processed on the next frame when the item is encountered again. IMGUI_API int CalcTypematicPressedRepeatAmount(float t, float t_prev, float repeat_delay, float repeat_rate); From 1493de4f8173a54e2aa726a2b9a654aa43a735a3 Mon Sep 17 00:00:00 2001 From: omar Date: Fri, 12 Jan 2018 19:53:27 +0100 Subject: [PATCH 438/823] Internals: Merge of harmless stuff from Navigation stuff. Added GetHoveredID() internal helper. --- imgui.cpp | 11 +++++++++-- imgui_demo.cpp | 3 ++- imgui_internal.h | 1 + 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 1a1be794917f..910101143cb2 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1952,6 +1952,12 @@ void ImGui::SetHoveredID(ImGuiID id) g.HoveredIdTimer = (id != 0 && g.HoveredIdPreviousFrame == id) ? (g.HoveredIdTimer + g.IO.DeltaTime) : 0.0f; } +ImGuiID ImGui::GetHoveredID() +{ + ImGuiContext& g = *GImGui; + return g.HoveredId ? g.HoveredId : g.HoveredIdPreviousFrame; +} + void ImGui::KeepAliveID(ImGuiID id) { ImGuiContext& g = *GImGui; @@ -4773,6 +4779,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) const float window_rounding = window->WindowRounding; const float window_border_size = window->WindowBorderSize; ImRect title_bar_rect = window->TitleBarRect(); + const bool window_is_focused = want_focus || (g.NavWindow && window->RootNonPopupWindow == g.NavWindow->RootNonPopupWindow); if (window->Collapsed) { // Title bar only @@ -4788,7 +4795,6 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) window->DrawList->AddRectFilled(window->Pos+ImVec2(0,window->TitleBarHeight()), window->Pos+window->Size, bg_col, window_rounding, (flags & ImGuiWindowFlags_NoTitleBar) ? ImDrawCornerFlags_All : ImDrawCornerFlags_Bot); // Title bar - const bool window_is_focused = want_focus || (g.NavWindow && window->RootNonPopupWindow == g.NavWindow->RootNonPopupWindow); if (!(flags & ImGuiWindowFlags_NoTitleBar)) window->DrawList->AddRectFilled(title_bar_rect.Min, title_bar_rect.Max, GetColorU32(window_is_focused ? ImGuiCol_TitleBgActive : ImGuiCol_TitleBg), window_rounding, ImDrawCornerFlags_Top); @@ -6358,7 +6364,8 @@ bool ImGui::ButtonEx(const char* label, const ImVec2& size_arg, ImGuiButtonFlags if (!ItemAdd(bb, id)) return false; - if (window->DC.ItemFlags & ImGuiItemFlags_ButtonRepeat) flags |= ImGuiButtonFlags_Repeat; + if (window->DC.ItemFlags & ImGuiItemFlags_ButtonRepeat) + flags |= ImGuiButtonFlags_Repeat; bool hovered, held; bool pressed = ButtonBehavior(bb, id, &hovered, &held, flags); diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 9cebf88b3914..87e4f57cfc39 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -1552,7 +1552,7 @@ void ImGui::ShowDemoWindow(bool* p_open) ImGui::OpenPopup("Stacked 2"); if (ImGui::BeginPopupModal("Stacked 2")) { - ImGui::Text("Hello from Stacked The Second"); + ImGui::Text("Hello from Stacked The Second!"); if (ImGui::Button("Close")) ImGui::CloseCurrentPopup(); ImGui::EndPopup(); @@ -1857,6 +1857,7 @@ void ImGui::ShowDemoWindow(bool* p_open) ImGui::InputText("3 (tab skip)", buf, IM_ARRAYSIZE(buf)); if (ImGui::IsItemActive()) has_focus = 3; ImGui::PopAllowKeyboardFocus(); + if (has_focus) ImGui::Text("Item with focus: %d", has_focus); else diff --git a/imgui_internal.h b/imgui_internal.h index 51702eab9782..87a4a131a803 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -880,6 +880,7 @@ namespace ImGui IMGUI_API void SetActiveID(ImGuiID id, ImGuiWindow* window); IMGUI_API void ClearActiveID(); IMGUI_API void SetHoveredID(ImGuiID id); + IMGUI_API ImGuiID GetHoveredID(); IMGUI_API void KeepAliveID(ImGuiID id); IMGUI_API void ItemSize(const ImVec2& size, float text_offset_y = 0.0f); From db63e71f13eac9fa9350baedaaef6552ecae7ed5 Mon Sep 17 00:00:00 2001 From: omar Date: Fri, 12 Jan 2018 20:07:01 +0100 Subject: [PATCH 439/823] Internals: Exposed SetCurrentFont() in imgui_internal.h --- imgui.cpp | 3 +-- imgui_internal.h | 2 ++ 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 755d49f8d566..57b24157c04c 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -674,7 +674,6 @@ static bool IsKeyPressedMap(ImGuiKey key, bool repeat = true); static ImFont* GetDefaultFont(); -static void SetCurrentFont(ImFont* font); static void SetCurrentWindow(ImGuiWindow* window); static void SetWindowScrollX(ImGuiWindow* window, float new_scroll_x); static void SetWindowScrollY(ImGuiWindow* window, float new_scroll_y); @@ -6220,7 +6219,7 @@ static ImFont* GetDefaultFont() return g.IO.FontDefault ? g.IO.FontDefault : g.IO.Fonts->Fonts[0]; } -static void SetCurrentFont(ImFont* font) +void ImGui::SetCurrentFont(ImFont* font) { ImGuiContext& g = *GImGui; IM_ASSERT(font && font->IsLoaded()); // Font Atlas not created. Did you call io.Fonts->GetTexDataAsRGBA32 / GetTexDataAsAlpha8 ? diff --git a/imgui_internal.h b/imgui_internal.h index 8f4ecc206515..2d6ec52ba996 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -996,6 +996,8 @@ namespace ImGui IMGUI_API void PushItemFlag(ImGuiItemFlags option, bool enabled); IMGUI_API void PopItemFlag(); + IMGUI_API void SetCurrentFont(ImFont* font); + IMGUI_API void OpenPopupEx(ImGuiID id); IMGUI_API void ClosePopup(ImGuiID id); IMGUI_API bool IsPopupOpen(ImGuiID id); From daa38f2ad0c8cbb7582a833051ab60055a54d0c6 Mon Sep 17 00:00:00 2001 From: Crunkle Date: Sun, 14 Jan 2018 03:31:22 +0000 Subject: [PATCH 440/823] Fix cross compilers --- imgui.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/imgui.cpp b/imgui.cpp index 910101143cb2..ff6b871d468b 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -11524,7 +11524,11 @@ void ImGui::EndDragDropTarget() #if defined(_WIN32) && !defined(_WINDOWS_) && (!defined(IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCTIONS) || !defined(IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS)) #undef WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN +#ifndef __MINGW32__ #include +#else +#include +#endif #endif // Win32 API clipboard implementation From 514d30d8cdd659b6af3c93512583a00ee18ecbaf Mon Sep 17 00:00:00 2001 From: omar Date: Sun, 14 Jan 2018 14:13:54 +0100 Subject: [PATCH 441/823] MovingWindow: Track click offset based on MovingWindow and not its RootWindow. Followup to 3849bb4470aebb4ff276113170f26cc82f990f49. Comments + adding a local to ease patch #1345. --- imgui.cpp | 15 +++++++++++---- imgui_internal.h | 2 +- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index ff6b871d468b..fee26e2ff47d 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2392,10 +2392,17 @@ void ImGui::NewFrame() IM_ASSERT(g.MovingWindow->MoveId == g.MovingWindowMoveId); if (g.IO.MouseDown[0]) { + // MovingWindow = window we clicked on, could be a child window. We track it to preserve Focus and so that ActiveIdWindow == MovingWindow and ActiveId == MovingWindow->MoveId for consistency. + // actually_moving_window = MovingWindow->RootWindow. + ImGuiWindow* actually_moving_window = g.MovingWindow->RootWindow; ImVec2 pos = g.IO.MousePos - g.ActiveIdClickOffset; - if (g.MovingWindow->RootWindow->PosFloat.x != pos.x || g.MovingWindow->RootWindow->PosFloat.y != pos.y) - MarkIniSettingsDirty(g.MovingWindow->RootWindow); - g.MovingWindow->RootWindow->PosFloat = pos; + if (actually_moving_window != g.MovingWindow) + pos += actually_moving_window->PosFloat - g.MovingWindow->PosFloat; + if (actually_moving_window->PosFloat.x != pos.x || actually_moving_window->PosFloat.y != pos.y) + { + MarkIniSettingsDirty(actually_moving_window); + actually_moving_window->PosFloat = pos; + } FocusWindow(g.MovingWindow); } else @@ -2950,7 +2957,7 @@ void ImGui::EndFrame() // Set ActiveId even if the _NoMove flag is set, without it dragging away from a window with _NoMove would activate hover on other windows. FocusWindow(g.HoveredWindow); SetActiveID(g.HoveredWindow->MoveId, g.HoveredWindow); - g.ActiveIdClickOffset = g.IO.MousePos - g.HoveredRootWindow->Pos; + g.ActiveIdClickOffset = g.IO.MousePos - g.HoveredWindow->Pos; if (!(g.HoveredWindow->Flags & ImGuiWindowFlags_NoMove) && !(g.HoveredRootWindow->Flags & ImGuiWindowFlags_NoMove)) { g.MovingWindow = g.HoveredWindow; diff --git a/imgui_internal.h b/imgui_internal.h index 87a4a131a803..797f70758579 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -534,7 +534,7 @@ struct ImGuiContext bool ActiveIdAllowOverlap; // Active widget allows another widget to steal active id (generally for overlapping widgets, but not always) ImVec2 ActiveIdClickOffset; // Clicked offset from upper-left corner, if applicable (currently only set by ButtonBehavior) ImGuiWindow* ActiveIdWindow; - ImGuiWindow* MovingWindow; // Track the child window we clicked on to move a window. + ImGuiWindow* MovingWindow; // Track the window we clicked on (in order to preserve focus). The actually window that is moved is generally MovingWindow->RootWindow. ImGuiID MovingWindowMoveId; // == MovingWindow->MoveId ImVector ColorModifiers; // Stack for PushStyleColor()/PopStyleColor() ImVector StyleModifiers; // Stack for PushStyleVar()/PopStyleVar() From 6eff21ee5e33bc6daab915020915fa8d94459812 Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 15 Jan 2018 16:19:01 +0100 Subject: [PATCH 442/823] Revert "Nav: Fixed RenderNavHighlight() clipping, essentially revert 6ea90af6b76f2b9f7b86c12813bafd6f0408bdc0. (#787)" This reverts commit 03f5cd6ca128090f71df7959e0f92c6b40076184. --- imgui.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/imgui.cpp b/imgui.cpp index 57b24157c04c..368db256e34d 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -4159,6 +4159,7 @@ void ImGui::RenderNavHighlight(const ImRect& bb, ImGuiID id, ImGuiNavHighlightFl ImGuiWindow* window = ImGui::GetCurrentWindow(); ImRect display_rect = bb; + display_rect.ClipWith(window->ClipRect); if (flags & ImGuiNavHighlightFlags_TypeDefault) { const float THICKNESS = 2.0f; From 06eef2ce6fe3e41fec1a60eb37dbb8f97a0a89c9 Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 15 Jan 2018 17:25:11 +0100 Subject: [PATCH 443/823] Internals: DrawData: renamed fields only (committing separately so that next commit is less nosiy). --- imgui.cpp | 60 ++++++++++++++++++++++++------------------------ imgui_internal.h | 4 ++-- 2 files changed, 32 insertions(+), 32 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index fee26e2ff47d..4457ee5fd082 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2246,7 +2246,7 @@ ImGuiStyle& ImGui::GetStyle() // Same value as passed to your RenderDrawListsFn() function. valid after Render() and until the next call to NewFrame() ImDrawData* ImGui::GetDrawData() { - return GImGui->RenderDrawData.Valid ? &GImGui->RenderDrawData : NULL; + return GImGui->DrawData.Valid ? &GImGui->DrawData : NULL; } float ImGui::GetTime() @@ -2303,9 +2303,9 @@ void ImGui::NewFrame() g.OverlayDrawList.Flags = (g.Style.AntiAliasedLines ? ImDrawListFlags_AntiAliasedLines : 0) | (g.Style.AntiAliasedFill ? ImDrawListFlags_AntiAliasedFill : 0); // Mark rendering data as invalid to prevent user who may have a handle on it to use it - g.RenderDrawData.Valid = false; - g.RenderDrawData.CmdLists = NULL; - g.RenderDrawData.CmdListsCount = g.RenderDrawData.TotalVtxCount = g.RenderDrawData.TotalIdxCount = 0; + g.DrawData.Valid = false; + g.DrawData.CmdLists = NULL; + g.DrawData.CmdListsCount = g.DrawData.TotalVtxCount = g.DrawData.TotalIdxCount = 0; // Clear reference to active widget if the widget isn't alive anymore if (!g.HoveredIdPreviousFrame) @@ -2656,8 +2656,8 @@ void ImGui::Shutdown() g.FontStack.clear(); g.OpenPopupStack.clear(); g.CurrentPopupStack.clear(); - for (int i = 0; i < IM_ARRAYSIZE(g.RenderDrawLists); i++) - g.RenderDrawLists[i].clear(); + for (int i = 0; i < IM_ARRAYSIZE(g.DrawDataLists); i++) + g.DrawDataLists[i].clear(); g.OverlayDrawList.ClearFreeMemory(); g.PrivateClipboard.clear(); g.InputTextState.Text.clear(); @@ -2902,11 +2902,11 @@ static void AddWindowToRenderListSelectLayer(ImGuiWindow* window) ImGuiContext& g = *GImGui; g.IO.MetricsActiveWindows++; if (window->Flags & ImGuiWindowFlags_Popup) - AddWindowToRenderList(g.RenderDrawLists[1], window); + AddWindowToRenderList(g.DrawDataLists[1], window); else if (window->Flags & ImGuiWindowFlags_Tooltip) - AddWindowToRenderList(g.RenderDrawLists[2], window); + AddWindowToRenderList(g.DrawDataLists[2], window); else - AddWindowToRenderList(g.RenderDrawLists[0], window); + AddWindowToRenderList(g.DrawDataLists[0], window); } // When using this function it is sane to ensure that float are perfectly rounded to integer values, to that e.g. (int)(max.x-min.x) in user's render produce correct result. @@ -3031,8 +3031,8 @@ void ImGui::Render() { // Gather windows to render g.IO.MetricsRenderVertices = g.IO.MetricsRenderIndices = g.IO.MetricsActiveWindows = 0; - for (int i = 0; i < IM_ARRAYSIZE(g.RenderDrawLists); i++) - g.RenderDrawLists[i].resize(0); + for (int i = 0; i < IM_ARRAYSIZE(g.DrawDataLists); i++) + g.DrawDataLists[i].resize(0); for (int i = 0; i != g.Windows.Size; i++) { ImGuiWindow* window = g.Windows[i]; @@ -3041,17 +3041,17 @@ void ImGui::Render() } // Flatten layers - int n = g.RenderDrawLists[0].Size; + int n = g.DrawDataLists[0].Size; int flattened_size = n; - for (int i = 1; i < IM_ARRAYSIZE(g.RenderDrawLists); i++) - flattened_size += g.RenderDrawLists[i].Size; - g.RenderDrawLists[0].resize(flattened_size); - for (int i = 1; i < IM_ARRAYSIZE(g.RenderDrawLists); i++) + for (int i = 1; i < IM_ARRAYSIZE(g.DrawDataLists); i++) + flattened_size += g.DrawDataLists[i].Size; + g.DrawDataLists[0].resize(flattened_size); + for (int i = 1; i < IM_ARRAYSIZE(g.DrawDataLists); i++) { - ImVector& layer = g.RenderDrawLists[i]; + ImVector& layer = g.DrawDataLists[i]; if (layer.empty()) continue; - memcpy(&g.RenderDrawLists[0][n], &layer[0], layer.Size * sizeof(ImDrawList*)); + memcpy(&g.DrawDataLists[0][n], &layer[0], layer.Size * sizeof(ImDrawList*)); n += layer.Size; } @@ -3070,18 +3070,18 @@ void ImGui::Render() g.OverlayDrawList.PopTextureID(); } if (!g.OverlayDrawList.VtxBuffer.empty()) - AddDrawListToRenderList(g.RenderDrawLists[0], &g.OverlayDrawList); + AddDrawListToRenderList(g.DrawDataLists[0], &g.OverlayDrawList); // Setup draw data - g.RenderDrawData.Valid = true; - g.RenderDrawData.CmdLists = (g.RenderDrawLists[0].Size > 0) ? &g.RenderDrawLists[0][0] : NULL; - g.RenderDrawData.CmdListsCount = g.RenderDrawLists[0].Size; - g.RenderDrawData.TotalVtxCount = g.IO.MetricsRenderVertices; - g.RenderDrawData.TotalIdxCount = g.IO.MetricsRenderIndices; + g.DrawData.Valid = true; + g.DrawData.CmdLists = (g.DrawDataLists[0].Size > 0) ? &g.DrawDataLists[0][0] : NULL; + g.DrawData.CmdListsCount = g.DrawDataLists[0].Size; + g.DrawData.TotalVtxCount = g.IO.MetricsRenderVertices; + g.DrawData.TotalIdxCount = g.IO.MetricsRenderIndices; // Render. If user hasn't set a callback then they may retrieve the draw data via GetDrawData() - if (g.RenderDrawData.CmdListsCount > 0 && g.IO.RenderDrawListsFn != NULL) - g.IO.RenderDrawListsFn(&g.RenderDrawData); + if (g.DrawData.CmdListsCount > 0 && g.IO.RenderDrawListsFn != NULL) + g.IO.RenderDrawListsFn(&g.DrawData); } } @@ -11749,11 +11749,11 @@ void ImGui::ShowMetricsWindow(bool* p_open) ImGuiContext& g = *GImGui; // Access private state Funcs::NodeWindows(g.Windows, "Windows"); - if (ImGui::TreeNode("DrawList", "Active DrawLists (%d)", g.RenderDrawLists[0].Size)) + if (ImGui::TreeNode("DrawList", "Active DrawLists (%d)", g.DrawDataLists[0].Size)) { - for (int layer = 0; layer < IM_ARRAYSIZE(g.RenderDrawLists); layer++) - for (int i = 0; i < g.RenderDrawLists[layer].Size; i++) - Funcs::NodeDrawList(g.RenderDrawLists[0][i], "DrawList"); + for (int layer = 0; layer < IM_ARRAYSIZE(g.DrawDataLists); layer++) + for (int i = 0; i < g.DrawDataLists[layer].Size; i++) + Funcs::NodeDrawList(g.DrawDataLists[0][i], "DrawList"); ImGui::TreePop(); } if (ImGui::TreeNode("Popups", "Open Popups Stack (%d)", g.OpenPopupStack.Size)) diff --git a/imgui_internal.h b/imgui_internal.h index 797f70758579..aba8c419226f 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -546,8 +546,8 @@ struct ImGuiContext ImGuiCond NextTreeNodeOpenCond; // Render - ImDrawData RenderDrawData; // Main ImDrawData instance to pass render information to the user - ImVector RenderDrawLists[3]; + ImDrawData DrawData; // Main ImDrawData instance to pass render information to the user + ImVector DrawDataLists[3]; float ModalWindowDarkeningRatio; ImDrawList OverlayDrawList; // Optional software render of mouse cursors, if io.MouseDrawCursor is set + a few debug overlays ImGuiMouseCursor MouseCursor; From 061d8df0336589ffee5061cec356496088f1fd8e Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 15 Jan 2018 17:29:18 +0100 Subject: [PATCH 444/823] MIssing IMGUI_API for a type with non-inline methods. --- imgui_internal.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/imgui_internal.h b/imgui_internal.h index aba8c419226f..a0909f88834a 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -448,7 +448,7 @@ struct ImGuiColumnsSet } }; -struct ImDrawListSharedData +struct IMGUI_API ImDrawListSharedData { ImVec2 TexUvWhitePixel; // UV of white pixel in the atlas ImFont* Font; // Current/default font (optional, for simplified AddText overload) From 038453258e0dc03b159d9e8c16a98b092aedbc5f Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 15 Jan 2018 17:48:07 +0100 Subject: [PATCH 445/823] Internals: DrawData: Refactored chunks into a ImDrawDataBuilder we can reuse. --- imgui.cpp | 115 +++++++++++++++++++++++++---------------------- imgui_internal.h | 12 ++++- 2 files changed, 72 insertions(+), 55 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 4457ee5fd082..89afeced7c36 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -648,9 +648,9 @@ static ImGuiWindow* CreateNewWindow(const char* name, ImVec2 size, ImGuiWind static void CheckStacksSize(ImGuiWindow* window, bool write); static ImVec2 CalcNextScrollFromScrollTargetAndClamp(ImGuiWindow* window); -static void AddDrawListToRenderList(ImVector& out_render_list, ImDrawList* draw_list); -static void AddWindowToRenderList(ImVector& out_render_list, ImGuiWindow* window); -static void AddWindowToSortedBuffer(ImVector& out_sorted_windows, ImGuiWindow* window); +static void AddDrawListToRenderList(ImVector* out_render_list, ImDrawList* draw_list); +static void AddWindowToRenderList(ImVector* out_render_list, ImGuiWindow* window); +static void AddWindowToSortedBuffer(ImVector* out_sorted_windows, ImGuiWindow* window); static ImGuiWindowSettings* AddWindowSettings(const char* name); @@ -2656,8 +2656,7 @@ void ImGui::Shutdown() g.FontStack.clear(); g.OpenPopupStack.clear(); g.CurrentPopupStack.clear(); - for (int i = 0; i < IM_ARRAYSIZE(g.DrawDataLists); i++) - g.DrawDataLists[i].clear(); + g.DrawDataBuilder.ClearFreeMemory(); g.OverlayDrawList.ClearFreeMemory(); g.PrivateClipboard.clear(); g.InputTextState.Text.clear(); @@ -2847,7 +2846,7 @@ static void AddWindowToSortedBuffer(ImVector& out_sorted_windows, } } -static void AddDrawListToRenderList(ImVector& out_render_list, ImDrawList* draw_list) +static void AddDrawListToRenderList(ImVector* out_render_list, ImDrawList* draw_list) { if (draw_list->CmdBuffer.empty()) return; @@ -2866,9 +2865,9 @@ static void AddDrawListToRenderList(ImVector& out_render_list, ImDr IM_ASSERT(draw_list->IdxBuffer.Size == 0 || draw_list->_IdxWritePtr == draw_list->IdxBuffer.Data + draw_list->IdxBuffer.Size); IM_ASSERT((int)draw_list->_VtxCurrentIdx == draw_list->VtxBuffer.Size); - // Check that draw_list doesn't use more vertices than indexable in a single draw call (default ImDrawIdx = unsigned short = 2 bytes = 64K vertices per ImDrawList = per window) + // Check that draw_list doesn't use more vertices than indexable (default ImDrawIdx = unsigned short = 2 bytes = 64K vertices per ImDrawList = per window) // If this assert triggers because you are drawing lots of stuff manually: - // A) Make sure you are coarse clipping, because ImDrawList let all your vertices pass. You can use thre Metrics window to inspect draw list contents. + // A) Make sure you are coarse clipping, because ImDrawList let all your vertices pass. You can use the Metrics window to inspect draw list contents. // B) If you need/want meshes with more than 64K vertices, uncomment the '#define ImDrawIdx unsigned int' line in imconfig.h to set the index size to 4 bytes. // You'll need to handle the 4-bytes indices to your renderer. For example, the OpenGL example code detect index size at compile-time by doing: // glDrawElements(GL_TRIANGLES, (GLsizei)pcmd->ElemCount, sizeof(ImDrawIdx) == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, idx_buffer_offset); @@ -2877,36 +2876,61 @@ static void AddDrawListToRenderList(ImVector& out_render_list, ImDr if (sizeof(ImDrawIdx) == 2) IM_ASSERT(draw_list->_VtxCurrentIdx < (1 << 16) && "Too many vertices in ImDrawList using 16-bit indices. Read comment above"); - out_render_list.push_back(draw_list); - GImGui->IO.MetricsRenderVertices += draw_list->VtxBuffer.Size; - GImGui->IO.MetricsRenderIndices += draw_list->IdxBuffer.Size; + out_render_list->push_back(draw_list); } -static void AddWindowToRenderList(ImVector& out_render_list, ImGuiWindow* window) +static void AddWindowToRenderList(ImVector* out_render_list, ImGuiWindow* window) { AddDrawListToRenderList(out_render_list, window->DrawList); for (int i = 0; i < window->DC.ChildWindows.Size; i++) { ImGuiWindow* child = window->DC.ChildWindows[i]; - if (!child->Active) // clipped children may have been marked not active - continue; - if (child->HiddenFrames > 0) - continue; - AddWindowToRenderList(out_render_list, child); + if (child->Active && child->HiddenFrames <= 0) // clipped children may have been marked not active + AddWindowToRenderList(out_render_list, child); } } -static void AddWindowToRenderListSelectLayer(ImGuiWindow* window) +static void AddWindowToDrawDataSelectLayer(ImDrawDataBuilder* builder, ImGuiWindow* window) { - // FIXME: Generalize this with a proper layering system so e.g. user can draw in specific layers, below text, .. ImGuiContext& g = *GImGui; g.IO.MetricsActiveWindows++; - if (window->Flags & ImGuiWindowFlags_Popup) - AddWindowToRenderList(g.DrawDataLists[1], window); - else if (window->Flags & ImGuiWindowFlags_Tooltip) - AddWindowToRenderList(g.DrawDataLists[2], window); + if (window->Flags & ImGuiWindowFlags_Tooltip) + AddWindowToRenderList(&builder->Layers[2], window); + else if (window->Flags & ImGuiWindowFlags_Popup) + AddWindowToRenderList(&builder->Layers[1], window); else - AddWindowToRenderList(g.DrawDataLists[0], window); + AddWindowToRenderList(&builder->Layers[0], window); +} + +void ImDrawDataBuilder::FlattenIntoSingleLayer() +{ + int n = Layers[0].Size; + int size = n; + for (int i = 1; i < IM_ARRAYSIZE(Layers); i++) + size += Layers[i].Size; + Layers[0].resize(size); + for (int layer_n = 1; layer_n < IM_ARRAYSIZE(Layers); layer_n++) + { + ImVector& layer = Layers[layer_n]; + if (layer.empty()) + continue; + memcpy(&Layers[0][n], &layer[0], layer.Size * sizeof(ImDrawList*)); + n += layer.Size; + layer.resize(0); + } +} + +void ImDrawDataBuilder::SetupDrawData(ImDrawData* out_draw_data) +{ + out_draw_data->Valid = true; + out_draw_data->CmdLists = (Layers[0].Size > 0) ? Layers[0].Data : NULL; + out_draw_data->CmdListsCount = Layers[0].Size; + out_draw_data->TotalVtxCount = out_draw_data->TotalIdxCount = 0; + for (int n = 0; n < Layers[0].Size; n++) + { + out_draw_data->TotalVtxCount += Layers[0][n]->VtxBuffer.Size; + out_draw_data->TotalIdxCount += Layers[0][n]->IdxBuffer.Size; + } } // When using this function it is sane to ensure that float are perfectly rounded to integer values, to that e.g. (int)(max.x-min.x) in user's render produce correct result. @@ -3031,29 +3055,14 @@ void ImGui::Render() { // Gather windows to render g.IO.MetricsRenderVertices = g.IO.MetricsRenderIndices = g.IO.MetricsActiveWindows = 0; - for (int i = 0; i < IM_ARRAYSIZE(g.DrawDataLists); i++) - g.DrawDataLists[i].resize(0); + g.DrawDataBuilder.Clear(); for (int i = 0; i != g.Windows.Size; i++) { ImGuiWindow* window = g.Windows[i]; if (window->Active && window->HiddenFrames <= 0 && (window->Flags & (ImGuiWindowFlags_ChildWindow)) == 0) - AddWindowToRenderListSelectLayer(window); - } - - // Flatten layers - int n = g.DrawDataLists[0].Size; - int flattened_size = n; - for (int i = 1; i < IM_ARRAYSIZE(g.DrawDataLists); i++) - flattened_size += g.DrawDataLists[i].Size; - g.DrawDataLists[0].resize(flattened_size); - for (int i = 1; i < IM_ARRAYSIZE(g.DrawDataLists); i++) - { - ImVector& layer = g.DrawDataLists[i]; - if (layer.empty()) - continue; - memcpy(&g.DrawDataLists[0][n], &layer[0], layer.Size * sizeof(ImDrawList*)); - n += layer.Size; + AddWindowToDrawDataSelectLayer(&g.DrawDataBuilder, window); } + g.DrawDataBuilder.FlattenIntoSingleLayer(); // Draw software mouse cursor if requested if (g.IO.MouseDrawCursor) @@ -3070,14 +3079,12 @@ void ImGui::Render() g.OverlayDrawList.PopTextureID(); } if (!g.OverlayDrawList.VtxBuffer.empty()) - AddDrawListToRenderList(g.DrawDataLists[0], &g.OverlayDrawList); + AddDrawListToRenderList(&g.DrawDataBuilder.Layers[0], &g.OverlayDrawList); - // Setup draw data - g.DrawData.Valid = true; - g.DrawData.CmdLists = (g.DrawDataLists[0].Size > 0) ? &g.DrawDataLists[0][0] : NULL; - g.DrawData.CmdListsCount = g.DrawDataLists[0].Size; - g.DrawData.TotalVtxCount = g.IO.MetricsRenderVertices; - g.DrawData.TotalIdxCount = g.IO.MetricsRenderIndices; + // Setup ImDrawData structure for end-user + g.DrawDataBuilder.SetupDrawData(&g.DrawData); + g.IO.MetricsRenderVertices = g.DrawData.TotalVtxCount; + g.IO.MetricsRenderIndices = g.DrawData.TotalIdxCount; // Render. If user hasn't set a callback then they may retrieve the draw data via GetDrawData() if (g.DrawData.CmdListsCount > 0 && g.IO.RenderDrawListsFn != NULL) @@ -11747,13 +11754,13 @@ void ImGui::ShowMetricsWindow(bool* p_open) } }; - ImGuiContext& g = *GImGui; // Access private state + // Access private state, we are going to display the draw lists from last frame + ImGuiContext& g = *GImGui; Funcs::NodeWindows(g.Windows, "Windows"); - if (ImGui::TreeNode("DrawList", "Active DrawLists (%d)", g.DrawDataLists[0].Size)) + if (ImGui::TreeNode("DrawList", "Active DrawLists (%d)", g.DrawDataBuilder.Layers[0].Size)) { - for (int layer = 0; layer < IM_ARRAYSIZE(g.DrawDataLists); layer++) - for (int i = 0; i < g.DrawDataLists[layer].Size; i++) - Funcs::NodeDrawList(g.DrawDataLists[0][i], "DrawList"); + for (int i = 0; i < g.DrawDataBuilder.Layers[0].Size; i++) + Funcs::NodeDrawList(g.DrawDataBuilder.Layers[0][i], "DrawList"); ImGui::TreePop(); } if (ImGui::TreeNode("Popups", "Open Popups Stack (%d)", g.OpenPopupStack.Size)) diff --git a/imgui_internal.h b/imgui_internal.h index a0909f88834a..2c67cfcd362a 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -463,6 +463,16 @@ struct IMGUI_API ImDrawListSharedData ImDrawListSharedData(); }; +struct ImDrawDataBuilder +{ + ImVector Layers[3]; // Layered for: regular, popup, tooltip + + void Clear() { for (int n = 0; n < IM_ARRAYSIZE(Layers); n++) Layers[n].resize(0); } + void ClearFreeMemory() { for (int n = 0; n < IM_ARRAYSIZE(Layers); n++) Layers[n].clear(); } + IMGUI_API void FlattenIntoSingleLayer(); + IMGUI_API void SetupDrawData(ImDrawData* out_draw_data); +}; + // Storage for SetNexWindow** functions struct ImGuiNextWindowData { @@ -547,7 +557,7 @@ struct ImGuiContext // Render ImDrawData DrawData; // Main ImDrawData instance to pass render information to the user - ImVector DrawDataLists[3]; + ImDrawDataBuilder DrawDataBuilder; float ModalWindowDarkeningRatio; ImDrawList OverlayDrawList; // Optional software render of mouse cursors, if io.MouseDrawCursor is set + a few debug overlays ImGuiMouseCursor MouseCursor; From 0c06b43e6b5b0cb01a31c1985bd5009cf61ebc71 Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 15 Jan 2018 17:55:38 +0100 Subject: [PATCH 446/823] Metrics: Tweaks to hover-window-drawlist to see window bounding box. --- imgui.cpp | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 89afeced7c36..1937e96fb89f 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -11662,7 +11662,7 @@ void ImGui::ShowMetricsWindow(bool* p_open) struct Funcs { - static void NodeDrawList(ImDrawList* draw_list, const char* label) + static void NodeDrawList(ImGuiWindow* window, ImDrawList* draw_list, const char* label) { bool node_open = ImGui::TreeNode(draw_list, "%s: '%s' %d vtx, %d indices, %d cmds", label, draw_list->_OwnerName ? draw_list->_OwnerName : "", draw_list->VtxBuffer.Size, draw_list->IdxBuffer.Size, draw_list->CmdBuffer.Size); if (draw_list == ImGui::GetWindowDrawList()) @@ -11672,10 +11672,13 @@ void ImGui::ShowMetricsWindow(bool* p_open) if (node_open) ImGui::TreePop(); return; } + + ImDrawList* overlay_draw_list = &GImGui->OverlayDrawList; // Render additional visuals into the top-most draw list + if (window && ImGui::IsItemHovered()) + overlay_draw_list->AddRect(window->Pos, window->Pos + window->Size, IM_COL32(255, 255, 0, 255)); if (!node_open) return; - ImDrawList* overlay_draw_list = &GImGui->OverlayDrawList; // Render additional visuals into the top-most draw list int elem_offset = 0; for (const ImDrawCmd* pcmd = draw_list->CmdBuffer.begin(); pcmd < draw_list->CmdBuffer.end(); elem_offset += pcmd->ElemCount, pcmd++) { @@ -11741,10 +11744,8 @@ void ImGui::ShowMetricsWindow(bool* p_open) { if (!ImGui::TreeNode(window, "%s '%s', %d @ 0x%p", label, window->Name, window->Active || window->WasActive, window)) return; - NodeDrawList(window->DrawList, "DrawList"); + NodeDrawList(window, window->DrawList, "DrawList"); ImGui::BulletText("Pos: (%.1f,%.1f), Size: (%.1f,%.1f), SizeContents (%.1f,%.1f)", window->Pos.x, window->Pos.y, window->Size.x, window->Size.y, window->SizeContents.x, window->SizeContents.y); - if (ImGui::IsItemHovered()) - GImGui->OverlayDrawList.AddRect(window->Pos, window->Pos + window->Size, IM_COL32(255,255,0,255)); ImGui::BulletText("Scroll: (%.2f/%.2f,%.2f/%.2f)", window->Scroll.x, GetScrollMaxX(window), window->Scroll.y, GetScrollMaxY(window)); ImGui::BulletText("Active: %d, WriteAccessed: %d", window->Active, window->WriteAccessed); if (window->RootWindow != window) NodeWindow(window->RootWindow, "RootWindow"); @@ -11760,7 +11761,7 @@ void ImGui::ShowMetricsWindow(bool* p_open) if (ImGui::TreeNode("DrawList", "Active DrawLists (%d)", g.DrawDataBuilder.Layers[0].Size)) { for (int i = 0; i < g.DrawDataBuilder.Layers[0].Size; i++) - Funcs::NodeDrawList(g.DrawDataBuilder.Layers[0][i], "DrawList"); + Funcs::NodeDrawList(NULL, g.DrawDataBuilder.Layers[0][i], "DrawList"); ImGui::TreePop(); } if (ImGui::TreeNode("Popups", "Open Popups Stack (%d)", g.OpenPopupStack.Size)) From 1182174d818802e2c2692b515f0710224a53ffb6 Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 15 Jan 2018 18:00:13 +0100 Subject: [PATCH 447/823] Internals: DrawData: We don't need an intermediate layer for popups. --- imgui.cpp | 2 -- imgui_internal.h | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 1937e96fb89f..f33ab67fef8d 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2895,8 +2895,6 @@ static void AddWindowToDrawDataSelectLayer(ImDrawDataBuilder* builder, ImGuiWind ImGuiContext& g = *GImGui; g.IO.MetricsActiveWindows++; if (window->Flags & ImGuiWindowFlags_Tooltip) - AddWindowToRenderList(&builder->Layers[2], window); - else if (window->Flags & ImGuiWindowFlags_Popup) AddWindowToRenderList(&builder->Layers[1], window); else AddWindowToRenderList(&builder->Layers[0], window); diff --git a/imgui_internal.h b/imgui_internal.h index 2c67cfcd362a..81230757f356 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -465,7 +465,7 @@ struct IMGUI_API ImDrawListSharedData struct ImDrawDataBuilder { - ImVector Layers[3]; // Layered for: regular, popup, tooltip + ImVector Layers[2]; // Global layers for: regular, tooltip void Clear() { for (int n = 0; n < IM_ARRAYSIZE(Layers); n++) Layers[n].resize(0); } void ClearFreeMemory() { for (int n = 0; n < IM_ARRAYSIZE(Layers); n++) Layers[n].clear(); } From 28a76af185b180a3cc8fa210635746a93941a9a8 Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 15 Jan 2018 19:09:10 +0100 Subject: [PATCH 448/823] Internal: DrawData: Tidying, renaming. --- imgui.cpp | 44 +++++++++++++++++++++----------------------- imgui.h | 3 ++- imgui_internal.h | 1 - 3 files changed, 23 insertions(+), 25 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index f33ab67fef8d..f1f54e6bcb4b 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -648,8 +648,8 @@ static ImGuiWindow* CreateNewWindow(const char* name, ImVec2 size, ImGuiWind static void CheckStacksSize(ImGuiWindow* window, bool write); static ImVec2 CalcNextScrollFromScrollTargetAndClamp(ImGuiWindow* window); -static void AddDrawListToRenderList(ImVector* out_render_list, ImDrawList* draw_list); -static void AddWindowToRenderList(ImVector* out_render_list, ImGuiWindow* window); +static void AddDrawListToDrawData(ImVector* out_render_list, ImDrawList* draw_list); +static void AddWindowToDrawData(ImVector* out_render_list, ImGuiWindow* window); static void AddWindowToSortedBuffer(ImVector* out_sorted_windows, ImGuiWindow* window); static ImGuiWindowSettings* AddWindowSettings(const char* name); @@ -2303,9 +2303,7 @@ void ImGui::NewFrame() g.OverlayDrawList.Flags = (g.Style.AntiAliasedLines ? ImDrawListFlags_AntiAliasedLines : 0) | (g.Style.AntiAliasedFill ? ImDrawListFlags_AntiAliasedFill : 0); // Mark rendering data as invalid to prevent user who may have a handle on it to use it - g.DrawData.Valid = false; - g.DrawData.CmdLists = NULL; - g.DrawData.CmdListsCount = g.DrawData.TotalVtxCount = g.DrawData.TotalIdxCount = 0; + g.DrawData.Clear(); // Clear reference to active widget if the widget isn't alive anymore if (!g.HoveredIdPreviousFrame) @@ -2846,7 +2844,7 @@ static void AddWindowToSortedBuffer(ImVector& out_sorted_windows, } } -static void AddDrawListToRenderList(ImVector* out_render_list, ImDrawList* draw_list) +static void AddDrawListToDrawData(ImVector* out_render_list, ImDrawList* draw_list) { if (draw_list->CmdBuffer.empty()) return; @@ -2879,25 +2877,25 @@ static void AddDrawListToRenderList(ImVector* out_render_list, ImDr out_render_list->push_back(draw_list); } -static void AddWindowToRenderList(ImVector* out_render_list, ImGuiWindow* window) +static void AddWindowToDrawData(ImVector* out_render_list, ImGuiWindow* window) { - AddDrawListToRenderList(out_render_list, window->DrawList); + AddDrawListToDrawData(out_render_list, window->DrawList); for (int i = 0; i < window->DC.ChildWindows.Size; i++) { ImGuiWindow* child = window->DC.ChildWindows[i]; if (child->Active && child->HiddenFrames <= 0) // clipped children may have been marked not active - AddWindowToRenderList(out_render_list, child); + AddWindowToDrawData(out_render_list, child); } } -static void AddWindowToDrawDataSelectLayer(ImDrawDataBuilder* builder, ImGuiWindow* window) +static void AddWindowToDrawDataSelectLayer(ImGuiWindow* window) { ImGuiContext& g = *GImGui; g.IO.MetricsActiveWindows++; if (window->Flags & ImGuiWindowFlags_Tooltip) - AddWindowToRenderList(&builder->Layers[1], window); + AddWindowToDrawData(&g.DrawDataBuilder.Layers[1], window); else - AddWindowToRenderList(&builder->Layers[0], window); + AddWindowToDrawData(&g.DrawDataBuilder.Layers[0], window); } void ImDrawDataBuilder::FlattenIntoSingleLayer() @@ -2918,16 +2916,16 @@ void ImDrawDataBuilder::FlattenIntoSingleLayer() } } -void ImDrawDataBuilder::SetupDrawData(ImDrawData* out_draw_data) +static void SetupDrawData(ImVector* draw_lists, ImDrawData* out_draw_data) { out_draw_data->Valid = true; - out_draw_data->CmdLists = (Layers[0].Size > 0) ? Layers[0].Data : NULL; - out_draw_data->CmdListsCount = Layers[0].Size; + out_draw_data->CmdLists = (draw_lists->Size > 0) ? draw_lists->Data : NULL; + out_draw_data->CmdListsCount = draw_lists->Size; out_draw_data->TotalVtxCount = out_draw_data->TotalIdxCount = 0; - for (int n = 0; n < Layers[0].Size; n++) + for (int n = 0; n < draw_lists->Size; n++) { - out_draw_data->TotalVtxCount += Layers[0][n]->VtxBuffer.Size; - out_draw_data->TotalIdxCount += Layers[0][n]->IdxBuffer.Size; + out_draw_data->TotalVtxCount += draw_lists->Data[n]->VtxBuffer.Size; + out_draw_data->TotalIdxCount += draw_lists->Data[n]->IdxBuffer.Size; } } @@ -3054,11 +3052,11 @@ void ImGui::Render() // Gather windows to render g.IO.MetricsRenderVertices = g.IO.MetricsRenderIndices = g.IO.MetricsActiveWindows = 0; g.DrawDataBuilder.Clear(); - for (int i = 0; i != g.Windows.Size; i++) + for (int n = 0; n != g.Windows.Size; n++) { - ImGuiWindow* window = g.Windows[i]; + ImGuiWindow* window = g.Windows[n]; if (window->Active && window->HiddenFrames <= 0 && (window->Flags & (ImGuiWindowFlags_ChildWindow)) == 0) - AddWindowToDrawDataSelectLayer(&g.DrawDataBuilder, window); + AddWindowToDrawDataSelectLayer(window); } g.DrawDataBuilder.FlattenIntoSingleLayer(); @@ -3077,10 +3075,10 @@ void ImGui::Render() g.OverlayDrawList.PopTextureID(); } if (!g.OverlayDrawList.VtxBuffer.empty()) - AddDrawListToRenderList(&g.DrawDataBuilder.Layers[0], &g.OverlayDrawList); + AddDrawListToDrawData(&g.DrawDataBuilder.Layers[0], &g.OverlayDrawList); // Setup ImDrawData structure for end-user - g.DrawDataBuilder.SetupDrawData(&g.DrawData); + SetupDrawData(&g.DrawDataBuilder.Layers[0], &g.DrawData); g.IO.MetricsRenderVertices = g.DrawData.TotalVtxCount; g.IO.MetricsRenderIndices = g.DrawData.TotalIdxCount; diff --git a/imgui.h b/imgui.h index 6742540822b3..ee6f01354d90 100644 --- a/imgui.h +++ b/imgui.h @@ -1495,7 +1495,8 @@ struct ImDrawData int TotalIdxCount; // For convenience, sum of all cmd_lists idx_buffer.Size // Functions - ImDrawData() { Valid = false; CmdLists = NULL; CmdListsCount = TotalVtxCount = TotalIdxCount = 0; } + ImDrawData() { Clear(); } + void Clear() { Valid = false; CmdLists = NULL; CmdListsCount = TotalVtxCount = TotalIdxCount = 0; } // Draw lists are owned by the ImGuiContext and only pointed to here. IMGUI_API void DeIndexAllBuffers(); // For backward compatibility or convenience: convert all buffers from indexed to de-indexed, in case you cannot render indexed. Note: this is slow and most likely a waste of resources. Always prefer indexed rendering! IMGUI_API void ScaleClipRects(const ImVec2& sc); // Helper to scale the ClipRect field of each ImDrawCmd. Use if your final output buffer is at a different scale than ImGui expects, or if there is a difference between your window resolution and framebuffer resolution. }; diff --git a/imgui_internal.h b/imgui_internal.h index 81230757f356..0f90942c96b9 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -470,7 +470,6 @@ struct ImDrawDataBuilder void Clear() { for (int n = 0; n < IM_ARRAYSIZE(Layers); n++) Layers[n].resize(0); } void ClearFreeMemory() { for (int n = 0; n < IM_ARRAYSIZE(Layers); n++) Layers[n].clear(); } IMGUI_API void FlattenIntoSingleLayer(); - IMGUI_API void SetupDrawData(ImDrawData* out_draw_data); }; // Storage for SetNexWindow** functions From a221d253f3afcbd822f87e385c33906e388e8705 Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 15 Jan 2018 19:09:40 +0100 Subject: [PATCH 449/823] Nav: Comment. --- imgui_internal.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/imgui_internal.h b/imgui_internal.h index 1f39a662517b..0c8f4088ca00 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -583,7 +583,7 @@ struct ImGuiContext ImGuiID NavNextActivateId; // Set by ActivateItem(), queued until next frame ImGuiID NavJustMovedToId; // Just navigated to this id (result of a successfully MoveRequest) ImRect NavScoringRectScreen; // Rectangle used for scoring, in screen space. Based of window->DC.NavRefRectRel[], modified for directional navigation scoring. - ImGuiWindow* NavWindowingTarget; + ImGuiWindow* NavWindowingTarget; // When selecting a window (holding Menu+FocusPrev/Next, or equivalent of CTRL-TAB) this window is temporarily displayed front-most. float NavWindowingDisplayAlpha; bool NavWindowingToggleLayer; int NavLayer; // Layer we are navigating on. For now the system is hard-coded for 0=main contents and 1=menu/title bar, may expose layers later. From 05885b2e6df95d7c044f60581ddcef4b7c59c831 Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 15 Jan 2018 20:18:01 +0100 Subject: [PATCH 450/823] Merge fix. --- imgui.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/imgui.cpp b/imgui.cpp index 300dc7a3357f..406f3a303374 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -3869,7 +3869,7 @@ void ImGui::Render() AddWindowToDrawDataSelectLayer(window); } if (g.NavWindowingTarget && g.NavWindowingTarget->Active && g.NavWindowingTarget->HiddenFrames <= 0) // NavWindowingTarget is always temporarily displayed as the front-most window - AddWindowToDrawDataSelectLayer(&g.DrawDataBuilder, g.NavWindowingTarget); + AddWindowToDrawDataSelectLayer(g.NavWindowingTarget); g.DrawDataBuilder.FlattenIntoSingleLayer(); // Draw software mouse cursor if requested From 2f15cc085599db9a6e4d799a45b015574d76fc78 Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 15 Jan 2018 21:55:32 +0100 Subject: [PATCH 451/823] Nav: Fixed popup wrap-around logic for windows with scrolling. (#787) --- imgui.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/imgui.cpp b/imgui.cpp index 406f3a303374..c8cf136682bb 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -4790,7 +4790,7 @@ static void NavProcessMoveRequestWrapAround(ImGuiWindow* window) { g.NavMoveRequestForwardStep = 1; NavMoveRequestCancel(); - g.NavWindow->NavRectRel[0].Min.y = g.NavWindow->NavRectRel[0].Max.y = (g.NavMoveDir == ImGuiDir_Up) ? window->SizeFull.y : 0.0f; + g.NavWindow->NavRectRel[0].Min.y = g.NavWindow->NavRectRel[0].Max.y = ((g.NavMoveDir == ImGuiDir_Up) ? ImMax(window->SizeFull.y, window->SizeContents.y) : 0.0f) - window->Scroll.y; } } From 7ccbb765e2c0acc84b3e5d7335050e0af8bb555f Mon Sep 17 00:00:00 2001 From: omar Date: Wed, 17 Jan 2018 12:15:00 +0100 Subject: [PATCH 452/823] InputText: Cursor X position not lost when clicking outside on an item that's submitted after the InputText(). It was only noticeable when restoring focus programmatically. (#1418, #1554) --- imgui.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index f1f54e6bcb4b..904fe86100ec 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -8607,8 +8607,11 @@ bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2 } else if (io.MouseClicked[0] && !edit_state.SelectedAllMouseLock) { - stb_textedit_click(&edit_state, &edit_state.StbState, mouse_x, mouse_y); - edit_state.CursorAnimReset(); + if (hovered) + { + stb_textedit_click(&edit_state, &edit_state.StbState, mouse_x, mouse_y); + edit_state.CursorAnimReset(); + } } else if (io.MouseDown[0] && !edit_state.SelectedAllMouseLock && (io.MouseDelta.x != 0.0f || io.MouseDelta.y != 0.0f)) { From cc15512bfc2a3abb88d7c8969ecf6d67611e1b96 Mon Sep 17 00:00:00 2001 From: omar Date: Wed, 17 Jan 2018 12:15:24 +0100 Subject: [PATCH 453/823] InputText: Minor tweak. --- imgui_internal.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/imgui_internal.h b/imgui_internal.h index 0f90942c96b9..6873a293122f 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -357,7 +357,7 @@ struct IMGUI_API ImGuiTextEditState void CursorClamp() { StbState.cursor = ImMin(StbState.cursor, CurLenW); StbState.select_start = ImMin(StbState.select_start, CurLenW); StbState.select_end = ImMin(StbState.select_end, CurLenW); } bool HasSelection() const { return StbState.select_start != StbState.select_end; } void ClearSelection() { StbState.select_start = StbState.select_end = StbState.cursor; } - void SelectAll() { StbState.select_start = 0; StbState.select_end = CurLenW; StbState.cursor = StbState.select_end; StbState.has_preferred_x = false; } + void SelectAll() { StbState.select_start = 0; StbState.cursor = StbState.select_end = CurLenW; StbState.has_preferred_x = false; } void OnKeyPressed(int key); }; From d1f726cd9db6445e18090e488c8ee8ca4fe6e09c Mon Sep 17 00:00:00 2001 From: omar Date: Wed, 17 Jan 2018 12:46:07 +0100 Subject: [PATCH 454/823] Comments about Begin/End pair and handling of return value. --- imgui.h | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/imgui.h b/imgui.h index ee6f01354d90..91671ead3418 100644 --- a/imgui.h +++ b/imgui.h @@ -145,11 +145,11 @@ namespace ImGui IMGUI_API void ShowUserGuide(); // add basic help/info block (not a window): how to manipulate ImGui as a end-user (mouse/keyboard controls). // Window - IMGUI_API bool Begin(const char* name, bool* p_open = NULL, ImGuiWindowFlags flags = 0); // push window to the stack and start appending to it. see .cpp for details. return false when window is collapsed, so you can early out in your code. 'bool* p_open' creates a widget on the upper-right to close the window (which sets your bool to false). - IMGUI_API void End(); // finish appending to current window, pop it off the window stack. - IMGUI_API bool BeginChild(const char* str_id, const ImVec2& size = ImVec2(0,0), bool border = false, ImGuiWindowFlags extra_flags = 0); // begin a scrolling region. size==0.0f: use remaining window size, size<0.0f: use remaining window size minus abs(size). size>0.0f: fixed size. each axis can use a different mode, e.g. ImVec2(0,400). - IMGUI_API bool BeginChild(ImGuiID id, const ImVec2& size = ImVec2(0,0), bool border = false, ImGuiWindowFlags extra_flags = 0); // " - IMGUI_API void EndChild(); + IMGUI_API bool Begin(const char* name, bool* p_open = NULL, ImGuiWindowFlags flags = 0); // push window to the stack and start appending to it. see .cpp for details. return false when window is collapsed (so you can early out in your code) but you always need to call End() regardless. 'bool* p_open' creates a widget on the upper-right to close the window (which sets your bool to false). + IMGUI_API void End(); // always call even if Begin() return false (which indicates a collapsed window)! finish appending to current window, pop it off the window stack. + IMGUI_API bool BeginChild(const char* str_id, const ImVec2& size = ImVec2(0,0), bool border = false, ImGuiWindowFlags flags = 0); // begin a scrolling region. size==0.0f: use remaining window size, size<0.0f: use remaining window size minus abs(size). size>0.0f: fixed size. each axis can use a different mode, e.g. ImVec2(0,400). + IMGUI_API bool BeginChild(ImGuiID id, const ImVec2& size = ImVec2(0,0), bool border = false, ImGuiWindowFlags flags = 0); // " + IMGUI_API void EndChild(); // always call even if BeginChild() return false (which indicates a collapsed or clipping child window) IMGUI_API ImVec2 GetContentRegionMax(); // current content boundaries (typically window boundaries including scrolling, or current column boundaries), in windows coordinates IMGUI_API ImVec2 GetContentRegionAvail(); // == GetContentRegionMax() - GetCursorPos() IMGUI_API float GetContentRegionAvailWidth(); // @@ -303,7 +303,7 @@ namespace ImGui // The new BeginCombo()/EndCombo() api allows you to manage your contents and selection state however you want it. // The old Combo() api are helpers over BeginCombo()/EndCombo() which are kept available for convenience purpose. IMGUI_API bool BeginCombo(const char* label, const char* preview_value, ImGuiComboFlags flags = 0); - IMGUI_API void EndCombo(); + IMGUI_API void EndCombo(); // only call EndCombo() if BeginCombo() returns true! IMGUI_API bool Combo(const char* label, int* current_item, const char* const items[], int items_count, int popup_max_height_in_items = -1); IMGUI_API bool Combo(const char* label, int* current_item, const char* items_separated_by_zeros, int popup_max_height_in_items = -1); // Separate items with \0 within a string, end item-list with \0\0. e.g. "One\0Two\0Three\0" IMGUI_API bool Combo(const char* label, int* current_item, bool(*items_getter)(void* data, int idx, const char** out_text), void* data, int items_count, int popup_max_height_in_items = -1); @@ -397,23 +397,23 @@ namespace ImGui IMGUI_API void EndTooltip(); // Menus - IMGUI_API bool BeginMainMenuBar(); // create and append to a full screen menu-bar. only call EndMainMenuBar() if this returns true! - IMGUI_API void EndMainMenuBar(); - IMGUI_API bool BeginMenuBar(); // append to menu-bar of current window (requires ImGuiWindowFlags_MenuBar flag set on parent window). only call EndMenuBar() if this returns true! - IMGUI_API void EndMenuBar(); + IMGUI_API bool BeginMainMenuBar(); // create and append to a full screen menu-bar. + IMGUI_API void EndMainMenuBar(); // only call EndMainMenuBar() if BeginMainMenuBar() returns true! + IMGUI_API bool BeginMenuBar(); // append to menu-bar of current window (requires ImGuiWindowFlags_MenuBar flag set on parent window). + IMGUI_API void EndMenuBar(); // only call EndMenuBar() if BeginMenuBar() returns true! IMGUI_API bool BeginMenu(const char* label, bool enabled = true); // create a sub-menu entry. only call EndMenu() if this returns true! - IMGUI_API void EndMenu(); + IMGUI_API void EndMenu(); // only call EndBegin() if BeginMenu() returns true! IMGUI_API bool MenuItem(const char* label, const char* shortcut = NULL, bool selected = false, bool enabled = true); // return true when activated. shortcuts are displayed for convenience but not processed by ImGui at the moment IMGUI_API bool MenuItem(const char* label, const char* shortcut, bool* p_selected, bool enabled = true); // return true when activated + toggle (*p_selected) if p_selected != NULL // Popups IMGUI_API void OpenPopup(const char* str_id); // call to mark popup as open (don't call every frame!). popups are closed when user click outside, or if CloseCurrentPopup() is called within a BeginPopup()/EndPopup() block. By default, Selectable()/MenuItem() are calling CloseCurrentPopup(). Popup identifiers are relative to the current ID-stack (so OpenPopup and BeginPopup needs to be at the same level). - IMGUI_API bool BeginPopup(const char* str_id, ImGuiWindowFlags flags = 0); // return true if the popup is open, and you can start outputting to it. only call EndPopup() if BeginPopup() returned true! + IMGUI_API bool BeginPopup(const char* str_id, ImGuiWindowFlags flags = 0); // return true if the popup is open, and you can start outputting to it. only call EndPopup() if BeginPopup() returns true! IMGUI_API bool BeginPopupContextItem(const char* str_id = NULL, int mouse_button = 1); // helper to open and begin popup when clicked on last item. if you can pass a NULL str_id only if the previous item had an id. If you want to use that on a non-interactive item such as Text() you need to pass in an explicit ID here. read comments in .cpp! IMGUI_API bool BeginPopupContextWindow(const char* str_id = NULL, int mouse_button = 1, bool also_over_items = true); // helper to open and begin popup when clicked on current window. IMGUI_API bool BeginPopupContextVoid(const char* str_id = NULL, int mouse_button = 1); // helper to open and begin popup when clicked in void (where there are no imgui windows). IMGUI_API bool BeginPopupModal(const char* name, bool* p_open = NULL, ImGuiWindowFlags flags = 0); // modal dialog (regular window with title bar, block interactions behind the modal window, can't close the modal window by clicking outside) - IMGUI_API void EndPopup(); + IMGUI_API void EndPopup(); // only call EndPopup() if BeginPopupXXX() returns true! IMGUI_API bool OpenPopupOnItemClick(const char* str_id = NULL, int mouse_button = 1); // helper to open popup when clicked on last item. return true when just opened. IMGUI_API bool IsPopupOpen(const char* str_id); // return true if the popup is open IMGUI_API void CloseCurrentPopup(); // close the popup we have begin-ed into. clicking on a MenuItem or Selectable automatically close the current popup. @@ -430,10 +430,10 @@ namespace ImGui // [BETA API] Missing Demo code. API may evolve. IMGUI_API bool BeginDragDropSource(ImGuiDragDropFlags flags = 0, int mouse_button = 0); // call when the current item is active. If this return true, you can call SetDragDropPayload() + EndDragDropSource() IMGUI_API bool SetDragDropPayload(const char* type, const void* data, size_t size, ImGuiCond cond = 0);// type is a user defined string of maximum 8 characters. Strings starting with '_' are reserved for dear imgui internal types. Data is copied and held by imgui. - IMGUI_API void EndDragDropSource(); + IMGUI_API void EndDragDropSource(); // only call EndDragDropSource() if BeginDragDropSource() returns true! IMGUI_API bool BeginDragDropTarget(); // call after submitting an item that may receive an item. If this returns true, you can call AcceptDragDropPayload() + EndDragDropTarget() IMGUI_API const ImGuiPayload* AcceptDragDropPayload(const char* type, ImGuiDragDropFlags flags = 0); // accept contents of a given type. If ImGuiDragDropFlags_AcceptBeforeDelivery is set you can peek into the payload before the mouse button is released. - IMGUI_API void EndDragDropTarget(); + IMGUI_API void EndDragDropTarget(); // only call EndDragDropTarget() if BeginDragDropTarget() returns true! // Clipping IMGUI_API void PushClipRect(const ImVec2& clip_rect_min, const ImVec2& clip_rect_max, bool intersect_with_current_clip_rect); @@ -473,8 +473,8 @@ namespace ImGui IMGUI_API ImVec2 CalcTextSize(const char* text, const char* text_end = NULL, bool hide_text_after_double_hash = false, float wrap_width = -1.0f); IMGUI_API void CalcListClipping(int items_count, float items_height, int* out_items_display_start, int* out_items_display_end); // calculate coarse clipping for large list of evenly sized items. Prefer using the ImGuiListClipper higher-level helper if you can. - IMGUI_API bool BeginChildFrame(ImGuiID id, const ImVec2& size, ImGuiWindowFlags extra_flags = 0); // helper to create a child window / scrolling region that looks like a normal widget frame - IMGUI_API void EndChildFrame(); + IMGUI_API bool BeginChildFrame(ImGuiID id, const ImVec2& size, ImGuiWindowFlags flags = 0); // helper to create a child window / scrolling region that looks like a normal widget frame + IMGUI_API void EndChildFrame(); // always call EndChildFrame() regardless of BeginChildFrame() return values (which indicates a collapsed/clipped window) IMGUI_API ImVec4 ColorConvertU32ToFloat4(ImU32 in); IMGUI_API ImU32 ColorConvertFloat4ToU32(const ImVec4& in); From 60d5dc79029e4d9c778c9635987c1f11260ce87e Mon Sep 17 00:00:00 2001 From: omar Date: Thu, 18 Jan 2018 10:01:36 +0100 Subject: [PATCH 455/823] Examples: SDL: Fixed mapping of Insert key (#1555, fix bug introduced in #1541) --- examples/sdl_opengl2_example/imgui_impl_sdl.cpp | 2 +- examples/sdl_opengl3_example/imgui_impl_sdl_gl3.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/sdl_opengl2_example/imgui_impl_sdl.cpp b/examples/sdl_opengl2_example/imgui_impl_sdl.cpp index ac9200837e56..689c7ad37a80 100644 --- a/examples/sdl_opengl2_example/imgui_impl_sdl.cpp +++ b/examples/sdl_opengl2_example/imgui_impl_sdl.cpp @@ -214,7 +214,7 @@ bool ImGui_ImplSdlGL2_Init(SDL_Window* window) io.KeyMap[ImGuiKey_PageDown] = SDL_SCANCODE_PAGEDOWN; io.KeyMap[ImGuiKey_Home] = SDL_SCANCODE_HOME; io.KeyMap[ImGuiKey_End] = SDL_SCANCODE_END; - io.KeyMap[ImGuiKey_Insert] = SDLK_INSERT; + io.KeyMap[ImGuiKey_Insert] = SDL_SCANCODE_INSERT; io.KeyMap[ImGuiKey_Delete] = SDLK_DELETE; io.KeyMap[ImGuiKey_Backspace] = SDLK_BACKSPACE; io.KeyMap[ImGuiKey_Enter] = SDLK_RETURN; diff --git a/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.cpp b/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.cpp index f9e970f38daf..b16a0300cbaa 100644 --- a/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.cpp +++ b/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.cpp @@ -325,7 +325,7 @@ bool ImGui_ImplSdlGL3_Init(SDL_Window* window) io.KeyMap[ImGuiKey_PageDown] = SDL_SCANCODE_PAGEDOWN; io.KeyMap[ImGuiKey_Home] = SDL_SCANCODE_HOME; io.KeyMap[ImGuiKey_End] = SDL_SCANCODE_END; - io.KeyMap[ImGuiKey_Insert] = SDLK_INSERT; + io.KeyMap[ImGuiKey_Insert] = SDL_SCANCODE_INSERT; io.KeyMap[ImGuiKey_Delete] = SDLK_DELETE; io.KeyMap[ImGuiKey_Backspace] = SDLK_BACKSPACE; io.KeyMap[ImGuiKey_Enter] = SDLK_RETURN; From 932d3f01988276e5a9ee969b3faaf443c21c118d Mon Sep 17 00:00:00 2001 From: omar Date: Thu, 18 Jan 2018 10:06:58 +0100 Subject: [PATCH 456/823] NewFrame(): Added an assert to detect incorrect filling of the io.KeyMap[] array earlier. (#1555) + comments. --- imgui.cpp | 2 ++ imgui.h | 6 +++--- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 904fe86100ec..bd218caf2999 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2282,6 +2282,8 @@ void ImGui::NewFrame() IM_ASSERT(g.Style.CurveTessellationTol > 0.0f && "Invalid style setting"); IM_ASSERT(g.Style.Alpha >= 0.0f && g.Style.Alpha <= 1.0f && "Invalid style setting. Alpha cannot be negative (allows us to avoid a few clamps in color computations)"); IM_ASSERT((g.FrameCount == 0 || g.FrameCountEnded == g.FrameCount) && "Forgot to call Render() or EndFrame() at the end of the previous frame?"); + for (int n = 0; n < ImGuiKey_COUNT; n++) + IM_ASSERT(g.IO.KeyMap[n] >= -1 && g.IO.KeyMap[n] < IM_ARRAYSIZE(g.IO.KeysDown) && "io.KeyMap[] contains an out of bound value (need to be 0..512, or -1 for unmapped key)"); // Initialize on first frame if (!g.Initialized) diff --git a/imgui.h b/imgui.h index 91671ead3418..c6bf05ded035 100644 --- a/imgui.h +++ b/imgui.h @@ -881,8 +881,8 @@ struct ImGuiIO const char* LogFilename; // = "imgui_log.txt" // Path to .log file (default parameter to ImGui::LogToFile when no file is specified). float MouseDoubleClickTime; // = 0.30f // Time for a double-click, in seconds. float MouseDoubleClickMaxDist; // = 6.0f // Distance threshold to stay in to validate a double-click, in pixels. - float MouseDragThreshold; // = 6.0f // Distance threshold before considering we are dragging - int KeyMap[ImGuiKey_COUNT]; // // Map of indices into the KeysDown[512] entries array + float MouseDragThreshold; // = 6.0f // Distance threshold before considering we are dragging. + int KeyMap[ImGuiKey_COUNT]; // // Map of indices into the KeysDown[512] entries array which represent your "native" keyboard state. float KeyRepeatDelay; // = 0.250f // When holding a key/button, time before it starts repeating, in seconds (for buttons in Repeat mode, etc.). float KeyRepeatRate; // = 0.050f // When holding a key/button, rate at which it repeats, in seconds. void* UserData; // = NULL // Store your own data for retrieval by callbacks. @@ -936,7 +936,7 @@ struct ImGuiIO bool KeyShift; // Keyboard modifier pressed: Shift bool KeyAlt; // Keyboard modifier pressed: Alt bool KeySuper; // Keyboard modifier pressed: Cmd/Super/Windows - bool KeysDown[512]; // Keyboard keys that are pressed (in whatever storage order you naturally have access to keyboard data) + bool KeysDown[512]; // Keyboard keys that are pressed (ideally left in the "native" order your engine has access to keyboard keys, so you can use your own defines/enums for keys). ImWchar InputCharacters[16+1]; // List of characters input (translated by user from keypress+keyboard state). Fill using AddInputCharacter() helper. // Functions From 63d47e8328db78784c99685ee3b9f1e57e6a1aff Mon Sep 17 00:00:00 2001 From: omar Date: Thu, 18 Jan 2018 17:32:34 +0100 Subject: [PATCH 457/823] Drag and Drop: Increased payload type string to 12 characters instead of 8.(#143) --- imgui.cpp | 2 +- imgui.h | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index bd218caf2999..7b65d37af8a4 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -11397,7 +11397,7 @@ bool ImGui::SetDragDropPayload(const char* type, const void* data, size_t data_s cond = ImGuiCond_Always; IM_ASSERT(type != NULL); - IM_ASSERT(strlen(type) < IM_ARRAYSIZE(payload.DataType)); // Payload type can be at most 8 characters longs + IM_ASSERT(strlen(type) < IM_ARRAYSIZE(payload.DataType) && "Payload type can be at most 12 characters long"); IM_ASSERT((data != NULL && data_size > 0) || (data == NULL && data_size == 0)); IM_ASSERT(cond == ImGuiCond_Always || cond == ImGuiCond_Once); IM_ASSERT(payload.SourceId != 0); // Not called between BeginDragDropSource() and EndDragDropSource() diff --git a/imgui.h b/imgui.h index c6bf05ded035..33c66b454c9d 100644 --- a/imgui.h +++ b/imgui.h @@ -429,7 +429,7 @@ namespace ImGui // Drag and Drop // [BETA API] Missing Demo code. API may evolve. IMGUI_API bool BeginDragDropSource(ImGuiDragDropFlags flags = 0, int mouse_button = 0); // call when the current item is active. If this return true, you can call SetDragDropPayload() + EndDragDropSource() - IMGUI_API bool SetDragDropPayload(const char* type, const void* data, size_t size, ImGuiCond cond = 0);// type is a user defined string of maximum 8 characters. Strings starting with '_' are reserved for dear imgui internal types. Data is copied and held by imgui. + IMGUI_API bool SetDragDropPayload(const char* type, const void* data, size_t size, ImGuiCond cond = 0);// type is a user defined string of maximum 12 characters. Strings starting with '_' are reserved for dear imgui internal types. Data is copied and held by imgui. IMGUI_API void EndDragDropSource(); // only call EndDragDropSource() if BeginDragDropSource() returns true! IMGUI_API bool BeginDragDropTarget(); // call after submitting an item that may receive an item. If this returns true, you can call AcceptDragDropPayload() + EndDragDropTarget() IMGUI_API const ImGuiPayload* AcceptDragDropPayload(const char* type, ImGuiDragDropFlags flags = 0); // accept contents of a given type. If ImGuiDragDropFlags_AcceptBeforeDelivery is set you can peek into the payload before the mouse button is released. @@ -1239,7 +1239,7 @@ struct ImGuiPayload ImGuiID SourceId; // Source item id ImGuiID SourceParentId; // Source parent id (if available) int DataFrameCount; // Data timestamp - char DataType[8 + 1]; // Data type tag (short user-supplied string) + char DataType[12 + 1]; // Data type tag (short user-supplied string, 12 characters max) bool Preview; // Set when AcceptDragDropPayload() was called and mouse has been hovering the target item (nb: handle overlapping drag targets) bool Delivery; // Set when AcceptDragDropPayload() was called and mouse button is released over the target item. From c2ffce3e5aef30d17fdc89c3afa3ee55ed9376b6 Mon Sep 17 00:00:00 2001 From: omar Date: Thu, 18 Jan 2018 17:39:40 +0100 Subject: [PATCH 458/823] Drag and Drop: Fix comment. Removed IMGUI_PAYLOAD_TYPE_DOCKABLE from master branch. (#143) --- imgui.h | 2 +- imgui_internal.h | 3 --- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/imgui.h b/imgui.h index 33c66b454c9d..f5d8eb0297e5 100644 --- a/imgui.h +++ b/imgui.h @@ -655,7 +655,7 @@ enum ImGuiDragDropFlags_ ImGuiDragDropFlags_AcceptPeekOnly = ImGuiDragDropFlags_AcceptBeforeDelivery | ImGuiDragDropFlags_AcceptNoDrawDefaultRect // For peeking ahead and inspecting the payload before delivery. }; -// Standard Drag and Drop payload types. You can define you own payload types using 8-characters long strings. Types starting with '_' are defined by Dear ImGui. +// Standard Drag and Drop payload types. You can define you own payload types using 12-characters long strings. Types starting with '_' are defined by Dear ImGui. #define IMGUI_PAYLOAD_TYPE_COLOR_3F "_COL3F" // float[3] // Standard type for colors, without alpha. User code may use this type. #define IMGUI_PAYLOAD_TYPE_COLOR_4F "_COL4F" // float[4] // Standard type for colors. User code may use this type. diff --git a/imgui_internal.h b/imgui_internal.h index 6873a293122f..4a5edfc1f634 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -170,9 +170,6 @@ template void IM_DELETE(T*& p) { if (p) { p->~T(); ImGui::MemFree(p // Types //----------------------------------------------------------------------------- -// Internal Drag and Drop payload types. String starting with '_' are reserved for Dear ImGui. -#define IMGUI_PAYLOAD_TYPE_DOCKABLE "_IMDOCK" // ImGuiWindow* // [Internal] Docking/tabs - enum ImGuiButtonFlags_ { ImGuiButtonFlags_Repeat = 1 << 0, // hold to repeat From 74dc70c543107c14ddd9e635908958c90524abef Mon Sep 17 00:00:00 2001 From: omar Date: Fri, 19 Jan 2018 09:16:26 +0100 Subject: [PATCH 459/823] DragFloat: Fix/workaround for backends which do not preserve a valid mouse position when dragged out of bounds. (#1559) --- imgui.cpp | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 7b65d37af8a4..7dbc92c15203 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -3580,6 +3580,7 @@ bool ImGui::IsMousePosValid(const ImVec2* mouse_pos) return mouse_pos->x >= MOUSE_INVALID && mouse_pos->y >= MOUSE_INVALID; } +// NB: This is only valid if IsMousePosValid(). Backends in theory should always keep mouse position valid when dragging even outside the client window. ImVec2 ImGui::GetMouseDragDelta(int button, float lock_threshold) { ImGuiContext& g = *GImGui; @@ -7622,16 +7623,19 @@ bool ImGui::DragBehavior(const ImRect& frame_bb, ImGuiID id, float* v, float v_s float v_cur = g.DragCurrentValue; const ImVec2 mouse_drag_delta = GetMouseDragDelta(0, 1.0f); float adjust_delta = 0.0f; - //if (g.ActiveIdSource == ImGuiInputSource_Mouse) + if (IsMousePosValid()) { - adjust_delta = mouse_drag_delta.x - g.DragLastMouseDelta.x; - if (g.IO.KeyShift && g.DragSpeedScaleFast >= 0.0f) - adjust_delta *= g.DragSpeedScaleFast; - if (g.IO.KeyAlt && g.DragSpeedScaleSlow >= 0.0f) - adjust_delta *= g.DragSpeedScaleSlow; + //if (g.ActiveIdSource == ImGuiInputSource_Mouse) + { + adjust_delta = mouse_drag_delta.x - g.DragLastMouseDelta.x; + if (g.IO.KeyShift && g.DragSpeedScaleFast >= 0.0f) + adjust_delta *= g.DragSpeedScaleFast; + if (g.IO.KeyAlt && g.DragSpeedScaleSlow >= 0.0f) + adjust_delta *= g.DragSpeedScaleSlow; + } + g.DragLastMouseDelta.x = mouse_drag_delta.x; } adjust_delta *= v_speed; - g.DragLastMouseDelta.x = mouse_drag_delta.x; if (fabsf(adjust_delta) > 0.0f) { From ce17e0f27496ad09dcfc2ca8f605ed2494ed909d Mon Sep 17 00:00:00 2001 From: omar Date: Fri, 19 Jan 2018 09:25:31 +0100 Subject: [PATCH 460/823] Examples: SDL: Using SDL_WINDOW_INPUT_FOCUS instead of SDL_WINDOW_MOUSE_FOCUS (which is ~~hovered). We should use SDL_CaptureMouse + SDL_WINDOW_MOUSE_CAPTURE_FLAG which requires SDL 2.0.4 will give it a try shortly. (#1559) --- examples/sdl_opengl2_example/imgui_impl_sdl.cpp | 2 +- examples/sdl_opengl3_example/imgui_impl_sdl_gl3.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/sdl_opengl2_example/imgui_impl_sdl.cpp b/examples/sdl_opengl2_example/imgui_impl_sdl.cpp index 689c7ad37a80..205840b6e6ec 100644 --- a/examples/sdl_opengl2_example/imgui_impl_sdl.cpp +++ b/examples/sdl_opengl2_example/imgui_impl_sdl.cpp @@ -274,7 +274,7 @@ void ImGui_ImplSdlGL2_NewFrame(SDL_Window *window) // (we already got mouse wheel, keyboard keys & characters from SDL_PollEvent()) int mx, my; Uint32 mouseMask = SDL_GetMouseState(&mx, &my); - if (SDL_GetWindowFlags(window) & SDL_WINDOW_MOUSE_FOCUS) + if (SDL_GetWindowFlags(window) & SDL_WINDOW_INPUT_FOCUS) io.MousePos = ImVec2((float)mx, (float)my); else io.MousePos = ImVec2(-FLT_MAX,-FLT_MAX); diff --git a/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.cpp b/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.cpp index b16a0300cbaa..037f07239884 100644 --- a/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.cpp +++ b/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.cpp @@ -385,7 +385,7 @@ void ImGui_ImplSdlGL3_NewFrame(SDL_Window* window) // (we already got mouse wheel, keyboard keys & characters from SDL_PollEvent()) int mx, my; Uint32 mouseMask = SDL_GetMouseState(&mx, &my); - if (SDL_GetWindowFlags(window) & SDL_WINDOW_MOUSE_FOCUS) + if (SDL_GetWindowFlags(window) & SDL_WINDOW_INPUT_FOCUS) io.MousePos = ImVec2((float)mx, (float)my); else io.MousePos = ImVec2(-FLT_MAX, -FLT_MAX); From 15fd5b6c4c77e8f168d854118dd80d7a49808410 Mon Sep 17 00:00:00 2001 From: omar Date: Fri, 19 Jan 2018 09:43:28 +0100 Subject: [PATCH 461/823] Examples: SDL: Minor renaming. --- examples/sdl_opengl2_example/imgui_impl_sdl.cpp | 8 ++++---- examples/sdl_opengl3_example/imgui_impl_sdl_gl3.cpp | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/examples/sdl_opengl2_example/imgui_impl_sdl.cpp b/examples/sdl_opengl2_example/imgui_impl_sdl.cpp index 205840b6e6ec..263017dcb2c5 100644 --- a/examples/sdl_opengl2_example/imgui_impl_sdl.cpp +++ b/examples/sdl_opengl2_example/imgui_impl_sdl.cpp @@ -273,15 +273,15 @@ void ImGui_ImplSdlGL2_NewFrame(SDL_Window *window) // Setup inputs // (we already got mouse wheel, keyboard keys & characters from SDL_PollEvent()) int mx, my; - Uint32 mouseMask = SDL_GetMouseState(&mx, &my); + Uint32 mouse_buttons = SDL_GetMouseState(&mx, &my); if (SDL_GetWindowFlags(window) & SDL_WINDOW_INPUT_FOCUS) io.MousePos = ImVec2((float)mx, (float)my); else io.MousePos = ImVec2(-FLT_MAX,-FLT_MAX); - io.MouseDown[0] = g_MousePressed[0] || (mouseMask & SDL_BUTTON(SDL_BUTTON_LEFT)) != 0; // If a mouse press event came, always pass it as "mouse held this frame", so we don't miss click-release events that are shorter than 1 frame. - io.MouseDown[1] = g_MousePressed[1] || (mouseMask & SDL_BUTTON(SDL_BUTTON_RIGHT)) != 0; - io.MouseDown[2] = g_MousePressed[2] || (mouseMask & SDL_BUTTON(SDL_BUTTON_MIDDLE)) != 0; + io.MouseDown[0] = g_MousePressed[0] || (mouse_buttons & SDL_BUTTON(SDL_BUTTON_LEFT)) != 0; // If a mouse press event came, always pass it as "mouse held this frame", so we don't miss click-release events that are shorter than 1 frame. + io.MouseDown[1] = g_MousePressed[1] || (mouse_buttons & SDL_BUTTON(SDL_BUTTON_RIGHT)) != 0; + io.MouseDown[2] = g_MousePressed[2] || (mouse_buttons & SDL_BUTTON(SDL_BUTTON_MIDDLE)) != 0; g_MousePressed[0] = g_MousePressed[1] = g_MousePressed[2] = false; io.MouseWheel = g_MouseWheel; diff --git a/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.cpp b/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.cpp index 037f07239884..e9a1393cdea6 100644 --- a/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.cpp +++ b/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.cpp @@ -384,15 +384,15 @@ void ImGui_ImplSdlGL3_NewFrame(SDL_Window* window) // Setup inputs // (we already got mouse wheel, keyboard keys & characters from SDL_PollEvent()) int mx, my; - Uint32 mouseMask = SDL_GetMouseState(&mx, &my); + Uint32 mouse_buttons = SDL_GetMouseState(&mx, &my); if (SDL_GetWindowFlags(window) & SDL_WINDOW_INPUT_FOCUS) io.MousePos = ImVec2((float)mx, (float)my); else io.MousePos = ImVec2(-FLT_MAX, -FLT_MAX); - io.MouseDown[0] = g_MousePressed[0] || (mouseMask & SDL_BUTTON(SDL_BUTTON_LEFT)) != 0; // If a mouse press event came, always pass it as "mouse held this frame", so we don't miss click-release events that are shorter than 1 frame. - io.MouseDown[1] = g_MousePressed[1] || (mouseMask & SDL_BUTTON(SDL_BUTTON_RIGHT)) != 0; - io.MouseDown[2] = g_MousePressed[2] || (mouseMask & SDL_BUTTON(SDL_BUTTON_MIDDLE)) != 0; + io.MouseDown[0] = g_MousePressed[0] || (mouse_buttons & SDL_BUTTON(SDL_BUTTON_LEFT)) != 0; // If a mouse press event came, always pass it as "mouse held this frame", so we don't miss click-release events that are shorter than 1 frame. + io.MouseDown[1] = g_MousePressed[1] || (mouse_buttons & SDL_BUTTON(SDL_BUTTON_RIGHT)) != 0; + io.MouseDown[2] = g_MousePressed[2] || (mouse_buttons & SDL_BUTTON(SDL_BUTTON_MIDDLE)) != 0; g_MousePressed[0] = g_MousePressed[1] = g_MousePressed[2] = false; io.MouseWheel = g_MouseWheel; From 79dca9d5e6f127f6dd236ca7146f28b55550489f Mon Sep 17 00:00:00 2001 From: omar Date: Fri, 19 Jan 2018 09:45:27 +0100 Subject: [PATCH 462/823] Examples: SDL+GL2: Renamed imgui_impl_sdl.* to imgui_impl_sdl_gl2.* for consistency and to emphasis on GL2-ness. --- examples/sdl_opengl2_example/build_win32.bat | 2 +- .../{imgui_impl_sdl.cpp => imgui_impl_sdl_gl2.cpp} | 6 +++--- .../{imgui_impl_sdl.h => imgui_impl_sdl_gl2.h} | 0 examples/sdl_opengl2_example/main.cpp | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) rename examples/sdl_opengl2_example/{imgui_impl_sdl.cpp => imgui_impl_sdl_gl2.cpp} (97%) rename examples/sdl_opengl2_example/{imgui_impl_sdl.h => imgui_impl_sdl_gl2.h} (100%) diff --git a/examples/sdl_opengl2_example/build_win32.bat b/examples/sdl_opengl2_example/build_win32.bat index 3cf81e60a781..799561dec6c5 100644 --- a/examples/sdl_opengl2_example/build_win32.bat +++ b/examples/sdl_opengl2_example/build_win32.bat @@ -1,3 +1,3 @@ @REM Build for Visual Studio compiler. Run your copy of vcvars32.bat or vcvarsall.bat to setup command-line compiler. mkdir Debug -cl /nologo /Zi /MD /I ..\.. /I ..\libs\gl3w /I %SDL_DIR%\include main.cpp imgui_impl_sdl.cpp ..\..\imgui*.cpp ..\libs\gl3w\GL\gl3w.c /FeDebug/sdl_opengl2_example.exe /FoDebug/ /link /libpath:%SDL_DIR%\lib\x86 SDL2.lib SDL2main.lib opengl32.lib /subsystem:console +cl /nologo /Zi /MD /I ..\.. /I ..\libs\gl3w /I %SDL_DIR%\include main.cpp imgui_impl_sdl_gl2.cpp ..\..\imgui*.cpp ..\libs\gl3w\GL\gl3w.c /FeDebug/sdl_opengl2_example.exe /FoDebug/ /link /libpath:%SDL_DIR%\lib\x86 SDL2.lib SDL2main.lib opengl32.lib /subsystem:console diff --git a/examples/sdl_opengl2_example/imgui_impl_sdl.cpp b/examples/sdl_opengl2_example/imgui_impl_sdl_gl2.cpp similarity index 97% rename from examples/sdl_opengl2_example/imgui_impl_sdl.cpp rename to examples/sdl_opengl2_example/imgui_impl_sdl_gl2.cpp index 263017dcb2c5..154a6d238cb6 100644 --- a/examples/sdl_opengl2_example/imgui_impl_sdl.cpp +++ b/examples/sdl_opengl2_example/imgui_impl_sdl_gl2.cpp @@ -19,7 +19,7 @@ #include #include #include -#include "imgui_impl_sdl.h" +#include "imgui_impl_sdl_gl2.h" // Data static double g_Time = 0.0f; @@ -30,7 +30,7 @@ static GLuint g_FontTexture = 0; // This is the main rendering function that you have to implement and provide to ImGui (via setting up 'RenderDrawListsFn' in the ImGuiIO structure) // Note that this implementation is little overcomplicated because we are saving/setting up/restoring every OpenGL state explicitly, in order to be able to run within any OpenGL engine that doesn't do so. // 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) -void ImGui_ImplSdl_RenderDrawLists(ImDrawData* draw_data) +void ImGui_ImplSdlGL2_RenderDrawLists(ImDrawData* draw_data) { // Avoid rendering when minimized, scale coordinates for retina displays (screen coordinates != framebuffer coordinates) ImGuiIO& io = ImGui::GetIO(); @@ -226,7 +226,7 @@ bool ImGui_ImplSdlGL2_Init(SDL_Window* window) io.KeyMap[ImGuiKey_Y] = SDLK_y; io.KeyMap[ImGuiKey_Z] = SDLK_z; - io.RenderDrawListsFn = ImGui_ImplSdl_RenderDrawLists; // Alternatively you can set this to NULL and call ImGui::GetDrawData() after ImGui::Render() to get the same ImDrawData pointer. + io.RenderDrawListsFn = ImGui_ImplSdlGL2_RenderDrawLists; // Alternatively you can set this to NULL and call ImGui::GetDrawData() after ImGui::Render() to get the same ImDrawData pointer. io.SetClipboardTextFn = ImGui_ImplSdl_SetClipboardText; io.GetClipboardTextFn = ImGui_ImplSdl_GetClipboardText; io.ClipboardUserData = NULL; diff --git a/examples/sdl_opengl2_example/imgui_impl_sdl.h b/examples/sdl_opengl2_example/imgui_impl_sdl_gl2.h similarity index 100% rename from examples/sdl_opengl2_example/imgui_impl_sdl.h rename to examples/sdl_opengl2_example/imgui_impl_sdl_gl2.h diff --git a/examples/sdl_opengl2_example/main.cpp b/examples/sdl_opengl2_example/main.cpp index 1396fcca023a..21b567a835e9 100644 --- a/examples/sdl_opengl2_example/main.cpp +++ b/examples/sdl_opengl2_example/main.cpp @@ -7,7 +7,7 @@ // See imgui_impl_sdl.cpp for details. #include -#include "imgui_impl_sdl.h" +#include "imgui_impl_sdl_gl2.h" #include #include #include From ba99900023000e6c7bb6001100744549f869f53b Mon Sep 17 00:00:00 2001 From: omar Date: Fri, 19 Jan 2018 09:48:23 +0100 Subject: [PATCH 463/823] Examples: GLFW+GL2: Renamed imgui_impl_glfw.* to imgui_impl_glfw_gl2.* for consistency and to emphasis on GL2-ness. --- examples/opengl2_example/Makefile | 2 +- .../{imgui_impl_glfw.cpp => imgui_impl_glfw_gl2.cpp} | 2 +- .../{imgui_impl_glfw.h => imgui_impl_glfw_gl2.h} | 0 examples/opengl2_example/main.cpp | 2 +- examples/opengl2_example/opengl2_example.vcxproj | 4 ++-- examples/opengl2_example/opengl2_example.vcxproj.filters | 4 ++-- 6 files changed, 7 insertions(+), 7 deletions(-) rename examples/opengl2_example/{imgui_impl_glfw.cpp => imgui_impl_glfw_gl2.cpp} (99%) rename examples/opengl2_example/{imgui_impl_glfw.h => imgui_impl_glfw_gl2.h} (100%) diff --git a/examples/opengl2_example/Makefile b/examples/opengl2_example/Makefile index 932aebedeefc..f10c59a8d03d 100644 --- a/examples/opengl2_example/Makefile +++ b/examples/opengl2_example/Makefile @@ -11,7 +11,7 @@ #CXX = g++ EXE = opengl2_example -OBJS = main.o imgui_impl_glfw.o +OBJS = main.o imgui_impl_glfw_gl2.o OBJS += ../../imgui.o ../../imgui_demo.o ../../imgui_draw.o UNAME_S := $(shell uname -s) diff --git a/examples/opengl2_example/imgui_impl_glfw.cpp b/examples/opengl2_example/imgui_impl_glfw_gl2.cpp similarity index 99% rename from examples/opengl2_example/imgui_impl_glfw.cpp rename to examples/opengl2_example/imgui_impl_glfw_gl2.cpp index d2eb657f602e..4ce831d9be6d 100644 --- a/examples/opengl2_example/imgui_impl_glfw.cpp +++ b/examples/opengl2_example/imgui_impl_glfw_gl2.cpp @@ -16,7 +16,7 @@ // https://github.com/ocornut/imgui #include -#include "imgui_impl_glfw.h" +#include "imgui_impl_glfw_gl2.h" // GLFW #include diff --git a/examples/opengl2_example/imgui_impl_glfw.h b/examples/opengl2_example/imgui_impl_glfw_gl2.h similarity index 100% rename from examples/opengl2_example/imgui_impl_glfw.h rename to examples/opengl2_example/imgui_impl_glfw_gl2.h diff --git a/examples/opengl2_example/main.cpp b/examples/opengl2_example/main.cpp index ef098e54ae8f..6359f5b6253f 100644 --- a/examples/opengl2_example/main.cpp +++ b/examples/opengl2_example/main.cpp @@ -7,7 +7,7 @@ // See imgui_impl_glfw.cpp for details. #include -#include "imgui_impl_glfw.h" +#include "imgui_impl_glfw_gl2.h" #include #include diff --git a/examples/opengl2_example/opengl2_example.vcxproj b/examples/opengl2_example/opengl2_example.vcxproj index a6cbebd637cd..237eba7dab03 100644 --- a/examples/opengl2_example/opengl2_example.vcxproj +++ b/examples/opengl2_example/opengl2_example.vcxproj @@ -153,14 +153,14 @@ - + - + diff --git a/examples/opengl2_example/opengl2_example.vcxproj.filters b/examples/opengl2_example/opengl2_example.vcxproj.filters index f2282bf69824..3cc7ee9e1792 100644 --- a/examples/opengl2_example/opengl2_example.vcxproj.filters +++ b/examples/opengl2_example/opengl2_example.vcxproj.filters @@ -16,7 +16,7 @@ imgui - + sources @@ -33,7 +33,7 @@ imgui - + sources From 00351ee2ab7562e07aaec70c3923a58385b6f760 Mon Sep 17 00:00:00 2001 From: omar Date: Fri, 19 Jan 2018 09:53:55 +0100 Subject: [PATCH 464/823] Examples: SDL: Minor renaming. --- examples/sdl_opengl2_example/imgui_impl_sdl_gl2.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/examples/sdl_opengl2_example/imgui_impl_sdl_gl2.cpp b/examples/sdl_opengl2_example/imgui_impl_sdl_gl2.cpp index 154a6d238cb6..802a31be6eef 100644 --- a/examples/sdl_opengl2_example/imgui_impl_sdl_gl2.cpp +++ b/examples/sdl_opengl2_example/imgui_impl_sdl_gl2.cpp @@ -111,12 +111,12 @@ void ImGui_ImplSdlGL2_RenderDrawLists(ImDrawData* draw_data) glScissor(last_scissor_box[0], last_scissor_box[1], (GLsizei)last_scissor_box[2], (GLsizei)last_scissor_box[3]); } -static const char* ImGui_ImplSdl_GetClipboardText(void*) +static const char* ImGui_ImplSdlGL2_GetClipboardText(void*) { return SDL_GetClipboardText(); } -static void ImGui_ImplSdl_SetClipboardText(void*, const char* text) +static void ImGui_ImplSdlGL2_SetClipboardText(void*, const char* text) { SDL_SetClipboardText(text); } @@ -227,8 +227,8 @@ bool ImGui_ImplSdlGL2_Init(SDL_Window* window) io.KeyMap[ImGuiKey_Z] = SDLK_z; io.RenderDrawListsFn = ImGui_ImplSdlGL2_RenderDrawLists; // Alternatively you can set this to NULL and call ImGui::GetDrawData() after ImGui::Render() to get the same ImDrawData pointer. - io.SetClipboardTextFn = ImGui_ImplSdl_SetClipboardText; - io.GetClipboardTextFn = ImGui_ImplSdl_GetClipboardText; + io.SetClipboardTextFn = ImGui_ImplSdlGL2_SetClipboardText; + io.GetClipboardTextFn = ImGui_ImplSdlGL2_GetClipboardText; io.ClipboardUserData = NULL; #ifdef _WIN32 @@ -267,7 +267,7 @@ void ImGui_ImplSdlGL2_NewFrame(SDL_Window *window) // Setup time step Uint32 time = SDL_GetTicks(); double current_time = time / 1000.0; - io.DeltaTime = g_Time > 0.0 ? (float)(current_time - g_Time) : (float)(1.0f/60.0f); + io.DeltaTime = g_Time > 0.0 ? (float)(current_time - g_Time) : (float)(1.0f / 60.0f); g_Time = current_time; // Setup inputs From f3e510a9bf508337244433f8c1dcc6c120dcc990 Mon Sep 17 00:00:00 2001 From: omar Date: Fri, 19 Jan 2018 10:46:54 +0100 Subject: [PATCH 465/823] Examples: SDL: Using SDL_CaptureMouse() to retrieve coordinates outside of client area when dragging. (#1559) Digging into sdl window/mouse stuff will also be useful for multi-viewport work. --- .../imgui_impl_sdl_gl2.cpp | 28 +++++++++++------ .../imgui_impl_sdl_gl3.cpp | 30 ++++++++++++------- 2 files changed, 39 insertions(+), 19 deletions(-) diff --git a/examples/sdl_opengl2_example/imgui_impl_sdl_gl2.cpp b/examples/sdl_opengl2_example/imgui_impl_sdl_gl2.cpp index 802a31be6eef..6bcd4c388ab8 100644 --- a/examples/sdl_opengl2_example/imgui_impl_sdl_gl2.cpp +++ b/examples/sdl_opengl2_example/imgui_impl_sdl_gl2.cpp @@ -270,23 +270,33 @@ void ImGui_ImplSdlGL2_NewFrame(SDL_Window *window) io.DeltaTime = g_Time > 0.0 ? (float)(current_time - g_Time) : (float)(1.0f / 60.0f); g_Time = current_time; - // Setup inputs - // (we already got mouse wheel, keyboard keys & characters from SDL_PollEvent()) + // Setup mouse inputs (we already got mouse wheel, keyboard keys & characters from our event handler) int mx, my; Uint32 mouse_buttons = SDL_GetMouseState(&mx, &my); - if (SDL_GetWindowFlags(window) & SDL_WINDOW_INPUT_FOCUS) - io.MousePos = ImVec2((float)mx, (float)my); - else - io.MousePos = ImVec2(-FLT_MAX,-FLT_MAX); - + io.MousePos = ImVec2(-FLT_MAX, -FLT_MAX); + io.MouseWheel = g_MouseWheel; io.MouseDown[0] = g_MousePressed[0] || (mouse_buttons & SDL_BUTTON(SDL_BUTTON_LEFT)) != 0; // If a mouse press event came, always pass it as "mouse held this frame", so we don't miss click-release events that are shorter than 1 frame. io.MouseDown[1] = g_MousePressed[1] || (mouse_buttons & SDL_BUTTON(SDL_BUTTON_RIGHT)) != 0; io.MouseDown[2] = g_MousePressed[2] || (mouse_buttons & SDL_BUTTON(SDL_BUTTON_MIDDLE)) != 0; g_MousePressed[0] = g_MousePressed[1] = g_MousePressed[2] = false; - - io.MouseWheel = g_MouseWheel; g_MouseWheel = 0.0f; + // We need to use SDL_CaptureMouse() to easily retrieve mouse coordinates outside of the client area. This is only supported from SDL 2.0.4 (released Jan 2016) +#if (SDL_MAJOR_VERSION >= 2) && (SDL_MINOR_VERSION >= 0) && (SDL_PATCHLEVEL >= 4) + if ((SDL_GetWindowFlags(window) & (SDL_WINDOW_MOUSE_FOCUS | SDL_WINDOW_MOUSE_CAPTURE)) != 0) + io.MousePos = ImVec2((float)mx, (float)my); + bool any_mouse_button_down = false; + for (int n = 0; n < IM_ARRAYSIZE(io.MouseDown); n++) + any_mouse_button_down |= io.MouseDown[n]; + if (any_mouse_button_down && (SDL_GetWindowFlags(window) & SDL_WINDOW_MOUSE_CAPTURE) == 0) + SDL_CaptureMouse(SDL_TRUE); + if (!any_mouse_button_down && (SDL_GetWindowFlags(window) & SDL_WINDOW_MOUSE_CAPTURE) != 0) + SDL_CaptureMouse(SDL_FALSE); +#else + if ((SDL_GetWindowFlags(window) & SDL_WINDOW_INPUT_FOCUS) != 0) + io.MousePos = ImVec2((float)mx, (float)my); +#endif + // Hide OS mouse cursor if ImGui is drawing it SDL_ShowCursor(io.MouseDrawCursor ? 0 : 1); diff --git a/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.cpp b/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.cpp index e9a1393cdea6..ef1957a5d33c 100644 --- a/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.cpp +++ b/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.cpp @@ -381,23 +381,33 @@ void ImGui_ImplSdlGL3_NewFrame(SDL_Window* window) io.DeltaTime = g_Time > 0.0 ? (float)(current_time - g_Time) : (float)(1.0f / 60.0f); g_Time = current_time; - // Setup inputs - // (we already got mouse wheel, keyboard keys & characters from SDL_PollEvent()) + // Setup mouse inputs (we already got mouse wheel, keyboard keys & characters from our event handler) int mx, my; Uint32 mouse_buttons = SDL_GetMouseState(&mx, &my); - if (SDL_GetWindowFlags(window) & SDL_WINDOW_INPUT_FOCUS) - io.MousePos = ImVec2((float)mx, (float)my); - else - io.MousePos = ImVec2(-FLT_MAX, -FLT_MAX); - - io.MouseDown[0] = g_MousePressed[0] || (mouse_buttons & SDL_BUTTON(SDL_BUTTON_LEFT)) != 0; // If a mouse press event came, always pass it as "mouse held this frame", so we don't miss click-release events that are shorter than 1 frame. + io.MousePos = ImVec2(-FLT_MAX, -FLT_MAX); + io.MouseWheel = g_MouseWheel; + io.MouseDown[0] = g_MousePressed[0] || (mouse_buttons & SDL_BUTTON(SDL_BUTTON_LEFT)) != 0; // If a mouse press event came, always pass it as "mouse held this frame", so we don't miss click-release events that are shorter than 1 frame. io.MouseDown[1] = g_MousePressed[1] || (mouse_buttons & SDL_BUTTON(SDL_BUTTON_RIGHT)) != 0; io.MouseDown[2] = g_MousePressed[2] || (mouse_buttons & SDL_BUTTON(SDL_BUTTON_MIDDLE)) != 0; g_MousePressed[0] = g_MousePressed[1] = g_MousePressed[2] = false; - - io.MouseWheel = g_MouseWheel; g_MouseWheel = 0.0f; + // We need to use SDL_CaptureMouse() to easily retrieve mouse coordinates outside of the client area. This is only supported from SDL 2.0.4 (released Jan 2016) +#if (SDL_MAJOR_VERSION >= 2) && (SDL_MINOR_VERSION >= 0) && (SDL_PATCHLEVEL >= 4) + if ((SDL_GetWindowFlags(window) & (SDL_WINDOW_MOUSE_FOCUS | SDL_WINDOW_MOUSE_CAPTURE)) != 0) + io.MousePos = ImVec2((float)mx, (float)my); + bool any_mouse_button_down = false; + for (int n = 0; n < IM_ARRAYSIZE(io.MouseDown); n++) + any_mouse_button_down |= io.MouseDown[n]; + if (any_mouse_button_down && (SDL_GetWindowFlags(window) & SDL_WINDOW_MOUSE_CAPTURE) == 0) + SDL_CaptureMouse(SDL_TRUE); + if (!any_mouse_button_down && (SDL_GetWindowFlags(window) & SDL_WINDOW_MOUSE_CAPTURE) != 0) + SDL_CaptureMouse(SDL_FALSE); +#else + if ((SDL_GetWindowFlags(window) & SDL_WINDOW_INPUT_FOCUS) != 0) + io.MousePos = ImVec2((float)mx, (float)my); +#endif + // Hide OS mouse cursor if ImGui is drawing it SDL_ShowCursor(io.MouseDrawCursor ? 0 : 1); From 0978f00911df253196b0a013b77adc4c8202fdcb Mon Sep 17 00:00:00 2001 From: omar Date: Fri, 19 Jan 2018 15:06:39 +0100 Subject: [PATCH 466/823] MovingWindow: Track click offset based on root window (undo 514d30d8cdd659b6af3c93512583a00ee18ecbaf). This should not affect the patch used for #1345 as the RootWindow for Child+Tooltip window points to itself now. --- imgui.cpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 7dbc92c15203..41ce93da78db 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2393,11 +2393,8 @@ void ImGui::NewFrame() if (g.IO.MouseDown[0]) { // MovingWindow = window we clicked on, could be a child window. We track it to preserve Focus and so that ActiveIdWindow == MovingWindow and ActiveId == MovingWindow->MoveId for consistency. - // actually_moving_window = MovingWindow->RootWindow. ImGuiWindow* actually_moving_window = g.MovingWindow->RootWindow; ImVec2 pos = g.IO.MousePos - g.ActiveIdClickOffset; - if (actually_moving_window != g.MovingWindow) - pos += actually_moving_window->PosFloat - g.MovingWindow->PosFloat; if (actually_moving_window->PosFloat.x != pos.x || actually_moving_window->PosFloat.y != pos.y) { MarkIniSettingsDirty(actually_moving_window); @@ -2979,7 +2976,7 @@ void ImGui::EndFrame() // Set ActiveId even if the _NoMove flag is set, without it dragging away from a window with _NoMove would activate hover on other windows. FocusWindow(g.HoveredWindow); SetActiveID(g.HoveredWindow->MoveId, g.HoveredWindow); - g.ActiveIdClickOffset = g.IO.MousePos - g.HoveredWindow->Pos; + g.ActiveIdClickOffset = g.IO.MousePos - g.HoveredRootWindow->Pos; if (!(g.HoveredWindow->Flags & ImGuiWindowFlags_NoMove) && !(g.HoveredRootWindow->Flags & ImGuiWindowFlags_NoMove)) { g.MovingWindow = g.HoveredWindow; From 42a612d7c9fa69fc87e0fd37eef800e7b875add1 Mon Sep 17 00:00:00 2001 From: omar Date: Fri, 19 Jan 2018 15:33:35 +0100 Subject: [PATCH 467/823] Begin: Removed asserts that got in the way of some flags combination. (#1345) --- imgui.cpp | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 41ce93da78db..b38120bdea8c 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -4649,12 +4649,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) // Apply minimum/maximum window size constraints and final size window->SizeFull = CalcSizeAfterConstraint(window, window->SizeFull); - window->Size = window->Collapsed ? window->TitleBarRect().GetSize() : window->SizeFull; - if ((flags & ImGuiWindowFlags_ChildWindow) && !(flags & ImGuiWindowFlags_Popup)) - { - IM_ASSERT(window_size_x_set_by_api && window_size_y_set_by_api); // Submitted by BeginChild() - window->Size = window->SizeFull; - } + window->Size = window->Collapsed && !(flags & ImGuiWindowFlags_ChildWindow) ? window->TitleBarRect().GetSize() : window->SizeFull; // SCROLLBAR STATUS From e5a6e85f6d24da8506f8141f258c9f4f0c9d3281 Mon Sep 17 00:00:00 2001 From: omar Date: Fri, 19 Jan 2018 15:37:25 +0100 Subject: [PATCH 468/823] Basic undocumented/unsupported combination of Child+Tooltip. The full feature needs substancially more work but this is enough for simplest cases. (#1345) --- imgui.cpp | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index b38120bdea8c..ca142754d728 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -4560,10 +4560,12 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) // When reusing window again multiple times a frame, just append content (don't need to setup again) if (first_begin_of_the_frame) { + const bool is_pinned_child_tooltip = (flags & ImGuiWindowFlags_ChildWindow) && (flags & ImGuiWindowFlags_Tooltip); // FIXME-WIP: Undocumented behavior of Child+Tooltip for pinned tooltip (#1345) + // Initialize window->ParentWindow = parent_window; window->RootWindow = window->RootNonPopupWindow = window; - if (parent_window && (flags & ImGuiWindowFlags_ChildWindow)) + if (parent_window && (flags & ImGuiWindowFlags_ChildWindow) && !is_pinned_child_tooltip) window->RootWindow = parent_window->RootWindow; if (parent_window && !(flags & ImGuiWindowFlags_Modal) && (flags & (ImGuiWindowFlags_ChildWindow | ImGuiWindowFlags_Popup))) window->RootNonPopupWindow = parent_window->RootNonPopupWindow; @@ -4681,8 +4683,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) { window->BeginOrderWithinParent = parent_window->DC.ChildWindows.Size; parent_window->DC.ChildWindows.push_back(window); - - if (!(flags & ImGuiWindowFlags_Popup) && !window_pos_set_by_api) + if (!(flags & ImGuiWindowFlags_Popup) && !window_pos_set_by_api && !is_pinned_child_tooltip) window->Pos = window->PosFloat = parent_window->DC.CursorPos; } @@ -4713,7 +4714,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) } // Position tooltip (always follows mouse) - if ((flags & ImGuiWindowFlags_Tooltip) != 0 && !window_pos_set_by_api) + if ((flags & ImGuiWindowFlags_Tooltip) != 0 && !window_pos_set_by_api && !is_pinned_child_tooltip) { ImVec2 ref_pos = g.IO.MousePos; ImRect rect_to_avoid(ref_pos.x - 16, ref_pos.y - 8, ref_pos.x + 24, ref_pos.y + 24); // FIXME: Completely hard-coded. Store boxes in mouse cursor data? Scale? Center on cursor hit-point? @@ -4771,7 +4772,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) window->DrawList->Flags = (g.Style.AntiAliasedLines ? ImDrawListFlags_AntiAliasedLines : 0) | (g.Style.AntiAliasedFill ? ImDrawListFlags_AntiAliasedFill : 0); window->DrawList->PushTextureID(g.Font->ContainerAtlas->TexID); ImRect fullscreen_rect(GetVisibleRect()); - if ((flags & ImGuiWindowFlags_ChildWindow) && !(flags & ImGuiWindowFlags_Popup)) + if ((flags & ImGuiWindowFlags_ChildWindow) && !(flags & ImGuiWindowFlags_Popup) && !is_pinned_child_tooltip) PushClipRect(parent_window->ClipRect.Min, parent_window->ClipRect.Max, true); else PushClipRect(fullscreen_rect.Min, fullscreen_rect.Max, true); From d4bf9b46863be00c7c968051430d6c5b429a04f7 Mon Sep 17 00:00:00 2001 From: omar Date: Fri, 19 Jan 2018 15:47:10 +0100 Subject: [PATCH 469/823] Renaming for consistency. --- imgui.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index ca142754d728..9205dac6a63a 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -4560,12 +4560,12 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) // When reusing window again multiple times a frame, just append content (don't need to setup again) if (first_begin_of_the_frame) { - const bool is_pinned_child_tooltip = (flags & ImGuiWindowFlags_ChildWindow) && (flags & ImGuiWindowFlags_Tooltip); // FIXME-WIP: Undocumented behavior of Child+Tooltip for pinned tooltip (#1345) + const bool window_is_child_tooltip = (flags & ImGuiWindowFlags_ChildWindow) && (flags & ImGuiWindowFlags_Tooltip); // FIXME-WIP: Undocumented behavior of Child+Tooltip for pinned tooltip (#1345) // Initialize window->ParentWindow = parent_window; window->RootWindow = window->RootNonPopupWindow = window; - if (parent_window && (flags & ImGuiWindowFlags_ChildWindow) && !is_pinned_child_tooltip) + if (parent_window && (flags & ImGuiWindowFlags_ChildWindow) && !window_is_child_tooltip) window->RootWindow = parent_window->RootWindow; if (parent_window && !(flags & ImGuiWindowFlags_Modal) && (flags & (ImGuiWindowFlags_ChildWindow | ImGuiWindowFlags_Popup))) window->RootNonPopupWindow = parent_window->RootNonPopupWindow; @@ -4683,7 +4683,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) { window->BeginOrderWithinParent = parent_window->DC.ChildWindows.Size; parent_window->DC.ChildWindows.push_back(window); - if (!(flags & ImGuiWindowFlags_Popup) && !window_pos_set_by_api && !is_pinned_child_tooltip) + if (!(flags & ImGuiWindowFlags_Popup) && !window_pos_set_by_api && !window_is_child_tooltip) window->Pos = window->PosFloat = parent_window->DC.CursorPos; } @@ -4714,7 +4714,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) } // Position tooltip (always follows mouse) - if ((flags & ImGuiWindowFlags_Tooltip) != 0 && !window_pos_set_by_api && !is_pinned_child_tooltip) + if ((flags & ImGuiWindowFlags_Tooltip) != 0 && !window_pos_set_by_api && !window_is_child_tooltip) { ImVec2 ref_pos = g.IO.MousePos; ImRect rect_to_avoid(ref_pos.x - 16, ref_pos.y - 8, ref_pos.x + 24, ref_pos.y + 24); // FIXME: Completely hard-coded. Store boxes in mouse cursor data? Scale? Center on cursor hit-point? @@ -4772,7 +4772,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) window->DrawList->Flags = (g.Style.AntiAliasedLines ? ImDrawListFlags_AntiAliasedLines : 0) | (g.Style.AntiAliasedFill ? ImDrawListFlags_AntiAliasedFill : 0); window->DrawList->PushTextureID(g.Font->ContainerAtlas->TexID); ImRect fullscreen_rect(GetVisibleRect()); - if ((flags & ImGuiWindowFlags_ChildWindow) && !(flags & ImGuiWindowFlags_Popup) && !is_pinned_child_tooltip) + if ((flags & ImGuiWindowFlags_ChildWindow) && !(flags & ImGuiWindowFlags_Popup) && !window_is_child_tooltip) PushClipRect(parent_window->ClipRect.Min, parent_window->ClipRect.Max, true); else PushClipRect(fullscreen_rect.Min, fullscreen_rect.Max, true); From 0b1fecb792ffe00313b43a01f4dadb41e69850e7 Mon Sep 17 00:00:00 2001 From: omar Date: Sat, 20 Jan 2018 12:36:16 +0100 Subject: [PATCH 470/823] Horizontal mouse wheel: renamed io.MouseHorizWheel to io.MouseWheelH. Reorganized the code in NewFrame(). Examples: Updated GLFW+GL and SDL+GL accordingly. (#1463) --- .../opengl2_example/imgui_impl_glfw_gl2.cpp | 13 ++-- .../opengl3_example/imgui_impl_glfw_gl3.cpp | 13 ++-- .../imgui_impl_sdl_gl2.cpp | 21 +++---- .../imgui_impl_sdl_gl3.cpp | 21 +++---- imgui.cpp | 60 +++++++++---------- imgui.h | 4 +- 6 files changed, 59 insertions(+), 73 deletions(-) diff --git a/examples/opengl2_example/imgui_impl_glfw_gl2.cpp b/examples/opengl2_example/imgui_impl_glfw_gl2.cpp index 2b7efc146854..8dcd71e9fac2 100644 --- a/examples/opengl2_example/imgui_impl_glfw_gl2.cpp +++ b/examples/opengl2_example/imgui_impl_glfw_gl2.cpp @@ -31,8 +31,7 @@ static GLFWwindow* g_Window = NULL; static double g_Time = 0.0f; static bool g_MouseJustPressed[3] = { false, false, false }; -static float g_MouseHorizWheel = 0.0f; -static float g_MouseWheel = 0.0f; +static ImVec2 g_MouseWheel = ImVec2(0.0f, 0.0f); static GLuint g_FontTexture = 0; // This is the main rendering function that you have to implement and provide to ImGui (via setting up 'RenderDrawListsFn' in the ImGuiIO structure) @@ -137,8 +136,8 @@ void ImGui_ImplGlfwGL2_MouseButtonCallback(GLFWwindow*, int button, int action, void ImGui_ImplGlfwGL2_ScrollCallback(GLFWwindow*, double xoffset, double yoffset) { - g_MouseHorizWheel += (float)xoffset; // Use fractional mouse wheel. - g_MouseWheel += (float)yoffset; + g_MouseWheel.x += (float)xoffset; // Use fractional mouse wheel. + g_MouseWheel.y += (float)yoffset; } void ImGui_ImplGlfwGL2_KeyCallback(GLFWwindow*, int key, int, int action, int mods) @@ -297,9 +296,9 @@ void ImGui_ImplGlfwGL2_NewFrame() g_MouseJustPressed[i] = false; } - io.MouseHorizWheel = g_MouseHorizWheel; - io.MouseWheel = g_MouseWheel; - g_MouseHorizWheel = g_MouseWheel = 0.0f; + io.MouseWheel = g_MouseWheel.y; + io.MouseWheelH = g_MouseWheel.x; + g_MouseWheel.x = g_MouseWheel.x = 0.0f; // Hide OS mouse cursor if ImGui is drawing it glfwSetInputMode(g_Window, GLFW_CURSOR, io.MouseDrawCursor ? GLFW_CURSOR_HIDDEN : GLFW_CURSOR_NORMAL); diff --git a/examples/opengl3_example/imgui_impl_glfw_gl3.cpp b/examples/opengl3_example/imgui_impl_glfw_gl3.cpp index 8808d8bb1404..79a62531fff3 100644 --- a/examples/opengl3_example/imgui_impl_glfw_gl3.cpp +++ b/examples/opengl3_example/imgui_impl_glfw_gl3.cpp @@ -25,8 +25,7 @@ static GLFWwindow* g_Window = NULL; static double g_Time = 0.0f; static bool g_MouseJustPressed[3] = { false, false, false }; -static float g_MouseHorizWheel = 0.0f; -static float g_MouseWheel = 0.0f; +static ImVec2 g_MouseWheel = ImVec2(0.0f, 0.0f); static GLuint g_FontTexture = 0; static int g_ShaderHandle = 0, g_VertHandle = 0, g_FragHandle = 0; static int g_AttribLocationTex = 0, g_AttribLocationProjMtx = 0; @@ -158,8 +157,8 @@ void ImGui_ImplGlfwGL3_MouseButtonCallback(GLFWwindow*, int button, int action, void ImGui_ImplGlfwGL3_ScrollCallback(GLFWwindow*, double xoffset, double yoffset) { - g_MouseHorizWheel += (float)xoffset; // Use fractional mouse wheel. - g_MouseWheel += (float)yoffset; + g_MouseWheel.x += (float)xoffset; // Use fractional mouse wheel. + g_MouseWheel.y += (float)yoffset; } void ImGui_ImplGlfwGL3_KeyCallback(GLFWwindow*, int key, int, int action, int mods) @@ -409,9 +408,9 @@ void ImGui_ImplGlfwGL3_NewFrame() g_MouseJustPressed[i] = false; } - io.MouseHorizWheel = g_MouseHorizWheel; - io.MouseWheel = g_MouseWheel; - g_MouseHorizWheel = g_MouseWheel = 0.0f; + io.MouseWheel = g_MouseWheel.y; + io.MouseWheelH = g_MouseWheel.x; + g_MouseWheel.x = g_MouseWheel.x = 0.0f; // Hide OS mouse cursor if ImGui is drawing it glfwSetInputMode(g_Window, GLFW_CURSOR, io.MouseDrawCursor ? GLFW_CURSOR_HIDDEN : GLFW_CURSOR_NORMAL); diff --git a/examples/sdl_opengl2_example/imgui_impl_sdl_gl2.cpp b/examples/sdl_opengl2_example/imgui_impl_sdl_gl2.cpp index e1adbe86aec5..d55af2b7f0c0 100644 --- a/examples/sdl_opengl2_example/imgui_impl_sdl_gl2.cpp +++ b/examples/sdl_opengl2_example/imgui_impl_sdl_gl2.cpp @@ -24,8 +24,7 @@ // Data static double g_Time = 0.0f; static bool g_MousePressed[3] = { false, false, false }; -static float g_MouseHorizWheel = 0.0f; -static float g_MouseWheel = 0.0f; +static ImVec2 g_MouseWheel = ImVec2(0.0f, 0.0f); static GLuint g_FontTexture = 0; // This is the main rendering function that you have to implement and provide to ImGui (via setting up 'RenderDrawListsFn' in the ImGuiIO structure) @@ -133,14 +132,10 @@ bool ImGui_ImplSdlGL2_ProcessEvent(SDL_Event* event) { case SDL_MOUSEWHEEL: { - if (event->wheel.x > 0) - g_MouseHorizWheel = 1; - if (event->wheel.x < 0) - g_MouseHorizWheel = -1; - if (event->wheel.y > 0) - g_MouseWheel = 1; - if (event->wheel.y < 0) - g_MouseWheel = -1; + if (event->wheel.x > 0) g_MouseWheel.x = +1; + if (event->wheel.x < 0) g_MouseWheel.x = -1; + if (event->wheel.y > 0) g_MouseWheel.y = +1; + if (event->wheel.y < 0) g_MouseWheel.y = -1; return true; } case SDL_MOUSEBUTTONDOWN: @@ -279,13 +274,13 @@ void ImGui_ImplSdlGL2_NewFrame(SDL_Window *window) int mx, my; Uint32 mouse_buttons = SDL_GetMouseState(&mx, &my); io.MousePos = ImVec2(-FLT_MAX, -FLT_MAX); - io.MouseWheel = g_MouseWheel; - io.MouseHorizWheel = g_MouseHorizWheel; + io.MouseWheel = g_MouseWheel.y; + io.MouseWheelH = g_MouseWheel.x; io.MouseDown[0] = g_MousePressed[0] || (mouse_buttons & SDL_BUTTON(SDL_BUTTON_LEFT)) != 0; // If a mouse press event came, always pass it as "mouse held this frame", so we don't miss click-release events that are shorter than 1 frame. io.MouseDown[1] = g_MousePressed[1] || (mouse_buttons & SDL_BUTTON(SDL_BUTTON_RIGHT)) != 0; io.MouseDown[2] = g_MousePressed[2] || (mouse_buttons & SDL_BUTTON(SDL_BUTTON_MIDDLE)) != 0; g_MousePressed[0] = g_MousePressed[1] = g_MousePressed[2] = false; - g_MouseWheel = g_MouseHorizWheel = 0.0f; + g_MouseWheel.x = g_MouseWheel.x = 0.0f; // We need to use SDL_CaptureMouse() to easily retrieve mouse coordinates outside of the client area. This is only supported from SDL 2.0.4 (released Jan 2016) #if (SDL_MAJOR_VERSION >= 2) && (SDL_MINOR_VERSION >= 0) && (SDL_PATCHLEVEL >= 4) diff --git a/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.cpp b/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.cpp index 264ac64b090f..0a07cd0827d6 100644 --- a/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.cpp +++ b/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.cpp @@ -19,8 +19,7 @@ // Data static double g_Time = 0.0f; static bool g_MousePressed[3] = { false, false, false }; -static float g_MouseHorizWheel = 0.0f; -static float g_MouseWheel = 0.0f; +static ImVec2 g_MouseWheel = ImVec2(0.0f, 0.0f); static GLuint g_FontTexture = 0; static int g_ShaderHandle = 0, g_VertHandle = 0, g_FragHandle = 0; static int g_AttribLocationTex = 0, g_AttribLocationProjMtx = 0; @@ -155,14 +154,10 @@ bool ImGui_ImplSdlGL3_ProcessEvent(SDL_Event* event) { case SDL_MOUSEWHEEL: { - if (event->wheel.x > 0) - g_MouseHorizWheel = 1; - if (event->wheel.x < 0) - g_MouseHorizWheel = -1; - if (event->wheel.y > 0) - g_MouseWheel = 1; - if (event->wheel.y < 0) - g_MouseWheel = -1; + if (event->wheel.x > 0) g_MouseWheel.x = +1; + if (event->wheel.x < 0) g_MouseWheel.x = -1; + if (event->wheel.y > 0) g_MouseWheel.y = +1; + if (event->wheel.y < 0) g_MouseWheel.y = -1; return true; } case SDL_MOUSEBUTTONDOWN: @@ -390,13 +385,13 @@ void ImGui_ImplSdlGL3_NewFrame(SDL_Window* window) int mx, my; Uint32 mouse_buttons = SDL_GetMouseState(&mx, &my); io.MousePos = ImVec2(-FLT_MAX, -FLT_MAX); - io.MouseWheel = g_MouseWheel; - io.MouseHorizWheel = g_MouseHorizWheel; + io.MouseWheel = g_MouseWheel.y; + io.MouseWheelH = g_MouseWheel.x; io.MouseDown[0] = g_MousePressed[0] || (mouse_buttons & SDL_BUTTON(SDL_BUTTON_LEFT)) != 0; // If a mouse press event came, always pass it as "mouse held this frame", so we don't miss click-release events that are shorter than 1 frame. io.MouseDown[1] = g_MousePressed[1] || (mouse_buttons & SDL_BUTTON(SDL_BUTTON_RIGHT)) != 0; io.MouseDown[2] = g_MousePressed[2] || (mouse_buttons & SDL_BUTTON(SDL_BUTTON_MIDDLE)) != 0; g_MousePressed[0] = g_MousePressed[1] = g_MousePressed[2] = false; - g_MouseHorizWheel = g_MouseWheel = 0.0f; + g_MouseWheel.x = g_MouseWheel.x = 0.0f; // We need to use SDL_CaptureMouse() to easily retrieve mouse coordinates outside of the client area. This is only supported from SDL 2.0.4 (released Jan 2016) #if (SDL_MAJOR_VERSION >= 2) && (SDL_MINOR_VERSION >= 0) && (SDL_PATCHLEVEL >= 4) diff --git a/imgui.cpp b/imgui.cpp index 781e1ff3ef00..0020c2c1b74d 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2483,47 +2483,45 @@ void ImGui::NewFrame() if (!mouse_avail_to_imgui && !mouse_dragging_extern_payload) g.HoveredWindow = g.HoveredRootWindow = NULL; - // Scale & Scrolling - if (g.HoveredWindow && g.IO.MouseWheel != 0.0f && !g.HoveredWindow->Collapsed) + // Mouse wheel scrolling, scale + if (g.HoveredWindow && !g.HoveredWindow->Collapsed && (g.IO.MouseWheel != 0.0f || g.IO.MouseWheelH != 0.0f)) { + // If a child window has the ImGuiWindowFlags_NoScrollWithMouse flag, we give a chance to scroll its parent (unless either ImGuiWindowFlags_NoInputs or ImGuiWindowFlags_NoScrollbar are also set). ImGuiWindow* window = g.HoveredWindow; - if (g.IO.KeyCtrl && g.IO.FontAllowUserScaling) - { - // Zoom / Scale window - const float new_font_scale = ImClamp(window->FontWindowScale + g.IO.MouseWheel * 0.10f, 0.50f, 2.50f); - const float scale = new_font_scale / window->FontWindowScale; - window->FontWindowScale = new_font_scale; + ImGuiWindow* scroll_window = window; + while ((scroll_window->Flags & ImGuiWindowFlags_ChildWindow) && (scroll_window->Flags & ImGuiWindowFlags_NoScrollWithMouse) && !(scroll_window->Flags & ImGuiWindowFlags_NoScrollbar) && !(scroll_window->Flags & ImGuiWindowFlags_NoInputs) && scroll_window->ParentWindow) + scroll_window = scroll_window->ParentWindow; + const bool scroll_allowed = !(scroll_window->Flags & ImGuiWindowFlags_NoScrollWithMouse) && !(scroll_window->Flags & ImGuiWindowFlags_NoInputs); - const ImVec2 offset = window->Size * (1.0f - scale) * (g.IO.MousePos - window->Pos) / window->Size; - window->Pos += offset; - window->PosFloat += offset; - window->Size *= scale; - window->SizeFull *= scale; - } - else if (!g.IO.KeyCtrl) + if (g.IO.MouseWheel != 0.0f) { - // Mouse wheel Scrolling - // If a child window has the ImGuiWindowFlags_NoScrollWithMouse flag, we give a chance to scroll its parent (unless either ImGuiWindowFlags_NoInputs or ImGuiWindowFlags_NoScrollbar are also set). - ImGuiWindow* scroll_window = window; - while ((scroll_window->Flags & ImGuiWindowFlags_ChildWindow) && (scroll_window->Flags & ImGuiWindowFlags_NoScrollWithMouse) && !(scroll_window->Flags & ImGuiWindowFlags_NoScrollbar) && !(scroll_window->Flags & ImGuiWindowFlags_NoInputs) && scroll_window->ParentWindow) - scroll_window = scroll_window->ParentWindow; - - if (!(scroll_window->Flags & ImGuiWindowFlags_NoScrollWithMouse) && !(scroll_window->Flags & ImGuiWindowFlags_NoInputs)) + if (g.IO.KeyCtrl && g.IO.FontAllowUserScaling) + { + // Zoom / Scale window + const float new_font_scale = ImClamp(window->FontWindowScale + g.IO.MouseWheel * 0.10f, 0.50f, 2.50f); + const float scale = new_font_scale / window->FontWindowScale; + window->FontWindowScale = new_font_scale; + + const ImVec2 offset = window->Size * (1.0f - scale) * (g.IO.MousePos - window->Pos) / window->Size; + window->Pos += offset; + window->PosFloat += offset; + window->Size *= scale; + window->SizeFull *= scale; + } + else if (!g.IO.KeyCtrl && scroll_allowed) { + // Mouse wheel vertical scrolling float scroll_amount = 5 * scroll_window->CalcFontSize(); scroll_amount = (float)(int)ImMin(scroll_amount, (scroll_window->ContentsRegionRect.GetHeight() + scroll_window->WindowPadding.y * 2.0f) * 0.67f); SetWindowScrollY(scroll_window, scroll_window->Scroll.y - g.IO.MouseWheel * scroll_amount); } } - } - - // Horizontal wheel scrolling; for consistency, only allowed if Ctrl is not pressed. - if (g.HoveredWindow && g.IO.MouseHorizWheel != 0.0f && !g.HoveredWindow->Collapsed) - { - ImGuiWindow* window = g.HoveredWindow; - if (!g.IO.KeyCtrl && !(window->Flags & ImGuiWindowFlags_NoScrollWithMouse)) + if (g.IO.MouseWheelH != 0.0f && scroll_allowed) { - SetWindowScrollX(window, window->Scroll.x - g.IO.MouseHorizWheel * 10.f); + // Mouse wheel horizontal scrolling (for hardware that supports it) + float scroll_amount = scroll_window->CalcFontSize(); + if (!g.IO.KeyCtrl && !(window->Flags & ImGuiWindowFlags_NoScrollWithMouse)) + SetWindowScrollX(window, window->Scroll.x - g.IO.MouseWheelH * scroll_amount); } } @@ -3040,7 +3038,7 @@ void ImGui::EndFrame() g.Windows.swap(g.WindowsSortBuffer); // Clear Input data for next frame - g.IO.MouseWheel = 0.0f; + g.IO.MouseWheel = g.IO.MouseWheelH = 0.0f; memset(g.IO.InputCharacters, 0, sizeof(g.IO.InputCharacters)); g.FrameCountEnded = g.FrameCount; diff --git a/imgui.h b/imgui.h index 01fe3f777b3d..f8d36ba41940 100644 --- a/imgui.h +++ b/imgui.h @@ -930,8 +930,8 @@ struct ImGuiIO ImVec2 MousePos; // Mouse position, in pixels. Set to ImVec2(-FLT_MAX,-FLT_MAX) if mouse is unavailable (on another screen, etc.) bool MouseDown[5]; // Mouse buttons: left, right, middle + extras. ImGui itself mostly only uses left button (BeginPopupContext** are using right button). Others buttons allows us to track if the mouse is being used by your application + available to user as a convenience via IsMouse** API. - float MouseWheel; // Mouse wheel: 1 unit scrolls about 5 lines text. - float MouseHorizWheel; // Horizontal mouse wheel + float MouseWheel; // Mouse wheel: 1 unit scrolls about 5 lines text. + float MouseWheelH; // Mouse wheel (Horizontal). Most users don't have a mouse with an horizontal wheel, may not be filled by all back ends. bool MouseDrawCursor; // Request ImGui to draw a mouse cursor for you (if you are on a platform without a mouse cursor). bool KeyCtrl; // Keyboard modifier pressed: Control bool KeyShift; // Keyboard modifier pressed: Shift From 7dea158175615dc8939c57a06641bac911e33e8c Mon Sep 17 00:00:00 2001 From: omar Date: Sat, 20 Jan 2018 12:36:59 +0100 Subject: [PATCH 471/823] Examples: Allegro, Apple, DirectX9/10/11, Glfw+Vulkan :Added support for horizontal mouse wheel. (#1463) --- examples/allegro5_example/imgui_impl_a5.cpp | 1 + examples/apple_example/imguiex-ios/imgui_impl_ios.mm | 4 ++-- examples/directx10_example/imgui_impl_dx10.cpp | 3 +++ examples/directx11_example/imgui_impl_dx11.cpp | 3 +++ examples/directx9_example/imgui_impl_dx9.cpp | 3 +++ examples/vulkan_example/imgui_impl_glfw_vulkan.cpp | 12 +++++++----- 6 files changed, 19 insertions(+), 7 deletions(-) diff --git a/examples/allegro5_example/imgui_impl_a5.cpp b/examples/allegro5_example/imgui_impl_a5.cpp index d3ccffd23d9c..62f7af67296f 100644 --- a/examples/allegro5_example/imgui_impl_a5.cpp +++ b/examples/allegro5_example/imgui_impl_a5.cpp @@ -215,6 +215,7 @@ bool ImGui_ImplA5_ProcessEvent(ALLEGRO_EVENT *ev) { case ALLEGRO_EVENT_MOUSE_AXES: io.MouseWheel += ev->mouse.dz; + io.MouseWheelH += ev->mouse.dw; return true; case ALLEGRO_EVENT_KEY_CHAR: if (ev->keyboard.display == g_Display) diff --git a/examples/apple_example/imguiex-ios/imgui_impl_ios.mm b/examples/apple_example/imguiex-ios/imgui_impl_ios.mm index 9db45d0f29a8..5b56d3ca39dd 100644 --- a/examples/apple_example/imguiex-ios/imgui_impl_ios.mm +++ b/examples/apple_example/imguiex-ios/imgui_impl_ios.mm @@ -587,9 +587,9 @@ - (void)newFrame io.MouseDown[i] = g_MousePressed[i]; } - // This is an arbitrary scaling factor that works for me. Not sure what units these - // mousewheel values from synergy are supposed to be in + // This is an arbitrary scaling factor that works for me. Not sure what units these mousewheel values from synergy are supposed to be in. io.MouseWheel = g_mouseWheelY / 500.0; + io.MouseWheelH = g_mouseWheelX / 500.0; } else { diff --git a/examples/directx10_example/imgui_impl_dx10.cpp b/examples/directx10_example/imgui_impl_dx10.cpp index 4f7117a7bc20..14a47c4af52b 100644 --- a/examples/directx10_example/imgui_impl_dx10.cpp +++ b/examples/directx10_example/imgui_impl_dx10.cpp @@ -275,6 +275,9 @@ IMGUI_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hwnd, UINT msg, WPARAM wPa case WM_MOUSEWHEEL: io.MouseWheel += GET_WHEEL_DELTA_WPARAM(wParam) > 0 ? +1.0f : -1.0f; return 0; + case WM_MOUSEHWHEEL: + io.MouseWheelH += GET_WHEEL_DELTA_WPARAM(wParam) > 0 ? +1.0f : -1.0f; + return 0; case WM_MOUSEMOVE: io.MousePos.x = (signed short)(lParam); io.MousePos.y = (signed short)(lParam >> 16); diff --git a/examples/directx11_example/imgui_impl_dx11.cpp b/examples/directx11_example/imgui_impl_dx11.cpp index 5df7bf1f04ff..4963fc12eaa3 100644 --- a/examples/directx11_example/imgui_impl_dx11.cpp +++ b/examples/directx11_example/imgui_impl_dx11.cpp @@ -282,6 +282,9 @@ IMGUI_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hwnd, UINT msg, WPARAM wPa case WM_MOUSEWHEEL: io.MouseWheel += GET_WHEEL_DELTA_WPARAM(wParam) > 0 ? +1.0f : -1.0f; return 0; + case WM_MOUSEHWHEEL: + io.MouseWheelH += GET_WHEEL_DELTA_WPARAM(wParam) > 0 ? +1.0f : -1.0f; + return 0; case WM_MOUSEMOVE: io.MousePos.x = (signed short)(lParam); io.MousePos.y = (signed short)(lParam >> 16); diff --git a/examples/directx9_example/imgui_impl_dx9.cpp b/examples/directx9_example/imgui_impl_dx9.cpp index 18ec0d9b5e5f..a4e676914ce4 100644 --- a/examples/directx9_example/imgui_impl_dx9.cpp +++ b/examples/directx9_example/imgui_impl_dx9.cpp @@ -221,6 +221,9 @@ IMGUI_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hwnd, UINT msg, WPARAM wPa case WM_MOUSEWHEEL: io.MouseWheel += GET_WHEEL_DELTA_WPARAM(wParam) > 0 ? +1.0f : -1.0f; return 0; + case WM_MOUSEHWHEEL: + io.MouseWheelH += GET_WHEEL_DELTA_WPARAM(wParam) > 0 ? +1.0f : -1.0f; + return 0; case WM_MOUSEMOVE: io.MousePos.x = (signed short)(lParam); io.MousePos.y = (signed short)(lParam >> 16); diff --git a/examples/vulkan_example/imgui_impl_glfw_vulkan.cpp b/examples/vulkan_example/imgui_impl_glfw_vulkan.cpp index 0af380cc626a..5e678144ecfe 100644 --- a/examples/vulkan_example/imgui_impl_glfw_vulkan.cpp +++ b/examples/vulkan_example/imgui_impl_glfw_vulkan.cpp @@ -25,7 +25,7 @@ static GLFWwindow* g_Window = NULL; static double g_Time = 0.0f; static bool g_MousePressed[3] = { false, false, false }; -static float g_MouseWheel = 0.0f; +static ImVec2 g_MouseWheel = ImVec2(0.0f, 0.0f); // Vulkan Data static VkAllocationCallbacks* g_Allocator = NULL; @@ -330,9 +330,10 @@ void ImGui_ImplGlfwVulkan_MouseButtonCallback(GLFWwindow*, int button, int actio g_MousePressed[button] = true; } -void ImGui_ImplGlfwVulkan_ScrollCallback(GLFWwindow*, double /*xoffset*/, double yoffset) +void ImGui_ImplGlfwVulkan_ScrollCallback(GLFWwindow*, double xoffset, double yoffset) { - g_MouseWheel += (float)yoffset; // Use fractional mouse wheel. + g_MouseWheel.x += (float)xoffset; // Use fractional mouse wheel. + g_MouseWheel.y += (float)yoffset; } void ImGui_ImplGlfwVulkan_KeyCallback(GLFWwindow*, int key, int, int action, int mods) @@ -825,8 +826,9 @@ void ImGui_ImplGlfwVulkan_NewFrame() g_MousePressed[i] = false; } - io.MouseWheel = g_MouseWheel; - g_MouseWheel = 0.0f; + io.MouseWheel = g_MouseWheel.y; + io.MouseWheelH = g_MouseWheel.x; + g_MouseWheel.x = g_MouseWheel.x = 0.0f; // Hide OS mouse cursor if ImGui is drawing it glfwSetInputMode(g_Window, GLFW_CURSOR, io.MouseDrawCursor ? GLFW_CURSOR_HIDDEN : GLFW_CURSOR_NORMAL); From 7e7c017b7556d1c2bcc2eccd92f6572b75af059f Mon Sep 17 00:00:00 2001 From: omar Date: Sat, 20 Jan 2018 12:45:31 +0100 Subject: [PATCH 472/823] Examples: Simplified mouse wheel handling. (#1463) --- .../marmalade_example/imgui_impl_marmalade.cpp | 8 ++------ .../opengl2_example/imgui_impl_glfw_gl2.cpp | 10 +++------- .../opengl3_example/imgui_impl_glfw_gl3.cpp | 10 +++------- .../sdl_opengl2_example/imgui_impl_sdl_gl2.cpp | 12 ++++-------- .../sdl_opengl3_example/imgui_impl_sdl_gl3.cpp | 12 ++++-------- .../vulkan_example/imgui_impl_glfw_vulkan.cpp | 18 +++++++----------- 6 files changed, 23 insertions(+), 47 deletions(-) diff --git a/examples/marmalade_example/imgui_impl_marmalade.cpp b/examples/marmalade_example/imgui_impl_marmalade.cpp index 39623cc4d3b6..36fc8328c862 100644 --- a/examples/marmalade_example/imgui_impl_marmalade.cpp +++ b/examples/marmalade_example/imgui_impl_marmalade.cpp @@ -21,7 +21,6 @@ // Data static double g_Time = 0.0f; static bool g_MousePressed[3] = { false, false, false }; -static float g_MouseWheel = 0.0f; static CIwTexture* g_FontTexture = NULL; static char* g_ClipboardText = NULL; static bool g_osdKeyboardEnabled = false; @@ -128,9 +127,9 @@ int32 ImGui_Marmalade_PointerButtonEventCallback(void* SystemData, void* pUserDa if (pEvent->m_Button == S3E_POINTER_BUTTON_MIDDLEMOUSE) g_MousePressed[2] = true; if (pEvent->m_Button == S3E_POINTER_BUTTON_MOUSEWHEELUP) - g_MouseWheel += pEvent->m_y; + io.MouseWheel += pEvent->m_y; if (pEvent->m_Button == S3E_POINTER_BUTTON_MOUSEWHEELDOWN) - g_MouseWheel += pEvent->m_y; + io.MouseWheel += pEvent->m_y; } return 0; @@ -282,9 +281,6 @@ void ImGui_Marmalade_NewFrame() g_MousePressed[i] = false; } - io.MouseWheel = g_MouseWheel; - g_MouseWheel = 0.0f; - // TODO: Hide OS mouse cursor if ImGui is drawing it // s3ePointerSetInt(S3E_POINTER_HIDE_CURSOR,(io.MouseDrawCursor ? 0 : 1)); diff --git a/examples/opengl2_example/imgui_impl_glfw_gl2.cpp b/examples/opengl2_example/imgui_impl_glfw_gl2.cpp index 8dcd71e9fac2..e5fe2f47bcb0 100644 --- a/examples/opengl2_example/imgui_impl_glfw_gl2.cpp +++ b/examples/opengl2_example/imgui_impl_glfw_gl2.cpp @@ -31,7 +31,6 @@ static GLFWwindow* g_Window = NULL; static double g_Time = 0.0f; static bool g_MouseJustPressed[3] = { false, false, false }; -static ImVec2 g_MouseWheel = ImVec2(0.0f, 0.0f); static GLuint g_FontTexture = 0; // This is the main rendering function that you have to implement and provide to ImGui (via setting up 'RenderDrawListsFn' in the ImGuiIO structure) @@ -136,8 +135,9 @@ void ImGui_ImplGlfwGL2_MouseButtonCallback(GLFWwindow*, int button, int action, void ImGui_ImplGlfwGL2_ScrollCallback(GLFWwindow*, double xoffset, double yoffset) { - g_MouseWheel.x += (float)xoffset; // Use fractional mouse wheel. - g_MouseWheel.y += (float)yoffset; + ImGuiIO& io = ImGui::GetIO(); + io.MouseWheelH += (float)xoffset; + io.MouseWheel += (float)yoffset; } void ImGui_ImplGlfwGL2_KeyCallback(GLFWwindow*, int key, int, int action, int mods) @@ -296,10 +296,6 @@ void ImGui_ImplGlfwGL2_NewFrame() g_MouseJustPressed[i] = false; } - io.MouseWheel = g_MouseWheel.y; - io.MouseWheelH = g_MouseWheel.x; - g_MouseWheel.x = g_MouseWheel.x = 0.0f; - // Hide OS mouse cursor if ImGui is drawing it glfwSetInputMode(g_Window, GLFW_CURSOR, io.MouseDrawCursor ? GLFW_CURSOR_HIDDEN : GLFW_CURSOR_NORMAL); diff --git a/examples/opengl3_example/imgui_impl_glfw_gl3.cpp b/examples/opengl3_example/imgui_impl_glfw_gl3.cpp index 79a62531fff3..a71fc515dab5 100644 --- a/examples/opengl3_example/imgui_impl_glfw_gl3.cpp +++ b/examples/opengl3_example/imgui_impl_glfw_gl3.cpp @@ -25,7 +25,6 @@ static GLFWwindow* g_Window = NULL; static double g_Time = 0.0f; static bool g_MouseJustPressed[3] = { false, false, false }; -static ImVec2 g_MouseWheel = ImVec2(0.0f, 0.0f); static GLuint g_FontTexture = 0; static int g_ShaderHandle = 0, g_VertHandle = 0, g_FragHandle = 0; static int g_AttribLocationTex = 0, g_AttribLocationProjMtx = 0; @@ -157,8 +156,9 @@ void ImGui_ImplGlfwGL3_MouseButtonCallback(GLFWwindow*, int button, int action, void ImGui_ImplGlfwGL3_ScrollCallback(GLFWwindow*, double xoffset, double yoffset) { - g_MouseWheel.x += (float)xoffset; // Use fractional mouse wheel. - g_MouseWheel.y += (float)yoffset; + ImGuiIO& io = ImGui::GetIO(); + io.MouseWheelH += (float)xoffset; + io.MouseWheel += (float)yoffset; } void ImGui_ImplGlfwGL3_KeyCallback(GLFWwindow*, int key, int, int action, int mods) @@ -408,10 +408,6 @@ void ImGui_ImplGlfwGL3_NewFrame() g_MouseJustPressed[i] = false; } - io.MouseWheel = g_MouseWheel.y; - io.MouseWheelH = g_MouseWheel.x; - g_MouseWheel.x = g_MouseWheel.x = 0.0f; - // Hide OS mouse cursor if ImGui is drawing it glfwSetInputMode(g_Window, GLFW_CURSOR, io.MouseDrawCursor ? GLFW_CURSOR_HIDDEN : GLFW_CURSOR_NORMAL); diff --git a/examples/sdl_opengl2_example/imgui_impl_sdl_gl2.cpp b/examples/sdl_opengl2_example/imgui_impl_sdl_gl2.cpp index d55af2b7f0c0..76def29c3af8 100644 --- a/examples/sdl_opengl2_example/imgui_impl_sdl_gl2.cpp +++ b/examples/sdl_opengl2_example/imgui_impl_sdl_gl2.cpp @@ -24,7 +24,6 @@ // Data static double g_Time = 0.0f; static bool g_MousePressed[3] = { false, false, false }; -static ImVec2 g_MouseWheel = ImVec2(0.0f, 0.0f); static GLuint g_FontTexture = 0; // This is the main rendering function that you have to implement and provide to ImGui (via setting up 'RenderDrawListsFn' in the ImGuiIO structure) @@ -132,10 +131,10 @@ bool ImGui_ImplSdlGL2_ProcessEvent(SDL_Event* event) { case SDL_MOUSEWHEEL: { - if (event->wheel.x > 0) g_MouseWheel.x = +1; - if (event->wheel.x < 0) g_MouseWheel.x = -1; - if (event->wheel.y > 0) g_MouseWheel.y = +1; - if (event->wheel.y < 0) g_MouseWheel.y = -1; + if (event->wheel.x > 0) io.MouseWheelH += 1; + if (event->wheel.x < 0) io.MouseWheelH -= 1; + if (event->wheel.y > 0) io.MouseWheel += 1; + if (event->wheel.y < 0) io.MouseWheel -= 1; return true; } case SDL_MOUSEBUTTONDOWN: @@ -274,13 +273,10 @@ void ImGui_ImplSdlGL2_NewFrame(SDL_Window *window) int mx, my; Uint32 mouse_buttons = SDL_GetMouseState(&mx, &my); io.MousePos = ImVec2(-FLT_MAX, -FLT_MAX); - io.MouseWheel = g_MouseWheel.y; - io.MouseWheelH = g_MouseWheel.x; io.MouseDown[0] = g_MousePressed[0] || (mouse_buttons & SDL_BUTTON(SDL_BUTTON_LEFT)) != 0; // If a mouse press event came, always pass it as "mouse held this frame", so we don't miss click-release events that are shorter than 1 frame. io.MouseDown[1] = g_MousePressed[1] || (mouse_buttons & SDL_BUTTON(SDL_BUTTON_RIGHT)) != 0; io.MouseDown[2] = g_MousePressed[2] || (mouse_buttons & SDL_BUTTON(SDL_BUTTON_MIDDLE)) != 0; g_MousePressed[0] = g_MousePressed[1] = g_MousePressed[2] = false; - g_MouseWheel.x = g_MouseWheel.x = 0.0f; // We need to use SDL_CaptureMouse() to easily retrieve mouse coordinates outside of the client area. This is only supported from SDL 2.0.4 (released Jan 2016) #if (SDL_MAJOR_VERSION >= 2) && (SDL_MINOR_VERSION >= 0) && (SDL_PATCHLEVEL >= 4) diff --git a/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.cpp b/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.cpp index 0a07cd0827d6..35d9cdde1313 100644 --- a/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.cpp +++ b/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.cpp @@ -19,7 +19,6 @@ // Data static double g_Time = 0.0f; static bool g_MousePressed[3] = { false, false, false }; -static ImVec2 g_MouseWheel = ImVec2(0.0f, 0.0f); static GLuint g_FontTexture = 0; static int g_ShaderHandle = 0, g_VertHandle = 0, g_FragHandle = 0; static int g_AttribLocationTex = 0, g_AttribLocationProjMtx = 0; @@ -154,10 +153,10 @@ bool ImGui_ImplSdlGL3_ProcessEvent(SDL_Event* event) { case SDL_MOUSEWHEEL: { - if (event->wheel.x > 0) g_MouseWheel.x = +1; - if (event->wheel.x < 0) g_MouseWheel.x = -1; - if (event->wheel.y > 0) g_MouseWheel.y = +1; - if (event->wheel.y < 0) g_MouseWheel.y = -1; + if (event->wheel.x > 0) io.MouseWheelH += 1; + if (event->wheel.x < 0) io.MouseWheelH -= 1; + if (event->wheel.y > 0) io.MouseWheel += 1; + if (event->wheel.y < 0) io.MouseWheel -= 1; return true; } case SDL_MOUSEBUTTONDOWN: @@ -385,13 +384,10 @@ void ImGui_ImplSdlGL3_NewFrame(SDL_Window* window) int mx, my; Uint32 mouse_buttons = SDL_GetMouseState(&mx, &my); io.MousePos = ImVec2(-FLT_MAX, -FLT_MAX); - io.MouseWheel = g_MouseWheel.y; - io.MouseWheelH = g_MouseWheel.x; io.MouseDown[0] = g_MousePressed[0] || (mouse_buttons & SDL_BUTTON(SDL_BUTTON_LEFT)) != 0; // If a mouse press event came, always pass it as "mouse held this frame", so we don't miss click-release events that are shorter than 1 frame. io.MouseDown[1] = g_MousePressed[1] || (mouse_buttons & SDL_BUTTON(SDL_BUTTON_RIGHT)) != 0; io.MouseDown[2] = g_MousePressed[2] || (mouse_buttons & SDL_BUTTON(SDL_BUTTON_MIDDLE)) != 0; g_MousePressed[0] = g_MousePressed[1] = g_MousePressed[2] = false; - g_MouseWheel.x = g_MouseWheel.x = 0.0f; // We need to use SDL_CaptureMouse() to easily retrieve mouse coordinates outside of the client area. This is only supported from SDL 2.0.4 (released Jan 2016) #if (SDL_MAJOR_VERSION >= 2) && (SDL_MINOR_VERSION >= 0) && (SDL_PATCHLEVEL >= 4) diff --git a/examples/vulkan_example/imgui_impl_glfw_vulkan.cpp b/examples/vulkan_example/imgui_impl_glfw_vulkan.cpp index 5e678144ecfe..b9e6d78f2397 100644 --- a/examples/vulkan_example/imgui_impl_glfw_vulkan.cpp +++ b/examples/vulkan_example/imgui_impl_glfw_vulkan.cpp @@ -24,8 +24,7 @@ // GLFW Data static GLFWwindow* g_Window = NULL; static double g_Time = 0.0f; -static bool g_MousePressed[3] = { false, false, false }; -static ImVec2 g_MouseWheel = ImVec2(0.0f, 0.0f); +static bool g_MouseJustPressed[3] = { false, false, false }; // Vulkan Data static VkAllocationCallbacks* g_Allocator = NULL; @@ -327,13 +326,14 @@ static void ImGui_ImplGlfwVulkan_SetClipboardText(void* user_data, const char* t void ImGui_ImplGlfwVulkan_MouseButtonCallback(GLFWwindow*, int button, int action, int /*mods*/) { if (action == GLFW_PRESS && button >= 0 && button < 3) - g_MousePressed[button] = true; + g_MouseJustPressed[button] = true; } void ImGui_ImplGlfwVulkan_ScrollCallback(GLFWwindow*, double xoffset, double yoffset) { - g_MouseWheel.x += (float)xoffset; // Use fractional mouse wheel. - g_MouseWheel.y += (float)yoffset; + ImGuiIO& io = ImGui::GetIO(); + io.MouseWheelH += (float)xoffset; + io.MouseWheel += (float)yoffset; } void ImGui_ImplGlfwVulkan_KeyCallback(GLFWwindow*, int key, int, int action, int mods) @@ -822,14 +822,10 @@ void ImGui_ImplGlfwVulkan_NewFrame() for (int i = 0; i < 3; i++) { - io.MouseDown[i] = g_MousePressed[i] || glfwGetMouseButton(g_Window, i) != 0; // If a mouse press event came, always pass it as "mouse held this frame", so we don't miss click-release events that are shorter than 1 frame. - g_MousePressed[i] = false; + io.MouseDown[i] = g_MouseJustPressed[i] || glfwGetMouseButton(g_Window, i) != 0; // If a mouse press event came, always pass it as "mouse held this frame", so we don't miss click-release events that are shorter than 1 frame. + g_MouseJustPressed[i] = false; } - io.MouseWheel = g_MouseWheel.y; - io.MouseWheelH = g_MouseWheel.x; - g_MouseWheel.x = g_MouseWheel.x = 0.0f; - // Hide OS mouse cursor if ImGui is drawing it glfwSetInputMode(g_Window, GLFW_CURSOR, io.MouseDrawCursor ? GLFW_CURSOR_HIDDEN : GLFW_CURSOR_NORMAL); From cd1409f4bf411fe63eaf5bf4de47f137a3aa388d Mon Sep 17 00:00:00 2001 From: omar Date: Sat, 20 Jan 2018 20:25:12 +0100 Subject: [PATCH 473/823] ImFontAtlas: Moved mouse cursor data out of ImGuiContext, fix drawing them with multiple context. Also remove the last remaining undesirable dependency on GImGui in imgui_draw.cpp, finishing the work recently done with ImDrawListSharedData. Hurra! (#939) --- imgui.cpp | 15 +++++++-------- imgui.h | 5 ++++- imgui_draw.cpp | 37 ++++++++++++++++++++----------------- imgui_internal.h | 13 ------------- 4 files changed, 31 insertions(+), 39 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 0020c2c1b74d..c34190b4078e 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -3069,17 +3069,16 @@ void ImGui::Render() g.DrawDataBuilder.FlattenIntoSingleLayer(); // Draw software mouse cursor if requested - if (g.IO.MouseDrawCursor) + ImVec2 offset, size, uv[4]; + if (g.IO.MouseDrawCursor && g.IO.Fonts->GetMouseCursorTexData(g.MouseCursor, &offset, &size, &uv[0], &uv[2])) { - const ImGuiMouseCursorData& cursor_data = g.MouseCursorData[g.MouseCursor]; - const ImVec2 pos = g.IO.MousePos - cursor_data.HotOffset; - const ImVec2 size = cursor_data.Size; + const ImVec2 pos = g.IO.MousePos - offset; const ImTextureID tex_id = g.IO.Fonts->TexID; g.OverlayDrawList.PushTextureID(tex_id); - g.OverlayDrawList.AddImage(tex_id, pos+ImVec2(1,0), pos+ImVec2(1,0) + size, cursor_data.TexUvMin[1], cursor_data.TexUvMax[1], IM_COL32(0,0,0,48)); // Shadow - g.OverlayDrawList.AddImage(tex_id, pos+ImVec2(2,0), pos+ImVec2(2,0) + size, cursor_data.TexUvMin[1], cursor_data.TexUvMax[1], IM_COL32(0,0,0,48)); // Shadow - g.OverlayDrawList.AddImage(tex_id, pos, pos + size, cursor_data.TexUvMin[1], cursor_data.TexUvMax[1], IM_COL32(0,0,0,255)); // Black border - g.OverlayDrawList.AddImage(tex_id, pos, pos + size, cursor_data.TexUvMin[0], cursor_data.TexUvMax[0], IM_COL32(255,255,255,255)); // White fill + g.OverlayDrawList.AddImage(tex_id, pos+ImVec2(1,0), pos+ImVec2(1,0) + size, uv[2], uv[3], IM_COL32(0,0,0,48)); // Shadow + g.OverlayDrawList.AddImage(tex_id, pos+ImVec2(2,0), pos+ImVec2(2,0) + size, uv[2], uv[3], IM_COL32(0,0,0,48)); // Shadow + g.OverlayDrawList.AddImage(tex_id, pos, pos + size, uv[2], uv[3], IM_COL32(0,0,0,255)); // Black border + g.OverlayDrawList.AddImage(tex_id, pos, pos + size, uv[0], uv[1], IM_COL32(255,255,255,255)); // White fill g.OverlayDrawList.PopTextureID(); } if (!g.OverlayDrawList.VtxBuffer.empty()) diff --git a/imgui.h b/imgui.h index f8d36ba41940..57ffff1811f3 100644 --- a/imgui.h +++ b/imgui.h @@ -1611,9 +1611,12 @@ struct ImFontAtlas IMGUI_API int AddCustomRectRegular(unsigned int id, int width, int height); // Id needs to be >= 0x10000. Id >= 0x80000000 are reserved for ImGui and ImDrawList IMGUI_API int AddCustomRectFontGlyph(ImFont* font, ImWchar id, int width, int height, float advance_x, const ImVec2& offset = ImVec2(0,0)); // Id needs to be < 0x10000 to register a rectangle to map into a specific font. - IMGUI_API void CalcCustomRectUV(const CustomRect* rect, ImVec2* out_uv_min, ImVec2* out_uv_max); const CustomRect* GetCustomRectByIndex(int index) const { if (index < 0) return NULL; return &CustomRects[index]; } + // Internals + IMGUI_API void CalcCustomRectUV(const CustomRect* rect, ImVec2* out_uv_min, ImVec2* out_uv_max); + IMGUI_API bool GetMouseCursorTexData(ImGuiMouseCursor cursor, ImVec2* out_offset, ImVec2* out_size, ImVec2 out_uv_border[2], ImVec2 out_uv_fill[2]); + //------------------------------------------- // Members //------------------------------------------- diff --git a/imgui_draw.cpp b/imgui_draw.cpp index 0cb7cd82f545..9d99bf19b234 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -1352,7 +1352,6 @@ static const ImVec2 FONT_ATLAS_DEFAULT_TEX_CURSOR_DATA[ImGuiMouseCursor_Count_][ { ImVec2(55,0), ImVec2(17,17), ImVec2( 9, 9) }, // ImGuiMouseCursor_ResizeNWSE }; - ImFontAtlas::ImFontAtlas() { TexID = NULL; @@ -1609,6 +1608,26 @@ void ImFontAtlas::CalcCustomRectUV(const CustomRect* rect, ImVec2* out_uv_min, I *out_uv_max = ImVec2((float)(rect->X + rect->Width) / TexWidth, (float)(rect->Y + rect->Height) / TexHeight); } +bool ImFontAtlas::GetMouseCursorTexData(ImGuiMouseCursor cursor_type, ImVec2* out_offset, ImVec2* out_size, ImVec2 out_uv_border[2], ImVec2 out_uv_fill[2]) +{ + if (cursor_type <= ImGuiMouseCursor_None || cursor_type >= ImGuiMouseCursor_Count_) + return false; + + ImFontAtlas::CustomRect& r = CustomRects[CustomRectIds[0]]; + IM_ASSERT(r.ID == FONT_ATLAS_DEFAULT_TEX_DATA_ID); + ImVec2 uv_scale(1.0f / TexWidth, 1.0f / TexHeight); + ImVec2 pos = FONT_ATLAS_DEFAULT_TEX_CURSOR_DATA[cursor_type][0] + ImVec2((float)r.X, (float)r.Y); + ImVec2 size = FONT_ATLAS_DEFAULT_TEX_CURSOR_DATA[cursor_type][1]; + *out_size = size; + *out_offset = FONT_ATLAS_DEFAULT_TEX_CURSOR_DATA[cursor_type][2]; + out_uv_border[0] = (pos) * uv_scale; + out_uv_border[1] = (pos + size) * uv_scale; + pos.x += FONT_ATLAS_DEFAULT_TEX_DATA_W_HALF + 1; + out_uv_fill[0] = (pos) * uv_scale; + out_uv_fill[1] = (pos + size) * uv_scale; + return true; +} + bool ImFontAtlas::Build() { return ImFontAtlasBuildWithStbTruetype(this); @@ -1891,22 +1910,6 @@ static void ImFontAtlasBuildRenderDefaultTexData(ImFontAtlas* atlas) } const ImVec2 tex_uv_scale(1.0f / atlas->TexWidth, 1.0f / atlas->TexHeight); atlas->TexUvWhitePixel = ImVec2((r.X + 0.5f) * tex_uv_scale.x, (r.Y + 0.5f) * tex_uv_scale.y); - - // Setup mouse cursors - for (int type = 0; type < ImGuiMouseCursor_Count_; type++) - { - ImGuiMouseCursorData& cursor_data = GImGui->MouseCursorData[type]; - ImVec2 pos = FONT_ATLAS_DEFAULT_TEX_CURSOR_DATA[type][0] + ImVec2((float)r.X, (float)r.Y); - const ImVec2 size = FONT_ATLAS_DEFAULT_TEX_CURSOR_DATA[type][1]; - cursor_data.Type = type; - cursor_data.Size = size; - cursor_data.HotOffset = FONT_ATLAS_DEFAULT_TEX_CURSOR_DATA[type][2]; - cursor_data.TexUvMin[0] = (pos) * tex_uv_scale; - cursor_data.TexUvMax[0] = (pos + size) * tex_uv_scale; - pos.x += FONT_ATLAS_DEFAULT_TEX_DATA_W_HALF + 1; - cursor_data.TexUvMin[1] = (pos) * tex_uv_scale; - cursor_data.TexUvMax[1] = (pos + size) * tex_uv_scale; - } } void ImFontAtlasBuildFinish(ImFontAtlas* atlas) diff --git a/imgui_internal.h b/imgui_internal.h index 4a5edfc1f634..d6d19a426075 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -38,7 +38,6 @@ struct ImGuiGroupData; struct ImGuiMenuColumns; struct ImGuiDrawContext; struct ImGuiTextEditState; -struct ImGuiMouseCursorData; struct ImGuiPopupRef; struct ImGuiWindow; struct ImGuiWindowSettings; @@ -382,16 +381,6 @@ struct ImGuiSettingsHandler ImGuiSettingsHandler() { memset(this, 0, sizeof(*this)); } }; -// Mouse cursor data (used when io.MouseDrawCursor is set) -struct ImGuiMouseCursorData -{ - ImGuiMouseCursor Type; - ImVec2 HotOffset; - ImVec2 Size; - ImVec2 TexUvMin[2]; - ImVec2 TexUvMax[2]; -}; - // Storage for current popup stack struct ImGuiPopupRef { @@ -557,7 +546,6 @@ struct ImGuiContext float ModalWindowDarkeningRatio; ImDrawList OverlayDrawList; // Optional software render of mouse cursors, if io.MouseDrawCursor is set + a few debug overlays ImGuiMouseCursor MouseCursor; - ImGuiMouseCursorData MouseCursorData[ImGuiMouseCursor_Count_]; // Drag and Drop bool DragDropActive; @@ -645,7 +633,6 @@ struct ImGuiContext OverlayDrawList._Data = &DrawListSharedData; OverlayDrawList._OwnerName = "##Overlay"; // Give it a name for debugging MouseCursor = ImGuiMouseCursor_Arrow; - memset(MouseCursorData, 0, sizeof(MouseCursorData)); DragDropActive = false; DragDropSourceFlags = 0; From 5eb293c87970b37f7890c89b9e21250e1fd24450 Mon Sep 17 00:00:00 2001 From: omar Date: Sat, 20 Jan 2018 20:32:23 +0100 Subject: [PATCH 474/823] ImFontAtlas: Added TexUvScale (= 1.0f / (float)TexWidth, 1.0f / (float)TexHeight) --- imgui.h | 1 + imgui_draw.cpp | 23 ++++++++++++----------- 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/imgui.h b/imgui.h index 57ffff1811f3..6d411738ae4d 100644 --- a/imgui.h +++ b/imgui.h @@ -1631,6 +1631,7 @@ struct ImFontAtlas unsigned int* TexPixelsRGBA32; // 4 component per pixel, each component is unsigned 8-bit. Total size = TexWidth * TexHeight * 4 int TexWidth; // Texture width calculated during Build(). int TexHeight; // Texture height calculated during Build(). + ImVec2 TexUvScale; // = (1.0f/TexWidth, 1.0f/TexHeight) ImVec2 TexUvWhitePixel; // Texture coordinates to a white pixel ImVector Fonts; // Hold all the fonts returned by AddFont*. Fonts[0] is the default font upon calling ImGui::NewFrame(), use ImGui::PushFont()/PopFont() to change the current font. ImVector CustomRects; // Rectangles for packing custom texture data into the atlas. diff --git a/imgui_draw.cpp b/imgui_draw.cpp index 9d99bf19b234..216cf3fd7c1f 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -1360,7 +1360,8 @@ ImFontAtlas::ImFontAtlas() TexPixelsAlpha8 = NULL; TexPixelsRGBA32 = NULL; TexWidth = TexHeight = 0; - TexUvWhitePixel = ImVec2(0, 0); + TexUvScale = ImVec2(0.0f, 0.0f); + TexUvWhitePixel = ImVec2(0.0f, 0.0f); for (int n = 0; n < IM_ARRAYSIZE(CustomRectIds); n++) CustomRectIds[n] = -1; } @@ -1604,8 +1605,8 @@ void ImFontAtlas::CalcCustomRectUV(const CustomRect* rect, ImVec2* out_uv_min, I { IM_ASSERT(TexWidth > 0 && TexHeight > 0); // Font atlas needs to be built before we can calculate UV coordinates IM_ASSERT(rect->IsPacked()); // Make sure the rectangle has been packed - *out_uv_min = ImVec2((float)rect->X / TexWidth, (float)rect->Y / TexHeight); - *out_uv_max = ImVec2((float)(rect->X + rect->Width) / TexWidth, (float)(rect->Y + rect->Height) / TexHeight); + *out_uv_min = ImVec2((float)rect->X * TexUvScale.x, (float)rect->Y * TexUvScale.y); + *out_uv_max = ImVec2((float)(rect->X + rect->Width) * TexUvScale.x, (float)(rect->Y + rect->Height) * TexUvScale.y); } bool ImFontAtlas::GetMouseCursorTexData(ImGuiMouseCursor cursor_type, ImVec2* out_offset, ImVec2* out_size, ImVec2 out_uv_border[2], ImVec2 out_uv_fill[2]) @@ -1615,16 +1616,15 @@ bool ImFontAtlas::GetMouseCursorTexData(ImGuiMouseCursor cursor_type, ImVec2* ou ImFontAtlas::CustomRect& r = CustomRects[CustomRectIds[0]]; IM_ASSERT(r.ID == FONT_ATLAS_DEFAULT_TEX_DATA_ID); - ImVec2 uv_scale(1.0f / TexWidth, 1.0f / TexHeight); ImVec2 pos = FONT_ATLAS_DEFAULT_TEX_CURSOR_DATA[cursor_type][0] + ImVec2((float)r.X, (float)r.Y); ImVec2 size = FONT_ATLAS_DEFAULT_TEX_CURSOR_DATA[cursor_type][1]; *out_size = size; *out_offset = FONT_ATLAS_DEFAULT_TEX_CURSOR_DATA[cursor_type][2]; - out_uv_border[0] = (pos) * uv_scale; - out_uv_border[1] = (pos + size) * uv_scale; + out_uv_border[0] = (pos) * TexUvScale; + out_uv_border[1] = (pos + size) * TexUvScale; pos.x += FONT_ATLAS_DEFAULT_TEX_DATA_W_HALF + 1; - out_uv_fill[0] = (pos) * uv_scale; - out_uv_fill[1] = (pos + size) * uv_scale; + out_uv_fill[0] = (pos) * TexUvScale; + out_uv_fill[1] = (pos + size) * TexUvScale; return true; } @@ -1658,7 +1658,8 @@ bool ImFontAtlasBuildWithStbTruetype(ImFontAtlas* atlas) atlas->TexID = NULL; atlas->TexWidth = atlas->TexHeight = 0; - atlas->TexUvWhitePixel = ImVec2(0, 0); + atlas->TexUvScale = ImVec2(0.0f, 0.0f); + atlas->TexUvWhitePixel = ImVec2(0.0f, 0.0f); atlas->ClearTexData(); // Count glyphs/ranges @@ -1767,6 +1768,7 @@ bool ImFontAtlasBuildWithStbTruetype(ImFontAtlas* atlas) // Create texture atlas->TexHeight = ImUpperPowerOfTwo(atlas->TexHeight); + atlas->TexUvScale = ImVec2(1.0f / atlas->TexWidth, 1.0f / atlas->TexHeight); atlas->TexPixelsAlpha8 = (unsigned char*)ImGui::MemAlloc(atlas->TexWidth * atlas->TexHeight); memset(atlas->TexPixelsAlpha8, 0, atlas->TexWidth * atlas->TexHeight); spc.pixels = atlas->TexPixelsAlpha8; @@ -1908,8 +1910,7 @@ static void ImFontAtlasBuildRenderDefaultTexData(ImFontAtlas* atlas) atlas->TexPixelsAlpha8[offset0] = FONT_ATLAS_DEFAULT_TEX_DATA_PIXELS[n] == '.' ? 0xFF : 0x00; atlas->TexPixelsAlpha8[offset1] = FONT_ATLAS_DEFAULT_TEX_DATA_PIXELS[n] == 'X' ? 0xFF : 0x00; } - const ImVec2 tex_uv_scale(1.0f / atlas->TexWidth, 1.0f / atlas->TexHeight); - atlas->TexUvWhitePixel = ImVec2((r.X + 0.5f) * tex_uv_scale.x, (r.Y + 0.5f) * tex_uv_scale.y); + atlas->TexUvWhitePixel = ImVec2((r.X + 0.5f) * atlas->TexUvScale.x, (r.Y + 0.5f) * atlas->TexUvScale.y); } void ImFontAtlasBuildFinish(ImFontAtlas* atlas) From 7c8a19978d52384d277e67b77e61f24a00b9ea23 Mon Sep 17 00:00:00 2001 From: Panos Karabelas Date: Sun, 21 Jan 2018 16:02:09 +0000 Subject: [PATCH 475/823] Simplified return of ImGui::IsKeyReleased() --- imgui.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index c34190b4078e..c41c8b52a193 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -3507,9 +3507,7 @@ bool ImGui::IsKeyReleased(int user_key_index) ImGuiContext& g = *GImGui; if (user_key_index < 0) return false; IM_ASSERT(user_key_index >= 0 && user_key_index < IM_ARRAYSIZE(g.IO.KeysDown)); - if (g.IO.KeysDownDurationPrev[user_key_index] >= 0.0f && !g.IO.KeysDown[user_key_index]) - return true; - return false; + return g.IO.KeysDownDurationPrev[user_key_index] >= 0.0f && !g.IO.KeysDown[user_key_index]; } bool ImGui::IsMouseDown(int button) From ac5b7a1bdf2e7fa40fc467c90d58b5cf0fed3928 Mon Sep 17 00:00:00 2001 From: omar Date: Sun, 21 Jan 2018 19:53:02 +0100 Subject: [PATCH 476/823] Comments --- imgui.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index c41c8b52a193..637721af76ed 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -164,7 +164,7 @@ - A minimal render function skeleton may be: - void void MyRenderFunction(ImDrawData* draw_data)(ImDrawData* draw_data) + void void MyRenderFunction(ImDrawData* draw_data) { // TODO: Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled // TODO: Setup viewport, orthographic projection matrix @@ -2278,8 +2278,8 @@ void ImGui::NewFrame() // (We pass an error message in the assert expression as a trick to get it visible to programmers who are not using a debugger, as most assert handlers display their argument) IM_ASSERT(g.IO.DeltaTime >= 0.0f && "Need a positive DeltaTime (zero is tolerated but will cause some timing issues)"); IM_ASSERT(g.IO.DisplaySize.x >= 0.0f && g.IO.DisplaySize.y >= 0.0f && "Invalid DisplaySize value"); - IM_ASSERT(g.IO.Fonts->Fonts.Size > 0 && "Font Atlas not created. Did you call io.Fonts->GetTexDataAsRGBA32 / GetTexDataAsAlpha8 ?"); - IM_ASSERT(g.IO.Fonts->Fonts[0]->IsLoaded() && "Font Atlas not created. Did you call io.Fonts->GetTexDataAsRGBA32 / GetTexDataAsAlpha8 ?"); + IM_ASSERT(g.IO.Fonts->Fonts.Size > 0 && "Font Atlas not built. Did you call io.Fonts->GetTexDataAsRGBA32() / GetTexDataAsAlpha8() ?"); + IM_ASSERT(g.IO.Fonts->Fonts[0]->IsLoaded() && "Font Atlas not built. Did you call io.Fonts->GetTexDataAsRGBA32() / GetTexDataAsAlpha8() ?"); IM_ASSERT(g.Style.CurveTessellationTol > 0.0f && "Invalid style setting"); IM_ASSERT(g.Style.Alpha >= 0.0f && g.Style.Alpha <= 1.0f && "Invalid style setting. Alpha cannot be negative (allows us to avoid a few clamps in color computations)"); IM_ASSERT((g.FrameCount == 0 || g.FrameCountEnded == g.FrameCount) && "Forgot to call Render() or EndFrame() at the end of the previous frame?"); From 5a301c29dc1c334e2469783f57d1aa40889c270a Mon Sep 17 00:00:00 2001 From: omar Date: Sat, 20 Jan 2018 21:41:46 +0100 Subject: [PATCH 477/823] Context: Removed allocator parameters from CreateContext(), they are now setup with SetMemoryAllocators() and shared by all contexts. (#1565, #586, #992, #1007, #1558) --- imgui.cpp | 43 +++++++++++++++++++++++++++---------------- imgui.h | 12 ++++-------- 2 files changed, 31 insertions(+), 24 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index c34190b4078e..71e6371db0d0 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -213,6 +213,7 @@ Here is a change-log of API breaking changes, if you are using one of the functions listed, expect to have to fix some code. Also read releases logs https://github.com/ocornut/imgui/releases for more details. + - 2018/01/20 (1.XX) - removed allocator parameters from CreateContext(), they are now setup with SetMemoryAllocators() and shared by all contexts. - 2018/01/11 (1.54) - obsoleted IsAnyWindowHovered() in favor of IsWindowHovered(ImGuiHoveredFlags_AnyWindow). Kept redirection function (will obsolete). - 2018/01/11 (1.54) - obsoleted IsAnyWindowFocused() in favor of IsWindowFocused(ImGuiFocusedFlags_AnyWindow). Kept redirection function (will obsolete). - 2018/01/03 (1.54) - renamed ImGuiSizeConstraintCallback to ImGuiSizeCallback, ImGuiSizeConstraintCallbackData to ImGuiSizeCallbackData. @@ -709,6 +710,17 @@ static ImGuiContext GImDefaultContext; ImGuiContext* GImGui = &GImDefaultContext; #endif +// Memory Allocator Functions. Use SetMemoryAllocators() to change them. +// If you use DLL hotreloading you might need to call SetMemoryAllocators() after reloading code from this file. +// Otherwise, you probably don't want to modify them mid-program, and if you use global/static e.g. ImVector<> instances you may need to keep them accessible during program destruction. +static void* MallocWrapper(size_t size, void* user_data) { (void)user_data; return malloc(size); } +static void FreeWrapper(void* ptr, void* user_data) { (void)user_data; free(ptr); } + +static void* (*GImAllocatorAllocFunc)(size_t size, void* user_data) = MallocWrapper; +static void (*GImAllocatorFreeFunc)(void* ptr, void* user_data) = FreeWrapper; +static void* GImAllocatorUserData = NULL; +static size_t GImAllocatorActiveCount = 0; + //----------------------------------------------------------------------------- // User facing structures //----------------------------------------------------------------------------- @@ -807,8 +819,6 @@ ImGuiIO::ImGuiIO() // Settings (User Functions) RenderDrawListsFn = NULL; - MemAllocFn = malloc; - MemFreeFn = free; GetClipboardTextFn = GetClipboardTextFn_DefaultImpl; // Platform dependent default implementations SetClipboardTextFn = SetClipboardTextFn_DefaultImpl; ClipboardUserData = NULL; @@ -2173,14 +2183,14 @@ float ImGui::CalcWrapWidthForPos(const ImVec2& pos, float wrap_pos_x) void* ImGui::MemAlloc(size_t sz) { - GImGui->IO.MetricsAllocs++; - return GImGui->IO.MemAllocFn(sz); + GImAllocatorActiveCount++; + return GImAllocatorAllocFunc(sz, GImAllocatorUserData); } void ImGui::MemFree(void* ptr) { - if (ptr) GImGui->IO.MetricsAllocs--; - return GImGui->IO.MemFreeFn(ptr); + if (ptr) GImAllocatorActiveCount--; + return GImAllocatorFreeFunc(ptr, GImAllocatorUserData); } const char* ImGui::GetClipboardText() @@ -2215,23 +2225,24 @@ void ImGui::SetCurrentContext(ImGuiContext* ctx) #endif } -ImGuiContext* ImGui::CreateContext(void* (*malloc_fn)(size_t), void (*free_fn)(void*)) +void ImGui::SetMemoryAllocators(void* (*alloc_fn)(size_t sz, void* user_data), void(*free_fn)(void* ptr, void* user_data), void* user_data) +{ + GImAllocatorAllocFunc = alloc_fn; + GImAllocatorFreeFunc = free_fn; + GImAllocatorUserData = user_data; +} + +ImGuiContext* ImGui::CreateContext() { - if (!malloc_fn) malloc_fn = malloc; - ImGuiContext* ctx = (ImGuiContext*)malloc_fn(sizeof(ImGuiContext)); - IM_PLACEMENT_NEW(ctx) ImGuiContext(); - ctx->IO.MemAllocFn = malloc_fn; - ctx->IO.MemFreeFn = free_fn ? free_fn : free; + ImGuiContext* ctx = IM_NEW(ImGuiContext)(); return ctx; } void ImGui::DestroyContext(ImGuiContext* ctx) { - void (*free_fn)(void*) = ctx->IO.MemFreeFn; - ctx->~ImGuiContext(); - free_fn(ctx); if (GImGui == ctx) SetCurrentContext(NULL); + IM_DELETE(ctx); } ImGuiIO& ImGui::GetIO() @@ -11668,7 +11679,7 @@ void ImGui::ShowMetricsWindow(bool* p_open) ImGui::Text("Dear ImGui %s", ImGui::GetVersion()); ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate); ImGui::Text("%d vertices, %d indices (%d triangles)", ImGui::GetIO().MetricsRenderVertices, ImGui::GetIO().MetricsRenderIndices, ImGui::GetIO().MetricsRenderIndices / 3); - ImGui::Text("%d allocations", ImGui::GetIO().MetricsAllocs); + ImGui::Text("%d allocations", GImAllocatorActiveCount); static bool show_clip_rects = true; ImGui::Checkbox("Show clipping rectangles when hovering an ImDrawCmd", &show_clip_rects); ImGui::Separator(); diff --git a/imgui.h b/imgui.h index 6d411738ae4d..b137ab703a1c 100644 --- a/imgui.h +++ b/imgui.h @@ -509,10 +509,12 @@ namespace ImGui IMGUI_API const char* GetClipboardText(); IMGUI_API void SetClipboardText(const char* text); - // Internal context access - if you want to use multiple context, share context between modules (e.g. DLL). There is a default context created and active by default. + // Context creation and access, if you want to use multiple context, share context between modules (e.g. DLL). There is a default context created and active by default. // All contexts share a same ImFontAtlas by default. If you want different font atlas, you can new() them and overwrite the GetIO().Fonts variable of an ImGui context. + // All those functions are not reliant on the current context. IMGUI_API const char* GetVersion(); - IMGUI_API ImGuiContext* CreateContext(void* (*malloc_fn)(size_t) = NULL, void (*free_fn)(void*) = NULL); + IMGUI_API void SetMemoryAllocators(void* (*alloc_fn)(size_t sz, void* user_data), void(*free_fn)(void* ptr, void* user_data), void* user_data = NULL); + IMGUI_API ImGuiContext* CreateContext(); IMGUI_API void DestroyContext(ImGuiContext* ctx); IMGUI_API ImGuiContext* GetCurrentContext(); IMGUI_API void SetCurrentContext(ImGuiContext* ctx); @@ -914,11 +916,6 @@ struct ImGuiIO void (*SetClipboardTextFn)(void* user_data, const char* text); void* ClipboardUserData; - // Optional: override memory allocations. MemFreeFn() may be called with a NULL pointer. - // (default to posix malloc/free) - void* (*MemAllocFn)(size_t sz); - void (*MemFreeFn)(void* ptr); - // Optional: notify OS Input Method Editor of the screen position of your cursor for text input position (e.g. when using Japanese/Chinese IME in Windows) // (default to use native imm32 api on Windows) void (*ImeSetInputScreenPosFn)(int x, int y); @@ -954,7 +951,6 @@ struct ImGuiIO bool WantTextInput; // Mobile/console: when io.WantTextInput is true, you may display an on-screen keyboard. This is set by ImGui when it wants textual keyboard input to happen (e.g. when a InputText widget is active). bool WantMoveMouse; // [BETA-NAV] MousePos has been altered, back-end should reposition mouse on next frame. Set only when 'NavMovesMouse=true'. float Framerate; // Application framerate estimation, in frame per second. Solely for convenience. Rolling average estimation based on IO.DeltaTime over 120 frames - int MetricsAllocs; // Number of active memory allocations int MetricsRenderVertices; // Vertices output during last call to Render() int MetricsRenderIndices; // Indices output during last call to Render() = number of triangles * 3 int MetricsActiveWindows; // Number of visible root windows (exclude child windows) From e45d7a7060454a9cd80db56772ac5ce0891fa95d Mon Sep 17 00:00:00 2001 From: omar Date: Sun, 21 Jan 2018 18:54:22 +0100 Subject: [PATCH 478/823] Context: Added IMGUI_DISABLE_DEFAULT_ALLOCATORS to disable linking with malloc/free. (#1565, #586, #992, #1007, #1558) --- imgui.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/imgui.cpp b/imgui.cpp index 71e6371db0d0..99839f4c12cc 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -713,8 +713,13 @@ ImGuiContext* GImGui = &GImDefaultContext; // Memory Allocator Functions. Use SetMemoryAllocators() to change them. // If you use DLL hotreloading you might need to call SetMemoryAllocators() after reloading code from this file. // Otherwise, you probably don't want to modify them mid-program, and if you use global/static e.g. ImVector<> instances you may need to keep them accessible during program destruction. +#ifndef IMGUI_DISABLE_DEFAULT_ALLOCATORS static void* MallocWrapper(size_t size, void* user_data) { (void)user_data; return malloc(size); } static void FreeWrapper(void* ptr, void* user_data) { (void)user_data; free(ptr); } +#else +static void* MallocWrapper(size_t size, void* user_data) { (void)user_data; (void)size; IM_ASSERT(0); return NULL; } +static void FreeWrapper(void* ptr, void* user_data) { (void)user_data; (void)ptr; IM_ASSERT(0); } +#endif static void* (*GImAllocatorAllocFunc)(size_t size, void* user_data) = MallocWrapper; static void (*GImAllocatorFreeFunc)(void* ptr, void* user_data) = FreeWrapper; From 7e4d28a49d457ee6dce520bca16453ea8c3e9d49 Mon Sep 17 00:00:00 2001 From: omar Date: Sun, 21 Jan 2018 19:44:48 +0100 Subject: [PATCH 479/823] Context: Renamed SetMemoryAllocators() to SetAllocatorFunctions(). Tweaked comments. (#1565, #586, #992, #1007, #1558) --- imgui.cpp | 20 ++++++++++---------- imgui.h | 6 +++--- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 99839f4c12cc..fa6e542d0e12 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -213,7 +213,7 @@ Here is a change-log of API breaking changes, if you are using one of the functions listed, expect to have to fix some code. Also read releases logs https://github.com/ocornut/imgui/releases for more details. - - 2018/01/20 (1.XX) - removed allocator parameters from CreateContext(), they are now setup with SetMemoryAllocators() and shared by all contexts. + - 2018/01/20 (1.XX) - removed allocator parameters from CreateContext(), they are now setup with SetAllocatorFunctions() and shared by all contexts. - 2018/01/11 (1.54) - obsoleted IsAnyWindowHovered() in favor of IsWindowHovered(ImGuiHoveredFlags_AnyWindow). Kept redirection function (will obsolete). - 2018/01/11 (1.54) - obsoleted IsAnyWindowFocused() in favor of IsWindowFocused(ImGuiFocusedFlags_AnyWindow). Kept redirection function (will obsolete). - 2018/01/03 (1.54) - renamed ImGuiSizeConstraintCallback to ImGuiSizeCallback, ImGuiSizeConstraintCallbackData to ImGuiSizeCallbackData. @@ -710,8 +710,8 @@ static ImGuiContext GImDefaultContext; ImGuiContext* GImGui = &GImDefaultContext; #endif -// Memory Allocator Functions. Use SetMemoryAllocators() to change them. -// If you use DLL hotreloading you might need to call SetMemoryAllocators() after reloading code from this file. +// Memory Allocator functions. Use SetAllocatorFunctions() to change them. +// If you use DLL hotreloading you might need to call SetAllocatorFunctions() after reloading code from this file. // Otherwise, you probably don't want to modify them mid-program, and if you use global/static e.g. ImVector<> instances you may need to keep them accessible during program destruction. #ifndef IMGUI_DISABLE_DEFAULT_ALLOCATORS static void* MallocWrapper(size_t size, void* user_data) { (void)user_data; return malloc(size); } @@ -724,7 +724,7 @@ static void FreeWrapper(void* ptr, void* user_data) { (void)user_data; static void* (*GImAllocatorAllocFunc)(size_t size, void* user_data) = MallocWrapper; static void (*GImAllocatorFreeFunc)(void* ptr, void* user_data) = FreeWrapper; static void* GImAllocatorUserData = NULL; -static size_t GImAllocatorActiveCount = 0; +static size_t GImAllocatorActiveAllocationsCount = 0; //----------------------------------------------------------------------------- // User facing structures @@ -2188,13 +2188,13 @@ float ImGui::CalcWrapWidthForPos(const ImVec2& pos, float wrap_pos_x) void* ImGui::MemAlloc(size_t sz) { - GImAllocatorActiveCount++; + GImAllocatorActiveAllocationsCount++; return GImAllocatorAllocFunc(sz, GImAllocatorUserData); } void ImGui::MemFree(void* ptr) { - if (ptr) GImAllocatorActiveCount--; + if (ptr) GImAllocatorActiveAllocationsCount--; return GImAllocatorFreeFunc(ptr, GImAllocatorUserData); } @@ -2230,10 +2230,10 @@ void ImGui::SetCurrentContext(ImGuiContext* ctx) #endif } -void ImGui::SetMemoryAllocators(void* (*alloc_fn)(size_t sz, void* user_data), void(*free_fn)(void* ptr, void* user_data), void* user_data) +void ImGui::SetAllocatorFunctions(void* (*alloc_func)(size_t sz, void* user_data), void(*free_func)(void* ptr, void* user_data), void* user_data) { - GImAllocatorAllocFunc = alloc_fn; - GImAllocatorFreeFunc = free_fn; + GImAllocatorAllocFunc = alloc_func; + GImAllocatorFreeFunc = free_func; GImAllocatorUserData = user_data; } @@ -11684,7 +11684,7 @@ void ImGui::ShowMetricsWindow(bool* p_open) ImGui::Text("Dear ImGui %s", ImGui::GetVersion()); ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate); ImGui::Text("%d vertices, %d indices (%d triangles)", ImGui::GetIO().MetricsRenderVertices, ImGui::GetIO().MetricsRenderIndices, ImGui::GetIO().MetricsRenderIndices / 3); - ImGui::Text("%d allocations", GImAllocatorActiveCount); + ImGui::Text("%d allocations", GImAllocatorActiveAllocationsCount); static bool show_clip_rects = true; ImGui::Checkbox("Show clipping rectangles when hovering an ImDrawCmd", &show_clip_rects); ImGui::Separator(); diff --git a/imgui.h b/imgui.h index b137ab703a1c..fff343d05dd3 100644 --- a/imgui.h +++ b/imgui.h @@ -503,8 +503,9 @@ namespace ImGui IMGUI_API void CaptureKeyboardFromApp(bool capture = true); // manually override io.WantCaptureKeyboard flag next frame (said flag is entirely left for your application handle). e.g. force capture keyboard when your widget is being hovered. IMGUI_API void CaptureMouseFromApp(bool capture = true); // manually override io.WantCaptureMouse flag next frame (said flag is entirely left for your application handle). - // Helpers functions to access functions pointers in ImGui::GetIO() - IMGUI_API void* MemAlloc(size_t sz); + // Helpers functions to access memory allocators and clipboard functions. + IMGUI_API void SetAllocatorFunctions(void* (*alloc_func)(size_t sz, void* user_data), void(*free_func)(void* ptr, void* user_data), void* user_data = NULL); + IMGUI_API void* MemAlloc(size_t size); IMGUI_API void MemFree(void* ptr); IMGUI_API const char* GetClipboardText(); IMGUI_API void SetClipboardText(const char* text); @@ -513,7 +514,6 @@ namespace ImGui // All contexts share a same ImFontAtlas by default. If you want different font atlas, you can new() them and overwrite the GetIO().Fonts variable of an ImGui context. // All those functions are not reliant on the current context. IMGUI_API const char* GetVersion(); - IMGUI_API void SetMemoryAllocators(void* (*alloc_fn)(size_t sz, void* user_data), void(*free_fn)(void* ptr, void* user_data), void* user_data = NULL); IMGUI_API ImGuiContext* CreateContext(); IMGUI_API void DestroyContext(ImGuiContext* ctx); IMGUI_API ImGuiContext* GetCurrentContext(); From 5e2aa6185ccacbdd93cc2d79c8e46c7fbc8a0ee3 Mon Sep 17 00:00:00 2001 From: omar Date: Sun, 21 Jan 2018 19:58:32 +0100 Subject: [PATCH 480/823] Reorganized context handling to be more explicit, - YOU NOW NEED TO CALL ImGui::CreateContext() AT THE BEGINNING OF YOUR APP, AND CALL ImGui::DestroyContext() AT THE END. - removed Shutdown() function, as DestroyContext() serve this purpose. - you may pass a ImFontAtlas* pointer to CreateContext() to share a font atlas between contexts. Otherwhise CreateContext() will create its own font atlas instance. - removed allocator parameters from CreateContext(), they are now setup with SetAllocatorFunctions(), and shared by all contexts. - removed the default global context and font atlas instance, which were confusing for users of DLL reloading and users of multiple contexts (#1565, #586, #992, #1007, #1558) --- imgui.cpp | 56 +++++++++++++++++++++++++++++------------------- imgui.h | 19 ++++++++-------- imgui_internal.h | 8 +++++-- 3 files changed, 49 insertions(+), 34 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index fa6e542d0e12..8eb17280d5b4 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -125,6 +125,7 @@ - A minimal application skeleton may be: // Application init + ImGui::CreateContext(); ImGuiIO& io = ImGui::GetIO(); io.DisplaySize.x = 1920.0f; io.DisplaySize.y = 1280.0f; @@ -162,6 +163,10 @@ SwapBuffers(); } + // Shutdown + ImGui::DestroyContext(); + + - A minimal render function skeleton may be: void void MyRenderFunction(ImDrawData* draw_data)(ImDrawData* draw_data) @@ -213,7 +218,12 @@ Here is a change-log of API breaking changes, if you are using one of the functions listed, expect to have to fix some code. Also read releases logs https://github.com/ocornut/imgui/releases for more details. - - 2018/01/20 (1.XX) - removed allocator parameters from CreateContext(), they are now setup with SetAllocatorFunctions() and shared by all contexts. + - 2018/01/21 (1.XX) - reorganized context handling to be more explicit, + - YOU NOW NEED TO CALL ImGui::CreateContext() AT THE BEGINNING OF YOUR APP, AND CALL ImGui::DestroyContext() AT THE END. + - removed Shutdown() function, as DestroyContext() serve this purpose. + - you may pass a ImFontAtlas* pointer to CreateContext() to share a font atlas between contexts. Otherwhise CreateContext() will create its own font atlas instance. + - removed allocator parameters from CreateContext(), they are now setup with SetAllocatorFunctions(), and shared by all contexts. + - removed the default global context and font atlas instance, which were confusing for users of DLL reloading and users of multiple contexts. - 2018/01/11 (1.54) - obsoleted IsAnyWindowHovered() in favor of IsWindowHovered(ImGuiHoveredFlags_AnyWindow). Kept redirection function (will obsolete). - 2018/01/11 (1.54) - obsoleted IsAnyWindowFocused() in favor of IsWindowFocused(ImGuiFocusedFlags_AnyWindow). Kept redirection function (will obsolete). - 2018/01/03 (1.54) - renamed ImGuiSizeConstraintCallback to ImGuiSizeCallback, ImGuiSizeConstraintCallbackData to ImGuiSizeCallbackData. @@ -695,19 +705,14 @@ static void ImeSetInputScreenPosFn_DefaultImpl(int x, int y); // Context //----------------------------------------------------------------------------- -// Default font atlas storage. -// New contexts always point by default to this font atlas. It can be changed by reassigning the GetIO().Fonts variable. -static ImFontAtlas GImDefaultFontAtlas; - -// Default context storage + current context pointer. -// Implicitely used by all ImGui functions. Always assumed to be != NULL. Change to a different context by calling ImGui::SetCurrentContext() -// If you are hot-reloading this code in a DLL you will lose the static/global variables. Create your own context+font atlas instead of relying on those default (see FAQ entry "How can I preserve my ImGui context across reloading a DLL?"). -// ImGui is currently not thread-safe because of this variable. If you want thread-safety to allow N threads to access N different contexts, you might work around it by: +// Current context pointer. Implicitely used by all ImGui functions. Always assumed to be != NULL. +// CreateContext() will automatically set this pointer if it is NULL. Change to a different context by calling ImGui::SetCurrentContext(). +// If you use DLL hotreloading you might need to call SetCurrentContext() after reloading code from this file. +// ImGui functions are not thread-safe because of this pointer. If you want thread-safety to allow N threads to access N different contexts, you can: +// - Change this variable to use thread local storage. You may #define GImGui in imconfig.h for that purpose. Future development aim to make this context pointer explicit to all calls. Also read https://github.com/ocornut/imgui/issues/586 // - Having multiple instances of the ImGui code compiled inside different namespace (easiest/safest, if you have a finite number of contexts) -// - or: Changing this variable to be TLS. You may #define GImGui in imconfig.h for further custom hackery. Future development aim to make this context pointer explicit to all calls. Also read https://github.com/ocornut/imgui/issues/586 #ifndef GImGui -static ImGuiContext GImDefaultContext; -ImGuiContext* GImGui = &GImDefaultContext; +ImGuiContext* GImGui = NULL; #endif // Memory Allocator functions. Use SetAllocatorFunctions() to change them. @@ -807,7 +812,7 @@ ImGuiIO::ImGuiIO() KeyRepeatRate = 0.050f; UserData = NULL; - Fonts = &GImDefaultFontAtlas; + Fonts = NULL; FontGlobalScale = 1.0f; FontDefault = NULL; FontAllowUserScaling = false; @@ -2237,14 +2242,19 @@ void ImGui::SetAllocatorFunctions(void* (*alloc_func)(size_t sz, void* user_data GImAllocatorUserData = user_data; } -ImGuiContext* ImGui::CreateContext() +ImGuiContext* ImGui::CreateContext(ImFontAtlas* shared_font_atlas) { - ImGuiContext* ctx = IM_NEW(ImGuiContext)(); + ImGuiContext* ctx = IM_NEW(ImGuiContext)(shared_font_atlas); + if (GImGui == NULL) + SetCurrentContext(ctx); return ctx; } void ImGui::DestroyContext(ImGuiContext* ctx) { + if (ctx == NULL) + ctx = GImGui; + Shutdown(ctx); if (GImGui == ctx) SetCurrentContext(NULL); IM_DELETE(ctx); @@ -2252,11 +2262,13 @@ void ImGui::DestroyContext(ImGuiContext* ctx) ImGuiIO& ImGui::GetIO() { + IM_ASSERT(GImGui != NULL && "No current context. Did you call ImGui::CreateContext() or ImGui::SetCurrentContext()?"); return GImGui->IO; } ImGuiStyle& ImGui::GetStyle() { + IM_ASSERT(GImGui != NULL && "No current context. Did you call ImGui::CreateContext() or ImGui::SetCurrentContext()?"); return GImGui->Style; } @@ -2304,7 +2316,7 @@ void ImGui::NewFrame() // Initialize on first frame if (!g.Initialized) - Initialize(); + Initialize(&g); g.Time += g.IO.DeltaTime; g.FrameCount += 1; @@ -2624,9 +2636,9 @@ static void SettingsHandlerWindow_WriteAll(ImGuiContext* imgui_ctx, ImGuiSetting } } -void ImGui::Initialize() +void ImGui::Initialize(ImGuiContext* context) { - ImGuiContext& g = *GImGui; + ImGuiContext& g = *context; g.LogClipboard = IM_NEW(ImGuiTextBuffer)(); // Add .ini handle for ImGuiWindow type @@ -2645,13 +2657,13 @@ void ImGui::Initialize() } // This function is merely here to free heap allocations. -void ImGui::Shutdown() +void ImGui::Shutdown(ImGuiContext* context) { - ImGuiContext& g = *GImGui; + ImGuiContext& g = *context; // The fonts atlas can be used prior to calling NewFrame(), so we clear it even if g.Initialized is FALSE (which would happen if we never called NewFrame) - if (g.IO.Fonts) // Testing for NULL to allow user to NULLify in case of running Shutdown() on multiple contexts. Bit hacky. - g.IO.Fonts->Clear(); + if (g.IO.Fonts && g.FontAtlasOwnedByContext) + IM_DELETE(g.IO.Fonts); // Cleanup of other data are conditional on actually having initialize ImGui. if (!g.Initialized) diff --git a/imgui.h b/imgui.h index fff343d05dd3..ef8b9a37aefd 100644 --- a/imgui.h +++ b/imgui.h @@ -127,6 +127,14 @@ struct ImVec4 // In a namespace so that user can add extra functions in a separate file (e.g. Value() helpers for your vector or common types) namespace ImGui { + // Context creation and access, if you want to use multiple context, share context between modules (e.g. DLL). + // All contexts share a same ImFontAtlas by default. If you want different font atlas, you can new() them and overwrite the GetIO().Fonts variable of an ImGui context. + // All those functions are not reliant on the current context. + IMGUI_API ImGuiContext* CreateContext(ImFontAtlas* shared_font_atlas = NULL); + IMGUI_API void DestroyContext(ImGuiContext* ctx = NULL); // NULL = Destroy current context + IMGUI_API ImGuiContext* GetCurrentContext(); + IMGUI_API void SetCurrentContext(ImGuiContext* ctx); + // Main IMGUI_API ImGuiIO& GetIO(); IMGUI_API ImGuiStyle& GetStyle(); @@ -134,7 +142,6 @@ namespace ImGui IMGUI_API void NewFrame(); // start a new ImGui frame, you can submit any command from this point until Render()/EndFrame(). IMGUI_API void Render(); // ends the ImGui frame, finalize the draw data, then call your io.RenderDrawListsFn() function if set. IMGUI_API void EndFrame(); // ends the ImGui frame. automatically called by Render(), so most likely don't need to ever call that yourself directly. If you don't need to render you may call EndFrame() but you'll have wasted CPU already. If you don't need to render, better to not create any imgui windows instead! - IMGUI_API void Shutdown(); // Demo, Debug, Informations IMGUI_API void ShowDemoWindow(bool* p_open = NULL); // create demo/test window (previously called ShowTestWindow). demonstrate most ImGui features. call this to learn about the library! try to make it always available in your application! @@ -143,6 +150,7 @@ namespace ImGui IMGUI_API bool ShowStyleSelector(const char* label); IMGUI_API void ShowFontSelector(const char* label); IMGUI_API void ShowUserGuide(); // add basic help/info block (not a window): how to manipulate ImGui as a end-user (mouse/keyboard controls). + IMGUI_API const char* GetVersion(); // Window IMGUI_API bool Begin(const char* name, bool* p_open = NULL, ImGuiWindowFlags flags = 0); // push window to the stack and start appending to it. see .cpp for details. return false when window is collapsed (so you can early out in your code) but you always need to call End() regardless. 'bool* p_open' creates a widget on the upper-right to close the window (which sets your bool to false). @@ -510,15 +518,6 @@ namespace ImGui IMGUI_API const char* GetClipboardText(); IMGUI_API void SetClipboardText(const char* text); - // Context creation and access, if you want to use multiple context, share context between modules (e.g. DLL). There is a default context created and active by default. - // All contexts share a same ImFontAtlas by default. If you want different font atlas, you can new() them and overwrite the GetIO().Fonts variable of an ImGui context. - // All those functions are not reliant on the current context. - IMGUI_API const char* GetVersion(); - IMGUI_API ImGuiContext* CreateContext(); - IMGUI_API void DestroyContext(ImGuiContext* ctx); - IMGUI_API ImGuiContext* GetCurrentContext(); - IMGUI_API void SetCurrentContext(ImGuiContext* ctx); - } // namespace ImGui // Flags for ImGui::Begin() diff --git a/imgui_internal.h b/imgui_internal.h index d6d19a426075..e6ba06221e9b 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -497,6 +497,7 @@ struct ImGuiNextWindowData struct ImGuiContext { bool Initialized; + bool FontAtlasOwnedByContext; // Io.Fonts-> is owned by the ImGuiContext and will be destructed along with it. ImGuiIO IO; ImGuiStyle Style; ImFont* Font; // (Shortcut) == FontStack.empty() ? IO.Font : FontStack.back() @@ -598,11 +599,13 @@ struct ImGuiContext int WantTextInputNextFrame; char TempBuffer[1024*3+1]; // temporary text buffer - ImGuiContext() : OverlayDrawList(NULL) + ImGuiContext(ImFontAtlas* shared_font_atlas) : OverlayDrawList(NULL) { Initialized = false; Font = NULL; FontSize = FontBaseSize = 0.0f; + FontAtlasOwnedByContext = shared_font_atlas ? false : true; + IO.Fonts = shared_font_atlas ? shared_font_atlas : IM_NEW(ImFontAtlas)(); Time = 0.0f; FrameCount = 0; @@ -864,7 +867,8 @@ namespace ImGui IMGUI_API void BringWindowToBack(ImGuiWindow* window); IMGUI_API bool IsWindowChildOf(ImGuiWindow* window, ImGuiWindow* potential_parent); - IMGUI_API void Initialize(); + IMGUI_API void Initialize(ImGuiContext* context); + IMGUI_API void Shutdown(ImGuiContext* context); // Since 1.54 this is a _private_ function. You can call DestroyContext() to destroy the context created by CreateContext(). IMGUI_API void MarkIniSettingsDirty(); IMGUI_API ImGuiSettingsHandler* FindSettingsHandler(const char* type_name); From d3e826c247378c2b1f26e3d9a62980f3a9e96e11 Mon Sep 17 00:00:00 2001 From: omar Date: Sun, 21 Jan 2018 20:09:30 +0100 Subject: [PATCH 481/823] Examples: Updated for reorganized context functions. Calling CreateContext(), DestroyContext() in example code. Removed Shutdown() from binding code. (#1565, #586, #992, #1007, #1558) --- examples/allegro5_example/imgui_impl_a5.cpp | 1 - examples/allegro5_example/main.cpp | 2 ++ examples/directx10_example/imgui_impl_dx10.cpp | 1 - examples/directx10_example/main.cpp | 3 +++ examples/directx11_example/imgui_impl_dx11.cpp | 1 - examples/directx11_example/main.cpp | 3 +++ examples/directx9_example/imgui_impl_dx9.cpp | 1 - examples/directx9_example/main.cpp | 3 +++ examples/marmalade_example/imgui_impl_marmalade.cpp | 4 ---- examples/marmalade_example/main.cpp | 5 +++++ examples/null_example/main.cpp | 5 +++-- examples/opengl2_example/imgui_impl_glfw_gl2.cpp | 1 - examples/opengl2_example/main.cpp | 2 ++ examples/opengl3_example/imgui_impl_glfw_gl3.cpp | 1 - examples/opengl3_example/main.cpp | 2 ++ examples/sdl_opengl2_example/imgui_impl_sdl_gl2.cpp | 1 - examples/sdl_opengl2_example/main.cpp | 3 +++ examples/sdl_opengl3_example/imgui_impl_sdl_gl3.cpp | 1 - examples/sdl_opengl3_example/main.cpp | 3 +++ examples/vulkan_example/imgui_impl_glfw_vulkan.cpp | 1 - examples/vulkan_example/main.cpp | 2 ++ 21 files changed, 31 insertions(+), 15 deletions(-) diff --git a/examples/allegro5_example/imgui_impl_a5.cpp b/examples/allegro5_example/imgui_impl_a5.cpp index 62f7af67296f..dddb4c3a0cd0 100644 --- a/examples/allegro5_example/imgui_impl_a5.cpp +++ b/examples/allegro5_example/imgui_impl_a5.cpp @@ -200,7 +200,6 @@ bool ImGui_ImplA5_Init(ALLEGRO_DISPLAY* display) void ImGui_ImplA5_Shutdown() { ImGui_ImplA5_InvalidateDeviceObjects(); - ImGui::Shutdown(); } // You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs. diff --git a/examples/allegro5_example/main.cpp b/examples/allegro5_example/main.cpp index 3c9c9770eb1c..11ec724c92e9 100644 --- a/examples/allegro5_example/main.cpp +++ b/examples/allegro5_example/main.cpp @@ -23,6 +23,7 @@ int main(int, char**) al_register_event_source(queue, al_get_mouse_event_source()); // Setup ImGui binding + ImGui::CreateContext(); ImGui_ImplA5_Init(display); // Setup style @@ -109,6 +110,7 @@ int main(int, char**) // Cleanup ImGui_ImplA5_Shutdown(); + ImGui::DestroyContext(); al_destroy_event_queue(queue); al_destroy_display(display); diff --git a/examples/directx10_example/imgui_impl_dx10.cpp b/examples/directx10_example/imgui_impl_dx10.cpp index 14a47c4af52b..66b411e47833 100644 --- a/examples/directx10_example/imgui_impl_dx10.cpp +++ b/examples/directx10_example/imgui_impl_dx10.cpp @@ -569,7 +569,6 @@ bool ImGui_ImplDX10_Init(void* hwnd, ID3D10Device* device) void ImGui_ImplDX10_Shutdown() { ImGui_ImplDX10_InvalidateDeviceObjects(); - ImGui::Shutdown(); g_pd3dDevice = NULL; g_hWnd = (HWND)0; } diff --git a/examples/directx10_example/main.cpp b/examples/directx10_example/main.cpp index 38f4054eada3..8b54fabfb3e6 100644 --- a/examples/directx10_example/main.cpp +++ b/examples/directx10_example/main.cpp @@ -122,6 +122,7 @@ int main(int, char**) UpdateWindow(hwnd); // Setup ImGui binding + ImGui::CreateContext(); ImGui_ImplDX10_Init(hwnd, g_pd3dDevice); // Setup style @@ -204,6 +205,8 @@ int main(int, char**) } ImGui_ImplDX10_Shutdown(); + ImGui::DestroyContext(); + CleanupDeviceD3D(); UnregisterClass(_T("ImGui Example"), wc.hInstance); diff --git a/examples/directx11_example/imgui_impl_dx11.cpp b/examples/directx11_example/imgui_impl_dx11.cpp index 4963fc12eaa3..61860f5c1f26 100644 --- a/examples/directx11_example/imgui_impl_dx11.cpp +++ b/examples/directx11_example/imgui_impl_dx11.cpp @@ -571,7 +571,6 @@ bool ImGui_ImplDX11_Init(void* hwnd, ID3D11Device* device, ID3D11DeviceContex void ImGui_ImplDX11_Shutdown() { ImGui_ImplDX11_InvalidateDeviceObjects(); - ImGui::Shutdown(); g_pd3dDevice = NULL; g_pd3dDeviceContext = NULL; g_hWnd = (HWND)0; diff --git a/examples/directx11_example/main.cpp b/examples/directx11_example/main.cpp index 79e7bb169ddc..84db742d6c2e 100644 --- a/examples/directx11_example/main.cpp +++ b/examples/directx11_example/main.cpp @@ -125,6 +125,7 @@ int main(int, char**) UpdateWindow(hwnd); // Setup ImGui binding + ImGui::CreateContext(); ImGui_ImplDX11_Init(hwnd, g_pd3dDevice, g_pd3dDeviceContext); // Setup style @@ -207,6 +208,8 @@ int main(int, char**) } ImGui_ImplDX11_Shutdown(); + ImGui::DestroyContext(); + CleanupDeviceD3D(); UnregisterClass(_T("ImGui Example"), wc.hInstance); diff --git a/examples/directx9_example/imgui_impl_dx9.cpp b/examples/directx9_example/imgui_impl_dx9.cpp index a4e676914ce4..af30fbf49ebd 100644 --- a/examples/directx9_example/imgui_impl_dx9.cpp +++ b/examples/directx9_example/imgui_impl_dx9.cpp @@ -288,7 +288,6 @@ bool ImGui_ImplDX9_Init(void* hwnd, IDirect3DDevice9* device) void ImGui_ImplDX9_Shutdown() { ImGui_ImplDX9_InvalidateDeviceObjects(); - ImGui::Shutdown(); g_pd3dDevice = NULL; g_hWnd = 0; } diff --git a/examples/directx9_example/main.cpp b/examples/directx9_example/main.cpp index 09a109d981bc..64159b9e05e7 100644 --- a/examples/directx9_example/main.cpp +++ b/examples/directx9_example/main.cpp @@ -75,6 +75,7 @@ int main(int, char**) } // Setup ImGui binding + ImGui::CreateContext(); ImGui_ImplDX9_Init(hwnd, g_pd3dDevice); // Setup style @@ -173,6 +174,8 @@ int main(int, char**) } ImGui_ImplDX9_Shutdown(); + ImGui::DestroyContext(); + if (g_pd3dDevice) g_pd3dDevice->Release(); if (pD3D) pD3D->Release(); UnregisterClass(_T("ImGui Example"), wc.hInstance); diff --git a/examples/marmalade_example/imgui_impl_marmalade.cpp b/examples/marmalade_example/imgui_impl_marmalade.cpp index 36fc8328c862..0ce0edc4618b 100644 --- a/examples/marmalade_example/imgui_impl_marmalade.cpp +++ b/examples/marmalade_example/imgui_impl_marmalade.cpp @@ -207,8 +207,6 @@ void ImGui_Marmalade_InvalidateDeviceObjects() bool ImGui_Marmalade_Init(bool install_callbacks) { - IwGxInit(); - ImGuiIO& io = ImGui::GetIO(); io.KeyMap[ImGuiKey_Tab] = s3eKeyTab; // Keyboard mapping. ImGui will use those indices to peek into the io.KeyDown[] array. io.KeyMap[ImGuiKey_LeftArrow] = s3eKeyLeft; @@ -248,8 +246,6 @@ bool ImGui_Marmalade_Init(bool install_callbacks) void ImGui_Marmalade_Shutdown() { ImGui_Marmalade_InvalidateDeviceObjects(); - ImGui::Shutdown(); - IwGxTerminate(); } void ImGui_Marmalade_NewFrame() diff --git a/examples/marmalade_example/main.cpp b/examples/marmalade_example/main.cpp index 2b5edb77f78d..4ad1fe2591f9 100644 --- a/examples/marmalade_example/main.cpp +++ b/examples/marmalade_example/main.cpp @@ -14,7 +14,10 @@ int main(int, char**) { + IwGxInit(); + // Setup ImGui binding + ImGui::CreateContext(); ImGui_Marmalade_Init(true); // Setup style @@ -95,6 +98,8 @@ int main(int, char**) // Cleanup ImGui_Marmalade_Shutdown(); + ImGui::DestroyContext(); + IwGxTerminate(); return 0; } diff --git a/examples/null_example/main.cpp b/examples/null_example/main.cpp index 04c1bda40702..f60b8054a3de 100644 --- a/examples/null_example/main.cpp +++ b/examples/null_example/main.cpp @@ -4,6 +4,7 @@ int main(int, char**) { + ImGui::CreateContext(); ImGuiIO& io = ImGui::GetIO(); // Build atlas @@ -27,7 +28,7 @@ int main(int, char**) ImGui::Render(); } - printf("Shutdown()\n"); - ImGui::Shutdown(); + printf("DestroyContext()\n"); + ImGui::DestroyContext(); return 0; } diff --git a/examples/opengl2_example/imgui_impl_glfw_gl2.cpp b/examples/opengl2_example/imgui_impl_glfw_gl2.cpp index e5fe2f47bcb0..4c450ed5a37d 100644 --- a/examples/opengl2_example/imgui_impl_glfw_gl2.cpp +++ b/examples/opengl2_example/imgui_impl_glfw_gl2.cpp @@ -246,7 +246,6 @@ bool ImGui_ImplGlfwGL2_Init(GLFWwindow* window, bool install_callbacks) void ImGui_ImplGlfwGL2_Shutdown() { ImGui_ImplGlfwGL2_InvalidateDeviceObjects(); - ImGui::Shutdown(); } void ImGui_ImplGlfwGL2_NewFrame() diff --git a/examples/opengl2_example/main.cpp b/examples/opengl2_example/main.cpp index 6359f5b6253f..ef4f876e376c 100644 --- a/examples/opengl2_example/main.cpp +++ b/examples/opengl2_example/main.cpp @@ -27,6 +27,7 @@ int main(int, char**) glfwSwapInterval(1); // Enable vsync // Setup ImGui binding + ImGui::CreateContext(); ImGui_ImplGlfwGL2_Init(window, true); // Setup style @@ -105,6 +106,7 @@ int main(int, char**) // Cleanup ImGui_ImplGlfwGL2_Shutdown(); + ImGui::DestroyContext(); glfwTerminate(); return 0; diff --git a/examples/opengl3_example/imgui_impl_glfw_gl3.cpp b/examples/opengl3_example/imgui_impl_glfw_gl3.cpp index a71fc515dab5..3b39e1853f79 100644 --- a/examples/opengl3_example/imgui_impl_glfw_gl3.cpp +++ b/examples/opengl3_example/imgui_impl_glfw_gl3.cpp @@ -358,7 +358,6 @@ bool ImGui_ImplGlfwGL3_Init(GLFWwindow* window, bool install_callbacks) void ImGui_ImplGlfwGL3_Shutdown() { ImGui_ImplGlfwGL3_InvalidateDeviceObjects(); - ImGui::Shutdown(); } void ImGui_ImplGlfwGL3_NewFrame() diff --git a/examples/opengl3_example/main.cpp b/examples/opengl3_example/main.cpp index 6beb855dc4f0..7c29cb7128cb 100644 --- a/examples/opengl3_example/main.cpp +++ b/examples/opengl3_example/main.cpp @@ -32,6 +32,7 @@ int main(int, char**) gl3wInit(); // Setup ImGui binding + ImGui::CreateContext(); ImGui_ImplGlfwGL3_Init(window, true); // Setup style @@ -109,6 +110,7 @@ int main(int, char**) // Cleanup ImGui_ImplGlfwGL3_Shutdown(); + ImGui::DestroyContext(); glfwTerminate(); return 0; diff --git a/examples/sdl_opengl2_example/imgui_impl_sdl_gl2.cpp b/examples/sdl_opengl2_example/imgui_impl_sdl_gl2.cpp index 76def29c3af8..f937bccadda0 100644 --- a/examples/sdl_opengl2_example/imgui_impl_sdl_gl2.cpp +++ b/examples/sdl_opengl2_example/imgui_impl_sdl_gl2.cpp @@ -245,7 +245,6 @@ bool ImGui_ImplSdlGL2_Init(SDL_Window* window) void ImGui_ImplSdlGL2_Shutdown() { ImGui_ImplSdlGL2_InvalidateDeviceObjects(); - ImGui::Shutdown(); } void ImGui_ImplSdlGL2_NewFrame(SDL_Window *window) diff --git a/examples/sdl_opengl2_example/main.cpp b/examples/sdl_opengl2_example/main.cpp index 21b567a835e9..115dfc653b80 100644 --- a/examples/sdl_opengl2_example/main.cpp +++ b/examples/sdl_opengl2_example/main.cpp @@ -33,6 +33,7 @@ int main(int, char**) SDL_GLContext glcontext = SDL_GL_CreateContext(window); // Setup ImGui binding + ImGui::CreateContext(); ImGui_ImplSdlGL2_Init(window); // Setup style @@ -116,6 +117,8 @@ int main(int, char**) // Cleanup ImGui_ImplSdlGL2_Shutdown(); + ImGui::DestroyContext(); + SDL_GL_DeleteContext(glcontext); SDL_DestroyWindow(window); SDL_Quit(); diff --git a/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.cpp b/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.cpp index 35d9cdde1313..a8c1363cf9c3 100644 --- a/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.cpp +++ b/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.cpp @@ -356,7 +356,6 @@ bool ImGui_ImplSdlGL3_Init(SDL_Window* window) void ImGui_ImplSdlGL3_Shutdown() { ImGui_ImplSdlGL3_InvalidateDeviceObjects(); - ImGui::Shutdown(); } void ImGui_ImplSdlGL3_NewFrame(SDL_Window* window) diff --git a/examples/sdl_opengl3_example/main.cpp b/examples/sdl_opengl3_example/main.cpp index 7ee60389c417..3cd07168de86 100644 --- a/examples/sdl_opengl3_example/main.cpp +++ b/examples/sdl_opengl3_example/main.cpp @@ -33,6 +33,7 @@ int main(int, char**) gl3wInit(); // Setup ImGui binding + ImGui::CreateContext(); ImGui_ImplSdlGL3_Init(window); // Setup style @@ -115,6 +116,8 @@ int main(int, char**) // Cleanup ImGui_ImplSdlGL3_Shutdown(); + ImGui::DestroyContext(); + SDL_GL_DeleteContext(glcontext); SDL_DestroyWindow(window); SDL_Quit(); diff --git a/examples/vulkan_example/imgui_impl_glfw_vulkan.cpp b/examples/vulkan_example/imgui_impl_glfw_vulkan.cpp index b9e6d78f2397..caf0312cdca5 100644 --- a/examples/vulkan_example/imgui_impl_glfw_vulkan.cpp +++ b/examples/vulkan_example/imgui_impl_glfw_vulkan.cpp @@ -787,7 +787,6 @@ bool ImGui_ImplGlfwVulkan_Init(GLFWwindow* window, bool install_callbacks, Im void ImGui_ImplGlfwVulkan_Shutdown() { ImGui_ImplGlfwVulkan_InvalidateDeviceObjects(); - ImGui::Shutdown(); } void ImGui_ImplGlfwVulkan_NewFrame() diff --git a/examples/vulkan_example/main.cpp b/examples/vulkan_example/main.cpp index 6c4ef33fe28b..b75fdaf0d4f1 100644 --- a/examples/vulkan_example/main.cpp +++ b/examples/vulkan_example/main.cpp @@ -615,6 +615,7 @@ int main(int, char**) setup_vulkan(window); // Setup ImGui binding + ImGui::CreateContext(); ImGui_ImplGlfwVulkan_Init_Data init_data = {}; init_data.allocator = g_Allocator; init_data.gpu = g_Gpu; @@ -737,6 +738,7 @@ int main(int, char**) VkResult err = vkDeviceWaitIdle(g_Device); check_vk_result(err); ImGui_ImplGlfwVulkan_Shutdown(); + ImGui::DestroyContext(); cleanup_vulkan(); glfwTerminate(); From 3ed2ddbfbe5c913fd5b3ff03c0f778e8e66747e0 Mon Sep 17 00:00:00 2001 From: omar Date: Sun, 21 Jan 2018 20:32:05 +0100 Subject: [PATCH 482/823] Metrics: Removed context size display. --- imgui.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/imgui.cpp b/imgui.cpp index 407809862915..62f86342ce3f 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -12810,7 +12810,6 @@ void ImGui::ShowMetricsWindow(bool* p_open) ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate); ImGui::Text("%d vertices, %d indices (%d triangles)", ImGui::GetIO().MetricsRenderVertices, ImGui::GetIO().MetricsRenderIndices, ImGui::GetIO().MetricsRenderIndices / 3); ImGui::Text("%d allocations", ImGui::GetIO().MetricsAllocs); - ImGui::Text("sizeof(ImGuiContext) = %u, sizeof(ImGuiWindow) = %u", (int)sizeof(ImGuiContext), (int)sizeof(ImGuiWindow)); static bool show_clip_rects = true; ImGui::Checkbox("Show clipping rectangles when hovering an ImDrawCmd", &show_clip_rects); ImGui::Separator(); From dd89c9ea59af9f8b832fc3fc024166e000d40225 Mon Sep 17 00:00:00 2001 From: omar Date: Sun, 21 Jan 2018 20:58:50 +0100 Subject: [PATCH 483/823] Examples: Made the Win32 proc handlers not assert if there is no active context yet, to be more flexible with creation order. (#1565) --- examples/directx10_example/imgui_impl_dx10.cpp | 3 +++ examples/directx11_example/imgui_impl_dx11.cpp | 3 +++ examples/directx9_example/imgui_impl_dx9.cpp | 3 +++ 3 files changed, 9 insertions(+) diff --git a/examples/directx10_example/imgui_impl_dx10.cpp b/examples/directx10_example/imgui_impl_dx10.cpp index 66b411e47833..2ba6549413a9 100644 --- a/examples/directx10_example/imgui_impl_dx10.cpp +++ b/examples/directx10_example/imgui_impl_dx10.cpp @@ -243,6 +243,9 @@ static bool IsAnyMouseButtonDown() // PS: We treat DBLCLK messages as regular mouse down messages, so this code will work on windows classes that have the CS_DBLCLKS flag set. Our own example app code doesn't set this flag. IMGUI_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { + if (ImGui::GetCurrentContext() == NULL) + return 0; + ImGuiIO& io = ImGui::GetIO(); switch (msg) { diff --git a/examples/directx11_example/imgui_impl_dx11.cpp b/examples/directx11_example/imgui_impl_dx11.cpp index 61860f5c1f26..1df2e30f9ac9 100644 --- a/examples/directx11_example/imgui_impl_dx11.cpp +++ b/examples/directx11_example/imgui_impl_dx11.cpp @@ -250,6 +250,9 @@ static bool IsAnyMouseButtonDown() // PS: We treat DBLCLK messages as regular mouse down messages, so this code will work on windows classes that have the CS_DBLCLKS flag set. Our own example app code doesn't set this flag. IMGUI_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { + if (ImGui::GetCurrentContext() == NULL) + return 0; + ImGuiIO& io = ImGui::GetIO(); switch (msg) { diff --git a/examples/directx9_example/imgui_impl_dx9.cpp b/examples/directx9_example/imgui_impl_dx9.cpp index af30fbf49ebd..bd42ecad34bc 100644 --- a/examples/directx9_example/imgui_impl_dx9.cpp +++ b/examples/directx9_example/imgui_impl_dx9.cpp @@ -189,6 +189,9 @@ static bool IsAnyMouseButtonDown() // PS: We treat DBLCLK messages as regular mouse down messages, so this code will work on windows classes that have the CS_DBLCLKS flag set. Our own example app code doesn't set this flag. IMGUI_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { + if (ImGui::GetCurrentContext() == NULL) + return 0; + ImGuiIO& io = ImGui::GetIO(); switch (msg) { From 2026e792cddaa8deba54b82bf93819034b937d78 Mon Sep 17 00:00:00 2001 From: omar Date: Sun, 21 Jan 2018 21:12:52 +0100 Subject: [PATCH 484/823] Context: NewFrame() asserts (#1565) --- imgui.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/imgui.cpp b/imgui.cpp index 8eb17280d5b4..3a1aaba3fcd1 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2300,6 +2300,7 @@ ImDrawListSharedData* ImGui::GetDrawListSharedData() void ImGui::NewFrame() { + IM_ASSERT(GImGui != NULL && "No current context. Did you call ImGui::CreateContext() or ImGui::SetCurrentContext()?"); ImGuiContext& g = *GImGui; // Check user data From 5097368bd519774f1d0faeff90ac6010954dfc57 Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 22 Jan 2018 11:59:40 +0100 Subject: [PATCH 485/823] Tweaked FAQ. --- README.md | 9 ++++--- imgui.cpp | 80 ++++++++++++++++++++++++++++++------------------------- 2 files changed, 49 insertions(+), 40 deletions(-) diff --git a/README.md b/README.md index bf30994601fd..c76e6a8f82b8 100644 --- a/README.md +++ b/README.md @@ -153,10 +153,9 @@ I occasionally tag [Releases](https://github.com/ocornut/imgui/releases) but it The library started its life and is best known as "ImGui" only due to the fact that I didn't give it a proper name when I released it. However, the term IMGUI (immediate-mode graphical user interface) was coined before and is being used in variety of other situations. It seemed confusing and unfair to hog the name. To reduce the ambiguity without affecting existing codebases, I have decided on an alternate, longer name "dear imgui" that people can use to refer to this specific library in ambiguous situations. -What is ImTextureID and how do I display an image? -
I integrated Dear ImGui in my engine and the text or lines are blurry.. -
I integrated Dear ImGui in my engine and some elements are disappearing when I move windows around.. -
How can I have multiple widgets with the same label? Can I have widget without a label? (Yes). A primer on labels/IDs. +How can I help +
How can I display an image? What is ImTextureID, how does it works? +
How can I have multiple widgets with the same label? Can I have widget without a label? (Yes). A primer on labels and the ID stack.
How can I tell when Dear ImGui wants my mouse/keyboard inputs VS when I can pass them to my application?
How can I load a different font than the default?
How can I easily use icons in my application? @@ -164,6 +163,8 @@ The library started its life and is best known as "ImGui" only due to the fact t
How can I display and input non-latin characters such as Chinese, Japanese, Korean, Cyrillic?
How can I preserve my Dear ImGui context across reloading a DLL? (loss of the global/static variables)
How can I use the drawing facilities without an Dear ImGui window? (using ImDrawList API) +
I integrated Dear ImGui in my engine and the text or lines are blurry.. +
I integrated Dear ImGui in my engine and some elements are disappearing when I move windows around.. See the FAQ in imgui.cpp for answers. diff --git a/imgui.cpp b/imgui.cpp index 637721af76ed..302a6712fbd5 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -23,10 +23,8 @@ - ISSUES & TODO LIST - FREQUENTLY ASKED QUESTIONS (FAQ), TIPS - How can I help? - - What is ImTextureID and how do I display an image? - - I integrated Dear ImGui in my engine and the text or lines are blurry.. - - I integrated Dear ImGui in my engine and some elements are clipping or disappearing when I move windows around.. - - How can I have multiple widgets with the same label? Can I have widget without a label? (Yes). A primer on labels/IDs. + - How can I dipslay an image? What is ImTextureID, how does it works? + - How can I have multiple widgets with the same label? Can I have widget without a label? (Yes). A primer on labels and the ID stack. - How can I tell when Dear ImGui wants my mouse/keyboard inputs VS when I can pass them to my application? - How can I load a different font than the default? - How can I easily use icons in my application? @@ -34,6 +32,8 @@ - How can I display and input non-latin characters such as Chinese, Japanese, Korean, Cyrillic? - How can I preserve my Dear ImGui context across reloading a DLL? (loss of the global/static variables) - How can I use the drawing facilities without an ImGui window? (using ImDrawList API) + - I integrated Dear ImGui in my engine and the text or lines are blurry.. + - I integrated Dear ImGui in my engine and some elements are clipping or disappearing when I move windows around.. - ISSUES & TODO-LIST - CODE @@ -374,10 +374,14 @@ ====================================== Q: How can I help? - A: - If you are experienced enough with Dear ImGui and with C/C++, look at the todo list and see how you want/can help! - - Become a Patron/donate! Convince your company to become a Patron or provide serious funding for development time! See http://www.patreon.com/imgui - - Q: What is ImTextureID and how do I display an image? + A: - If you are experienced with Dear ImGui and C++, look at the github issues, or TODO.txt and see how you want/can help! + - Convince your company to fund development time! Individual users: you can also become a Patron (patreon.com/imgui) or donate on PayPal! See README. + - Disclose your usage of dear imgui via a dev blog post, a tweet, a screenshot, a mention somewhere etc. + You may post screenshot or links in the gallery threads (github.com/ocornut/imgui/issues/1269). Visuals are ideal as they inspire other programmers. + But even without visuals, disclosing your use of dear imgui help the library grow credibility, and help other teams and programmers with taking decisions. + - If you have issues or if you need to hack into the library, even if you don't expect any support it is useful that you share your issues (on github or privately). + + Q: How can I display an image? What is ImTextureID, how does it works? A: ImTextureID is a void* used to pass renderer-agnostic texture references around until it hits your render function. Dear ImGui knows nothing about what those bits represent, it just passes them around. It is up to you to decide what you want the void* to carry! It could be an identifier to your OpenGL texture (cast GLuint to void*), a pointer to your custom engine material (cast MyMaterial* to void*), etc. @@ -386,26 +390,19 @@ (c++ tip: OpenGL uses integers to identify textures. You can safely store an integer into a void*, just cast it to void*, don't take it's address!) To display a custom image/texture within an ImGui window, you may use ImGui::Image(), ImGui::ImageButton(), ImDrawList::AddImage() functions. Dear ImGui will generate the geometry and draw calls using the ImTextureID that you passed and which your renderer can use. + You may call ImGui::ShowMetricsWindow() to explore active draw lists and visualize/understand how the draw data is generated. It is your responsibility to get textures uploaded to your GPU. - Q: I integrated Dear ImGui in my engine and the text or lines are blurry.. - A: In your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f). - Also make sure your orthographic projection matrix and io.DisplaySize matches your actual framebuffer dimension. - - Q: I integrated Dear ImGui in my engine and some elements are clipping or disappearing when I move windows around.. - A: You are probably mishandling the clipping rectangles in your render function. - Rectangles provided by ImGui are defined as (x1=left,y1=top,x2=right,y2=bottom) and NOT as (x1,y1,width,height). - Q: Can I have multiple widgets with the same label? Can I have widget without a label? - A: Yes. A primer on the use of labels/IDs in Dear ImGui.. + A: Yes. A primer on labels and the ID stack... - - Elements that are not clickable, such as Text() items don't need an ID. + - Elements that are typically not clickable, such as Text() items don't need an ID. - Interactive widgets require state to be carried over multiple frames (most typically Dear ImGui often needs to remember what is the "active" widget). to do so they need a unique ID. unique ID are typically derived from a string label, an integer index or a pointer. - Button("OK"); // Label = "OK", ID = hash of "OK" - Button("Cancel"); // Label = "Cancel", ID = hash of "Cancel" + Button("OK"); // Label = "OK", ID = hash of "OK" + Button("Cancel"); // Label = "Cancel", ID = hash of "Cancel" - ID are uniquely scoped within windows, tree nodes, etc. so no conflict can happen if you have two buttons called "OK" in two different windows or in two different locations of a tree. @@ -413,34 +410,35 @@ - If you have a same ID twice in the same location, you'll have a conflict: Button("OK"); - Button("OK"); // ID collision! Both buttons will be treated as the same. + Button("OK"); // ID collision! Both buttons will be treated as the same. Fear not! this is easy to solve and there are many ways to solve it! - - When passing a label you can optionally specify extra unique ID information within string itself. - This helps solving the simpler collision cases. Use "##" to pass a complement to the ID that won't be visible to the end-user: + - When passing a label you can optionally specify extra unique ID information within string itself. + Use "##" to pass a complement to the ID that won't be visible to the end-user. + This helps solving the simple collision cases when you know which items are going to be created. - Button("Play"); // Label = "Play", ID = hash of "Play" - Button("Play##foo1"); // Label = "Play", ID = hash of "Play##foo1" (different from above) - Button("Play##foo2"); // Label = "Play", ID = hash of "Play##foo2" (different from above) + Button("Play"); // Label = "Play", ID = hash of "Play" + Button("Play##foo1"); // Label = "Play", ID = hash of "Play##foo1" (different from above) + Button("Play##foo2"); // Label = "Play", ID = hash of "Play##foo2" (different from above) - If you want to completely hide the label, but still need an ID: - Checkbox("##On", &b); // Label = "", ID = hash of "##On" (no label!) + Checkbox("##On", &b); // Label = "", ID = hash of "##On" (no label!) - Occasionally/rarely you might want change a label while preserving a constant ID. This allows you to animate labels. - For example you may want to include varying information in a window title bar (and windows are uniquely identified by their ID.. obviously) + For example you may want to include varying information in a window title bar, but windows are uniquely identified by their ID.. Use "###" to pass a label that isn't part of ID: Button("Hello###ID"; // Label = "Hello", ID = hash of "ID" Button("World###ID"; // Label = "World", ID = hash of "ID" (same as above) - sprintf(buf, "My game (%f FPS)###MyGame"); + sprintf(buf, "My game (%f FPS)###MyGame", fps); Begin(buf); // Variable label, ID = hash of "MyGame" - Use PushID() / PopID() to create scopes and avoid ID conflicts within the same Window. This is the most convenient way of distinguishing ID if you are iterating and creating many UI elements. - You can push a pointer, a string or an integer value. Remember that ID are formed from the concatenation of everything in the ID stack! + You can push a pointer, a string or an integer value. Remember that ID are formed from the concatenation of _everything_ in the ID stack! for (int i = 0; i < 100; i++) { @@ -570,16 +568,25 @@ so you don't rely on the default globals. Q: How can I use the drawing facilities without an ImGui window? (using ImDrawList API) - A: The easiest way is to create a dummy window. Call Begin() with NoTitleBar|NoResize|NoMove|NoScrollbar|NoSavedSettings|NoInputs flag, - zero background alpha, then retrieve the ImDrawList* via GetWindowDrawList() and draw to it in any way you like. - You can also perfectly create a standalone ImDrawList instance _but_ you need ImGui to be initialized because ImDrawList pulls from ImGui - data to retrieve the coordinates of the white pixel. + A: - You can create a dummy window. Call Begin() with NoTitleBar|NoResize|NoMove|NoScrollbar|NoSavedSettings|NoInputs flag, + push a ImGuiCol_WindowBg with zero alpha, then retrieve the ImDrawList* via GetWindowDrawList() and draw to it in any way you like. + - You can call ImGui::GetOverlayDrawList() and use this draw list to display contents over every other imgui windows. + - You can create your own ImDrawList instance. You'll need to initialize them ImGui::GetDrawListSharedData(), or create your own ImDrawListSharedData. + + Q: I integrated Dear ImGui in my engine and the text or lines are blurry.. + A: In your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f). + Also make sure your orthographic projection matrix and io.DisplaySize matches your actual framebuffer dimension. + + Q: I integrated Dear ImGui in my engine and some elements are clipping or disappearing when I move windows around.. + A: You are probably mishandling the clipping rectangles in your render function. + Rectangles provided by ImGui are defined as (x1=left,y1=top,x2=right,y2=bottom) and NOT as (x1,y1,width,height). + - tip: you can call Begin() multiple times with the same name during the same frame, it will keep appending to the same window. - this is also useful to set yourself in the context of another window (to get/set other settings) + this is also useful to set yourself in the context of another window (to get/set other settings) - tip: you can create widgets without a Begin()/End() block, they will go in an implicit window called "Debug". - tip: the ImGuiOnceUponAFrame helper will allow run the block of code only once a frame. You can use it to quickly add custom UI in the middle - of a deep nested inner loop in your code. + of a deep nested inner loop in your code. - tip: you can call Render() multiple times (e.g for VR renders). - tip: call and read the ShowDemoWindow() code in imgui_demo.cpp for more example of how to use ImGui! @@ -3914,6 +3921,7 @@ bool ImGui::BeginPopupModal(const char* name, bool* p_open, ImGuiWindowFlags fla } // Center modal windows by default + // FIXME: Should test for (PosCond & window->SetWindowPosAllowFlags) with the upcoming window. if (g.NextWindowData.PosCond == 0) SetNextWindowPos(g.IO.DisplaySize * 0.5f, ImGuiCond_Appearing, ImVec2(0.5f, 0.5f)); From 1acb1554191dfa2f2d28198f8124906eb9d77e4a Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 22 Jan 2018 14:30:49 +0100 Subject: [PATCH 486/823] Internals: Moved unnecessary MovingWindowMoveId field. --- imgui.cpp | 8 +------- imgui_internal.h | 2 -- 2 files changed, 1 insertion(+), 9 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 302a6712fbd5..5dff60a01a5b 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2393,11 +2393,10 @@ void ImGui::NewFrame() g.IO.Framerate = 1.0f / (g.FramerateSecPerFrameAccum / (float)IM_ARRAYSIZE(g.FramerateSecPerFrame)); // Handle user moving window with mouse (at the beginning of the frame to avoid input lag or sheering). - if (g.MovingWindowMoveId && g.MovingWindowMoveId == g.ActiveId) + if (g.MovingWindow && g.MovingWindow->MoveId == g.ActiveId) { KeepAliveID(g.ActiveId); IM_ASSERT(g.MovingWindow && g.MovingWindow->RootWindow); - IM_ASSERT(g.MovingWindow->MoveId == g.MovingWindowMoveId); if (g.IO.MouseDown[0]) { // MovingWindow = window we clicked on, could be a child window. We track it to preserve Focus and so that ActiveIdWindow == MovingWindow and ActiveId == MovingWindow->MoveId for consistency. @@ -2414,7 +2413,6 @@ void ImGui::NewFrame() { ClearActiveID(); g.MovingWindow = NULL; - g.MovingWindowMoveId = 0; } } else @@ -2427,7 +2425,6 @@ void ImGui::NewFrame() ClearActiveID(); } g.MovingWindow = NULL; - g.MovingWindowMoveId = 0; } // Delay saving settings so we don't spam disk too much @@ -2994,10 +2991,7 @@ void ImGui::EndFrame() SetActiveID(g.HoveredWindow->MoveId, g.HoveredWindow); g.ActiveIdClickOffset = g.IO.MousePos - g.HoveredRootWindow->Pos; if (!(g.HoveredWindow->Flags & ImGuiWindowFlags_NoMove) && !(g.HoveredRootWindow->Flags & ImGuiWindowFlags_NoMove)) - { g.MovingWindow = g.HoveredWindow; - g.MovingWindowMoveId = g.MovingWindow->MoveId; - } } else if (g.NavWindow != NULL && GetFrontMostModalRootWindow() == NULL) { diff --git a/imgui_internal.h b/imgui_internal.h index d6d19a426075..7fe6dffa9777 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -530,7 +530,6 @@ struct ImGuiContext ImVec2 ActiveIdClickOffset; // Clicked offset from upper-left corner, if applicable (currently only set by ButtonBehavior) ImGuiWindow* ActiveIdWindow; ImGuiWindow* MovingWindow; // Track the window we clicked on (in order to preserve focus). The actually window that is moved is generally MovingWindow->RootWindow. - ImGuiID MovingWindowMoveId; // == MovingWindow->MoveId ImVector ColorModifiers; // Stack for PushStyleColor()/PopStyleColor() ImVector StyleModifiers; // Stack for PushStyleVar()/PopStyleVar() ImVector FontStack; // Stack for PushFont()/PopFont() @@ -625,7 +624,6 @@ struct ImGuiContext ActiveIdClickOffset = ImVec2(-1,-1); ActiveIdWindow = NULL; MovingWindow = NULL; - MovingWindowMoveId = 0; NextTreeNodeOpenVal = false; NextTreeNodeOpenCond = 0; From 9076366c172f7375f4f869dc7e4b1d5a8667df25 Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 23 Jan 2018 09:57:49 +0100 Subject: [PATCH 487/823] Style: Exposed ImGuiStyleVar_WindowTitleAlign, ImGuiStyleVar_ScrollbarSize, ImGuiStyleVar_ScrollbarRounding, ImGuiStyleVar_GrabRounding + added an assert to reduce accidental breakage. (#1181) --- imgui.cpp | 7 ++++++- imgui.h | 4 ++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/imgui.cpp b/imgui.cpp index 5dff60a01a5b..3f0ad4e5d6fa 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -5400,13 +5400,14 @@ struct ImGuiStyleVarInfo void* GetVarPtr(ImGuiStyle* style) const { return (void*)((unsigned char*)style + Offset); } }; -static const ImGuiStyleVarInfo GStyleVarInfo[ImGuiStyleVar_Count_] = +static const ImGuiStyleVarInfo GStyleVarInfo[] = { { ImGuiDataType_Float, (ImU32)IM_OFFSETOF(ImGuiStyle, Alpha) }, // ImGuiStyleVar_Alpha { ImGuiDataType_Float2, (ImU32)IM_OFFSETOF(ImGuiStyle, WindowPadding) }, // ImGuiStyleVar_WindowPadding { ImGuiDataType_Float, (ImU32)IM_OFFSETOF(ImGuiStyle, WindowRounding) }, // ImGuiStyleVar_WindowRounding { ImGuiDataType_Float, (ImU32)IM_OFFSETOF(ImGuiStyle, WindowBorderSize) }, // ImGuiStyleVar_WindowBorderSize { ImGuiDataType_Float2, (ImU32)IM_OFFSETOF(ImGuiStyle, WindowMinSize) }, // ImGuiStyleVar_WindowMinSize + { ImGuiDataType_Float2, (ImU32)IM_OFFSETOF(ImGuiStyle, WindowTitleAlign) }, // ImGuiStyleVar_WindowTitleAlign { ImGuiDataType_Float, (ImU32)IM_OFFSETOF(ImGuiStyle, ChildRounding) }, // ImGuiStyleVar_ChildRounding { ImGuiDataType_Float, (ImU32)IM_OFFSETOF(ImGuiStyle, ChildBorderSize) }, // ImGuiStyleVar_ChildBorderSize { ImGuiDataType_Float, (ImU32)IM_OFFSETOF(ImGuiStyle, PopupRounding) }, // ImGuiStyleVar_PopupRounding @@ -5417,13 +5418,17 @@ static const ImGuiStyleVarInfo GStyleVarInfo[ImGuiStyleVar_Count_] = { ImGuiDataType_Float2, (ImU32)IM_OFFSETOF(ImGuiStyle, ItemSpacing) }, // ImGuiStyleVar_ItemSpacing { ImGuiDataType_Float2, (ImU32)IM_OFFSETOF(ImGuiStyle, ItemInnerSpacing) }, // ImGuiStyleVar_ItemInnerSpacing { ImGuiDataType_Float, (ImU32)IM_OFFSETOF(ImGuiStyle, IndentSpacing) }, // ImGuiStyleVar_IndentSpacing + { ImGuiDataType_Float, (ImU32)IM_OFFSETOF(ImGuiStyle, ScrollbarSize) }, // ImGuiStyleVar_ScrollbarSize + { ImGuiDataType_Float, (ImU32)IM_OFFSETOF(ImGuiStyle, ScrollbarRounding) }, // ImGuiStyleVar_ScrollbarRounding { ImGuiDataType_Float, (ImU32)IM_OFFSETOF(ImGuiStyle, GrabMinSize) }, // ImGuiStyleVar_GrabMinSize + { ImGuiDataType_Float, (ImU32)IM_OFFSETOF(ImGuiStyle, GrabRounding) }, // ImGuiStyleVar_GrabRounding { ImGuiDataType_Float2, (ImU32)IM_OFFSETOF(ImGuiStyle, ButtonTextAlign) }, // ImGuiStyleVar_ButtonTextAlign }; static const ImGuiStyleVarInfo* GetStyleVarInfo(ImGuiStyleVar idx) { IM_ASSERT(idx >= 0 && idx < ImGuiStyleVar_Count_); + IM_ASSERT(IM_ARRAYSIZE(GStyleVarInfo) == ImGuiStyleVar_Count_); return &GStyleVarInfo[idx]; } diff --git a/imgui.h b/imgui.h index 6d411738ae4d..6b2d5c6fb4b9 100644 --- a/imgui.h +++ b/imgui.h @@ -751,6 +751,7 @@ enum ImGuiStyleVar_ ImGuiStyleVar_WindowRounding, // float WindowRounding ImGuiStyleVar_WindowBorderSize, // float WindowBorderSize ImGuiStyleVar_WindowMinSize, // ImVec2 WindowMinSize + ImGuiStyleVar_WindowTitleAlign, // ImVec2 WindowTitleAlign ImGuiStyleVar_ChildRounding, // float ChildRounding ImGuiStyleVar_ChildBorderSize, // float ChildBorderSize ImGuiStyleVar_PopupRounding, // float PopupRounding @@ -761,7 +762,10 @@ enum ImGuiStyleVar_ ImGuiStyleVar_ItemSpacing, // ImVec2 ItemSpacing ImGuiStyleVar_ItemInnerSpacing, // ImVec2 ItemInnerSpacing ImGuiStyleVar_IndentSpacing, // float IndentSpacing + ImGuiStyleVar_ScrollbarSize, // float ScrollbarSize + ImGuiStyleVar_ScrollbarRounding, // float ScrollbarRounding ImGuiStyleVar_GrabMinSize, // float GrabMinSize + ImGuiStyleVar_GrabRounding, // float GrabRounding ImGuiStyleVar_ButtonTextAlign, // ImVec2 ButtonTextAlign ImGuiStyleVar_Count_ From db2ba13154e9c87b189f90e66bf2afd099d59045 Mon Sep 17 00:00:00 2001 From: omar Date: Fri, 12 Jan 2018 20:07:01 +0100 Subject: [PATCH 488/823] Internals: Exposed SetCurrentFont() in imgui_internal.h --- imgui.cpp | 3 +-- imgui_internal.h | 2 ++ 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 3f0ad4e5d6fa..965ea69992d6 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -644,7 +644,6 @@ static bool IsKeyPressedMap(ImGuiKey key, bool repeat = true); static ImFont* GetDefaultFont(); -static void SetCurrentFont(ImFont* font); static void SetCurrentWindow(ImGuiWindow* window); static void SetWindowScrollX(ImGuiWindow* window, float new_scroll_x); static void SetWindowScrollY(ImGuiWindow* window, float new_scroll_y); @@ -5276,7 +5275,7 @@ static ImFont* GetDefaultFont() return g.IO.FontDefault ? g.IO.FontDefault : g.IO.Fonts->Fonts[0]; } -static void SetCurrentFont(ImFont* font) +void ImGui::SetCurrentFont(ImFont* font) { ImGuiContext& g = *GImGui; IM_ASSERT(font && font->IsLoaded()); // Font Atlas not created. Did you call io.Fonts->GetTexDataAsRGBA32 / GetTexDataAsAlpha8 ? diff --git a/imgui_internal.h b/imgui_internal.h index 7fe6dffa9777..1acb45ec1425 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -887,6 +887,8 @@ namespace ImGui IMGUI_API void PushItemFlag(ImGuiItemFlags option, bool enabled); IMGUI_API void PopItemFlag(); + IMGUI_API void SetCurrentFont(ImFont* font); + IMGUI_API void OpenPopupEx(ImGuiID id); IMGUI_API void ClosePopup(ImGuiID id); IMGUI_API bool IsPopupOpen(ImGuiID id); From 13c407591ef340610a64b185c6b8aed80060ae20 Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 23 Jan 2018 16:45:46 +0100 Subject: [PATCH 489/823] Nav: Comments, tweaks --- imgui.cpp | 6 +++--- imgui.h | 6 +++++- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index d2d81ef86194..dd005063df04 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2020,10 +2020,10 @@ ImGuiID ImGui::GetActiveID() void ImGui::SetFocusID(ImGuiID id, ImGuiWindow* window) { - IM_ASSERT(id != 0); ImGuiContext& g = *GImGui; - - // Assume that SetActiveID() is called in the context where its NavLayer is the current layer, which is the case everywhere we call it. + IM_ASSERT(id != 0); + + // Assume that SetFocusID() is called in the context where its NavLayer is the current layer, which is the case everywhere we call it. const int nav_layer = window->DC.NavLayerCurrent; g.NavId = id; g.NavWindow = window; diff --git a/imgui.h b/imgui.h index 156cb5375ec2..f174d83a7609 100644 --- a/imgui.h +++ b/imgui.h @@ -698,6 +698,7 @@ enum ImGuiKey_ // Your code passing analog gamepad values is likely to want to transform your raw inputs, using a dead-zone and maybe a power curve. enum ImGuiNavInput_ { + // Gamepad Mapping ImGuiNavInput_PadActivate, // press button, tweak value // e.g. Circle button ImGuiNavInput_PadCancel, // close menu/popup/child, lose selection // e.g. Cross button ImGuiNavInput_PadInput, // text input // e.g. Triangle button @@ -714,6 +715,8 @@ enum ImGuiNavInput_ ImGuiNavInput_PadFocusNext, // prev window (with PadMenu held) // e.g. R-trigger ImGuiNavInput_PadTweakSlow, // slower tweaks // e.g. L-trigger, analog ImGuiNavInput_PadTweakFast, // faster tweaks // e.g. R-trigger, analog + // Keyboard Mapping + // [BETA] You can use gamepad mapping for most inputs ImGuiNavInput_KeyMenu, // access menu // e.g. ALT ImGuiNavInput_COUNT, }; @@ -920,7 +923,6 @@ struct ImGuiIO int KeyMap[ImGuiKey_COUNT]; // // Map of indices into the KeysDown[512] entries array which represent your "native" keyboard state. float KeyRepeatDelay; // = 0.250f // When holding a key/button, time before it starts repeating, in seconds (for buttons in Repeat mode, etc.). float KeyRepeatRate; // = 0.050f // When holding a key/button, rate at which it repeats, in seconds. - bool NavMovesMouse; // = false // Directional navigation can move the mouse cursor. Updates MousePos and set WantMoveMouse=true. If enabled you MUST honor those requests in your binding, otherwise ImGui will react as if mouse is jumping around. void* UserData; // = NULL // Store your own data for retrieval by callbacks. ImFontAtlas* Fonts; // // Load and assemble one or more fonts into a single tightly packed texture. Output to Fonts array. @@ -931,6 +933,8 @@ struct ImGuiIO ImVec2 DisplayVisibleMin; // (0.0f,0.0f) // If you use DisplaySize as a virtual space larger than your screen, set DisplayVisibleMin/Max to the visible area. ImVec2 DisplayVisibleMax; // (0.0f,0.0f) // If the values are the same, we defaults to Min=(0.0f) and Max=DisplaySize + // Gamepad/Keyboard Navigation + bool NavMovesMouse; // = false // Directional navigation can move the mouse cursor. Updates MousePos and set WantMoveMouse=true. If enabled you MUST honor those requests in your binding, otherwise ImGui will react as if mouse is jumping around. // Advanced/subtle behaviors bool OptMacOSXBehaviors; // = defined(__APPLE__) // OS X style: Text editing cursor movement using Alt instead of Ctrl, Shortcuts using Cmd/Super instead of Ctrl, Line/Text Start and End using Cmd+Arrows instead of Home/End, Double click selects by word instead of selecting whole text, Multi-selection in lists uses Cmd/Super instead of Ctrl bool OptCursorBlink; // = true // Enable blinking cursor, for users who consider it annoying. From 2645ab5f7f0be479abe45490e186db44e7083018 Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 23 Jan 2018 17:05:15 +0100 Subject: [PATCH 490/823] Comments + added legacy renamed GetItemsLineHeightWithSpacing() as stated in the doc, fixes 6190ab008420087c6d0dbbb64e55d668e66a91c0 --- imgui.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/imgui.h b/imgui.h index 6b2d5c6fb4b9..2ec07ec0d8b5 100644 --- a/imgui.h +++ b/imgui.h @@ -1001,6 +1001,7 @@ namespace ImGui static inline bool IsRootWindowFocused() { return IsWindowFocused(ImGuiFocusedFlags_RootWindow); } static inline bool IsRootWindowOrAnyChildFocused() { return IsWindowFocused(ImGuiFocusedFlags_RootAndChildWindows); } static inline void SetNextWindowContentWidth(float w) { SetNextWindowContentSize(ImVec2(w, 0.0f)); } + static inline float GetItemsLineHeightWithSpacing() { return GetFrameHeightWithSpacing(); } // OBSOLETED in 1.52 (between Aug 2017 and Oct 2017) bool Begin(const char* name, bool* p_open, const ImVec2& size_on_first_use, float bg_alpha_override = -1.0f, ImGuiWindowFlags flags = 0); // Use SetNextWindowSize() instead if you want to set a window size. static inline bool IsRootWindowOrAnyChildHovered() { return IsItemHovered(ImGuiHoveredFlags_RootAndChildWindows); } @@ -1423,6 +1424,7 @@ struct ImDrawList int _ChannelsCount; // [Internal] number of active channels (1+) ImVector _Channels; // [Internal] draw channels for columns API (not resized down so _ChannelsCount may be smaller than _Channels.Size) + // If you want to create ImDrawList instances, pass them ImGui::GetDrawListSharedData() or create and use your own ImDrawListSharedData (so you can use ImDrawList without ImGui) ImDrawList(const ImDrawListSharedData* shared_data) { _Data = shared_data; _OwnerName = NULL; Clear(); } ~ImDrawList() { ClearFreeMemory(); } IMGUI_API void PushClipRect(ImVec2 clip_rect_min, ImVec2 clip_rect_max, bool intersect_with_current_clip_rect = false); // Render-level scissoring. This is passed down to your render function but not used for CPU-side coarse clipping. Prefer using higher-level ImGui::PushClipRect() to affect logic (hit-testing and widget culling) From 9a76fd30fd21d0c4f6403b27a235b883ece71f28 Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 23 Jan 2018 19:13:49 +0100 Subject: [PATCH 491/823] Added SetNextWindowBgAlpha() helper. (#1567) particularly helpul with the marking of the old 5-parameters version of Begin() as obsolete. --- imgui.cpp | 31 +++++++++++++++---------------- imgui.h | 1 + imgui_demo.cpp | 3 +-- imgui_internal.h | 7 +++++-- 4 files changed, 22 insertions(+), 20 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 965ea69992d6..1c32c32209a8 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -4803,8 +4803,10 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) } else { - // Window background, Default Alpha + // Window background ImU32 bg_col = GetColorU32(GetWindowBgColorIdxFromFlags(flags)); + if (g.NextWindowData.BgAlphaCond != 0) + bg_col = (bg_col & ~IM_COL32_A_MASK) | (IM_F32_TO_INT8_SAT(g.NextWindowData.BgAlphaVal) << IM_COL32_A_SHIFT); window->DrawList->AddRectFilled(window->Pos+ImVec2(0,window->TitleBarHeight()), window->Pos+window->Size, bg_col, window_rounding, (flags & ImGuiWindowFlags_NoTitleBar) ? ImDrawCornerFlags_All : ImDrawCornerFlags_Bot); // Title bar @@ -5010,22 +5012,12 @@ bool ImGui::Begin(const char* name, bool* p_open, const ImVec2& size_on_first_us { // Old API feature: we could pass the initial window size as a parameter, however this was very misleading because in most cases it would only affect the window when it didn't have storage in the .ini file. if (size_on_first_use.x != 0.0f || size_on_first_use.y != 0.0f) - SetNextWindowSize(size_on_first_use, ImGuiCond_FirstUseEver); + ImGui::SetNextWindowSize(size_on_first_use, ImGuiCond_FirstUseEver); - // Old API feature: we could override the window background alpha with a parameter. This is actually tricky to reproduce manually because: - // (1) there are multiple variants of WindowBg (popup, tooltip, etc.) and (2) you can't call PushStyleColor before Begin and PopStyleColor just after Begin() because of how CheckStackSizes() behave. - // The user-side solution is to do backup = GetStyleColorVec4(ImGuiCol_xxxBG), PushStyleColor(ImGuiCol_xxxBg), Begin, PushStyleColor(ImGuiCol_xxxBg, backup), [...], PopStyleColor(), End(); PopStyleColor() - which is super awkward. - // The alpha override was rarely used but for now we'll leave the Begin() variant around for a bit. We may either lift the constraint on CheckStackSizes() either add a SetNextWindowBgAlpha() helper that does it magically. - ImGuiContext& g = *GImGui; - const ImGuiCol bg_color_idx = GetWindowBgColorIdxFromFlags(flags); - const ImVec4 bg_color_backup = g.Style.Colors[bg_color_idx]; - if (bg_alpha_override >= 0.0f) - g.Style.Colors[bg_color_idx].w = bg_alpha_override; - - bool ret = Begin(name, p_open, flags); + // Old API feature: override the window background alpha with a parameter. + ImGui::SetNextWindowBgAlpha(bg_alpha_override); - if (bg_alpha_override >= 0.0f) - g.Style.Colors[bg_color_idx] = bg_color_backup; + bool ret = ImGui::Begin(name, p_open, flags); return ret; } #endif // IMGUI_DISABLE_OBSOLETE_FUNCTIONS @@ -5803,7 +5795,14 @@ void ImGui::SetNextWindowCollapsed(bool collapsed, ImGuiCond cond) void ImGui::SetNextWindowFocus() { ImGuiContext& g = *GImGui; - g.NextWindowData.FocusCond = ImGuiCond_Always; + g.NextWindowData.FocusCond = ImGuiCond_Always; // Using a Cond member for consistency (may transition all of them to single flag set for fast Clear() op) +} + +void ImGui::SetNextWindowBgAlpha(float alpha) +{ + ImGuiContext& g = *GImGui; + g.NextWindowData.BgAlphaVal = alpha; + g.NextWindowData.BgAlphaCond = ImGuiCond_Always; // Using a Cond member for consistency (may transition all of them to single flag set for fast Clear() op) } // In window space (not screen space!) diff --git a/imgui.h b/imgui.h index 2ec07ec0d8b5..2486ffd0382d 100644 --- a/imgui.h +++ b/imgui.h @@ -171,6 +171,7 @@ namespace ImGui IMGUI_API void SetNextWindowContentSize(const ImVec2& size); // set next window content size (~ enforce the range of scrollbars). not including window decorations (title bar, menu bar, etc.). set an axis to 0.0f to leave it automatic. call before Begin() IMGUI_API void SetNextWindowCollapsed(bool collapsed, ImGuiCond cond = 0); // set next window collapsed state. call before Begin() IMGUI_API void SetNextWindowFocus(); // set next window to be focused / front-most. call before Begin() + IMGUI_API void SetNextWindowBgAlpha(float alpha); // set next window background color alpha. helper to easily modify ImGuiCol_WindowBg/ChildBg/PopupBg. IMGUI_API void SetWindowPos(const ImVec2& pos, ImGuiCond cond = 0); // (not recommended) set current window position - call within Begin()/End(). prefer using SetNextWindowPos(), as this may incur tearing and side-effects. IMGUI_API void SetWindowSize(const ImVec2& size, ImGuiCond cond = 0); // (not recommended) set current window size - call within Begin()/End(). set to ImVec2(0,0) to force an auto-fit. prefer using SetNextWindowSize(), as this may incur tearing and minor side-effects. IMGUI_API void SetWindowCollapsed(bool collapsed, ImGuiCond cond = 0); // (not recommended) set current window collapsed state. prefer using SetNextWindowCollapsed(). diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 87e4f57cfc39..9c49281fb848 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -2398,7 +2398,7 @@ static void ShowExampleAppFixedOverlay(bool* p_open) ImVec2 window_pos = ImVec2((corner & 1) ? ImGui::GetIO().DisplaySize.x - DISTANCE : DISTANCE, (corner & 2) ? ImGui::GetIO().DisplaySize.y - DISTANCE : DISTANCE); ImVec2 window_pos_pivot = ImVec2((corner & 1) ? 1.0f : 0.0f, (corner & 2) ? 1.0f : 0.0f); ImGui::SetNextWindowPos(window_pos, ImGuiCond_Always, window_pos_pivot); - ImGui::PushStyleColor(ImGuiCol_WindowBg, ImVec4(0.0f, 0.0f, 0.0f, 0.3f)); // Transparent background + ImGui::SetNextWindowBgAlpha(0.3f); // Transparent background if (ImGui::Begin("Example: Fixed Overlay", p_open, ImGuiWindowFlags_NoTitleBar|ImGuiWindowFlags_NoResize|ImGuiWindowFlags_AlwaysAutoResize|ImGuiWindowFlags_NoMove|ImGuiWindowFlags_NoSavedSettings)) { ImGui::Text("Simple overlay\nin the corner of the screen.\n(right-click to change position)"); @@ -2415,7 +2415,6 @@ static void ShowExampleAppFixedOverlay(bool* p_open) } ImGui::End(); } - ImGui::PopStyleColor(); } // Demonstrate using "##" and "###" in identifiers to manipulate ID generation. diff --git a/imgui_internal.h b/imgui_internal.h index 1acb45ec1425..b30dde60dbca 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -467,6 +467,7 @@ struct ImGuiNextWindowData ImGuiCond CollapsedCond; ImGuiCond SizeConstraintCond; ImGuiCond FocusCond; + ImGuiCond BgAlphaCond; ImVec2 PosVal; ImVec2 PosPivotVal; ImVec2 SizeVal; @@ -475,21 +476,23 @@ struct ImGuiNextWindowData ImRect SizeConstraintRect; // Valid if 'SetNextWindowSizeConstraint' is true ImGuiSizeCallback SizeCallback; void* SizeCallbackUserData; + float BgAlphaVal; ImGuiNextWindowData() { - PosCond = SizeCond = ContentSizeCond = CollapsedCond = SizeConstraintCond = FocusCond = 0; + PosCond = SizeCond = ContentSizeCond = CollapsedCond = SizeConstraintCond = FocusCond = BgAlphaCond = 0; PosVal = PosPivotVal = SizeVal = ImVec2(0.0f, 0.0f); ContentSizeVal = ImVec2(0.0f, 0.0f); CollapsedVal = false; SizeConstraintRect = ImRect(); SizeCallback = NULL; SizeCallbackUserData = NULL; + BgAlphaVal = FLT_MAX; } void Clear() { - PosCond = SizeCond = ContentSizeCond = CollapsedCond = SizeConstraintCond = FocusCond = 0; + PosCond = SizeCond = ContentSizeCond = CollapsedCond = SizeConstraintCond = FocusCond = BgAlphaCond = 0; } }; From f6ee8d30fb29a40888118e1e1e1dcc7bf14dc3c5 Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 23 Jan 2018 19:21:17 +0100 Subject: [PATCH 492/823] Comments (#1567) --- imgui.cpp | 13 ++++++------- imgui.h | 2 +- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 1c32c32209a8..a852867b1a68 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -5006,19 +5006,18 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) return !window->SkipItems; } -// Old Begin() API with 5 parameters, avoid calling this version directly! Use SetNextWindowSize()+Begin() instead. +// Old Begin() API with 5 parameters, avoid calling this version directly! Use SetNextWindowSize()/SetNextWindowBgAlpha() + Begin() instead. #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS -bool ImGui::Begin(const char* name, bool* p_open, const ImVec2& size_on_first_use, float bg_alpha_override, ImGuiWindowFlags flags) +bool ImGui::Begin(const char* name, bool* p_open, const ImVec2& size_first_use, float bg_alpha_override, ImGuiWindowFlags flags) { - // Old API feature: we could pass the initial window size as a parameter, however this was very misleading because in most cases it would only affect the window when it didn't have storage in the .ini file. - if (size_on_first_use.x != 0.0f || size_on_first_use.y != 0.0f) - ImGui::SetNextWindowSize(size_on_first_use, ImGuiCond_FirstUseEver); + // Old API feature: we could pass the initial window size as a parameter. This was misleading because it only had an effect if the window didn't have data in the .ini file. + if (size_first_use.x != 0.0f || size_first_use.y != 0.0f) + ImGui::SetNextWindowSize(size_first_use, ImGuiCond_FirstUseEver); // Old API feature: override the window background alpha with a parameter. ImGui::SetNextWindowBgAlpha(bg_alpha_override); - bool ret = ImGui::Begin(name, p_open, flags); - return ret; + return ImGui::Begin(name, p_open, flags); } #endif // IMGUI_DISABLE_OBSOLETE_FUNCTIONS diff --git a/imgui.h b/imgui.h index 2486ffd0382d..a0453eeac7e5 100644 --- a/imgui.h +++ b/imgui.h @@ -1004,7 +1004,7 @@ namespace ImGui static inline void SetNextWindowContentWidth(float w) { SetNextWindowContentSize(ImVec2(w, 0.0f)); } static inline float GetItemsLineHeightWithSpacing() { return GetFrameHeightWithSpacing(); } // OBSOLETED in 1.52 (between Aug 2017 and Oct 2017) - bool Begin(const char* name, bool* p_open, const ImVec2& size_on_first_use, float bg_alpha_override = -1.0f, ImGuiWindowFlags flags = 0); // Use SetNextWindowSize() instead if you want to set a window size. + bool Begin(const char* name, bool* p_open, const ImVec2& size_on_first_use, float bg_alpha_override = -1.0f, ImGuiWindowFlags flags = 0); // Use SetNextWindowSize(size, ImGuiCond_FirstUseEver) + SetNextWindowBgAlpha() instead. static inline bool IsRootWindowOrAnyChildHovered() { return IsItemHovered(ImGuiHoveredFlags_RootAndChildWindows); } static inline void AlignFirstTextHeightToWidgets() { AlignTextToFramePadding(); } static inline void SetNextWindowPosCenter(ImGuiCond c=0) { ImGuiIO& io = GetIO(); SetNextWindowPos(ImVec2(io.DisplaySize.x * 0.5f, io.DisplaySize.y * 0.5f), c, ImVec2(0.5f, 0.5f)); } From eb7ec781dc88e4517f9abd4a65fa09a52cd8e17e Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 23 Jan 2018 19:41:03 +0100 Subject: [PATCH 493/823] Nav: Tweak GetNavInputAmount(). Split debug defines. --- imgui.cpp | 30 ++++++++++++++++++------------ imgui.h | 2 +- 2 files changed, 19 insertions(+), 13 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 01f279af9d92..03c411d5c1a5 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -645,7 +645,8 @@ #include // intptr_t #endif -#define IMGUI_DEBUG_NAV 0 +#define IMGUI_DEBUG_NAV_SCORING 0 +#define IMGUI_DEBUG_NAV_RECTS 0 #ifdef _MSC_VER #pragma warning (disable: 4127) // condition expression is constant @@ -2197,7 +2198,7 @@ static bool NavScoreItem(ImRect cand) quadrant = (window->DC.LastItemId < g.NavId) ? ImGuiDir_Left : ImGuiDir_Right; } -#if IMGUI_DEBUG_NAV +#if IMGUI_DEBUG_NAV_SCORING if (ImGui::IsMouseHoveringRect(cand.Min, cand.Max)) { char buf[128]; @@ -2257,7 +2258,7 @@ static bool NavScoreItem(ImRect cand) static inline void NavUpdateAnyRequestFlag() { ImGuiContext& g = *GImGui; - g.NavAnyRequest = g.NavMoveRequest || g.NavInitRequest || IMGUI_DEBUG_NAV; + g.NavAnyRequest = g.NavMoveRequest || g.NavInitRequest || IMGUI_DEBUG_NAV_SCORING; } static void NavMoveRequestCancel() @@ -2294,7 +2295,7 @@ static void ImGui::NavProcessItem(ImGuiWindow* window, const ImRect& nav_bb, con // Scoring for navigation if (g.NavId != id && !(item_flags & ImGuiItemFlags_NoNav)) { -#if IMGUI_DEBUG_NAV +#if IMGUI_DEBUG_NAV_SCORING // [DEBUG] Score all items in NavWindow at all times if (!g.NavMoveRequest) g.NavMoveDir = g.NavMoveDirLast; @@ -2666,12 +2667,15 @@ static float GetNavInputAmount(ImGuiNavInput n, ImGuiNavReadMode mode) { ImGuiContext& g = *GImGui; if (mode == ImGuiNavReadMode_Down) - return g.IO.NavInputs[n]; // Instant, read analog input (0.0f..1.0f, as provided by user) - const float t = g.IO.NavInputsDownDuration[n]; // Duration pressed - if (mode == ImGuiNavReadMode_Pressed) // Return 1.0f when just pressed, no repeat, ignore analog input (we don't need it for Pressed logic) + return g.IO.NavInputs[n]; // Instant, read analog input (0.0f..1.0f, as provided by user) + + const float t = g.IO.NavInputsDownDuration[n]; + if (t < 0.0f && mode == ImGuiNavReadMode_Released) // Return 1.0f when just released, no repeat, ignore analog input. + return (g.IO.NavInputsDownDurationPrev[n] >= 0.0f ? 1.0f : 0.0f); + if (t < 0.0f) + return 0.0f; + if (mode == ImGuiNavReadMode_Pressed) // Return 1.0f when just pressed, no repeat, ignore analog input. return (t == 0.0f) ? 1.0f : 0.0f; - if (mode == ImGuiNavReadMode_Released) // Return 1.0f when just release, no repeat, ignore analog input (we don't need it for Pressed logic) - return (t < 0.0f && g.IO.NavInputsDownDurationPrev[n] >= 0.0f) ? 1.0f : 0.0f; if (mode == ImGuiNavReadMode_Repeat) return (float)ImGui::CalcTypematicPressedRepeatAmount(t, t - g.IO.DeltaTime, g.IO.KeyRepeatDelay * 0.80f, g.IO.KeyRepeatRate * 0.80f); if (mode == ImGuiNavReadMode_RepeatSlow) @@ -2688,7 +2692,7 @@ static bool IsNavInputDown(ImGuiNavInput n) } // Equivalent of IsKeyPressed() for NavInputs[] -static bool IsNavInputPressed(ImGuiNavInput n, ImGuiNavReadMode mode)// = ImGuiNavReadMode_Re) +static bool IsNavInputPressed(ImGuiNavInput n, ImGuiNavReadMode mode) { return GetNavInputAmount(n, mode) > 0.0f; } @@ -2708,7 +2712,7 @@ static ImVec2 GetNavInputAmount2d(int stick_no, ImGuiNavReadMode mode, float slo return delta; } -// Window management mode (change focus, move/resize window, toggle menu layer) +// Window management mode (hold to: change focus/move/resize, tap to: toggle menu layer) static void ImGui::NavUpdateWindowing() { ImGuiContext& g = *GImGui; @@ -3057,7 +3061,9 @@ static void ImGui::NavUpdate() g.NavScoringRectScreen.Min.x = ImMin(g.NavScoringRectScreen.Min.x + 1.0f, g.NavScoringRectScreen.Max.x); g.NavScoringRectScreen.Max.x = g.NavScoringRectScreen.Min.x; //g.OverlayDrawList.AddRect(g.NavScoringRectScreen.Min, g.NavScoringRectScreen.Max, IM_COL32(255,200,0,255)); // [DEBUG] - //if (g.NavWindow) for (int layer = 0; layer < 2; layer++) g.OverlayDrawList.AddRect(g.NavWindow->Pos + g.NavWindow->NavRectRel[layer].Min, g.NavWindow->Pos + g.NavWindow->NavRectRel[layer].Max, IM_COL32(255,200,0,255)); // [DEBUG] +#if IMGUI_DEBUG_NAV_RECTS + if (g.NavWindow) for (int layer = 0; layer < 2; layer++) g.OverlayDrawList.AddRect(g.NavWindow->Pos + g.NavWindow->NavRectRel[layer].Min, g.NavWindow->Pos + g.NavWindow->NavRectRel[layer].Max, IM_COL32(255,200,0,255)); // [DEBUG] +#endif } void ImGui::NewFrame() diff --git a/imgui.h b/imgui.h index 574a4f8876ea..b17ee5584ede 100644 --- a/imgui.h +++ b/imgui.h @@ -999,7 +999,7 @@ struct ImGuiIO bool WantCaptureKeyboard; // When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application. This is set by ImGui when it wants to use your keyboard inputs. bool WantTextInput; // Mobile/console: when io.WantTextInput is true, you may display an on-screen keyboard. This is set by ImGui when it wants textual keyboard input to happen (e.g. when a InputText widget is active). bool WantMoveMouse; // MousePos has been altered, back-end should reposition mouse on next frame. Set only when 'NavMovesMouse=true'. - bool NavUsable; // Directional navigation is currently allowed (will handle ImGuiKey_NavXXX events). + bool NavUsable; // Directional navigation is currently allowed (will handle ImGuiKey_NavXXX events) ~ a window is focused and it doesn't use the ImGuiWindowFlags_NoNavInputs flag. bool NavActive; // Directional navigation is active/visible and currently allowed (will handle ImGuiKey_NavXXX events). float Framerate; // Application framerate estimation, in frame per second. Solely for convenience. Rolling average estimation based on IO.DeltaTime over 120 frames int MetricsAllocs; // Number of active memory allocations From cea78cc576eae0380f9cf43333e3b7e89730b663 Mon Sep 17 00:00:00 2001 From: omar Date: Wed, 24 Jan 2018 10:24:41 +0100 Subject: [PATCH 494/823] Nav: Update hovered logic, so IsItemHovered and ButtonBehavior are more consistent with each other. The known case this fixes is nav focusing on a color button, tooltip appears, mouse move: previously tooltip would stay up. (#787) --- imgui.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 03c411d5c1a5..bafcb158fea8 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2367,7 +2367,7 @@ bool ImGui::IsItemHovered(ImGuiHoveredFlags flags) { ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; - if (g.NavDisableMouseHover) + if (g.NavDisableMouseHover && !g.NavDisableHighlight) return IsItemFocused(); // Test for bounding box overlap, as updated as ItemAdd() @@ -7331,7 +7331,7 @@ bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool // Gamepad/Keyboard navigation // We report navigated item as hovered but we don't set g.HoveredId to not interfere with mouse. - if (g.NavId == id && !g.NavDisableHighlight && (g.ActiveId == 0 || g.ActiveId == id || g.ActiveId == window->MoveId)) + if (g.NavId == id && !g.NavDisableHighlight && g.NavDisableMouseHover && (g.ActiveId == 0 || g.ActiveId == id || g.ActiveId == window->MoveId)) hovered = true; if (g.NavActivateDownId == id) From 64b786c2aa5e157d846d889963d211385267f2f0 Mon Sep 17 00:00:00 2001 From: omar Date: Wed, 24 Jan 2018 10:31:54 +0100 Subject: [PATCH 495/823] Nav: Tweak/fixed popup positioning when using nav without the io.NavMovesMouse flag (it was always assuming a mouse cursor and allocating space for it) (#787) Note that this bit include badly hardcoded sizes, expecting an improvement later. --- imgui.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/imgui.cpp b/imgui.cpp index bafcb158fea8..06476e2cf018 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -5647,7 +5647,11 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) if ((flags & ImGuiWindowFlags_Tooltip) != 0 && !window_pos_set_by_api && !window_is_child_tooltip) { ImVec2 ref_pos = (!g.NavDisableHighlight && g.NavDisableMouseHover) ? NavCalcPreferredMousePos() : g.IO.MousePos; - ImRect rect_to_avoid(ref_pos.x - 16, ref_pos.y - 8, ref_pos.x + 24, ref_pos.y + 24); // FIXME: Completely hard-coded. Store boxes in mouse cursor data? Scale? Center on cursor hit-point? + ImRect rect_to_avoid; + if (!g.NavDisableHighlight && g.NavDisableMouseHover && !g.IO.NavMovesMouse) + rect_to_avoid = ImRect(ref_pos.x - 16, ref_pos.y - 8, ref_pos.x + 16, ref_pos.y + 8); + else + rect_to_avoid = ImRect(ref_pos.x - 16, ref_pos.y - 8, ref_pos.x + 24, ref_pos.y + 24); // FIXME-NAV: Completely hard-coded based on expected mouse cursor size. Store boxes in mouse cursor data? Scale? Center on cursor hit-point? window->PosFloat = FindBestWindowPosForPopup(ref_pos, window->Size, &window->AutoPosLastDirection, rect_to_avoid); if (window->AutoPosLastDirection == ImGuiDir_None) window->PosFloat = ref_pos + ImVec2(2,2); // If there's not enough room, for tooltip we prefer avoiding the cursor at all cost even if it means that part of the tooltip won't be visible. From 823e1f0b94a05168d61dbbd0aa1b956c83341efd Mon Sep 17 00:00:00 2001 From: omar Date: Wed, 24 Jan 2018 10:35:47 +0100 Subject: [PATCH 496/823] Nav: Reordered NavInput enums to match directional order of ImGuiDir_ and ImGuiKey_ + comments (#787) --- imgui.h | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/imgui.h b/imgui.h index b17ee5584ede..f98bc8106150 100644 --- a/imgui.h +++ b/imgui.h @@ -703,21 +703,21 @@ enum ImGuiNavInput_ ImGuiNavInput_PadActivate, // press button, tweak value // e.g. Circle button ImGuiNavInput_PadCancel, // close menu/popup/child, lose selection // e.g. Cross button ImGuiNavInput_PadInput, // text input // e.g. Triangle button - ImGuiNavInput_PadMenu, // access menu, focus, move, resize // e.g. Square button - ImGuiNavInput_PadUp, // move up, resize window (with PadMenu held) // e.g. D-pad up/down/left/right, analog - ImGuiNavInput_PadDown, // move down - ImGuiNavInput_PadLeft, // move left + ImGuiNavInput_PadMenu, // toggle menu, hold to: focus, move, resize // e.g. Square button + ImGuiNavInput_PadLeft, // move left, resize window (with PadMenu) // e.g. D-pad or left stick directions (analog) ImGuiNavInput_PadRight, // move right - ImGuiNavInput_PadScrollUp, // scroll up, move window (with PadMenu held) // e.g. right stick up/down/left/right, analog - ImGuiNavInput_PadScrollDown, // " - ImGuiNavInput_PadScrollLeft, // - ImGuiNavInput_PadScrollRight, // - ImGuiNavInput_PadFocusPrev, // next window (with PadMenu held) // e.g. L-trigger - ImGuiNavInput_PadFocusNext, // prev window (with PadMenu held) // e.g. R-trigger + ImGuiNavInput_PadUp, // move up + ImGuiNavInput_PadDown, // move down + ImGuiNavInput_PadScrollLeft, // scroll up, move window (with PadMenu) // e.g. right stick directions (analog) + ImGuiNavInput_PadScrollRight, // scroll right + ImGuiNavInput_PadScrollUp, // scroll up + ImGuiNavInput_PadScrollDown, // scroll down + ImGuiNavInput_PadFocusPrev, // next window (with PadMenu) // e.g. L-trigger + ImGuiNavInput_PadFocusNext, // prev window (with PadMenu) // e.g. R-trigger ImGuiNavInput_PadTweakSlow, // slower tweaks // e.g. L-trigger, analog ImGuiNavInput_PadTweakFast, // faster tweaks // e.g. R-trigger, analog // Keyboard Mapping - // [BETA] You can use gamepad mapping for most inputs + // [BETA] You can map keyboard keys on the gamepad mapping for most inputs. Will add specialized keyboard mappings as we add features. ImGuiNavInput_KeyMenu, // access menu // e.g. ALT ImGuiNavInput_COUNT, }; From 37ee99983fe94bc292d6c76c35a2bccf45c3d92e Mon Sep 17 00:00:00 2001 From: omar Date: Wed, 24 Jan 2018 15:09:02 +0100 Subject: [PATCH 497/823] Clear BgAlphaCond properly after consuming it. Fixes 9a76fd30fd21d0c4f6403b27a235b883ece71f28 (#1567) --- imgui.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/imgui.cpp b/imgui.cpp index a852867b1a68..8d9c1a1d4ff3 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -4806,7 +4806,10 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) // Window background ImU32 bg_col = GetColorU32(GetWindowBgColorIdxFromFlags(flags)); if (g.NextWindowData.BgAlphaCond != 0) + { bg_col = (bg_col & ~IM_COL32_A_MASK) | (IM_F32_TO_INT8_SAT(g.NextWindowData.BgAlphaVal) << IM_COL32_A_SHIFT); + g.NextWindowData.BgAlphaCond = 0; + } window->DrawList->AddRectFilled(window->Pos+ImVec2(0,window->TitleBarHeight()), window->Pos+window->Size, bg_col, window_rounding, (flags & ImGuiWindowFlags_NoTitleBar) ? ImDrawCornerFlags_All : ImDrawCornerFlags_Bot); // Title bar From 5148937d4dbcad9e8564375dfb29dce5b8bb6a38 Mon Sep 17 00:00:00 2001 From: omar Date: Wed, 24 Jan 2018 17:39:21 +0100 Subject: [PATCH 498/823] Fixed old Begin() calling SetNextWindowBgAlpha() with negative values. (#1567, #1568) --- imgui.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/imgui.cpp b/imgui.cpp index 8d9c1a1d4ff3..b5aa30e1fd84 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -5018,7 +5018,8 @@ bool ImGui::Begin(const char* name, bool* p_open, const ImVec2& size_first_use, ImGui::SetNextWindowSize(size_first_use, ImGuiCond_FirstUseEver); // Old API feature: override the window background alpha with a parameter. - ImGui::SetNextWindowBgAlpha(bg_alpha_override); + if (bg_alpha_override >= 0.0f) + ImGui::SetNextWindowBgAlpha(bg_alpha_override); return ImGui::Begin(name, p_open, flags); } From bd278e958e3fdd53bc0e56818bc826223a9f1a03 Mon Sep 17 00:00:00 2001 From: omar Date: Wed, 24 Jan 2018 14:38:33 +0100 Subject: [PATCH 499/823] Nav: Added ImGuiNavInput_KeyLeft/Right/Up/Down set so we can differenciate gamepad/keyboard inputs. (#787) --- imgui.cpp | 45 ++++++++++++++++++++++++++++++--------------- imgui.h | 6 +++++- 2 files changed, 35 insertions(+), 16 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 01f8052f38bd..65e623e04fc0 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2662,6 +2662,15 @@ enum ImGuiNavReadMode ImGuiNavReadMode_RepeatFast }; +typedef int ImGuiNavDirSource; + +enum ImGuiNavDirSource_ +{ + ImGuiNavDirSource_Key = 1 << 0, + ImGuiNavDirSource_PadStickL = 1 << 1, + ImGuiNavDirSource_PadStickR = 1 << 2 +}; + // FIXME-NAV: Expose navigation repeat delay/rate static float GetNavInputAmount(ImGuiNavInput n, ImGuiNavReadMode mode) { @@ -2697,14 +2706,20 @@ static bool IsNavInputPressed(ImGuiNavInput n, ImGuiNavReadMode mode) return GetNavInputAmount(n, mode) > 0.0f; } -static ImVec2 GetNavInputAmount2d(int stick_no, ImGuiNavReadMode mode, float slow_factor = 0.0f, float fast_factor = 0.0f) +static bool IsNavInputPressedAnyOfTwo(ImGuiNavInput n1, ImGuiNavInput n2, ImGuiNavReadMode mode) { - IM_ASSERT(ImGuiNavInput_PadScrollUp == ImGuiNavInput_PadUp + 4); - IM_ASSERT(stick_no >= 0 && stick_no < 2); + return (GetNavInputAmount(n1, mode) + GetNavInputAmount(n2, mode)) > 0.0f; +} - ImVec2 delta; - delta.x = GetNavInputAmount(ImGuiNavInput_PadRight + stick_no*4, mode) - GetNavInputAmount(ImGuiNavInput_PadLeft + stick_no*4, mode); - delta.y = GetNavInputAmount(ImGuiNavInput_PadDown + stick_no*4, mode) - GetNavInputAmount(ImGuiNavInput_PadUp + stick_no*4, mode); +static ImVec2 GetNavInputAmount2d(ImGuiNavDirSource dir_sources, ImGuiNavReadMode mode, float slow_factor = 0.0f, float fast_factor = 0.0f) +{ + ImVec2 delta(0.0f, 0.0f); + if (dir_sources & ImGuiNavDirSource_Key) + delta += ImVec2(GetNavInputAmount(ImGuiNavInput_KeyRight, mode) - GetNavInputAmount(ImGuiNavInput_KeyLeft, mode), GetNavInputAmount(ImGuiNavInput_KeyDown, mode) - GetNavInputAmount(ImGuiNavInput_KeyUp, mode)); + if (dir_sources & ImGuiNavDirSource_PadStickL) + delta += ImVec2(GetNavInputAmount(ImGuiNavInput_PadRight, mode) - GetNavInputAmount(ImGuiNavInput_PadLeft, mode), GetNavInputAmount(ImGuiNavInput_PadDown, mode) - GetNavInputAmount(ImGuiNavInput_PadUp, mode)); + if (dir_sources & ImGuiNavDirSource_PadStickR) + delta += ImVec2(GetNavInputAmount(ImGuiNavInput_PadScrollRight, mode) - GetNavInputAmount(ImGuiNavInput_PadScrollLeft, mode), GetNavInputAmount(ImGuiNavInput_PadScrollDown, mode) - GetNavInputAmount(ImGuiNavInput_PadScrollUp, mode)); if (slow_factor != 0.0f && IsNavInputDown(ImGuiNavInput_PadTweakSlow)) delta *= slow_factor; if (fast_factor != 0.0f && IsNavInputDown(ImGuiNavInput_PadTweakFast)) @@ -2753,7 +2768,7 @@ static void ImGui::NavUpdateWindowing() // Move window if (g.NavWindowingTarget && !(g.NavWindowingTarget->Flags & ImGuiWindowFlags_NoMove)) { - const ImVec2 move_delta = GetNavInputAmount2d(1, ImGuiNavReadMode_Down); + const ImVec2 move_delta = GetNavInputAmount2d(ImGuiNavDirSource_PadStickR, ImGuiNavReadMode_Down); if (move_delta.x != 0.0f || move_delta.y != 0.0f) { const float move_speed = ImFloor(600 * g.IO.DeltaTime * ImMin(g.IO.DisplayFramebufferScale.x, g.IO.DisplayFramebufferScale.y)); @@ -2978,10 +2993,10 @@ static void ImGui::NavUpdate() g.NavMoveDir = ImGuiDir_None; if (g.NavWindow && !g.NavWindowingTarget && allowed_dir_flags && !(g.NavWindow->Flags & ImGuiWindowFlags_NoNavInputs)) { - if ((allowed_dir_flags & (1<ScrollbarX) { SetWindowScrollX(window, ImFloor(window->Scroll.x + scroll_dir.x * scroll_speed)); @@ -5334,7 +5349,7 @@ static void ImGui::UpdateManualResize(ImGuiWindow* window, const ImVec2& size_au // Navigation/gamepad resize if (g.NavWindowingTarget == window) { - ImVec2 nav_resize_delta = GetNavInputAmount2d(0, ImGuiNavReadMode_Down); + ImVec2 nav_resize_delta = GetNavInputAmount2d(ImGuiNavDirSource_PadStickL, ImGuiNavReadMode_Down); if (nav_resize_delta.x != 0.0f || nav_resize_delta.y != 0.0f) { const float GAMEPAD_RESIZE_SPEED = 600.0f; @@ -8379,7 +8394,7 @@ bool ImGui::SliderBehavior(const ImRect& frame_bb, ImGuiID id, float* v, float v } else if (g.ActiveIdSource == ImGuiInputSource_Nav && g.NavActivateDownId == id) { - const ImVec2 delta2 = GetNavInputAmount2d(0, ImGuiNavReadMode_RepeatFast, 0.0f, 0.0f); + const ImVec2 delta2 = GetNavInputAmount2d(ImGuiNavDirSource_Key|ImGuiNavDirSource_PadStickL, ImGuiNavReadMode_RepeatFast, 0.0f, 0.0f); float delta = is_horizontal ? delta2.x : -delta2.y; if (delta != 0.0f) { @@ -8726,7 +8741,7 @@ bool ImGui::DragBehavior(const ImRect& frame_bb, ImGuiID id, float* v, float v_s } if (g.ActiveIdSource == ImGuiInputSource_Nav) { - adjust_delta = GetNavInputAmount2d(0, ImGuiNavReadMode_RepeatFast, 1.0f/10.0f, 10.0f).x; + adjust_delta = GetNavInputAmount2d(ImGuiNavDirSource_Key|ImGuiNavDirSource_PadStickL, ImGuiNavReadMode_RepeatFast, 1.0f/10.0f, 10.0f).x; v_speed = ImMax(v_speed, GetMinimumStepAtDecimalPrecision(decimal_precision)); } adjust_delta *= v_speed; diff --git a/imgui.h b/imgui.h index f9a4e00295d4..f6eedaa315bf 100644 --- a/imgui.h +++ b/imgui.h @@ -718,7 +718,11 @@ enum ImGuiNavInput_ ImGuiNavInput_PadTweakFast, // faster tweaks // e.g. R-trigger, analog // Keyboard Mapping // [BETA] You can map keyboard keys on the gamepad mapping for most inputs. Will add specialized keyboard mappings as we add features. - ImGuiNavInput_KeyMenu, // access menu // e.g. ALT + ImGuiNavInput_KeyMenu, // toggle menu // e.g. ALT + ImGuiNavInput_KeyLeft, // move left // e.g. Arrow keys + ImGuiNavInput_KeyRight, // move right + ImGuiNavInput_KeyUp, // move up + ImGuiNavInput_KeyDown, // move down ImGuiNavInput_COUNT, }; From c09016b12af8e4396c38f06a6cfee2c4e41a18b3 Mon Sep 17 00:00:00 2001 From: omar Date: Wed, 24 Jan 2018 14:42:28 +0100 Subject: [PATCH 500/823] Nav: Renamed ImGuiNavInput_PadLeft / etc. to ImGuiNavInput_PadLStickLeft. Renamed ImGuiNavInput_PadScrollLeft to ImGuiNavInput_PadRStickLeft, aka removing trying-too-hard semantic from the enums. (#787) --- imgui.cpp | 32 ++++++++++++++++---------------- imgui.h | 16 ++++++++-------- 2 files changed, 24 insertions(+), 24 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 65e623e04fc0..24c246879231 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2667,8 +2667,8 @@ typedef int ImGuiNavDirSource; enum ImGuiNavDirSource_ { ImGuiNavDirSource_Key = 1 << 0, - ImGuiNavDirSource_PadStickL = 1 << 1, - ImGuiNavDirSource_PadStickR = 1 << 2 + ImGuiNavDirSource_PadLStick = 1 << 1, + ImGuiNavDirSource_PadRStick = 1 << 2 }; // FIXME-NAV: Expose navigation repeat delay/rate @@ -2715,11 +2715,11 @@ static ImVec2 GetNavInputAmount2d(ImGuiNavDirSource dir_sources, ImGuiNavReadMod { ImVec2 delta(0.0f, 0.0f); if (dir_sources & ImGuiNavDirSource_Key) - delta += ImVec2(GetNavInputAmount(ImGuiNavInput_KeyRight, mode) - GetNavInputAmount(ImGuiNavInput_KeyLeft, mode), GetNavInputAmount(ImGuiNavInput_KeyDown, mode) - GetNavInputAmount(ImGuiNavInput_KeyUp, mode)); - if (dir_sources & ImGuiNavDirSource_PadStickL) - delta += ImVec2(GetNavInputAmount(ImGuiNavInput_PadRight, mode) - GetNavInputAmount(ImGuiNavInput_PadLeft, mode), GetNavInputAmount(ImGuiNavInput_PadDown, mode) - GetNavInputAmount(ImGuiNavInput_PadUp, mode)); - if (dir_sources & ImGuiNavDirSource_PadStickR) - delta += ImVec2(GetNavInputAmount(ImGuiNavInput_PadScrollRight, mode) - GetNavInputAmount(ImGuiNavInput_PadScrollLeft, mode), GetNavInputAmount(ImGuiNavInput_PadScrollDown, mode) - GetNavInputAmount(ImGuiNavInput_PadScrollUp, mode)); + delta += ImVec2(GetNavInputAmount(ImGuiNavInput_KeyRight, mode) - GetNavInputAmount(ImGuiNavInput_KeyLeft, mode), GetNavInputAmount(ImGuiNavInput_KeyDown, mode) - GetNavInputAmount(ImGuiNavInput_KeyUp, mode)); + if (dir_sources & ImGuiNavDirSource_PadLStick) + delta += ImVec2(GetNavInputAmount(ImGuiNavInput_PadLStickRight, mode) - GetNavInputAmount(ImGuiNavInput_PadLStickLeft, mode), GetNavInputAmount(ImGuiNavInput_PadLStickDown, mode) - GetNavInputAmount(ImGuiNavInput_PadLStickUp, mode)); + if (dir_sources & ImGuiNavDirSource_PadRStick) + delta += ImVec2(GetNavInputAmount(ImGuiNavInput_PadRStickRight, mode) - GetNavInputAmount(ImGuiNavInput_PadRStickLeft, mode), GetNavInputAmount(ImGuiNavInput_PadRStickDown, mode) - GetNavInputAmount(ImGuiNavInput_PadRStickUp, mode)); if (slow_factor != 0.0f && IsNavInputDown(ImGuiNavInput_PadTweakSlow)) delta *= slow_factor; if (fast_factor != 0.0f && IsNavInputDown(ImGuiNavInput_PadTweakFast)) @@ -2768,7 +2768,7 @@ static void ImGui::NavUpdateWindowing() // Move window if (g.NavWindowingTarget && !(g.NavWindowingTarget->Flags & ImGuiWindowFlags_NoMove)) { - const ImVec2 move_delta = GetNavInputAmount2d(ImGuiNavDirSource_PadStickR, ImGuiNavReadMode_Down); + const ImVec2 move_delta = GetNavInputAmount2d(ImGuiNavDirSource_PadRStick, ImGuiNavReadMode_Down); if (move_delta.x != 0.0f || move_delta.y != 0.0f) { const float move_speed = ImFloor(600 * g.IO.DeltaTime * ImMin(g.IO.DisplayFramebufferScale.x, g.IO.DisplayFramebufferScale.y)); @@ -2993,10 +2993,10 @@ static void ImGui::NavUpdate() g.NavMoveDir = ImGuiDir_None; if (g.NavWindow && !g.NavWindowingTarget && allowed_dir_flags && !(g.NavWindow->Flags & ImGuiWindowFlags_NoNavInputs)) { - if ((allowed_dir_flags & (1<ScrollbarX) { SetWindowScrollX(window, ImFloor(window->Scroll.x + scroll_dir.x * scroll_speed)); @@ -5349,7 +5349,7 @@ static void ImGui::UpdateManualResize(ImGuiWindow* window, const ImVec2& size_au // Navigation/gamepad resize if (g.NavWindowingTarget == window) { - ImVec2 nav_resize_delta = GetNavInputAmount2d(ImGuiNavDirSource_PadStickL, ImGuiNavReadMode_Down); + ImVec2 nav_resize_delta = GetNavInputAmount2d(ImGuiNavDirSource_PadLStick, ImGuiNavReadMode_Down); if (nav_resize_delta.x != 0.0f || nav_resize_delta.y != 0.0f) { const float GAMEPAD_RESIZE_SPEED = 600.0f; @@ -8394,7 +8394,7 @@ bool ImGui::SliderBehavior(const ImRect& frame_bb, ImGuiID id, float* v, float v } else if (g.ActiveIdSource == ImGuiInputSource_Nav && g.NavActivateDownId == id) { - const ImVec2 delta2 = GetNavInputAmount2d(ImGuiNavDirSource_Key|ImGuiNavDirSource_PadStickL, ImGuiNavReadMode_RepeatFast, 0.0f, 0.0f); + const ImVec2 delta2 = GetNavInputAmount2d(ImGuiNavDirSource_Key|ImGuiNavDirSource_PadLStick, ImGuiNavReadMode_RepeatFast, 0.0f, 0.0f); float delta = is_horizontal ? delta2.x : -delta2.y; if (delta != 0.0f) { @@ -8741,7 +8741,7 @@ bool ImGui::DragBehavior(const ImRect& frame_bb, ImGuiID id, float* v, float v_s } if (g.ActiveIdSource == ImGuiInputSource_Nav) { - adjust_delta = GetNavInputAmount2d(ImGuiNavDirSource_Key|ImGuiNavDirSource_PadStickL, ImGuiNavReadMode_RepeatFast, 1.0f/10.0f, 10.0f).x; + adjust_delta = GetNavInputAmount2d(ImGuiNavDirSource_Key|ImGuiNavDirSource_PadLStick, ImGuiNavReadMode_RepeatFast, 1.0f/10.0f, 10.0f).x; v_speed = ImMax(v_speed, GetMinimumStepAtDecimalPrecision(decimal_precision)); } adjust_delta *= v_speed; diff --git a/imgui.h b/imgui.h index f6eedaa315bf..9bb3d7fabf87 100644 --- a/imgui.h +++ b/imgui.h @@ -704,14 +704,14 @@ enum ImGuiNavInput_ ImGuiNavInput_PadCancel, // close menu/popup/child, lose selection // e.g. Cross button ImGuiNavInput_PadInput, // text input // e.g. Triangle button ImGuiNavInput_PadMenu, // toggle menu, hold to: focus, move, resize // e.g. Square button - ImGuiNavInput_PadLeft, // move left, resize window (with PadMenu) // e.g. D-pad or left stick directions (analog) - ImGuiNavInput_PadRight, // move right - ImGuiNavInput_PadUp, // move up - ImGuiNavInput_PadDown, // move down - ImGuiNavInput_PadScrollLeft, // scroll up, move window (with PadMenu) // e.g. right stick directions (analog) - ImGuiNavInput_PadScrollRight, // scroll right - ImGuiNavInput_PadScrollUp, // scroll up - ImGuiNavInput_PadScrollDown, // scroll down + ImGuiNavInput_PadLStickLeft, // move left, resize window (with PadMenu) // e.g. D-pad + left stick directions (analog) + ImGuiNavInput_PadLStickRight, // move right + ImGuiNavInput_PadLStickUp, // move up + ImGuiNavInput_PadLStickDown, // move down + ImGuiNavInput_PadRStickLeft, // scroll up, move window (with PadMenu) // e.g. right stick directions (analog) + ImGuiNavInput_PadRStickRight, // scroll right + ImGuiNavInput_PadRStickUp, // scroll up + ImGuiNavInput_PadRStickDown, // scroll down ImGuiNavInput_PadFocusPrev, // next window (with PadMenu) // e.g. L-trigger ImGuiNavInput_PadFocusNext, // prev window (with PadMenu) // e.g. R-trigger ImGuiNavInput_PadTweakSlow, // slower tweaks // e.g. L-trigger, analog From 8227176c170ac3f1902f49bf22f433a67fb2a0a3 Mon Sep 17 00:00:00 2001 From: omar Date: Wed, 24 Jan 2018 15:03:59 +0100 Subject: [PATCH 501/823] Nav: Menus: Fix for using Left direction inside a menu with widgets layed out horizontally. Left to close is now handled as a fallback inside EndMenu(). (#787) --- imgui.cpp | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 24c246879231..e5c4aa4f4d39 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -10842,7 +10842,7 @@ void ImGui::EndMenuBar() return; ImGuiContext& g = *GImGui; - // When a move request within one of our child menu failed, capture the request to navigate among our siblings. + // Nav: When a move request within one of our child menu failed, capture the request to navigate among our siblings. if (g.NavMoveRequest && g.NavMoveResultId == 0 && (g.NavMoveDir == ImGuiDir_Left || g.NavMoveDir == ImGuiDir_Right) && (g.NavWindow->Flags & ImGuiWindowFlags_ChildMenu)) { ImGuiWindow* nav_earliest_child = g.NavWindow; @@ -10926,7 +10926,7 @@ bool ImGui::BeginMenu(const char* label, bool enabled) g.NavWindow = backed_nav_window; bool want_open = false, want_close = false; - if (window->DC.LayoutType != ImGuiLayoutType_Horizontal) // (window->Flags & (ImGuiWindowFlags_Popup|ImGuiWindowFlags_ChildMenu)) + if (window->DC.LayoutType == ImGuiLayoutType_Vertical) // (window->Flags & (ImGuiWindowFlags_Popup|ImGuiWindowFlags_ChildMenu)) { // Implement http://bjk5.com/post/44698559168/breaking-down-amazons-mega-dropdown to avoid using timers, so menus feels more reactive. bool moving_within_opened_triangle = false; @@ -10960,11 +10960,6 @@ bool ImGui::BeginMenu(const char* label, bool enabled) want_open = true; g.NavMoveRequest = false; } - if (g.NavWindow && g.NavWindow->ParentWindow == window && g.NavMoveRequest && g.NavMoveDir == ImGuiDir_Left && IsPopupOpen(id)) // Nav-Left to close - { - want_close = true; - g.NavMoveRequest = false; - } } else { @@ -11013,6 +11008,15 @@ bool ImGui::BeginMenu(const char* label, bool enabled) void ImGui::EndMenu() { + // Nav: When a left move request within our child menu failed, close the menu + ImGuiContext& g = *GImGui; + ImGuiWindow* window = g.CurrentWindow; + if (g.NavWindow && g.NavWindow->ParentWindow == window && g.NavMoveRequest && g.NavMoveResultId == 0 && g.NavMoveDir == ImGuiDir_Left && window->DC.LayoutType == ImGuiLayoutType_Vertical) + { + ClosePopupToLevel(g.OpenPopupStack.Size - 1); + g.NavMoveRequest = false; + } + EndPopup(); } From 28671aa821e37cddce8d0d7a94bd0e972d2f2392 Mon Sep 17 00:00:00 2001 From: omar Date: Wed, 24 Jan 2018 16:37:20 +0100 Subject: [PATCH 502/823] Nav: Internals: Moved some enums and functions to internals, renamed ImGuiNavReadMode to ImGuiInputReadMode as well. (#787) --- imgui.cpp | 90 +++++++++++++++++++----------------------------- imgui_internal.h | 21 +++++++++++ 2 files changed, 56 insertions(+), 55 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index e5c4aa4f4d39..53811859da12 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2652,45 +2652,25 @@ static ImGuiWindow* FindWindowNavigable(int i_start, int i_stop, int dir) // FIX return NULL; } -enum ImGuiNavReadMode -{ - ImGuiNavReadMode_Down, - ImGuiNavReadMode_Pressed, - ImGuiNavReadMode_Released, - ImGuiNavReadMode_Repeat, - ImGuiNavReadMode_RepeatSlow, - ImGuiNavReadMode_RepeatFast -}; - -typedef int ImGuiNavDirSource; - -enum ImGuiNavDirSource_ -{ - ImGuiNavDirSource_Key = 1 << 0, - ImGuiNavDirSource_PadLStick = 1 << 1, - ImGuiNavDirSource_PadRStick = 1 << 2 -}; - -// FIXME-NAV: Expose navigation repeat delay/rate -static float GetNavInputAmount(ImGuiNavInput n, ImGuiNavReadMode mode) +float ImGui::GetNavInputAmount(ImGuiNavInput n, ImGuiInputReadMode mode) { ImGuiContext& g = *GImGui; - if (mode == ImGuiNavReadMode_Down) - return g.IO.NavInputs[n]; // Instant, read analog input (0.0f..1.0f, as provided by user) + if (mode == ImGuiInputReadMode_Down) + return g.IO.NavInputs[n]; // Instant, read analog input (0.0f..1.0f, as provided by user) const float t = g.IO.NavInputsDownDuration[n]; - if (t < 0.0f && mode == ImGuiNavReadMode_Released) // Return 1.0f when just released, no repeat, ignore analog input. + if (t < 0.0f && mode == ImGuiInputReadMode_Released) // Return 1.0f when just released, no repeat, ignore analog input. return (g.IO.NavInputsDownDurationPrev[n] >= 0.0f ? 1.0f : 0.0f); if (t < 0.0f) return 0.0f; - if (mode == ImGuiNavReadMode_Pressed) // Return 1.0f when just pressed, no repeat, ignore analog input. + if (mode == ImGuiInputReadMode_Pressed) // Return 1.0f when just pressed, no repeat, ignore analog input. return (t == 0.0f) ? 1.0f : 0.0f; - if (mode == ImGuiNavReadMode_Repeat) - return (float)ImGui::CalcTypematicPressedRepeatAmount(t, t - g.IO.DeltaTime, g.IO.KeyRepeatDelay * 0.80f, g.IO.KeyRepeatRate * 0.80f); - if (mode == ImGuiNavReadMode_RepeatSlow) - return (float)ImGui::CalcTypematicPressedRepeatAmount(t, t - g.IO.DeltaTime, g.IO.KeyRepeatDelay * 1.00f, g.IO.KeyRepeatRate * 2.00f); - if (mode == ImGuiNavReadMode_RepeatFast) - return (float)ImGui::CalcTypematicPressedRepeatAmount(t, t - g.IO.DeltaTime, g.IO.KeyRepeatDelay * 0.80f, g.IO.KeyRepeatRate * 0.30f); + if (mode == ImGuiInputReadMode_Repeat) + return (float)CalcTypematicPressedRepeatAmount(t, t - g.IO.DeltaTime, g.IO.KeyRepeatDelay * 0.80f, g.IO.KeyRepeatRate * 0.80f); + if (mode == ImGuiInputReadMode_RepeatSlow) + return (float)CalcTypematicPressedRepeatAmount(t, t - g.IO.DeltaTime, g.IO.KeyRepeatDelay * 1.00f, g.IO.KeyRepeatRate * 2.00f); + if (mode == ImGuiInputReadMode_RepeatFast) + return (float)CalcTypematicPressedRepeatAmount(t, t - g.IO.DeltaTime, g.IO.KeyRepeatDelay * 0.80f, g.IO.KeyRepeatRate * 0.30f); return 0.0f; } @@ -2701,24 +2681,24 @@ static bool IsNavInputDown(ImGuiNavInput n) } // Equivalent of IsKeyPressed() for NavInputs[] -static bool IsNavInputPressed(ImGuiNavInput n, ImGuiNavReadMode mode) +static bool IsNavInputPressed(ImGuiNavInput n, ImGuiInputReadMode mode) { - return GetNavInputAmount(n, mode) > 0.0f; + return ImGui::GetNavInputAmount(n, mode) > 0.0f; } -static bool IsNavInputPressedAnyOfTwo(ImGuiNavInput n1, ImGuiNavInput n2, ImGuiNavReadMode mode) +static bool IsNavInputPressedAnyOfTwo(ImGuiNavInput n1, ImGuiNavInput n2, ImGuiInputReadMode mode) { - return (GetNavInputAmount(n1, mode) + GetNavInputAmount(n2, mode)) > 0.0f; + return (ImGui::GetNavInputAmount(n1, mode) + ImGui::GetNavInputAmount(n2, mode)) > 0.0f; } -static ImVec2 GetNavInputAmount2d(ImGuiNavDirSource dir_sources, ImGuiNavReadMode mode, float slow_factor = 0.0f, float fast_factor = 0.0f) +ImVec2 ImGui::GetNavInputAmount2d(ImGuiNavDirSourceFlags dir_sources, ImGuiInputReadMode mode, float slow_factor, float fast_factor) { ImVec2 delta(0.0f, 0.0f); - if (dir_sources & ImGuiNavDirSource_Key) + if (dir_sources & ImGuiNavDirSourceFlags_Key) delta += ImVec2(GetNavInputAmount(ImGuiNavInput_KeyRight, mode) - GetNavInputAmount(ImGuiNavInput_KeyLeft, mode), GetNavInputAmount(ImGuiNavInput_KeyDown, mode) - GetNavInputAmount(ImGuiNavInput_KeyUp, mode)); - if (dir_sources & ImGuiNavDirSource_PadLStick) + if (dir_sources & ImGuiNavDirSourceFlags_PadLStick) delta += ImVec2(GetNavInputAmount(ImGuiNavInput_PadLStickRight, mode) - GetNavInputAmount(ImGuiNavInput_PadLStickLeft, mode), GetNavInputAmount(ImGuiNavInput_PadLStickDown, mode) - GetNavInputAmount(ImGuiNavInput_PadLStickUp, mode)); - if (dir_sources & ImGuiNavDirSource_PadRStick) + if (dir_sources & ImGuiNavDirSourceFlags_PadRStick) delta += ImVec2(GetNavInputAmount(ImGuiNavInput_PadRStickRight, mode) - GetNavInputAmount(ImGuiNavInput_PadRStickLeft, mode), GetNavInputAmount(ImGuiNavInput_PadRStickDown, mode) - GetNavInputAmount(ImGuiNavInput_PadRStickUp, mode)); if (slow_factor != 0.0f && IsNavInputDown(ImGuiNavInput_PadTweakSlow)) delta *= slow_factor; @@ -2733,7 +2713,7 @@ static void ImGui::NavUpdateWindowing() ImGuiContext& g = *GImGui; bool toggle_layer = false; - if (!g.NavWindowingTarget && IsNavInputPressed(ImGuiNavInput_PadMenu, ImGuiNavReadMode_Pressed)) + if (!g.NavWindowingTarget && IsNavInputPressed(ImGuiNavInput_PadMenu, ImGuiInputReadMode_Pressed)) { ImGuiWindow* window = g.NavWindow; if (!window) @@ -2753,7 +2733,7 @@ static void ImGui::NavUpdateWindowing() g.NavWindowingToggleLayer &= (g.NavWindowingDisplayAlpha < 1.0f); // Once button is held long enough we don't consider it a tag-to-toggle-layer press anymore. // Select window to focus - const int focus_change_dir = (int)IsNavInputPressed(ImGuiNavInput_PadFocusPrev, ImGuiNavReadMode_RepeatSlow) - (int)IsNavInputPressed(ImGuiNavInput_PadFocusNext, ImGuiNavReadMode_RepeatSlow); + const int focus_change_dir = (int)IsNavInputPressed(ImGuiNavInput_PadFocusPrev, ImGuiInputReadMode_RepeatSlow) - (int)IsNavInputPressed(ImGuiNavInput_PadFocusNext, ImGuiInputReadMode_RepeatSlow); if (focus_change_dir != 0 && !(g.NavWindowingTarget->Flags & ImGuiWindowFlags_Modal)) { const int i_current = FindWindowIndex(g.NavWindowingTarget); @@ -2768,7 +2748,7 @@ static void ImGui::NavUpdateWindowing() // Move window if (g.NavWindowingTarget && !(g.NavWindowingTarget->Flags & ImGuiWindowFlags_NoMove)) { - const ImVec2 move_delta = GetNavInputAmount2d(ImGuiNavDirSource_PadRStick, ImGuiNavReadMode_Down); + const ImVec2 move_delta = GetNavInputAmount2d(ImGuiNavDirSourceFlags_PadRStick, ImGuiInputReadMode_Down); if (move_delta.x != 0.0f || move_delta.y != 0.0f) { const float move_speed = ImFloor(600 * g.IO.DeltaTime * ImMin(g.IO.DisplayFramebufferScale.x, g.IO.DisplayFramebufferScale.y)); @@ -2802,7 +2782,7 @@ static void ImGui::NavUpdateWindowing() } // Keyboard: Press and release ALT to toggle menu - if ((g.ActiveId == 0 || g.ActiveIdAllowOverlap) && IsNavInputPressed(ImGuiNavInput_KeyMenu, ImGuiNavReadMode_Released)) + if ((g.ActiveId == 0 || g.ActiveIdAllowOverlap) && IsNavInputPressed(ImGuiNavInput_KeyMenu, ImGuiInputReadMode_Released)) toggle_layer = true; if (toggle_layer && g.NavWindow) @@ -2921,7 +2901,7 @@ static void ImGui::NavUpdate() g.IO.NavActive = (g.IO.NavUsable && g.NavId != 0 && !g.NavDisableHighlight) || (g.NavWindowingTarget != NULL) || g.NavInitRequest; // Process NavCancel input (to close a popup, get back to parent, clear focus) - if (IsNavInputPressed(ImGuiNavInput_PadCancel, ImGuiNavReadMode_Pressed)) + if (IsNavInputPressed(ImGuiNavInput_PadCancel, ImGuiInputReadMode_Pressed)) { if (g.ActiveId != 0) { @@ -2965,11 +2945,11 @@ static void ImGui::NavUpdate() g.NavActivateId = g.NavActivateDownId = g.NavInputId = 0; if (g.NavId != 0 && !g.NavDisableHighlight && !g.NavWindowingTarget) { - if (g.ActiveId == 0 && IsNavInputPressed(ImGuiNavInput_PadActivate, ImGuiNavReadMode_Pressed)) + if (g.ActiveId == 0 && IsNavInputPressed(ImGuiNavInput_PadActivate, ImGuiInputReadMode_Pressed)) g.NavActivateId = g.NavId; if ((g.ActiveId == 0 || g.ActiveId == g.NavId) && IsNavInputDown(ImGuiNavInput_PadActivate)) g.NavActivateDownId = g.NavId; - if (g.ActiveId == 0 && IsNavInputPressed(ImGuiNavInput_PadInput, ImGuiNavReadMode_Pressed)) + if (g.ActiveId == 0 && IsNavInputPressed(ImGuiNavInput_PadInput, ImGuiInputReadMode_Pressed)) g.NavInputId = g.NavId; } if (g.NavWindow && (g.NavWindow->Flags & ImGuiWindowFlags_NoNavInputs)) @@ -2993,10 +2973,10 @@ static void ImGui::NavUpdate() g.NavMoveDir = ImGuiDir_None; if (g.NavWindow && !g.NavWindowingTarget && allowed_dir_flags && !(g.NavWindow->Flags & ImGuiWindowFlags_NoNavInputs)) { - if ((allowed_dir_flags & (1<ScrollbarX) { SetWindowScrollX(window, ImFloor(window->Scroll.x + scroll_dir.x * scroll_speed)); @@ -5349,7 +5329,7 @@ static void ImGui::UpdateManualResize(ImGuiWindow* window, const ImVec2& size_au // Navigation/gamepad resize if (g.NavWindowingTarget == window) { - ImVec2 nav_resize_delta = GetNavInputAmount2d(ImGuiNavDirSource_PadLStick, ImGuiNavReadMode_Down); + ImVec2 nav_resize_delta = GetNavInputAmount2d(ImGuiNavDirSourceFlags_PadLStick, ImGuiInputReadMode_Down); if (nav_resize_delta.x != 0.0f || nav_resize_delta.y != 0.0f) { const float GAMEPAD_RESIZE_SPEED = 600.0f; @@ -7359,7 +7339,7 @@ bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool if (g.NavActivateDownId == id) { bool nav_activated_by_code = (g.NavActivateId == id); - bool nav_activated_by_inputs = IsNavInputPressed(ImGuiNavInput_PadActivate, (flags & ImGuiButtonFlags_Repeat) ? ImGuiNavReadMode_Repeat : ImGuiNavReadMode_Pressed); + bool nav_activated_by_inputs = IsNavInputPressed(ImGuiNavInput_PadActivate, (flags & ImGuiButtonFlags_Repeat) ? ImGuiInputReadMode_Repeat : ImGuiInputReadMode_Pressed); if (nav_activated_by_code || nav_activated_by_inputs) pressed = true; if (nav_activated_by_code || nav_activated_by_inputs || g.ActiveId == id) @@ -8394,7 +8374,7 @@ bool ImGui::SliderBehavior(const ImRect& frame_bb, ImGuiID id, float* v, float v } else if (g.ActiveIdSource == ImGuiInputSource_Nav && g.NavActivateDownId == id) { - const ImVec2 delta2 = GetNavInputAmount2d(ImGuiNavDirSource_Key|ImGuiNavDirSource_PadLStick, ImGuiNavReadMode_RepeatFast, 0.0f, 0.0f); + const ImVec2 delta2 = GetNavInputAmount2d(ImGuiNavDirSourceFlags_Key|ImGuiNavDirSourceFlags_PadLStick, ImGuiInputReadMode_RepeatFast, 0.0f, 0.0f); float delta = is_horizontal ? delta2.x : -delta2.y; if (delta != 0.0f) { @@ -8741,7 +8721,7 @@ bool ImGui::DragBehavior(const ImRect& frame_bb, ImGuiID id, float* v, float v_s } if (g.ActiveIdSource == ImGuiInputSource_Nav) { - adjust_delta = GetNavInputAmount2d(ImGuiNavDirSource_Key|ImGuiNavDirSource_PadLStick, ImGuiNavReadMode_RepeatFast, 1.0f/10.0f, 10.0f).x; + adjust_delta = GetNavInputAmount2d(ImGuiNavDirSourceFlags_Key|ImGuiNavDirSourceFlags_PadLStick, ImGuiInputReadMode_RepeatFast, 1.0f/10.0f, 10.0f).x; v_speed = ImMax(v_speed, GetMinimumStepAtDecimalPrecision(decimal_precision)); } adjust_delta *= v_speed; diff --git a/imgui_internal.h b/imgui_internal.h index 693f03c90bed..c94cb222e7ae 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -47,6 +47,7 @@ typedef int ImGuiLayoutType; // enum: horizontal or vertical typedef int ImGuiButtonFlags; // flags: for ButtonEx(), ButtonBehavior() // enum ImGuiButtonFlags_ typedef int ImGuiItemFlags; // flags: for PushItemFlag() // enum ImGuiItemFlags_ typedef int ImGuiNavHighlightFlags; // flags: for RenderNavHighlight() // enum ImGuiNavHighlightFlags_ +typedef int ImGuiNavDirSourceFlags; // flags: for GetNavInputAmount2d() // enum ImGuiNavDirSourceFlags_ typedef int ImGuiSeparatorFlags; // flags: for Separator() - internal // enum ImGuiSeparatorFlags_ typedef int ImGuiSliderFlags; // flags: for SliderBehavior() // enum ImGuiSliderFlags_ @@ -254,6 +255,17 @@ enum ImGuiInputSource ImGuiInputSource_Count_, }; +// FIXME-NAV: Clarify/expose various repeat delay/rate +enum ImGuiInputReadMode +{ + ImGuiInputReadMode_Down, + ImGuiInputReadMode_Pressed, + ImGuiInputReadMode_Released, + ImGuiInputReadMode_Repeat, + ImGuiInputReadMode_RepeatSlow, + ImGuiInputReadMode_RepeatFast +}; + enum ImGuiDir { ImGuiDir_None = -1, @@ -271,6 +283,13 @@ enum ImGuiNavHighlightFlags_ ImGuiNavHighlightFlags_AlwaysDraw = 1 << 2 }; +enum ImGuiNavDirSourceFlags_ +{ + ImGuiNavDirSourceFlags_Key = 1 << 0, + ImGuiNavDirSourceFlags_PadLStick = 1 << 1, + ImGuiNavDirSourceFlags_PadRStick = 1 << 2 +}; + // 2D axis aligned bounding-box // NB: we can't rely on ImVec2 math operators being available here struct IMGUI_API ImRect @@ -1001,6 +1020,8 @@ namespace ImGui IMGUI_API void NavInitWindow(ImGuiWindow* window, bool force_reinit); IMGUI_API void ActivateItem(ImGuiID id); // Remotely activate a button, checkbox, tree node etc. given its unique ID. activation is queued and processed on the next frame when the item is encountered again. + IMGUI_API float GetNavInputAmount(ImGuiNavInput n, ImGuiInputReadMode mode); + IMGUI_API ImVec2 GetNavInputAmount2d(ImGuiNavDirSourceFlags dir_sources, ImGuiInputReadMode mode, float slow_factor = 0.0f, float fast_factor = 0.0f); IMGUI_API int CalcTypematicPressedRepeatAmount(float t, float t_prev, float repeat_delay, float repeat_rate); IMGUI_API void Scrollbar(ImGuiLayoutType direction); From 455989b8b1534947886d9650e9ae44386e311121 Mon Sep 17 00:00:00 2001 From: omar Date: Wed, 24 Jan 2018 16:57:16 +0100 Subject: [PATCH 503/823] Nav: Added io.NavFlags to hold various options. Added ImGuiNavFlags_EnableGamepad and ImGuiNavFlags_EnableKeyboard for bindings to use (#787) --- imgui.cpp | 7 ++++--- imgui.h | 12 ++++++++++-- imgui_demo.cpp | 12 +++++++----- 3 files changed, 21 insertions(+), 10 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 53811859da12..f330711e6fa1 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -830,13 +830,13 @@ ImGuiIO::ImGuiIO() IniSavingRate = 5.0f; IniFilename = "imgui.ini"; LogFilename = "imgui_log.txt"; + NavFlags = 0x00; MouseDoubleClickTime = 0.30f; MouseDoubleClickMaxDist = 6.0f; for (int i = 0; i < ImGuiKey_COUNT; i++) KeyMap[i] = -1; KeyRepeatDelay = 0.250f; KeyRepeatRate = 0.050f; - NavMovesMouse = false; UserData = NULL; Fonts = &GImDefaultFontAtlas; @@ -2883,7 +2883,7 @@ static void ImGui::NavUpdate() if (g.NavMousePosDirty && g.NavIdIsAlive) { // Set mouse position given our knowledge of the nav widget position from last frame - if (g.IO.NavMovesMouse) + if (g.IO.NavFlags & ImGuiNavFlags_MoveMouse) { g.IO.MousePos = g.IO.MousePosPrev = NavCalcPreferredMousePos(); g.IO.WantMoveMouse = true; @@ -5643,7 +5643,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) { ImVec2 ref_pos = (!g.NavDisableHighlight && g.NavDisableMouseHover) ? NavCalcPreferredMousePos() : g.IO.MousePos; ImRect rect_to_avoid; - if (!g.NavDisableHighlight && g.NavDisableMouseHover && !g.IO.NavMovesMouse) + if (!g.NavDisableHighlight && g.NavDisableMouseHover && !(g.IO.NavFlags & ImGuiNavFlags_MoveMouse)) rect_to_avoid = ImRect(ref_pos.x - 16, ref_pos.y - 8, ref_pos.x + 16, ref_pos.y + 8); else rect_to_avoid = ImRect(ref_pos.x - 16, ref_pos.y - 8, ref_pos.x + 24, ref_pos.y + 24); // FIXME-NAV: Completely hard-coded based on expected mouse cursor size. Store boxes in mouse cursor data? Scale? Center on cursor hit-point? @@ -7288,6 +7288,7 @@ bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool if (hovered && (flags & ImGuiButtonFlags_AllowItemOverlap) && (g.HoveredIdPreviousFrame != id && g.HoveredIdPreviousFrame != 0)) hovered = false; + // Mouse if (hovered) { if (!(flags & ImGuiButtonFlags_NoKeyModifiers) || (!g.IO.KeyCtrl && !g.IO.KeyShift && !g.IO.KeyAlt)) diff --git a/imgui.h b/imgui.h index 9bb3d7fabf87..4eef8b054579 100644 --- a/imgui.h +++ b/imgui.h @@ -90,6 +90,7 @@ typedef int ImGuiComboFlags; // flags: for BeginCombo() typedef int ImGuiFocusedFlags; // flags: for IsWindowFocused() // enum ImGuiFocusedFlags_ typedef int ImGuiHoveredFlags; // flags: for IsItemHovered() etc. // enum ImGuiHoveredFlags_ typedef int ImGuiInputTextFlags; // flags: for InputText*() // enum ImGuiInputTextFlags_ +typedef int ImGuiNavFlags; // flags: for io.NavFlags // enum ImGuiNavFlags_ typedef int ImGuiSelectableFlags; // flags: for Selectable() // enum ImGuiSelectableFlags_ typedef int ImGuiTreeNodeFlags; // flags: for TreeNode*(),CollapsingHeader()// enum ImGuiTreeNodeFlags_ typedef int ImGuiWindowFlags; // flags: for Begin*() // enum ImGuiWindowFlags_ @@ -726,6 +727,14 @@ enum ImGuiNavInput_ ImGuiNavInput_COUNT, }; +// [BETA] Gamepad/Keyboard directional navigation options +enum ImGuiNavFlags_ +{ + ImGuiNavFlags_EnableGamepad = 1 << 0, // Master gamepad navigation enable flag. This is to instruct your imgui binding whether to fill in gamepad navigation inputs. imgui itself won't use this flag. + ImGuiNavFlags_EnableKeyboard = 1 << 1, // Master keyboard navigation enable flag. This is to instruct your imgui binding whether to fill in keyboard navigation inputs. imgui itself won't use this flag. + ImGuiNavFlags_MoveMouse = 1 << 2 // Allow directional navigation to move the mouse cursor. May be useful on TV/console systems where moving a virtual mouse is awkward. Will update io.MousePos and set io.WantMoveMouse=true. If enabled you MUST honor io.WantMoveMouse requests in your binding, otherwise ImGui will react as if the mouse is jumping around back and forth. +}; + // Enumeration for PushStyleColor() / PopStyleColor() enum ImGuiCol_ { @@ -926,6 +935,7 @@ struct ImGuiIO float IniSavingRate; // = 5.0f // Maximum time between saving positions/sizes to .ini file, in seconds. const char* IniFilename; // = "imgui.ini" // Path to .ini file. NULL to disable .ini saving. const char* LogFilename; // = "imgui_log.txt" // Path to .log file (default parameter to ImGui::LogToFile when no file is specified). + ImGuiNavFlags NavFlags; // = 0 // See ImGuiNavFlags_. Gamepad/keyboard navigation options. float MouseDoubleClickTime; // = 0.30f // Time for a double-click, in seconds. float MouseDoubleClickMaxDist; // = 6.0f // Distance threshold to stay in to validate a double-click, in pixels. float MouseDragThreshold; // = 6.0f // Distance threshold before considering we are dragging. @@ -942,8 +952,6 @@ struct ImGuiIO ImVec2 DisplayVisibleMin; // (0.0f,0.0f) // If you use DisplaySize as a virtual space larger than your screen, set DisplayVisibleMin/Max to the visible area. ImVec2 DisplayVisibleMax; // (0.0f,0.0f) // If the values are the same, we defaults to Min=(0.0f) and Max=DisplaySize - // Gamepad/Keyboard Navigation - bool NavMovesMouse; // = false // Directional navigation can move the mouse cursor. Updates MousePos and set WantMoveMouse=true. If enabled you MUST honor those requests in your binding, otherwise ImGui will react as if mouse is jumping around. // Advanced/subtle behaviors bool OptMacOSXBehaviors; // = defined(__APPLE__) // OS X style: Text editing cursor movement using Alt instead of Ctrl, Shortcuts using Cmd/Super instead of Ctrl, Line/Text Start and End using Cmd+Arrows instead of Home/End, Double click selects by word instead of selecting whole text, Multi-selection in lists uses Cmd/Super instead of Ctrl bool OptCursorBlink; // = true // Enable blinking cursor, for users who consider it annoying. diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 574f49eafa0d..47397269b049 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -1788,17 +1788,19 @@ void ImGui::ShowDemoWindow(bool* p_open) if (ImGui::CollapsingHeader("Inputs, Navigation & Focus")) { ImGuiIO& io = ImGui::GetIO(); - ImGui::Checkbox("io.NavMovesMouse", &io.NavMovesMouse); - ImGui::SameLine(); ShowHelpMarker("Request ImGui to move your move cursor when using gamepad/keyboard navigation. NewFrame() will change io.MousePos and set the io.WantMoveMouse flag, your backend will need to apply the new mouse position."); - - ImGui::Checkbox("io.MouseDrawCursor", &io.MouseDrawCursor); - ImGui::SameLine(); ShowHelpMarker("Request ImGui to render a mouse cursor for you in software. Note that a mouse cursor rendered via your application GPU rendering path will feel more laggy than hardware cursor, but will be more in sync with your other visuals.\n\nSome desktop applications may use both kinds of cursors (e.g. enable software cursor only when resizing/dragging something)."); ImGui::Text("WantCaptureMouse: %d", io.WantCaptureMouse); ImGui::Text("WantCaptureKeyboard: %d", io.WantCaptureKeyboard); ImGui::Text("WantTextInput: %d", io.WantTextInput); ImGui::Text("WantMoveMouse: %d", io.WantMoveMouse); + ImGui::Checkbox("io.MouseDrawCursor", &io.MouseDrawCursor); + ImGui::SameLine(); ShowHelpMarker("Request ImGui to render a mouse cursor for you in software. Note that a mouse cursor rendered via your application GPU rendering path will feel more laggy than hardware cursor, but will be more in sync with your other visuals.\n\nSome desktop applications may use both kinds of cursors (e.g. enable software cursor only when resizing/dragging something)."); + ImGui::CheckboxFlags("io.NavFlags: EnableGamepad", (unsigned int *)&io.NavFlags, ImGuiNavFlags_EnableGamepad); + ImGui::CheckboxFlags("io.NavFlags: EnableKeyboard", (unsigned int *)&io.NavFlags, ImGuiNavFlags_EnableKeyboard); + ImGui::CheckboxFlags("io.NavFlags: MoveMouse", (unsigned int *)&io.NavFlags, ImGuiNavFlags_MoveMouse); + ImGui::SameLine(); ShowHelpMarker("Request ImGui to move your move cursor when using gamepad/keyboard navigation. NewFrame() will change io.MousePos and set the io.WantMoveMouse flag, your backend will need to apply the new mouse position."); + if (ImGui::TreeNode("Keyboard, Mouse & Navigation State")) { if (ImGui::IsMousePosValid()) From 6f366fff6b130c994d366e479302baed06370598 Mon Sep 17 00:00:00 2001 From: omar Date: Wed, 24 Jan 2018 17:08:37 +0100 Subject: [PATCH 504/823] Demo: Tweaked example menu with colors + menu items, was currently particularly inconvenient for Nav. Will rework later. (#787) --- imgui_demo.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 47397269b049..a642e5d1d386 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -2330,15 +2330,16 @@ static void ShowExampleMenuFile() } if (ImGui::BeginMenu("Colors")) { - ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0,0)); + float sz = ImGui::GetTextLineHeight(); for (int i = 0; i < ImGuiCol_COUNT; i++) { const char* name = ImGui::GetStyleColorName((ImGuiCol)i); - ImGui::ColorButton(name, ImGui::GetStyleColorVec4((ImGuiCol)i)); + ImVec2 p = ImGui::GetCursorScreenPos(); + ImGui::GetWindowDrawList()->AddRectFilled(p, ImVec2(p.x+sz, p.y+sz), ImGui::GetColorU32((ImGuiCol)i)); + ImGui::Dummy(ImVec2(sz, sz)); ImGui::SameLine(); ImGui::MenuItem(name); } - ImGui::PopStyleVar(); ImGui::EndMenu(); } if (ImGui::BeginMenu("Disabled", false)) // Disabled From 277f6e7842e2a1464bde74457cce1ae21068cadd Mon Sep 17 00:00:00 2001 From: omar Date: Wed, 24 Jan 2018 18:40:23 +0100 Subject: [PATCH 505/823] Examples: Comments --- examples/README.txt | 36 ++++++++++++++++++++---------------- 1 file changed, 20 insertions(+), 16 deletions(-) diff --git a/examples/README.txt b/examples/README.txt index 1f00756f1f42..cf99c5dc3f46 100644 --- a/examples/README.txt +++ b/examples/README.txt @@ -1,10 +1,13 @@ -Those are standalone ready-to-build applications to demonstrate ImGui. +Those are standalone ready-to-build applications to demonstrate Dear ImGui. Binaries of some of those demos: http://www.miracleworld.net/imgui/binaries -Third party languages and frameworks bindings: https://github.com/ocornut/imgui/wiki/Links -(languages: C, .net, rust, D, Python, Lua..) -(frameworks: DX12, Vulkan, Cinder, OpenGLES, openFrameworks, Cocos2d-x, SFML, Flexium, NanoRT, Irrlicht..) -(extras: RemoteImGui, ImWindow, imgui_wm..) +Third party languages and frameworks bindings: + https://github.com/ocornut/imgui/wiki/Links +(languages: C, C#, ChaiScript, D, Go, Haxe, Odin, Python, Rust, Lua, Pascal) +(frameworks: DX12, OpenGLES, FreeGlut, Cinder, Cocos2d-x, SFML, GML/GameMaker Studio, Irrlicht, Ogre, + OpenSceneGraph, openFrameworks, LOVE, NanoRT, Qt3d, SFML, Unreal Engine 4, etc.) +(extras: RemoteImGui, ImWindow, imgui_wm, etc.) + TL;DR; - Newcomers, read 'PROGRAMMER GUIDE' in imgui.cpp for notes on how to setup ImGui in your codebase. @@ -19,14 +22,14 @@ TL;DR; existing rendering backends, don't feel forced to rewrite them with your own engine API, or you can do that later when you already got things to work. -ImGui is highly portable and only requires a few things to run: +Dear ImGui is highly portable and only requires a few things to run and render. - Providing mouse/keyboard inputs - Load the font atlas texture into graphics memory - Providing a render function to render indexed textured triangles - Optional: clipboard support, mouse cursor supports, Windows IME support, etc. So this is essentially what those examples are doing + the obligatory cruft for portability. -Unfortunately in 2016 it is still tedious to create and maintain portable build files using external +Unfortunately in 2018 it is still tedious to create and maintain portable build files using external libraries (the kind we're using here to create a window and render 3D triangles) without relying on third party software. For most examples here I choose to provide: - Makefiles for Linux/OSX @@ -36,14 +39,15 @@ Please let me know if they don't work with your setup! You can probably just import the imgui_impl_xxx.cpp/.h files into your own codebase or compile those directly with a command-line compiler. -ImGui has zero frame of lag for most behaviors and one frame of lag for some behaviors. -At 60 FPS your experience should be pleasant. Consider that OS mouse cursors are typically drawn through -a specific hardware accelerated route and may feel smoother than other GPU rendered contents. You may -experiment with the io.MouseDrawCursor flag to request ImGui to draw a mouse cursor itself, to visualize -the lag between a hardware cursor and a software cursor. It might be beneficial to the user experience -to switch to a software rendered cursor when an interactive drag is in progress. -Also note that some setup or GPU drivers may be causing extra lag (possibly by enforcing triple buffering), -leaving you with no option but sadness/anger (Intel GPU drivers were reported as such). +Dear ImGui has zero to one frame of lag for most behaviors, at 60 FPS your experience should be pleasant. +Consider that OS mouse cursors are typically drawn through a specific hardware accelerated route and may +feel smoother than other GPU rendered contents. You may experiment with the io.MouseDrawCursor flag to +request ImGui to draw a mouse cursor itself, to visualize the lag between a hardware cursor and a software +cursor. It might be beneficial to the user experience to switch to a software rendered cursor when an +interactive drag is in progress. +Also note that some setup or GPU drivers may be causing extra lag (possibly by enforcing triple buffering), +leaving you with little option but sadness (Intel GPU drivers were reported as such). + opengl2_example/ **DO NOT USE THIS CODE IF YOUR CODE/ENGINE IS USING MODERN OPENGL (SHADERS, VBO, VAO, etc.)** @@ -99,4 +103,4 @@ vulkan_example/ Vulkan example. This is quite long and tedious, because: Vulkan. -TODO: Apple, SDL GL/GL3, Allegro, Marmalade, Vulkan examples do not honor the io.WantMoveMouse flag. +TODO: Apple, SDL GL2/GL3, Allegro, Marmalade, Vulkan examples do not honor the io.WantMoveMouse flag. From c2e92ab61bf4ead7f1b219debbf993f3c6247818 Mon Sep 17 00:00:00 2001 From: omar Date: Wed, 24 Jan 2018 18:40:54 +0100 Subject: [PATCH 506/823] Added imgui.natvis helper for visual studio users. Added to examples projects. --- .../directx10_example.vcxproj | 1 + .../directx10_example.vcxproj.filters | 3 ++ .../directx11_example.vcxproj | 1 + .../directx11_example.vcxproj.filters | 3 ++ .../directx9_example/directx9_example.vcxproj | 1 + .../directx9_example.vcxproj.filters | 3 ++ examples/libs/imgui.natvis | 35 +++++++++++++++++++ .../opengl2_example/opengl2_example.vcxproj | 1 + .../opengl2_example.vcxproj.filters | 3 ++ .../opengl3_example/opengl3_example.vcxproj | 1 + .../opengl3_example.vcxproj.filters | 3 ++ 11 files changed, 55 insertions(+) create mode 100644 examples/libs/imgui.natvis diff --git a/examples/directx10_example/directx10_example.vcxproj b/examples/directx10_example/directx10_example.vcxproj index 8583e1dec836..3a403518e32e 100644 --- a/examples/directx10_example/directx10_example.vcxproj +++ b/examples/directx10_example/directx10_example.vcxproj @@ -153,6 +153,7 @@
+ diff --git a/examples/directx10_example/directx10_example.vcxproj.filters b/examples/directx10_example/directx10_example.vcxproj.filters index 15e924c446cc..5a358463eae7 100644 --- a/examples/directx10_example/directx10_example.vcxproj.filters +++ b/examples/directx10_example/directx10_example.vcxproj.filters @@ -41,5 +41,8 @@ + + sources + \ No newline at end of file diff --git a/examples/directx11_example/directx11_example.vcxproj b/examples/directx11_example/directx11_example.vcxproj index 7099a7bd4090..347b4f007656 100644 --- a/examples/directx11_example/directx11_example.vcxproj +++ b/examples/directx11_example/directx11_example.vcxproj @@ -153,6 +153,7 @@ + diff --git a/examples/directx11_example/directx11_example.vcxproj.filters b/examples/directx11_example/directx11_example.vcxproj.filters index 5cd0ca4156a8..a79484cc1c44 100644 --- a/examples/directx11_example/directx11_example.vcxproj.filters +++ b/examples/directx11_example/directx11_example.vcxproj.filters @@ -41,5 +41,8 @@ + + sources + \ No newline at end of file diff --git a/examples/directx9_example/directx9_example.vcxproj b/examples/directx9_example/directx9_example.vcxproj index 6fe7c9cecf51..e63bd35b57cf 100644 --- a/examples/directx9_example/directx9_example.vcxproj +++ b/examples/directx9_example/directx9_example.vcxproj @@ -153,6 +153,7 @@ + diff --git a/examples/directx9_example/directx9_example.vcxproj.filters b/examples/directx9_example/directx9_example.vcxproj.filters index 5cf0283438e7..b0843b3975e7 100644 --- a/examples/directx9_example/directx9_example.vcxproj.filters +++ b/examples/directx9_example/directx9_example.vcxproj.filters @@ -42,5 +42,8 @@ + + sources + \ No newline at end of file diff --git a/examples/libs/imgui.natvis b/examples/libs/imgui.natvis new file mode 100644 index 000000000000..807129ad074b --- /dev/null +++ b/examples/libs/imgui.natvis @@ -0,0 +1,35 @@ + + + + + + + + {{Size={Size} Capacity={Capacity}}} + + + Size + Data + + + + + + {{x={x,g} y={y,g}}} + + + + {{x={x,g} y={y,g} z={z,g} w={w,g}}} + + + + {{Min=({Min.x,g} {Min.y,g}) Max=({Max.x,g} {Max.y,g}) Size=({Max.x-Min.x,g} {Max.y-Min.y,g})}} + + Min + Max + Max.x - Min.x + Max.x - Min.x + + + + \ No newline at end of file diff --git a/examples/opengl2_example/opengl2_example.vcxproj b/examples/opengl2_example/opengl2_example.vcxproj index 237eba7dab03..bf1a3ed4ea6f 100644 --- a/examples/opengl2_example/opengl2_example.vcxproj +++ b/examples/opengl2_example/opengl2_example.vcxproj @@ -163,6 +163,7 @@ + diff --git a/examples/opengl2_example/opengl2_example.vcxproj.filters b/examples/opengl2_example/opengl2_example.vcxproj.filters index 3cc7ee9e1792..35fd6ffaf119 100644 --- a/examples/opengl2_example/opengl2_example.vcxproj.filters +++ b/examples/opengl2_example/opengl2_example.vcxproj.filters @@ -42,5 +42,8 @@ + + sources + \ No newline at end of file diff --git a/examples/opengl3_example/opengl3_example.vcxproj b/examples/opengl3_example/opengl3_example.vcxproj index d481c943adbb..2a78226f736d 100644 --- a/examples/opengl3_example/opengl3_example.vcxproj +++ b/examples/opengl3_example/opengl3_example.vcxproj @@ -166,6 +166,7 @@ + diff --git a/examples/opengl3_example/opengl3_example.vcxproj.filters b/examples/opengl3_example/opengl3_example.vcxproj.filters index f19cd16b2ec0..c743ace31979 100644 --- a/examples/opengl3_example/opengl3_example.vcxproj.filters +++ b/examples/opengl3_example/opengl3_example.vcxproj.filters @@ -54,5 +54,8 @@ + + sources + \ No newline at end of file From 6f27d6b5b892a5a762c1d0db27434ccd46f75626 Mon Sep 17 00:00:00 2001 From: omar Date: Wed, 24 Jan 2018 18:52:26 +0100 Subject: [PATCH 507/823] Natvis: Made ImGuiWindow display shorter. --- examples/libs/imgui.natvis | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/examples/libs/imgui.natvis b/examples/libs/imgui.natvis index 807129ad074b..eb32708d91f7 100644 --- a/examples/libs/imgui.natvis +++ b/examples/libs/imgui.natvis @@ -31,5 +31,10 @@ Max.x - Min.x + + + {{Name={Name,s}}} + {{Name={Name,s}} Inactive} + \ No newline at end of file From 8c57d8cc1e34c2cbf0529296cec8280876b58d9d Mon Sep 17 00:00:00 2001 From: omar Date: Wed, 24 Jan 2018 19:10:09 +0100 Subject: [PATCH 508/823] Natvis: Fix ImRect expanded height display being broken and dumb. (#1569) --- examples/libs/imgui.natvis | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/libs/imgui.natvis b/examples/libs/imgui.natvis index eb32708d91f7..38c676c757f8 100644 --- a/examples/libs/imgui.natvis +++ b/examples/libs/imgui.natvis @@ -28,7 +28,7 @@ Min Max Max.x - Min.x - Max.x - Min.x + Max.y - Min.y From 89b0ca1f8f044324aa7836ad98856fd2602273d1 Mon Sep 17 00:00:00 2001 From: omar Date: Wed, 24 Jan 2018 19:55:56 +0100 Subject: [PATCH 509/823] Nav: FocusWindow() doesn't reset NavRectRel (which was flickering e.g. when returning to a parent menu). This was added in the initial nav branch commit and I don't see a reason for it. (#787) --- imgui.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index f330711e6fa1..7e19e18b9855 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -3057,7 +3057,8 @@ static void ImGui::NavUpdate() g.NavScoringRectScreen.Max.x = g.NavScoringRectScreen.Min.x; //g.OverlayDrawList.AddRect(g.NavScoringRectScreen.Min, g.NavScoringRectScreen.Max, IM_COL32(255,200,0,255)); // [DEBUG] #if IMGUI_DEBUG_NAV_RECTS - if (g.NavWindow) for (int layer = 0; layer < 2; layer++) g.OverlayDrawList.AddRect(g.NavWindow->Pos + g.NavWindow->NavRectRel[layer].Min, g.NavWindow->Pos + g.NavWindow->NavRectRel[layer].Max, IM_COL32(255,200,0,255)); // [DEBUG] + if (g.NavWindow) { for (int layer = 0; layer < 2; layer++) g.OverlayDrawList.AddRect(g.NavWindow->Pos + g.NavWindow->NavRectRel[layer].Min, g.NavWindow->Pos + g.NavWindow->NavRectRel[layer].Max, IM_COL32(255,200,0,255)); } // [DEBUG] + if (g.NavWindow) { ImU32 col = (g.NavWindow->HiddenFrames <= 0) ? IM_COL32(255,0,255,255) : IM_COL32(255,0,0,255); ImVec2 p = NavCalcPreferredMousePos(); char buf[32]; ImFormatString(buf, 32, "%d", g.NavLayer); g.OverlayDrawList.AddCircleFilled(p, 3.0f, col); g.OverlayDrawList.AddText(NULL, 13.0f, p + ImVec2(8,-4), col, buf); } #endif } @@ -6151,8 +6152,6 @@ void ImGui::FocusWindow(ImGuiWindow* window) g.NavLayer = 0; if (window && g.NavDisableMouseHover) g.NavMousePosDirty = true; - if (window) - window->NavRectRel[0].Min = window->NavRectRel[0].Max = window->DC.CursorStartPos - window->Pos; g.NavWindow = window; } From d404b93b6bbcc6a652f14f43ee68588853449602 Mon Sep 17 00:00:00 2001 From: omar Date: Wed, 24 Jan 2018 19:57:39 +0100 Subject: [PATCH 510/823] Nav: Mouse clicking on a window (to select/move) disables hides nav highlight. (#787) + comments --- imgui.cpp | 1 + imgui_internal.h | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/imgui.cpp b/imgui.cpp index 7e19e18b9855..56060c4ed591 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -3791,6 +3791,7 @@ void ImGui::EndFrame() // Set ActiveId even if the _NoMove flag is set, without it dragging away from a window with _NoMove would activate hover on other windows. FocusWindow(g.HoveredWindow); SetActiveID(g.HoveredWindow->MoveId, g.HoveredWindow); + g.NavDisableHighlight = true; g.ActiveIdClickOffset = g.IO.MousePos - g.HoveredRootWindow->Pos; if (!(g.HoveredWindow->Flags & ImGuiWindowFlags_NoMove) && !(g.HoveredRootWindow->Flags & ImGuiWindowFlags_NoMove)) g.MovingWindow = g.HoveredWindow; diff --git a/imgui_internal.h b/imgui_internal.h index c94cb222e7ae..a3def3178353 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -905,7 +905,7 @@ struct IMGUI_API ImGuiWindow ImVec2 SetWindowPosPivot; // store window pivot for positioning. ImVec2(0,0) when positioning from top-left corner; ImVec2(0.5f,0.5f) for centering; ImVec2(1,1) for bottom right. ImGuiID NavLastIds[2]; // Last known NavId for this window, per layer (0/1) - ImRect NavRectRel[2]; // Reference rectangle, in window space + ImRect NavRectRel[2]; // Reference rectangle, in window relative space ImGuiDrawContext DC; // Temporary per-window data, reset at the beginning of the frame ImVector IDStack; // ID stack. ID are hashes seeded with the value at the top of the stack From 5f7f27c8de469192d80918b736fbaed85eccd28f Mon Sep 17 00:00:00 2001 From: omar Date: Wed, 24 Jan 2018 20:05:36 +0100 Subject: [PATCH 511/823] Nav: Comments. (#787) --- imgui.cpp | 27 ++++++++++----------------- imgui.h | 4 ++-- 2 files changed, 12 insertions(+), 19 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 56060c4ed591..0886e04f7cfe 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -217,29 +217,22 @@ - Consider emulating a mouse cursor with DualShock4 touch pad or a spare analog stick as a mouse-emulation fallback. - Consider using Synergy host (on your computer) + uSynergy.c (in your console/tablet/phone app) to use PC mouse/keyboard. - Your inputs are passed to imgui by filling the io.NavInputs[] array. See 'enum ImGuiNavInput_' in imgui.h for a description of available inputs. + - The ImGuiNavFlags_EnableGamepad and ImGuiNavFlags_EnableKeyboard flags of io.NavFlags are only here to instruct your binding whether to find inputs. - For gamepad use, the easiest approach is to go all-or-nothing, with a buttons combo that toggle your inputs between imgui and your game/application. Sharing inputs in a more advanced or granular way between imgui and your game/application may be tricky and requires further work on imgui. For more advanced uses, you may want to use: - io.NavUsable: true when a window is focused and it doesn't have the ImGuiWindowFlags_NoNavInputs flag set. - io.NavActive: true when the navigation cursor is visible (and usually goes false when mouse is used). - query focus information with IsWindowFocused(), IsAnyWindowFocused(), IsAnyItemFocused() functions. - The reality is more complex than what those flags can express. Please discuss your issues and usage scenario in the thread above. + The reality is more complex than what those flags can express. Please discuss your issues and usage scenario in the thread above! As we head toward more keyboard-oriented development this aspect will need to be improved. - - It is recommended that you enable the 'io.NavMovesMouse' option. Enabling it instructs ImGui that it can move your move cursor to track navigated items and ease readability. - When enabled and using directional navigation (with d-pad or arrow keys), the NewFrame() functions may alter 'io.MousePos' and set 'io.WantMoveMouse' to notify you that it did so. - When that happens your back-end NEEDS to move the OS or underlying mouse cursor on the next frame. The examples binding in examples/ do that. - (Important: It you set 'io.NavMovesMouse' to true but don't honor 'io.WantMoveMouse' properly, imgui will misbehave as it will think your mouse is moving back and forth.) - - // Application init - io.NavMovesMouse = true; - - // Application main loop - if (io.WantMoveMouse) - MyFuncToSetMousePosition(io.MousePos.x, io.MousePos.y); - ImGui::NewFrame(); - - In a setup when you may not have easy control over the mouse cursor (e.g. uSynergy.c doesn't expose moving remote mouse cursor), - you might want to set a boolean to ignore your other external mouse positions until they move again. + - On a TV/console system where readability may be lower or mouse inputs may be awkward, you may want to set the ImGuiNavFlags_MoveMouse flag in io.NavFlags. + Enabling ImGuiNavFlags_MoveMouse instructs dear imgui to move your mouse cursor along when navigation movement. + When enabled, the NewFrame() functions may alter 'io.MousePos' and set 'io.WantMoveMouse' to notify you that it did so. + When that happens your back-end NEEDS to move the OS or underlying mouse cursor on the next frame. Some of the binding in examples/ do that. + (Important: It you set the ImGuiNavFlags_MoveMouse flag but don't honor 'io.WantMoveMouse' properly, imgui will misbehave as it will think your mouse is moving back and forth.) + (In a setup when you may not have easy control over the mouse cursor, e.g. uSynergy.c doesn't expose moving remote mouse cursor, you may want + to set a boolean to ignore your other external mouse positions until the external source is moved again.) API BREAKING CHANGES @@ -3135,7 +3128,7 @@ void ImGui::NewFrame() for (int i = 0; i < IM_ARRAYSIZE(g.IO.NavInputs); i++) g.IO.NavInputsDownDuration[i] = (g.IO.NavInputs[i] > 0.0f) ? (g.IO.NavInputsDownDuration[i] < 0.0f ? 0.0f : g.IO.NavInputsDownDuration[i] + g.IO.DeltaTime) : -1.0f; - // Update directional navigation which may override MousePos if 'NavMovesMouse=true' + // Update directional navigation which may override MousePos if ImGuiNavFlags_MoveMouse is enabled. NavUpdate(); // Update mouse input state diff --git a/imgui.h b/imgui.h index 4eef8b054579..c5e4e39d7b08 100644 --- a/imgui.h +++ b/imgui.h @@ -732,7 +732,7 @@ enum ImGuiNavFlags_ { ImGuiNavFlags_EnableGamepad = 1 << 0, // Master gamepad navigation enable flag. This is to instruct your imgui binding whether to fill in gamepad navigation inputs. imgui itself won't use this flag. ImGuiNavFlags_EnableKeyboard = 1 << 1, // Master keyboard navigation enable flag. This is to instruct your imgui binding whether to fill in keyboard navigation inputs. imgui itself won't use this flag. - ImGuiNavFlags_MoveMouse = 1 << 2 // Allow directional navigation to move the mouse cursor. May be useful on TV/console systems where moving a virtual mouse is awkward. Will update io.MousePos and set io.WantMoveMouse=true. If enabled you MUST honor io.WantMoveMouse requests in your binding, otherwise ImGui will react as if the mouse is jumping around back and forth. + ImGuiNavFlags_MoveMouse = 1 << 2 // Request navigation to allow move the mouse cursor. May be useful on TV/console systems where moving a virtual mouse is awkward. Will update io.MousePos and set io.WantMoveMouse=true. If enabled you MUST honor io.WantMoveMouse requests in your binding, otherwise ImGui will react as if the mouse is jumping around back and forth. }; // Enumeration for PushStyleColor() / PopStyleColor() @@ -1010,7 +1010,7 @@ struct ImGuiIO bool WantCaptureMouse; // When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application. This is set by ImGui when it wants to use your mouse (e.g. unclicked mouse is hovering a window, or a widget is active). bool WantCaptureKeyboard; // When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application. This is set by ImGui when it wants to use your keyboard inputs. bool WantTextInput; // Mobile/console: when io.WantTextInput is true, you may display an on-screen keyboard. This is set by ImGui when it wants textual keyboard input to happen (e.g. when a InputText widget is active). - bool WantMoveMouse; // MousePos has been altered, back-end should reposition mouse on next frame. Set only when 'NavMovesMouse=true'. + bool WantMoveMouse; // MousePos has been altered, back-end should reposition mouse on next frame. Set only when ImGuiNavFlags_MoveMouse flag is enabled in io.NavFlags. bool NavUsable; // Directional navigation is currently allowed (will handle ImGuiKey_NavXXX events) ~ a window is focused and it doesn't use the ImGuiWindowFlags_NoNavInputs flag. bool NavActive; // Directional navigation is active/visible and currently allowed (will handle ImGuiKey_NavXXX events). float Framerate; // Application framerate estimation, in frame per second. Solely for convenience. Rolling average estimation based on IO.DeltaTime over 120 frames From 2c7324da56fc4ceec73eeb603c4222c9ff66ade7 Mon Sep 17 00:00:00 2001 From: omar Date: Thu, 25 Jan 2018 12:38:15 +0100 Subject: [PATCH 512/823] TODO list, added uSynergy README --- TODO.txt | 4 ++++ examples/libs/usynergy/README.txt | 8 ++++++++ 2 files changed, 12 insertions(+) create mode 100644 examples/libs/usynergy/README.txt diff --git a/TODO.txt b/TODO.txt index a9bc641e72b8..3a6535a03334 100644 --- a/TODO.txt +++ b/TODO.txt @@ -162,6 +162,7 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i - shortcuts,menus: global-style shortcut api e.g. "Save (CTRL+S)" -> explicit flag for recursing into closed menu - shortcuts: programmatically access shortcuts "Focus("&Save")) - menus: menubars: main menu-bar could affect clamping of windows position (~ akin to modifying DisplayMin) + - menus: hovering from menu to menu on a menu-bar has 1 frame without any menu, which is a little annoying. ideally either 0 either longer. - text: selectable text (for copy) as a generic feature (ItemFlags?) - text: proper alignment options in imgui_internal.h @@ -175,6 +176,7 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i - tree node: try to apply scrolling at time of TreePop() if node was just opened and end of node is past scrolling limits? - tree node / selectable render mismatch which is visible if you use them both next to each other (e.g. cf. property viewer) - tree node: tweak color scheme to distinguish headers from selected tree node (#581) + - tree node: leaf/non-leaf highlight mismatch. !- settings: expose enough to save/load .ini from RAM instead of fopen - settings: write more decent code to allow saving/loading new fields: columns, selected tree nodes? @@ -246,6 +248,8 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i - misc: fix for compilation settings where stdcall isn't the default (e.g. vectorcall) (#1230) - remote: make a system like RemoteImGui first-class citizen/project (#75) + - natvis: more the imgui.natvis file in a better location. perhaps reorganize extra_fonts/? (#1569) + - demo: add vertical separator demo - demo: add virtual scrolling example? - examples: directx9: save/restore device state more thoroughly. diff --git a/examples/libs/usynergy/README.txt b/examples/libs/usynergy/README.txt new file mode 100644 index 000000000000..c86b90965bee --- /dev/null +++ b/examples/libs/usynergy/README.txt @@ -0,0 +1,8 @@ + +uSynergy client -- Implementation for the embedded Synergy client library +version 1.0.0, July 7th, 2012 +Copyright (c) 2012 Alex Evans + +This is a copy of the files once found at: + https://github.com/symless/synergy-core/tree/790d108a56ada9caad8e56ff777d444485a69da9/src/micro + From c226e02ca02dd42ba4ccfc0650cabba484c7366e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Pasquier?= Date: Thu, 25 Jan 2018 13:27:57 +0100 Subject: [PATCH 513/823] Fix sdl_opengl2_example filename in README.md's build instructions --- examples/sdl_opengl2_example/README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/sdl_opengl2_example/README.md b/examples/sdl_opengl2_example/README.md index deae323929ca..a1a44a5845b4 100644 --- a/examples/sdl_opengl2_example/README.md +++ b/examples/sdl_opengl2_example/README.md @@ -5,18 +5,18 @@ ``` set SDL2DIR=path_to_your_sdl2_folder -cl /Zi /MD /I %SDL2DIR%\include /I ..\.. main.cpp imgui_impl_sdl.cpp ..\..\imgui*.cpp /link /LIBPATH:%SDL2DIR%\lib SDL2.lib SDL2main.lib opengl32.lib /subsystem:console +cl /Zi /MD /I %SDL2DIR%\include /I ..\.. main.cpp imgui_impl_sdl_gl2.cpp ..\..\imgui*.cpp /link /LIBPATH:%SDL2DIR%\lib SDL2.lib SDL2main.lib opengl32.lib /subsystem:console ``` - On Linux and similar Unixes ``` -c++ `sdl2-config --cflags` -I ../.. main.cpp imgui_impl_sdl.cpp ../../imgui*.cpp `sdl2-config --libs` -lGL -o sdl2example +c++ `sdl2-config --cflags` -I ../.. main.cpp imgui_impl_sdl_gl2.cpp ../../imgui*.cpp `sdl2-config --libs` -lGL -o sdl2example ``` - On Mac OS X ``` brew install sdl2 -c++ `sdl2-config --cflags` -I ../.. main.cpp imgui_impl_sdl.cpp ../../imgui*.cpp `sdl2-config --libs` -framework OpenGl -o sdl2example +c++ `sdl2-config --cflags` -I ../.. main.cpp imgui_impl_sdl_gl2.cpp ../../imgui*.cpp `sdl2-config --libs` -framework OpenGl -o sdl2example ``` From 94ed44b5cbdeec85c3d4961c0382b7393b7b509c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Pasquier?= Date: Thu, 25 Jan 2018 13:33:35 +0100 Subject: [PATCH 514/823] Fix allegro5_example build instructions --- examples/allegro5_example/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/allegro5_example/README.md b/examples/allegro5_example/README.md index d891982b7a5a..dcd83b8a92aa 100644 --- a/examples/allegro5_example/README.md +++ b/examples/allegro5_example/README.md @@ -4,7 +4,7 @@ - On Ubuntu 14.04+ ```bash -g++ -I ../imgui main.cpp imgui_impl_a5.cpp ../imgui/imgui*.cpp -lallegro -lallegro_primitives +g++ -I ../.. main.cpp imgui_impl_a5.cpp ../../imgui*.cpp -lallegro -lallegro_primitives -o allegro5_example ``` - On Windows with Visual Studio's CLI From 8bf0c89c0daa1189faccb7ff1c77d32180bf7bd7 Mon Sep 17 00:00:00 2001 From: omar Date: Thu, 25 Jan 2018 14:24:57 +0100 Subject: [PATCH 515/823] Internals: ImRect::Contains(ImRect&) include boundaries (whereas Contains(ImVec2) should not). --- imgui_internal.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/imgui_internal.h b/imgui_internal.h index b30dde60dbca..a00a88a0947a 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -273,9 +273,9 @@ struct IMGUI_API ImRect ImVec2 GetTR() const { return ImVec2(Max.x, Min.y); } // Top-right ImVec2 GetBL() const { return ImVec2(Min.x, Max.y); } // Bottom-left ImVec2 GetBR() const { return Max; } // Bottom-right - bool Contains(const ImVec2& p) const { return p.x >= Min.x && p.y >= Min.y && p.x < Max.x && p.y < Max.y; } - bool Contains(const ImRect& r) const { return r.Min.x >= Min.x && r.Min.y >= Min.y && r.Max.x < Max.x && r.Max.y < Max.y; } - bool Overlaps(const ImRect& r) const { return r.Min.y < Max.y && r.Max.y > Min.y && r.Min.x < Max.x && r.Max.x > Min.x; } + bool Contains(const ImVec2& p) const { return p.x >= Min.x && p.y >= Min.y && p.x < Max.x && p.y < Max.y; } + bool Contains(const ImRect& r) const { return r.Min.x >= Min.x && r.Min.y >= Min.y && r.Max.x <= Max.x && r.Max.y <= Max.y; } + bool Overlaps(const ImRect& r) const { return r.Min.y < Max.y && r.Max.y > Min.y && r.Min.x < Max.x && r.Max.x > Min.x; } void Add(const ImVec2& p) { if (Min.x > p.x) Min.x = p.x; if (Min.y > p.y) Min.y = p.y; if (Max.x < p.x) Max.x = p.x; if (Max.y < p.y) Max.y = p.y; } void Add(const ImRect& r) { if (Min.x > r.Min.x) Min.x = r.Min.x; if (Min.y > r.Min.y) Min.y = r.Min.y; if (Max.x < r.Max.x) Max.x = r.Max.x; if (Max.y < r.Max.y) Max.y = r.Max.y; } void Expand(const float amount) { Min.x -= amount; Min.y -= amount; Max.x += amount; Max.y += amount; } From 5d31e1696f83601ae1b323dc4e51d532c4eb238a Mon Sep 17 00:00:00 2001 From: omar Date: Thu, 25 Jan 2018 15:37:24 +0100 Subject: [PATCH 516/823] Fix SetNextWindowContentSize() with 0.0f on Y axis (or SetNextWindowContentWidth()) overwriting the contents size. Broken in eab6333a0b96bd30413bb17408303a5df438ffde. (#1363) --- imgui.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/imgui.cpp b/imgui.cpp index b5aa30e1fd84..076eb4b5c2aa 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -4544,7 +4544,8 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) { // Adjust passed "client size" to become a "window size" window->SizeContentsExplicit = g.NextWindowData.ContentSizeVal; - window->SizeContentsExplicit.y += window->TitleBarHeight() + window->MenuBarHeight(); + if (window->SizeContentsExplicit.y != 0.0f) + window->SizeContentsExplicit.y += window->TitleBarHeight() + window->MenuBarHeight(); g.NextWindowData.ContentSizeCond = 0; } else if (first_begin_of_the_frame) From 3967ff58b2d82afb6db5fc85fe0bbf0a09a5fb7b Mon Sep 17 00:00:00 2001 From: omar Date: Thu, 25 Jan 2018 15:48:30 +0100 Subject: [PATCH 517/823] Nav: Examples: DirectX11, Glfw+GL3: Basic code to map keyboard inputs when io.NavFlags & ImGuiNavFlags_EnableKeyboard is set. (will iterate/tweak before spreading to other examples). (#787) --- .../directx11_example/imgui_impl_dx11.cpp | 20 +++++++++++++++++ examples/directx11_example/main.cpp | 3 ++- .../opengl3_example/imgui_impl_glfw_gl3.cpp | 22 +++++++++++++++++++ examples/opengl3_example/main.cpp | 3 ++- 4 files changed, 46 insertions(+), 2 deletions(-) diff --git a/examples/directx11_example/imgui_impl_dx11.cpp b/examples/directx11_example/imgui_impl_dx11.cpp index 4963fc12eaa3..cd57bc97e4ac 100644 --- a/examples/directx11_example/imgui_impl_dx11.cpp +++ b/examples/directx11_example/imgui_impl_dx11.cpp @@ -605,6 +605,26 @@ void ImGui_ImplDX11_NewFrame() // io.MouseDown : filled by WM_*BUTTON* events // io.MouseWheel : filled by WM_MOUSEWHEEL events + // Gamepad/keyboard navigation mapping [BETA] + memset(io.NavInputs, 0, sizeof(io.NavInputs)); + if (io.NavFlags & ImGuiNavFlags_EnableKeyboard) + { + // Update keyboard + // FIXME-NAV: We are still using some of the ImGuiNavInput_PadXXX enums as keyboard support is incomplete. + #define MAP_KEY(NAV_NO, KEY_NO) { if (io.KeysDown[KEY_NO]) io.NavInputs[NAV_NO] = 1.0f; } + MAP_KEY(ImGuiNavInput_KeyLeft, VK_LEFT); + MAP_KEY(ImGuiNavInput_KeyRight, VK_RIGHT); + MAP_KEY(ImGuiNavInput_KeyUp, VK_UP); + MAP_KEY(ImGuiNavInput_KeyDown, VK_DOWN); + MAP_KEY(ImGuiNavInput_KeyMenu, VK_MENU); + MAP_KEY(ImGuiNavInput_PadActivate, VK_SPACE); + MAP_KEY(ImGuiNavInput_PadCancel, VK_ESCAPE); + MAP_KEY(ImGuiNavInput_PadInput, VK_RETURN); + MAP_KEY(ImGuiNavInput_PadTweakFast, VK_SHIFT); + MAP_KEY(ImGuiNavInput_PadTweakSlow, VK_CONTROL); + #undef MAP_KEY + } + // Set OS mouse position if requested last frame by io.WantMoveMouse flag (used when io.NavMovesTrue is enabled by user and using directional navigation) if (io.WantMoveMouse) { diff --git a/examples/directx11_example/main.cpp b/examples/directx11_example/main.cpp index 79e7bb169ddc..1ce5d49dae87 100644 --- a/examples/directx11_example/main.cpp +++ b/examples/directx11_example/main.cpp @@ -125,7 +125,9 @@ int main(int, char**) UpdateWindow(hwnd); // Setup ImGui binding + ImGuiIO& io = ImGui::GetIO(); (void)io; ImGui_ImplDX11_Init(hwnd, g_pd3dDevice, g_pd3dDeviceContext); + //io.NavFlags |= ImGuiNavFlags_EnableKeyboard; // Setup style ImGui::StyleColorsClassic(); @@ -138,7 +140,6 @@ int main(int, char**) // - The fonts will be rasterized at a given size (w/ oversampling) and stored into a texture when calling ImFontAtlas::Build()/GetTexDataAsXXXX(), which ImGui_ImplXXXX_NewFrame below will call. // - Read 'extra_fonts/README.txt' for more instructions and details. // - Remember that in C/C++ if you want to include a backslash \ in a string literal you need to write a double backslash \\ ! - //ImGuiIO& io = ImGui::GetIO(); //io.Fonts->AddFontDefault(); //io.Fonts->AddFontFromFileTTF("../../extra_fonts/Roboto-Medium.ttf", 16.0f); //io.Fonts->AddFontFromFileTTF("../../extra_fonts/Cousine-Regular.ttf", 15.0f); diff --git a/examples/opengl3_example/imgui_impl_glfw_gl3.cpp b/examples/opengl3_example/imgui_impl_glfw_gl3.cpp index a71fc515dab5..196f64131eff 100644 --- a/examples/opengl3_example/imgui_impl_glfw_gl3.cpp +++ b/examples/opengl3_example/imgui_impl_glfw_gl3.cpp @@ -411,6 +411,28 @@ void ImGui_ImplGlfwGL3_NewFrame() // Hide OS mouse cursor if ImGui is drawing it glfwSetInputMode(g_Window, GLFW_CURSOR, io.MouseDrawCursor ? GLFW_CURSOR_HIDDEN : GLFW_CURSOR_NORMAL); + // Gamepad/keyboard navigation mapping [BETA] + memset(io.NavInputs, 0, sizeof(io.NavInputs)); + if (io.NavFlags & ImGuiNavFlags_EnableKeyboard) + { + // Update keyboard + // FIXME-NAV: We are still using some of the ImGuiNavInput_PadXXX enums as keyboard support is incomplete. + #define MAP_KEY(NAV_NO, KEY_NO) { if (io.KeysDown[KEY_NO]) io.NavInputs[NAV_NO] = 1.0f; } + MAP_KEY(ImGuiNavInput_KeyLeft, GLFW_KEY_LEFT); + MAP_KEY(ImGuiNavInput_KeyRight, GLFW_KEY_RIGHT); + MAP_KEY(ImGuiNavInput_KeyUp, GLFW_KEY_UP); + MAP_KEY(ImGuiNavInput_KeyDown, GLFW_KEY_DOWN); + MAP_KEY(ImGuiNavInput_KeyMenu, GLFW_KEY_LEFT_ALT); + MAP_KEY(ImGuiNavInput_PadActivate, GLFW_KEY_SPACE); + MAP_KEY(ImGuiNavInput_PadCancel, GLFW_KEY_ESCAPE); + MAP_KEY(ImGuiNavInput_PadInput, GLFW_KEY_ENTER); + MAP_KEY(ImGuiNavInput_PadTweakSlow, GLFW_KEY_LEFT_ALT); + MAP_KEY(ImGuiNavInput_PadTweakSlow, GLFW_KEY_RIGHT_ALT); + MAP_KEY(ImGuiNavInput_PadTweakFast, GLFW_KEY_LEFT_SHIFT); + MAP_KEY(ImGuiNavInput_PadTweakFast, GLFW_KEY_RIGHT_SHIFT); + #undef MAP_KEY + } + // Start the frame. This call will update the io.WantCaptureMouse, io.WantCaptureKeyboard flag that you can use to dispatch inputs (or not) to your application. ImGui::NewFrame(); } diff --git a/examples/opengl3_example/main.cpp b/examples/opengl3_example/main.cpp index 6beb855dc4f0..4b3073af55e8 100644 --- a/examples/opengl3_example/main.cpp +++ b/examples/opengl3_example/main.cpp @@ -32,7 +32,9 @@ int main(int, char**) gl3wInit(); // Setup ImGui binding + ImGuiIO& io = ImGui::GetIO(); (void)io; ImGui_ImplGlfwGL3_Init(window, true); + //io.NavFlags |= ImGuiNavFlags_EnableKeyboard; // Setup style ImGui::StyleColorsClassic(); @@ -45,7 +47,6 @@ int main(int, char**) // - The fonts will be rasterized at a given size (w/ oversampling) and stored into a texture when calling ImFontAtlas::Build()/GetTexDataAsXXXX(), which ImGui_ImplXXXX_NewFrame below will call. // - Read 'extra_fonts/README.txt' for more instructions and details. // - Remember that in C/C++ if you want to include a backslash \ in a string literal you need to write a double backslash \\ ! - //ImGuiIO& io = ImGui::GetIO(); //io.Fonts->AddFontDefault(); //io.Fonts->AddFontFromFileTTF("../../extra_fonts/Roboto-Medium.ttf", 16.0f); //io.Fonts->AddFontFromFileTTF("../../extra_fonts/Cousine-Regular.ttf", 15.0f); From e9070e768ef99303ae72f0f3be3c10c8dc0e2d66 Mon Sep 17 00:00:00 2001 From: omar Date: Thu, 25 Jan 2018 16:17:36 +0100 Subject: [PATCH 518/823] Nav: Fixed renaming of c09016b12af8e4396c38f06a6cfee2c4e41a18b3 that were incorrect. ImGuiNavInput_PadLeft -> PadDpadLeft, _PadScrollLeft -> PadLStickLeft. (#787) --- imgui.cpp | 14 +++++++------- imgui.h | 16 ++++++++-------- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 0886e04f7cfe..c0ccf1f705f8 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2688,11 +2688,11 @@ ImVec2 ImGui::GetNavInputAmount2d(ImGuiNavDirSourceFlags dir_sources, ImGuiInput { ImVec2 delta(0.0f, 0.0f); if (dir_sources & ImGuiNavDirSourceFlags_Key) - delta += ImVec2(GetNavInputAmount(ImGuiNavInput_KeyRight, mode) - GetNavInputAmount(ImGuiNavInput_KeyLeft, mode), GetNavInputAmount(ImGuiNavInput_KeyDown, mode) - GetNavInputAmount(ImGuiNavInput_KeyUp, mode)); + delta += ImVec2(GetNavInputAmount(ImGuiNavInput_KeyRight, mode) - GetNavInputAmount(ImGuiNavInput_KeyLeft, mode), GetNavInputAmount(ImGuiNavInput_KeyDown, mode) - GetNavInputAmount(ImGuiNavInput_KeyUp, mode)); if (dir_sources & ImGuiNavDirSourceFlags_PadLStick) - delta += ImVec2(GetNavInputAmount(ImGuiNavInput_PadLStickRight, mode) - GetNavInputAmount(ImGuiNavInput_PadLStickLeft, mode), GetNavInputAmount(ImGuiNavInput_PadLStickDown, mode) - GetNavInputAmount(ImGuiNavInput_PadLStickUp, mode)); + delta += ImVec2(GetNavInputAmount(ImGuiNavInput_PadDpadRight, mode) - GetNavInputAmount(ImGuiNavInput_PadDpadLeft, mode), GetNavInputAmount(ImGuiNavInput_PadDpadDown, mode) - GetNavInputAmount(ImGuiNavInput_PadDpadUp, mode)); if (dir_sources & ImGuiNavDirSourceFlags_PadRStick) - delta += ImVec2(GetNavInputAmount(ImGuiNavInput_PadRStickRight, mode) - GetNavInputAmount(ImGuiNavInput_PadRStickLeft, mode), GetNavInputAmount(ImGuiNavInput_PadRStickDown, mode) - GetNavInputAmount(ImGuiNavInput_PadRStickUp, mode)); + delta += ImVec2(GetNavInputAmount(ImGuiNavInput_PadLStickRight, mode) - GetNavInputAmount(ImGuiNavInput_PadLStickLeft, mode), GetNavInputAmount(ImGuiNavInput_PadLStickDown, mode) - GetNavInputAmount(ImGuiNavInput_PadLStickUp, mode)); if (slow_factor != 0.0f && IsNavInputDown(ImGuiNavInput_PadTweakSlow)) delta *= slow_factor; if (fast_factor != 0.0f && IsNavInputDown(ImGuiNavInput_PadTweakFast)) @@ -2966,10 +2966,10 @@ static void ImGui::NavUpdate() g.NavMoveDir = ImGuiDir_None; if (g.NavWindow && !g.NavWindowingTarget && allowed_dir_flags && !(g.NavWindow->Flags & ImGuiWindowFlags_NoNavInputs)) { - if ((allowed_dir_flags & (1< Date: Thu, 25 Jan 2018 16:18:57 +0100 Subject: [PATCH 519/823] Nav: Examples: Glfw+GL3: Added basic gamepad mapping code when io.NavFlags & ImGuiNavFlags_EnableGamepad is set. (will iterate/tweak before spreading to other examples). (#787) --- .../opengl3_example/imgui_impl_glfw_gl3.cpp | 27 +++++++++++++++++++ examples/opengl3_example/main.cpp | 1 + 2 files changed, 28 insertions(+) diff --git a/examples/opengl3_example/imgui_impl_glfw_gl3.cpp b/examples/opengl3_example/imgui_impl_glfw_gl3.cpp index 196f64131eff..5e9f17876a5d 100644 --- a/examples/opengl3_example/imgui_impl_glfw_gl3.cpp +++ b/examples/opengl3_example/imgui_impl_glfw_gl3.cpp @@ -432,6 +432,33 @@ void ImGui_ImplGlfwGL3_NewFrame() MAP_KEY(ImGuiNavInput_PadTweakFast, GLFW_KEY_RIGHT_SHIFT); #undef MAP_KEY } + if (io.NavFlags & ImGuiNavFlags_EnableGamepad) + { + // Update gamepad inputs + #define MAP_BUTTON(NAV_NO, BUTTON_NO) { if (buttons_count > BUTTON_NO && buttons[BUTTON_NO] == GLFW_PRESS) io.NavInputs[NAV_NO] = 1.0f; } + #define MAP_ANALOG(NAV_NO, AXIS_NO, V0, V1) { float v = (axes_count > AXIS_NO) ? axes[AXIS_NO] : V0; v = (v - V0) / (V1 - V0); if (v > 1.0f) v = 1.0f; if (io.NavInputs[NAV_NO] < v) io.NavInputs[NAV_NO] = v; } + int axes_count = 0, buttons_count = 0; + const float* axes = glfwGetJoystickAxes(GLFW_JOYSTICK_1, &axes_count); + const unsigned char* buttons = glfwGetJoystickButtons(GLFW_JOYSTICK_1, &buttons_count); + MAP_BUTTON(ImGuiNavInput_PadActivate, 0); // Cross / A + MAP_BUTTON(ImGuiNavInput_PadCancel, 1); // Circle / B + MAP_BUTTON(ImGuiNavInput_PadMenu, 2); // Square / X + MAP_BUTTON(ImGuiNavInput_PadInput, 3); // Triangle / Y + MAP_BUTTON(ImGuiNavInput_PadDpadLeft, 13); // D-Pad Left + MAP_BUTTON(ImGuiNavInput_PadDpadRight, 11); // D-Pad Right + MAP_BUTTON(ImGuiNavInput_PadDpadUp, 10); // D-Pad Up + MAP_BUTTON(ImGuiNavInput_PadDpadDown, 12); // D-Pad Down + MAP_BUTTON(ImGuiNavInput_PadFocusPrev, 4); // L Trigger + MAP_BUTTON(ImGuiNavInput_PadFocusNext, 5); // R Trigger + MAP_BUTTON(ImGuiNavInput_PadTweakSlow, 4); // L Trigger + MAP_BUTTON(ImGuiNavInput_PadTweakFast, 5); // R Trigger + MAP_ANALOG(ImGuiNavInput_PadLStickLeft, 0, -0.3f, -0.9f); + MAP_ANALOG(ImGuiNavInput_PadLStickRight,0, +0.3f, +0.9f); + MAP_ANALOG(ImGuiNavInput_PadLStickUp, 1, +0.3f, +0.9f); + MAP_ANALOG(ImGuiNavInput_PadLStickDown, 1, -0.3f, -0.9f); + #undef MAP_BUTTON + #undef MAP_ANALOG + } // Start the frame. This call will update the io.WantCaptureMouse, io.WantCaptureKeyboard flag that you can use to dispatch inputs (or not) to your application. ImGui::NewFrame(); diff --git a/examples/opengl3_example/main.cpp b/examples/opengl3_example/main.cpp index 4b3073af55e8..7b5f1c5667a7 100644 --- a/examples/opengl3_example/main.cpp +++ b/examples/opengl3_example/main.cpp @@ -35,6 +35,7 @@ int main(int, char**) ImGuiIO& io = ImGui::GetIO(); (void)io; ImGui_ImplGlfwGL3_Init(window, true); //io.NavFlags |= ImGuiNavFlags_EnableKeyboard; + //io.NavFlags |= ImGuiNavFlags_EnableGamepad; // Setup style ImGui::StyleColorsClassic(); From ed088b00bec24ab89a41a8ec0d6cff50f50244d6 Mon Sep 17 00:00:00 2001 From: omar Date: Thu, 25 Jan 2018 18:50:30 +0100 Subject: [PATCH 520/823] Nav: Style: Improved display of windowing highlight (for focus selection via PadMenu or Ctrl+TAB). (#787, #707) --- imgui.cpp | 4 ++-- imgui_draw.cpp | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index c0ccf1f705f8..8d73ded980e2 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -5710,8 +5710,8 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) { ImRect bb = window->Rect(); bb.Expand(g.FontSize); - window->DrawList->AddRectFilled(bb.Min, bb.Max, GetColorU32(ImGuiCol_NavWindowingHighlight, g.NavWindowingDisplayAlpha), g.Style.WindowRounding); - window->DrawList->AddRect(bb.Min, bb.Max, GetColorU32(ImGuiCol_HeaderHovered, g.NavWindowingDisplayAlpha), g.Style.WindowRounding); + window->DrawList->AddRectFilled(bb.Min, bb.Max, GetColorU32(ImGuiCol_NavWindowingHighlight, g.NavWindowingDisplayAlpha * 0.25f), g.Style.WindowRounding); + window->DrawList->AddRect(bb.Min, bb.Max, GetColorU32(ImGuiCol_NavWindowingHighlight, g.NavWindowingDisplayAlpha), g.Style.WindowRounding, ~0, 3.0f); } // Draw window + handle manual resize diff --git a/imgui_draw.cpp b/imgui_draw.cpp index 1d21db4612d4..106ad586dbf1 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -176,7 +176,7 @@ void ImGui::StyleColorsClassic(ImGuiStyle* dst) colors[ImGuiCol_ModalWindowDarkening] = ImVec4(0.20f, 0.20f, 0.20f, 0.35f); colors[ImGuiCol_DragDropTarget] = ImVec4(1.00f, 1.00f, 0.00f, 0.90f); colors[ImGuiCol_NavHighlight] = colors[ImGuiCol_HeaderHovered]; - colors[ImGuiCol_NavWindowingHighlight] = ImVec4(1.00f, 1.00f, 1.00f, 0.12f); + colors[ImGuiCol_NavWindowingHighlight] = ImVec4(1.00f, 1.00f, 1.00f, 0.70f); } void ImGui::StyleColorsDark(ImGuiStyle* dst) @@ -228,7 +228,7 @@ void ImGui::StyleColorsDark(ImGuiStyle* dst) colors[ImGuiCol_ModalWindowDarkening] = ImVec4(0.80f, 0.80f, 0.80f, 0.35f); colors[ImGuiCol_DragDropTarget] = ImVec4(1.00f, 1.00f, 0.00f, 0.90f); colors[ImGuiCol_NavHighlight] = ImVec4(0.26f, 0.59f, 0.98f, 1.00f); - colors[ImGuiCol_NavWindowingHighlight] = ImVec4(1.00f, 1.00f, 1.00f, 0.12f); + colors[ImGuiCol_NavWindowingHighlight] = ImVec4(1.00f, 1.00f, 1.00f, 0.70f); } // Those light colors are better suited with a thicker font than the default one + FrameBorder @@ -283,7 +283,7 @@ void ImGui::StyleColorsLight(ImGuiStyle* dst) colors[ImGuiCol_ModalWindowDarkening] = ImVec4(0.20f, 0.20f, 0.20f, 0.35f); colors[ImGuiCol_DragDropTarget] = ImVec4(0.26f, 0.59f, 0.98f, 0.95f); colors[ImGuiCol_NavHighlight] = colors[ImGuiCol_HeaderHovered]; - colors[ImGuiCol_NavWindowingHighlight] = ImVec4(0.40f, 0.40f, 0.40f, 0.12f); + colors[ImGuiCol_NavWindowingHighlight] = ImVec4(0.70f, 0.70f, 0.70f, 0.70f); } //----------------------------------------------------------------------------- From f2d530040893d9ac91fcd629aa62285351f5c99d Mon Sep 17 00:00:00 2001 From: omar Date: Thu, 25 Jan 2018 19:03:47 +0100 Subject: [PATCH 521/823] Nav: Keyboard: Added CTRL+TAB (and CTRL+Shift+TAB) style window selection. (#787) --- TODO.txt | 1 - imgui.cpp | 117 +++++++++++++++++++++++++++++------------------ imgui.h | 4 +- imgui_internal.h | 7 ++- 4 files changed, 79 insertions(+), 50 deletions(-) diff --git a/TODO.txt b/TODO.txt index a9bc641e72b8..c21d68bb8fdf 100644 --- a/TODO.txt +++ b/TODO.txt @@ -237,7 +237,6 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i - focus: SetKeyboardFocusHere() on with >= 0 offset could be done on same frame (else latch and modulate on beginning of next frame) - focus: unable to use SetKeyboardFocusHere() on clipped widgets. (#787) - inputs: rework IO system to be able to pass actual ordered/timestamped events. use an event queue? (~#335, #71) - - inputs: allow to pass explicit double-clicks if that's the only thing the user's backend can get them. (e.g. for windows by the CS_DBLCLKS style). - inputs: support track pad style scrolling & slider edit. - misc: idle refresh: expose cursor blink animation timer for backend to be able to lower framerate. diff --git a/imgui.cpp b/imgui.cpp index 8d73ded980e2..9a58a65e471a 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2700,42 +2700,52 @@ ImVec2 ImGui::GetNavInputAmount2d(ImGuiNavDirSourceFlags dir_sources, ImGuiInput return delta; } +static void NavUpdateWindowingHighlightWindow(int focus_change_dir) +{ + ImGuiContext& g = *GImGui; + IM_ASSERT(g.NavWindowingTarget); + if (g.NavWindowingTarget->Flags & ImGuiWindowFlags_Modal) + return; + + const int i_current = FindWindowIndex(g.NavWindowingTarget); + ImGuiWindow* window_target = FindWindowNavigable(i_current + focus_change_dir, -INT_MAX, focus_change_dir); + if (!window_target) + window_target = FindWindowNavigable((focus_change_dir < 0) ? (g.Windows.Size - 1) : 0, i_current, focus_change_dir); + g.NavWindowingTarget = window_target; + g.NavWindowingToggleLayer = false; +} + // Window management mode (hold to: change focus/move/resize, tap to: toggle menu layer) static void ImGui::NavUpdateWindowing() { ImGuiContext& g = *GImGui; - bool toggle_layer = false; + ImGuiWindow* apply_focus_window = NULL; + bool apply_toggle_layer = false; - if (!g.NavWindowingTarget && IsNavInputPressed(ImGuiNavInput_PadMenu, ImGuiInputReadMode_Pressed)) - { - ImGuiWindow* window = g.NavWindow; - if (!window) - window = FindWindowNavigable(g.Windows.Size - 1, -1, -1); - if (window) + bool start_windowing_with_gamepad = !g.NavWindowingTarget && IsNavInputPressed(ImGuiNavInput_PadMenu, ImGuiInputReadMode_Pressed); + bool start_windowing_with_keyboard = !g.NavWindowingTarget && g.IO.KeyCtrl && IsKeyPressedMap(ImGuiKey_Tab) && (g.IO.NavFlags & ImGuiNavFlags_EnableKeyboard); + if (start_windowing_with_gamepad || start_windowing_with_keyboard) + if (ImGuiWindow* window = g.NavWindow ? g.NavWindow : FindWindowNavigable(g.Windows.Size - 1, -INT_MAX, -1)) { g.NavWindowingTarget = window->RootNonPopupWindow; - g.NavWindowingDisplayAlpha = 0.0f; - g.NavWindowingToggleLayer = true; + g.NavWindowingHighlightTimer = g.NavWindowingHighlightAlpha = 0.0f; + g.NavWindowingToggleLayer = start_windowing_with_keyboard ? false : true; + g.NavWindowingIsKeyboardMode = start_windowing_with_keyboard; } - } - if (g.NavWindowingTarget) + + // Gamepad update + g.NavWindowingHighlightTimer += g.IO.DeltaTime; + if (g.NavWindowingTarget && !g.NavWindowingIsKeyboardMode) { - // Visuals only appears after a brief time holding the button, so that a fast tap (to toggle NavLayer) doesn't add visual noise - const float pressed_duration = g.IO.NavInputsDownDuration[ImGuiNavInput_PadMenu]; - g.NavWindowingDisplayAlpha = ImMax(g.NavWindowingDisplayAlpha, ImSaturate((pressed_duration - 0.20f) / 0.05f)); - g.NavWindowingToggleLayer &= (g.NavWindowingDisplayAlpha < 1.0f); // Once button is held long enough we don't consider it a tag-to-toggle-layer press anymore. + // Highlight only appears after a brief time holding the button, so that a fast tap on PadMenu (to toggle NavLayer) doesn't add visual noise + g.NavWindowingHighlightAlpha = ImMax(g.NavWindowingHighlightAlpha, ImSaturate((g.NavWindowingHighlightTimer - 0.20f) / 0.05f)); // Select window to focus const int focus_change_dir = (int)IsNavInputPressed(ImGuiNavInput_PadFocusPrev, ImGuiInputReadMode_RepeatSlow) - (int)IsNavInputPressed(ImGuiNavInput_PadFocusNext, ImGuiInputReadMode_RepeatSlow); - if (focus_change_dir != 0 && !(g.NavWindowingTarget->Flags & ImGuiWindowFlags_Modal)) + if (focus_change_dir != 0) { - const int i_current = FindWindowIndex(g.NavWindowingTarget); - ImGuiWindow* window_target = FindWindowNavigable(i_current + focus_change_dir, -1, focus_change_dir); - if (!window_target) - window_target = FindWindowNavigable((focus_change_dir < 0) ? (g.Windows.Size - 1) : 0, i_current, focus_change_dir); - g.NavWindowingTarget = window_target; - g.NavWindowingToggleLayer = false; - g.NavWindowingDisplayAlpha = 1.0f; + NavUpdateWindowingHighlightWindow(focus_change_dir); + g.NavWindowingHighlightAlpha = 1.0f; } // Move window @@ -2751,34 +2761,51 @@ static void ImGui::NavUpdateWindowing() } } + // Single press toggles NavLayer, long press with L/R apply actual focus on release (until then the window was merely rendered front-most) if (!IsNavInputDown(ImGuiNavInput_PadMenu)) { - // Apply actual focus only when releasing the NavMenu button (until then the window was merely rendered front-most) - if (g.NavWindowingTarget && !g.NavWindowingToggleLayer && (!g.NavWindow || g.NavWindowingTarget != g.NavWindow->RootNonPopupWindow)) - { - FocusWindow(g.NavWindowingTarget); - g.NavDisableHighlight = false; - g.NavDisableMouseHover = true; - if (g.NavWindowingTarget->NavLastIds[0] == 0) - NavInitWindow(g.NavWindowingTarget, false); - - // If the window only has a menu layer, select it directly - if (g.NavWindowingTarget->DC.NavLayerActiveMask == 0x02) - g.NavLayer = 1; - } - - // Single press toggles NavLayer + g.NavWindowingToggleLayer &= (g.NavWindowingHighlightAlpha < 1.0f); // Once button was held long enough we don't consider it a tap-to-toggle-layer press anymore. if (g.NavWindowingToggleLayer && g.NavWindow) - toggle_layer = true; + apply_toggle_layer = true; + else if (!g.NavWindowingToggleLayer) + apply_focus_window = g.NavWindowingTarget; g.NavWindowingTarget = NULL; } } - - // Keyboard: Press and release ALT to toggle menu + + // Keyboard: Focus + if (g.NavWindowingTarget && g.NavWindowingIsKeyboardMode) + { + // Visuals only appears after a brief time after pressing TAB the first time, so that a fast CTRL+TAB doesn't add visual noise + g.NavWindowingHighlightAlpha = ImMax(g.NavWindowingHighlightAlpha, ImSaturate((g.NavWindowingHighlightTimer - 0.15f) / 0.04f)); // 1.0f + if (IsKeyPressedMap(ImGuiKey_Tab, true)) + NavUpdateWindowingHighlightWindow(g.IO.KeyShift ? +1 : -1); + if (!g.IO.KeyCtrl) + apply_focus_window = g.NavWindowingTarget; + } + + // Keyboard: Press and release ALT to toggle menu layer if ((g.ActiveId == 0 || g.ActiveIdAllowOverlap) && IsNavInputPressed(ImGuiNavInput_KeyMenu, ImGuiInputReadMode_Released)) - toggle_layer = true; + apply_toggle_layer = true; + + // Apply final focus + if (apply_focus_window && (g.NavWindow == NULL || apply_focus_window != g.NavWindow->RootNonPopupWindow)) + { + g.NavDisableHighlight = false; + g.NavDisableMouseHover = true; + FocusWindow(apply_focus_window); + if (apply_focus_window->NavLastIds[0] == 0) + NavInitWindow(apply_focus_window, false); + + // If the window only has a menu layer, select it directly + if (apply_focus_window->DC.NavLayerActiveMask == (1 << 1)) + g.NavLayer = 1; + } + if (apply_focus_window) + g.NavWindowingTarget = NULL; - if (toggle_layer && g.NavWindow) + // Apply menu/layer toggle + if (apply_toggle_layer && g.NavWindow) { if ((g.NavWindow->DC.NavLayerActiveMask & (1 << 1)) == 0 && (g.NavWindow->RootWindow->DC.NavLayerActiveMask & (1 << 1)) != 0) FocusWindow(g.NavWindow->RootWindow); @@ -5710,8 +5737,8 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) { ImRect bb = window->Rect(); bb.Expand(g.FontSize); - window->DrawList->AddRectFilled(bb.Min, bb.Max, GetColorU32(ImGuiCol_NavWindowingHighlight, g.NavWindowingDisplayAlpha * 0.25f), g.Style.WindowRounding); - window->DrawList->AddRect(bb.Min, bb.Max, GetColorU32(ImGuiCol_NavWindowingHighlight, g.NavWindowingDisplayAlpha), g.Style.WindowRounding, ~0, 3.0f); + window->DrawList->AddRectFilled(bb.Min, bb.Max, GetColorU32(ImGuiCol_NavWindowingHighlight, g.NavWindowingHighlightAlpha * 0.25f), g.Style.WindowRounding); + window->DrawList->AddRect(bb.Min, bb.Max, GetColorU32(ImGuiCol_NavWindowingHighlight, g.NavWindowingHighlightAlpha), g.Style.WindowRounding, ~0, 3.0f); } // Draw window + handle manual resize diff --git a/imgui.h b/imgui.h index 0f6b832db64a..9d3a5690939e 100644 --- a/imgui.h +++ b/imgui.h @@ -730,8 +730,8 @@ enum ImGuiNavInput_ // [BETA] Gamepad/Keyboard directional navigation options enum ImGuiNavFlags_ { - ImGuiNavFlags_EnableGamepad = 1 << 0, // Master gamepad navigation enable flag. This is to instruct your imgui binding whether to fill in gamepad navigation inputs. imgui itself won't use this flag. - ImGuiNavFlags_EnableKeyboard = 1 << 1, // Master keyboard navigation enable flag. This is to instruct your imgui binding whether to fill in keyboard navigation inputs. imgui itself won't use this flag. + ImGuiNavFlags_EnableGamepad = 1 << 0, // Master gamepad navigation enable flag. This is mostly to instruct your imgui binding whether to fill in gamepad navigation inputs. + ImGuiNavFlags_EnableKeyboard = 1 << 1, // Master keyboard navigation enable flag. This is mostly to instruct your imgui binding whether to fill in keyboard navigation inputs. ImGuiNavFlags_MoveMouse = 1 << 2 // Request navigation to allow move the mouse cursor. May be useful on TV/console systems where moving a virtual mouse is awkward. Will update io.MousePos and set io.WantMoveMouse=true. If enabled you MUST honor io.WantMoveMouse requests in your binding, otherwise ImGui will react as if the mouse is jumping around back and forth. }; diff --git a/imgui_internal.h b/imgui_internal.h index a3def3178353..2d5248e4f314 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -591,8 +591,10 @@ struct ImGuiContext ImGuiID NavJustMovedToId; // Just navigated to this id (result of a successfully MoveRequest) ImRect NavScoringRectScreen; // Rectangle used for scoring, in screen space. Based of window->DC.NavRefRectRel[], modified for directional navigation scoring. ImGuiWindow* NavWindowingTarget; // When selecting a window (holding Menu+FocusPrev/Next, or equivalent of CTRL-TAB) this window is temporarily displayed front-most. - float NavWindowingDisplayAlpha; + float NavWindowingHighlightTimer; + float NavWindowingHighlightAlpha; bool NavWindowingToggleLayer; + bool NavWindowingIsKeyboardMode; // Gamepad or keyboard mode int NavLayer; // Layer we are navigating on. For now the system is hard-coded for 0=main contents and 1=menu/title bar, may expose layers later. int NavIdTabCounter; // == NavWindow->DC.FocusIdxTabCounter at time of NavId processing bool NavIdIsAlive; // Nav widget has been seen this frame ~~ NavRefRectRel is valid @@ -710,8 +712,9 @@ struct ImGuiContext NavJustTabbedId = NavJustMovedToId = NavNextActivateId = 0; NavScoringRectScreen = ImRect(); NavWindowingTarget = NULL; - NavWindowingDisplayAlpha = 0.0f; + NavWindowingHighlightTimer = NavWindowingHighlightAlpha = 0.0f; NavWindowingToggleLayer = false; + NavWindowingIsKeyboardMode = false; NavLayer = 0; NavIdTabCounter = INT_MAX; NavIdIsAlive = false; From 486f0a8ba0eda020d912b2058f13c30e74a77aa2 Mon Sep 17 00:00:00 2001 From: omar Date: Thu, 25 Jan 2018 19:07:35 +0100 Subject: [PATCH 522/823] Fixed potential warning (forward declaration and definition didn't match signature. forward declaration only here for consistency) --- imgui.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 076eb4b5c2aa..c8944d68317d 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2838,9 +2838,9 @@ static int ChildWindowComparer(const void* lhs, const void* rhs) return (a->BeginOrderWithinParent - b->BeginOrderWithinParent); } -static void AddWindowToSortedBuffer(ImVector& out_sorted_windows, ImGuiWindow* window) +static void AddWindowToSortedBuffer(ImVector* out_sorted_windows, ImGuiWindow* window) { - out_sorted_windows.push_back(window); + out_sorted_windows->push_back(window); if (window->Active) { int count = window->DC.ChildWindows.Size; @@ -3031,7 +3031,7 @@ void ImGui::EndFrame() ImGuiWindow* window = g.Windows[i]; if (window->Active && (window->Flags & ImGuiWindowFlags_ChildWindow)) // if a child is active its parent will add it continue; - AddWindowToSortedBuffer(g.WindowsSortBuffer, window); + AddWindowToSortedBuffer(&g.WindowsSortBuffer, window); } IM_ASSERT(g.Windows.Size == g.WindowsSortBuffer.Size); // we done something wrong From d088bd86adf9eb8816a9ce1ca6e3cc1909de3a9b Mon Sep 17 00:00:00 2001 From: omar Date: Thu, 25 Jan 2018 19:23:13 +0100 Subject: [PATCH 523/823] Nav: Added keyboard moving and resizing via the CTRL-TAB windowing mode. (#787) --- imgui.cpp | 52 +++++++++++++++++++++++++++++----------------------- 1 file changed, 29 insertions(+), 23 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 9a58a65e471a..d47e585d84a5 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -27,7 +27,7 @@ - ISSUES & TODO LIST - FREQUENTLY ASKED QUESTIONS (FAQ), TIPS - How can I help? - - How can I dipslay an image? What is ImTextureID, how does it works? + - How can I display an image? What is ImTextureID, how does it works? - How can I have multiple widgets with the same label? Can I have widget without a label? (Yes). A primer on labels and the ID stack. - How can I tell when Dear ImGui wants my mouse/keyboard inputs VS when I can pass them to my application? - How can I load a different font than the default? @@ -2748,19 +2748,6 @@ static void ImGui::NavUpdateWindowing() g.NavWindowingHighlightAlpha = 1.0f; } - // Move window - if (g.NavWindowingTarget && !(g.NavWindowingTarget->Flags & ImGuiWindowFlags_NoMove)) - { - const ImVec2 move_delta = GetNavInputAmount2d(ImGuiNavDirSourceFlags_PadRStick, ImGuiInputReadMode_Down); - if (move_delta.x != 0.0f || move_delta.y != 0.0f) - { - const float move_speed = ImFloor(600 * g.IO.DeltaTime * ImMin(g.IO.DisplayFramebufferScale.x, g.IO.DisplayFramebufferScale.y)); - g.NavWindowingTarget->PosFloat += move_delta * move_speed; - g.NavDisableMouseHover = true; - MarkIniSettingsDirty(g.NavWindowingTarget); - } - } - // Single press toggles NavLayer, long press with L/R apply actual focus on release (until then the window was merely rendered front-most) if (!IsNavInputDown(ImGuiNavInput_PadMenu)) { @@ -2788,6 +2775,24 @@ static void ImGui::NavUpdateWindowing() if ((g.ActiveId == 0 || g.ActiveIdAllowOverlap) && IsNavInputPressed(ImGuiNavInput_KeyMenu, ImGuiInputReadMode_Released)) apply_toggle_layer = true; + // Move window + if (g.NavWindowingTarget && !(g.NavWindowingTarget->Flags & ImGuiWindowFlags_NoMove)) + { + ImVec2 move_delta; + if (g.NavWindowingIsKeyboardMode && !g.IO.KeyShift) + move_delta = GetNavInputAmount2d(ImGuiNavDirSourceFlags_Key, ImGuiInputReadMode_Down); + if (!g.NavWindowingIsKeyboardMode) + move_delta = GetNavInputAmount2d(ImGuiNavDirSourceFlags_PadRStick, ImGuiInputReadMode_Down); + if (move_delta.x != 0.0f || move_delta.y != 0.0f) + { + const float NAV_MOVE_SPEED = 800.0f; + const float move_speed = ImFloor(NAV_MOVE_SPEED * g.IO.DeltaTime * ImMin(g.IO.DisplayFramebufferScale.x, g.IO.DisplayFramebufferScale.y)); + g.NavWindowingTarget->PosFloat += move_delta * move_speed; + g.NavDisableMouseHover = true; + MarkIniSettingsDirty(g.NavWindowingTarget); + } + } + // Apply final focus if (apply_focus_window && (g.NavWindow == NULL || apply_focus_window != g.NavWindow->RootNonPopupWindow)) { @@ -5351,19 +5356,20 @@ static void ImGui::UpdateManualResize(ImGuiWindow* window, const ImVec2& size_au // Navigation/gamepad resize if (g.NavWindowingTarget == window) { - ImVec2 nav_resize_delta = GetNavInputAmount2d(ImGuiNavDirSourceFlags_PadLStick, ImGuiInputReadMode_Down); + ImVec2 nav_resize_delta; + if (g.NavWindowingIsKeyboardMode && g.IO.KeyShift) + nav_resize_delta = GetNavInputAmount2d(ImGuiNavDirSourceFlags_Key, ImGuiInputReadMode_Down); + if (!g.NavWindowingIsKeyboardMode) + nav_resize_delta = GetNavInputAmount2d(ImGuiNavDirSourceFlags_PadLStick, ImGuiInputReadMode_Down); if (nav_resize_delta.x != 0.0f || nav_resize_delta.y != 0.0f) { - const float GAMEPAD_RESIZE_SPEED = 600.0f; - nav_resize_delta *= ImFloor(GAMEPAD_RESIZE_SPEED * g.IO.DeltaTime * ImMin(g.IO.DisplayFramebufferScale.x, g.IO.DisplayFramebufferScale.y)); + const float NAV_RESIZE_SPEED = 600.0f; + nav_resize_delta *= ImFloor(NAV_RESIZE_SPEED * g.IO.DeltaTime * ImMin(g.IO.DisplayFramebufferScale.x, g.IO.DisplayFramebufferScale.y)); + g.NavWindowingToggleLayer = false; g.NavDisableMouseHover = true; resize_grip_col[0] = GetColorU32(ImGuiCol_ResizeGripActive); - if (nav_resize_delta.x != 0.0f || nav_resize_delta.y != 0.0f) - { - // FIXME-NAV: Should store and accumulate into a separate size buffer to handle sizing constraints properly, right now a constraint will make us stuck. - g.NavWindowingToggleLayer = false; - size_target = CalcSizeAfterConstraint(window, window->SizeFull + nav_resize_delta); - } + // FIXME-NAV: Should store and accumulate into a separate size buffer to handle sizing constraints properly, right now a constraint will make us stuck. + size_target = CalcSizeAfterConstraint(window, window->SizeFull + nav_resize_delta); } } From 04d5783ffd7a445ae2f08dca9c31d698a63c7400 Mon Sep 17 00:00:00 2001 From: omar Date: Thu, 25 Jan 2018 19:34:08 +0100 Subject: [PATCH 524/823] Nav: Cleaning up + using ImGuiInputSource source enum instead of a silly bool. (#787) --- imgui.cpp | 36 ++++++++++++++++++------------------ imgui_internal.h | 12 +++++++----- 2 files changed, 25 insertions(+), 23 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index d47e585d84a5..0301541f8020 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2687,11 +2687,11 @@ static bool IsNavInputPressedAnyOfTwo(ImGuiNavInput n1, ImGuiNavInput n2, ImGuiI ImVec2 ImGui::GetNavInputAmount2d(ImGuiNavDirSourceFlags dir_sources, ImGuiInputReadMode mode, float slow_factor, float fast_factor) { ImVec2 delta(0.0f, 0.0f); - if (dir_sources & ImGuiNavDirSourceFlags_Key) + if (dir_sources & ImGuiNavDirSourceFlags_Keyboard) delta += ImVec2(GetNavInputAmount(ImGuiNavInput_KeyRight, mode) - GetNavInputAmount(ImGuiNavInput_KeyLeft, mode), GetNavInputAmount(ImGuiNavInput_KeyDown, mode) - GetNavInputAmount(ImGuiNavInput_KeyUp, mode)); - if (dir_sources & ImGuiNavDirSourceFlags_PadLStick) + if (dir_sources & ImGuiNavDirSourceFlags_PadDPad) delta += ImVec2(GetNavInputAmount(ImGuiNavInput_PadDpadRight, mode) - GetNavInputAmount(ImGuiNavInput_PadDpadLeft, mode), GetNavInputAmount(ImGuiNavInput_PadDpadDown, mode) - GetNavInputAmount(ImGuiNavInput_PadDpadUp, mode)); - if (dir_sources & ImGuiNavDirSourceFlags_PadRStick) + if (dir_sources & ImGuiNavDirSourceFlags_PadLStick) delta += ImVec2(GetNavInputAmount(ImGuiNavInput_PadLStickRight, mode) - GetNavInputAmount(ImGuiNavInput_PadLStickLeft, mode), GetNavInputAmount(ImGuiNavInput_PadLStickDown, mode) - GetNavInputAmount(ImGuiNavInput_PadLStickUp, mode)); if (slow_factor != 0.0f && IsNavInputDown(ImGuiNavInput_PadTweakSlow)) delta *= slow_factor; @@ -2730,12 +2730,12 @@ static void ImGui::NavUpdateWindowing() g.NavWindowingTarget = window->RootNonPopupWindow; g.NavWindowingHighlightTimer = g.NavWindowingHighlightAlpha = 0.0f; g.NavWindowingToggleLayer = start_windowing_with_keyboard ? false : true; - g.NavWindowingIsKeyboardMode = start_windowing_with_keyboard; + g.NavWindowingInputSource = start_windowing_with_keyboard ? ImGuiInputSource_NavKeyboard : ImGuiInputSource_NavGamepad; } // Gamepad update g.NavWindowingHighlightTimer += g.IO.DeltaTime; - if (g.NavWindowingTarget && !g.NavWindowingIsKeyboardMode) + if (g.NavWindowingTarget && g.NavWindowingInputSource == ImGuiInputSource_NavGamepad) { // Highlight only appears after a brief time holding the button, so that a fast tap on PadMenu (to toggle NavLayer) doesn't add visual noise g.NavWindowingHighlightAlpha = ImMax(g.NavWindowingHighlightAlpha, ImSaturate((g.NavWindowingHighlightTimer - 0.20f) / 0.05f)); @@ -2761,7 +2761,7 @@ static void ImGui::NavUpdateWindowing() } // Keyboard: Focus - if (g.NavWindowingTarget && g.NavWindowingIsKeyboardMode) + if (g.NavWindowingTarget && g.NavWindowingInputSource == ImGuiInputSource_NavKeyboard) { // Visuals only appears after a brief time after pressing TAB the first time, so that a fast CTRL+TAB doesn't add visual noise g.NavWindowingHighlightAlpha = ImMax(g.NavWindowingHighlightAlpha, ImSaturate((g.NavWindowingHighlightTimer - 0.15f) / 0.04f)); // 1.0f @@ -2779,10 +2779,10 @@ static void ImGui::NavUpdateWindowing() if (g.NavWindowingTarget && !(g.NavWindowingTarget->Flags & ImGuiWindowFlags_NoMove)) { ImVec2 move_delta; - if (g.NavWindowingIsKeyboardMode && !g.IO.KeyShift) - move_delta = GetNavInputAmount2d(ImGuiNavDirSourceFlags_Key, ImGuiInputReadMode_Down); - if (!g.NavWindowingIsKeyboardMode) - move_delta = GetNavInputAmount2d(ImGuiNavDirSourceFlags_PadRStick, ImGuiInputReadMode_Down); + if (g.NavWindowingInputSource == ImGuiInputSource_NavKeyboard && !g.IO.KeyShift) + move_delta = GetNavInputAmount2d(ImGuiNavDirSourceFlags_Keyboard, ImGuiInputReadMode_Down); + if (g.NavWindowingInputSource == ImGuiInputSource_NavGamepad) + move_delta = GetNavInputAmount2d(ImGuiNavDirSourceFlags_PadLStick, ImGuiInputReadMode_Down); if (move_delta.x != 0.0f || move_delta.y != 0.0f) { const float NAV_MOVE_SPEED = 800.0f; @@ -3043,7 +3043,7 @@ static void ImGui::NavUpdate() // *Normal* Manual scroll with NavScrollXXX keys // Next movement request will clamp the NavId reference rectangle to the visible area, so navigation will resume within those bounds. - ImVec2 scroll_dir = GetNavInputAmount2d(ImGuiNavDirSourceFlags_PadRStick, ImGuiInputReadMode_Down, 1.0f/10.0f, 10.0f); + ImVec2 scroll_dir = GetNavInputAmount2d(ImGuiNavDirSourceFlags_PadLStick, ImGuiInputReadMode_Down, 1.0f/10.0f, 10.0f); if (scroll_dir.x != 0.0f && window->ScrollbarX) { SetWindowScrollX(window, ImFloor(window->Scroll.x + scroll_dir.x * scroll_speed)); @@ -5357,10 +5357,10 @@ static void ImGui::UpdateManualResize(ImGuiWindow* window, const ImVec2& size_au if (g.NavWindowingTarget == window) { ImVec2 nav_resize_delta; - if (g.NavWindowingIsKeyboardMode && g.IO.KeyShift) - nav_resize_delta = GetNavInputAmount2d(ImGuiNavDirSourceFlags_Key, ImGuiInputReadMode_Down); - if (!g.NavWindowingIsKeyboardMode) - nav_resize_delta = GetNavInputAmount2d(ImGuiNavDirSourceFlags_PadLStick, ImGuiInputReadMode_Down); + if (g.NavWindowingInputSource == ImGuiInputSource_NavKeyboard && g.IO.KeyShift) + nav_resize_delta = GetNavInputAmount2d(ImGuiNavDirSourceFlags_Keyboard, ImGuiInputReadMode_Down); + if (g.NavWindowingInputSource == ImGuiInputSource_NavGamepad) + nav_resize_delta = GetNavInputAmount2d(ImGuiNavDirSourceFlags_PadDPad, ImGuiInputReadMode_Down); if (nav_resize_delta.x != 0.0f || nav_resize_delta.y != 0.0f) { const float NAV_RESIZE_SPEED = 600.0f; @@ -8401,7 +8401,7 @@ bool ImGui::SliderBehavior(const ImRect& frame_bb, ImGuiID id, float* v, float v } else if (g.ActiveIdSource == ImGuiInputSource_Nav && g.NavActivateDownId == id) { - const ImVec2 delta2 = GetNavInputAmount2d(ImGuiNavDirSourceFlags_Key|ImGuiNavDirSourceFlags_PadLStick, ImGuiInputReadMode_RepeatFast, 0.0f, 0.0f); + const ImVec2 delta2 = GetNavInputAmount2d(ImGuiNavDirSourceFlags_Keyboard|ImGuiNavDirSourceFlags_PadDPad, ImGuiInputReadMode_RepeatFast, 0.0f, 0.0f); float delta = is_horizontal ? delta2.x : -delta2.y; if (delta != 0.0f) { @@ -8748,7 +8748,7 @@ bool ImGui::DragBehavior(const ImRect& frame_bb, ImGuiID id, float* v, float v_s } if (g.ActiveIdSource == ImGuiInputSource_Nav) { - adjust_delta = GetNavInputAmount2d(ImGuiNavDirSourceFlags_Key|ImGuiNavDirSourceFlags_PadLStick, ImGuiInputReadMode_RepeatFast, 1.0f/10.0f, 10.0f).x; + adjust_delta = GetNavInputAmount2d(ImGuiNavDirSourceFlags_Keyboard|ImGuiNavDirSourceFlags_PadDPad, ImGuiInputReadMode_RepeatFast, 1.0f/10.0f, 10.0f).x; v_speed = ImMax(v_speed, GetMinimumStepAtDecimalPrecision(decimal_precision)); } adjust_delta *= v_speed; @@ -12981,7 +12981,7 @@ void ImGui::ShowMetricsWindow(bool* p_open) } if (ImGui::TreeNode("Basic state")) { - const char* input_source_names[] = { "None", "Mouse", "Nav" }; IM_ASSERT(IM_ARRAYSIZE(input_source_names) == ImGuiInputSource_Count_); + const char* input_source_names[] = { "None", "Mouse", "Nav", "NavGamepad", "NavKeyboard" }; IM_ASSERT(IM_ARRAYSIZE(input_source_names) == ImGuiInputSource_Count_); ImGui::Text("HoveredWindow: '%s'", g.HoveredWindow ? g.HoveredWindow->Name : "NULL"); ImGui::Text("HoveredRootWindow: '%s'", g.HoveredRootWindow ? g.HoveredRootWindow->Name : "NULL"); ImGui::Text("HoveredId: 0x%08X/0x%08X (%.2f sec)", g.HoveredId, g.HoveredIdPreviousFrame, g.HoveredIdTimer); // Data is "in-flight" so depending on when the Metrics window is called we may see current frame information or not diff --git a/imgui_internal.h b/imgui_internal.h index 2d5248e4f314..3b1923d17912 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -252,6 +252,8 @@ enum ImGuiInputSource ImGuiInputSource_None = 0, ImGuiInputSource_Mouse, ImGuiInputSource_Nav, + ImGuiInputSource_NavKeyboard, // Only used occasionally for storage, not tested/handled by most code + ImGuiInputSource_NavGamepad, // " ImGuiInputSource_Count_, }; @@ -285,9 +287,9 @@ enum ImGuiNavHighlightFlags_ enum ImGuiNavDirSourceFlags_ { - ImGuiNavDirSourceFlags_Key = 1 << 0, - ImGuiNavDirSourceFlags_PadLStick = 1 << 1, - ImGuiNavDirSourceFlags_PadRStick = 1 << 2 + ImGuiNavDirSourceFlags_Keyboard = 1 << 0, + ImGuiNavDirSourceFlags_PadDPad = 1 << 1, + ImGuiNavDirSourceFlags_PadLStick = 1 << 2 }; // 2D axis aligned bounding-box @@ -594,7 +596,7 @@ struct ImGuiContext float NavWindowingHighlightTimer; float NavWindowingHighlightAlpha; bool NavWindowingToggleLayer; - bool NavWindowingIsKeyboardMode; // Gamepad or keyboard mode + ImGuiInputSource NavWindowingInputSource; // Gamepad or keyboard mode int NavLayer; // Layer we are navigating on. For now the system is hard-coded for 0=main contents and 1=menu/title bar, may expose layers later. int NavIdTabCounter; // == NavWindow->DC.FocusIdxTabCounter at time of NavId processing bool NavIdIsAlive; // Nav widget has been seen this frame ~~ NavRefRectRel is valid @@ -714,7 +716,7 @@ struct ImGuiContext NavWindowingTarget = NULL; NavWindowingHighlightTimer = NavWindowingHighlightAlpha = 0.0f; NavWindowingToggleLayer = false; - NavWindowingIsKeyboardMode = false; + NavWindowingInputSource = ImGuiInputSource_None; NavLayer = 0; NavIdTabCounter = INT_MAX; NavIdIsAlive = false; From 10a4a77b27d598bf10fb617e4180488eaf0adc2a Mon Sep 17 00:00:00 2001 From: omar Date: Thu, 25 Jan 2018 20:39:34 +0100 Subject: [PATCH 525/823] Nav: Drag, Slider: When already past a limit and pushing in the direction of the limit, we don't clamp values again. (#787) --- imgui.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 0301541f8020..a5f4dee66cc0 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2939,7 +2939,7 @@ static void ImGui::NavUpdate() ImGuiWindow* parent_window = g.NavWindow->ParentWindow; FocusWindow(parent_window); IM_ASSERT(child_window->ChildId != 0); - SetNavID(child_window->ChildId, g.NavLayer); // FIXME-NAV: Layer not necessarily correct + SetNavID(child_window->ChildId, 0); g.NavIdIsAlive = false; if (g.NavDisableMouseHover) g.NavMousePosDirty = true; @@ -8421,8 +8421,10 @@ bool ImGui::SliderBehavior(const ImRect& frame_bb, ImGuiID id, float* v, float v } if (IsNavInputDown(ImGuiNavInput_PadTweakFast)) delta *= 10.0f; - clicked_t = ImSaturate(clicked_t + delta); // FIXME-NAV: todo: cancel adjustment if current value already past edge and we are moving in edge direction, to avoid clamping value to edge. + clicked_t = ImSaturate(clicked_t + delta); set_new_value = true; + if ((clicked_t >= 1.0f && delta > 0.0f) || (clicked_t <= 0.0f && delta < 0.0f)) // This is to avoid applying the saturation when already past the limits + set_new_value = false; } } else @@ -8749,6 +8751,8 @@ bool ImGui::DragBehavior(const ImRect& frame_bb, ImGuiID id, float* v, float v_s if (g.ActiveIdSource == ImGuiInputSource_Nav) { adjust_delta = GetNavInputAmount2d(ImGuiNavDirSourceFlags_Keyboard|ImGuiNavDirSourceFlags_PadDPad, ImGuiInputReadMode_RepeatFast, 1.0f/10.0f, 10.0f).x; + if (v_min < v_max && ((v_cur >= v_max && adjust_delta > 0.0f) || (v_cur <= v_min && adjust_delta < 0.0f))) // This is to avoid applying the saturation when already past the limits + adjust_delta = 0.0f; v_speed = ImMax(v_speed, GetMinimumStepAtDecimalPrecision(decimal_precision)); } adjust_delta *= v_speed; From 1f3b66b10a96beca79603400bd9b80b0ae40c13c Mon Sep 17 00:00:00 2001 From: omar Date: Fri, 26 Jan 2018 11:38:25 +0100 Subject: [PATCH 526/823] Scrollbar: Fix ScrollbarX enable test subtracting WindowPadding.x. This has been here since 65a191c0050ca2a8360a25ca23403843cd3bdba2 (#246) tho at the time it is possible that SizeContents wasn't calculated as evenly. Test: auto-resize with: ImGui::Begin("Test", NULL, ImGuiWindowFlags_HorizontalScrollbar); ImGui::Button("##xxx", ImVec2(500,500)); ImGui::End(); --- imgui.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/imgui.cpp b/imgui.cpp index c8944d68317d..c14bcdbaed47 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -4670,7 +4670,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) float size_x_for_scrollbars = size_full_modified.x != FLT_MAX ? window->SizeFull.x : window->SizeFullAtLastBegin.x; float size_y_for_scrollbars = size_full_modified.y != FLT_MAX ? window->SizeFull.y : window->SizeFullAtLastBegin.y; window->ScrollbarY = (flags & ImGuiWindowFlags_AlwaysVerticalScrollbar) || ((window->SizeContents.y > size_y_for_scrollbars) && !(flags & ImGuiWindowFlags_NoScrollbar)); - window->ScrollbarX = (flags & ImGuiWindowFlags_AlwaysHorizontalScrollbar) || ((window->SizeContents.x > size_x_for_scrollbars - (window->ScrollbarY ? style.ScrollbarSize : 0.0f) - window->WindowPadding.x) && !(flags & ImGuiWindowFlags_NoScrollbar) && (flags & ImGuiWindowFlags_HorizontalScrollbar)); + window->ScrollbarX = (flags & ImGuiWindowFlags_AlwaysHorizontalScrollbar) || ((window->SizeContents.x > size_x_for_scrollbars - (window->ScrollbarY ? style.ScrollbarSize : 0.0f)) && !(flags & ImGuiWindowFlags_NoScrollbar) && (flags & ImGuiWindowFlags_HorizontalScrollbar)); if (window->ScrollbarX && !window->ScrollbarY) window->ScrollbarY = (window->SizeContents.y > size_y_for_scrollbars + style.ScrollbarSize) && !(flags & ImGuiWindowFlags_NoScrollbar); window->ScrollbarSizes = ImVec2(window->ScrollbarY ? style.ScrollbarSize : 0.0f, window->ScrollbarX ? style.ScrollbarSize : 0.0f); From 2d9d7a10caa6d043e880ff9041152fcd44cd6c92 Mon Sep 17 00:00:00 2001 From: omar Date: Fri, 26 Jan 2018 11:42:18 +0100 Subject: [PATCH 527/823] Scrollbar: Fix for ScrollbarY enable check after ScrollbarX has been enabled. (#1574) Looks like a bug introduced in c36e586cce1279b419ab4b443ca6ce63b03ce7cc. --- imgui.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/imgui.cpp b/imgui.cpp index c14bcdbaed47..8a08918bc550 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -4672,7 +4672,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) window->ScrollbarY = (flags & ImGuiWindowFlags_AlwaysVerticalScrollbar) || ((window->SizeContents.y > size_y_for_scrollbars) && !(flags & ImGuiWindowFlags_NoScrollbar)); window->ScrollbarX = (flags & ImGuiWindowFlags_AlwaysHorizontalScrollbar) || ((window->SizeContents.x > size_x_for_scrollbars - (window->ScrollbarY ? style.ScrollbarSize : 0.0f)) && !(flags & ImGuiWindowFlags_NoScrollbar) && (flags & ImGuiWindowFlags_HorizontalScrollbar)); if (window->ScrollbarX && !window->ScrollbarY) - window->ScrollbarY = (window->SizeContents.y > size_y_for_scrollbars + style.ScrollbarSize) && !(flags & ImGuiWindowFlags_NoScrollbar); + window->ScrollbarY = (window->SizeContents.y > size_y_for_scrollbars - style.ScrollbarSize) && !(flags & ImGuiWindowFlags_NoScrollbar); window->ScrollbarSizes = ImVec2(window->ScrollbarY ? style.ScrollbarSize : 0.0f, window->ScrollbarX ? style.ScrollbarSize : 0.0f); } From 578016d08bd2f650902064b5b5c599086b9ff5fe Mon Sep 17 00:00:00 2001 From: omar Date: Sat, 27 Jan 2018 17:26:25 +0100 Subject: [PATCH 528/823] ImVector comment (#1577) --- imgui.h | 1 + 1 file changed, 1 insertion(+) diff --git a/imgui.h b/imgui.h index a0453eeac7e5..56725bc07225 100644 --- a/imgui.h +++ b/imgui.h @@ -1073,6 +1073,7 @@ class ImVector Capacity = new_capacity; } + // NB: &v cannot be pointing inside the ImVector Data itself! e.g. v.push_back(v[10]) is forbidden. 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 void push_front(const value_type& v) { if (Size == 0) push_back(v); else insert(Data, v); } From 3571ab8b8837eb7e3178bbe0caf851a3f73d466b Mon Sep 17 00:00:00 2001 From: omar Date: Sun, 28 Jan 2018 17:21:07 +0100 Subject: [PATCH 529/823] imconfig.h comments --- imconfig.h | 27 +++++++++++++-------------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/imconfig.h b/imconfig.h index 824a81afeb03..90e127a98d6c 100644 --- a/imconfig.h +++ b/imconfig.h @@ -13,30 +13,31 @@ //#define IMGUI_API __declspec( dllexport ) //#define IMGUI_API __declspec( dllimport ) -//---- Don't define obsolete functions names. Consider enabling from time to time or when updating to reduce like hood of using already obsolete function/names +//---- Don't define obsolete functions names. Consider enabling from time to time or when updating to reduce likelihood of using already obsolete function/names //#define IMGUI_DISABLE_OBSOLETE_FUNCTIONS -//---- Include imgui_user.h at the end of imgui.h -//#define IMGUI_INCLUDE_IMGUI_USER_H - -//---- Don't implement default handlers for Windows (so as not to link with OpenClipboard() and others Win32 functions) -//#define IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCTIONS -//#define IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS +//---- Don't implement default handlers for Windows (so as not to link with certain functions) +//#define IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCTIONS // Don't use and link with OpenClipboard/GetClipboardData/CloseClipboard etc. +//#define IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS // Don't use and link with ImmGetContext/ImmSetCompositionWindow. //---- Don't implement demo windows functionality (ShowDemoWindow()/ShowStyleEditor()/ShowUserGuide() methods will be empty) -//---- It is very strongly recommended to NOT disable the demo windows. Please read the comment at the top of imgui_demo.cpp to learn why. +//---- It is very strongly recommended to NOT disable the demo windows. Please read the comment at the top of imgui_demo.cpp. //#define IMGUI_DISABLE_DEMO_WINDOWS //---- Don't implement ImFormatString(), ImFormatStringV() so you can reimplement them yourself. //#define IMGUI_DISABLE_FORMAT_STRING_FUNCTIONS -//---- Pack colors to BGRA instead of RGBA (remove need to post process vertex buffer in back ends) +//---- Include imgui_user.h at the end of imgui.h as a convenience +//#define IMGUI_INCLUDE_IMGUI_USER_H + +//---- Pack colors to BGRA8 instead of RGBA8 (if you needed to convert from one to another anyway) //#define IMGUI_USE_BGRA_PACKED_COLOR -//---- Implement STB libraries in a namespace to avoid linkage conflicts +//---- Implement STB libraries in a namespace to avoid linkage conflicts (defaults to global namespace) //#define IMGUI_STB_NAMESPACE ImGuiStb //---- Define constructor and implicit cast operators to convert back<>forth from your math types and ImVec2/ImVec4. +// This will be inlined as part of ImVec2 and ImVec4 class declarations. /* #define IM_VEC2_CLASS_EXTRA \ ImVec2(const MyVec2& f) { x = f.x; y = f.y; } \ @@ -47,15 +48,13 @@ operator MyVec4() const { return MyVec4(x,y,z,w); } */ -//---- Use 32-bit vertex indices (instead of default: 16-bit) to allow meshes with more than 64K vertices +//---- Use 32-bit vertex indices (instead of default 16-bit) to allow meshes with more than 64K vertices. Render function needs to support it. //#define ImDrawIdx unsigned int //---- Tip: You can add extra functions within the ImGui:: namespace, here or in your own headers files. -//---- e.g. create variants of the ImGui::Value() helper for your low-level math types, or your own widgets/helpers. /* namespace ImGui { - void Value(const char* prefix, const MyMatrix44& v, const char* float_format = NULL); + void MyFunction(const char* name, const MyMatrix44& v); } */ - From 94090eb08f8b9308be02617893c06dda9a02329d Mon Sep 17 00:00:00 2001 From: omar Date: Sun, 28 Jan 2018 17:47:28 +0100 Subject: [PATCH 530/823] Added IMGUI_USER_CONFIG to define a custom configuration filename. (#255, #1573, #1144, #41) --- imconfig.h | 9 ++++++--- imgui.h | 7 ++++++- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/imconfig.h b/imconfig.h index 90e127a98d6c..afa54914c751 100644 --- a/imconfig.h +++ b/imconfig.h @@ -1,7 +1,10 @@ //----------------------------------------------------------------------------- -// USER IMPLEMENTATION -// This file contains compile-time options for ImGui. -// Other options (memory allocation overrides, callbacks, etc.) can be set at runtime via the ImGuiIO structure - ImGui::GetIO(). +// COMPILE-TIME OPTIONS FOR DEAR IMGUI +// Most options (memory allocation, clipboard callbacks, etc.) can be set at runtime via the ImGuiIO structure - ImGui::GetIO(). +//----------------------------------------------------------------------------- +// A) You may edit imconfig.h (and not overwrite it when updating imgui, or maintain a patch/branch with your modifications to imconfig.h) +// B) or add configuration directives in your own file and compile with #define IMGUI_USER_CONFIG "myfilename.h" +// Note that options such as IMGUI_API, IM_VEC2_CLASS_EXTRA or ImDrawIdx needs to be defined consistently everywhere you include imgui.h, not only for the imgui*.cpp compilation units. //----------------------------------------------------------------------------- #pragma once diff --git a/imgui.h b/imgui.h index 56725bc07225..40b95149161b 100644 --- a/imgui.h +++ b/imgui.h @@ -8,9 +8,14 @@ #pragma once +// User-editable configuration files (edit stock imconfig.h or define IMGUI_USER_CONFIG to your own filename) +#ifdef IMGUI_USER_CONFIG +#include IMGUI_USER_CONFIG +#endif #if !defined(IMGUI_DISABLE_INCLUDE_IMCONFIG_H) || defined(IMGUI_INCLUDE_IMCONFIG_H) -#include "imconfig.h" // User-editable configuration file +#include "imconfig.h" #endif + #include // FLT_MAX #include // va_list #include // ptrdiff_t, NULL From 66d5712a8a60493b55eaf2d77310b9ed44d88792 Mon Sep 17 00:00:00 2001 From: omar Date: Sun, 28 Jan 2018 20:03:41 +0100 Subject: [PATCH 531/823] Examples: Vulkan: FIxed warnings in 32-bit modes (vulkan uses VkDeviceSize which is always 64-bit long) --- examples/vulkan_example/imgui_impl_glfw_vulkan.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/examples/vulkan_example/imgui_impl_glfw_vulkan.cpp b/examples/vulkan_example/imgui_impl_glfw_vulkan.cpp index b9e6d78f2397..080d57d3ea87 100644 --- a/examples/vulkan_example/imgui_impl_glfw_vulkan.cpp +++ b/examples/vulkan_example/imgui_impl_glfw_vulkan.cpp @@ -36,7 +36,7 @@ static VkDescriptorPool g_DescriptorPool = VK_NULL_HANDLE; static void (*g_CheckVkResult)(VkResult err) = NULL; static VkCommandBuffer g_CommandBuffer = VK_NULL_HANDLE; -static size_t g_BufferMemoryAlignment = 256; +static VkDeviceSize g_BufferMemoryAlignment = 256; static VkPipelineCreateFlags g_PipelineCreateFlags = 0; static int g_FrameIndex = 0; @@ -52,8 +52,8 @@ static VkImageView g_FontView = VK_NULL_HANDLE; static VkDeviceMemory g_VertexBufferMemory[IMGUI_VK_QUEUED_FRAMES] = {}; static VkDeviceMemory g_IndexBufferMemory[IMGUI_VK_QUEUED_FRAMES] = {}; -static size_t g_VertexBufferSize[IMGUI_VK_QUEUED_FRAMES] = {}; -static size_t g_IndexBufferSize[IMGUI_VK_QUEUED_FRAMES] = {}; +static VkDeviceSize g_VertexBufferSize[IMGUI_VK_QUEUED_FRAMES] = {}; +static VkDeviceSize g_IndexBufferSize[IMGUI_VK_QUEUED_FRAMES] = {}; static VkBuffer g_VertexBuffer[IMGUI_VK_QUEUED_FRAMES] = {}; static VkBuffer g_IndexBuffer[IMGUI_VK_QUEUED_FRAMES] = {}; @@ -164,7 +164,7 @@ void ImGui_ImplGlfwVulkan_RenderDrawLists(ImDrawData* draw_data) vkDestroyBuffer(g_Device, g_VertexBuffer[g_FrameIndex], g_Allocator); if (g_VertexBufferMemory[g_FrameIndex]) vkFreeMemory(g_Device, g_VertexBufferMemory[g_FrameIndex], g_Allocator); - size_t vertex_buffer_size = ((vertex_size-1) / g_BufferMemoryAlignment+1) * g_BufferMemoryAlignment; + VkDeviceSize vertex_buffer_size = ((vertex_size-1) / g_BufferMemoryAlignment+1) * g_BufferMemoryAlignment; VkBufferCreateInfo buffer_info = {}; buffer_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; buffer_info.size = vertex_buffer_size; @@ -194,7 +194,7 @@ void ImGui_ImplGlfwVulkan_RenderDrawLists(ImDrawData* draw_data) vkDestroyBuffer(g_Device, g_IndexBuffer[g_FrameIndex], g_Allocator); if (g_IndexBufferMemory[g_FrameIndex]) vkFreeMemory(g_Device, g_IndexBufferMemory[g_FrameIndex], g_Allocator); - size_t index_buffer_size = ((index_size-1) / g_BufferMemoryAlignment+1) * g_BufferMemoryAlignment; + VkDeviceSize index_buffer_size = ((index_size-1) / g_BufferMemoryAlignment+1) * g_BufferMemoryAlignment; VkBufferCreateInfo buffer_info = {}; buffer_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; buffer_info.size = index_buffer_size; From 858d75ab59c96d4689c5337c1750c32b9228e6be Mon Sep 17 00:00:00 2001 From: Omar Cornut Date: Sun, 28 Jan 2018 23:24:57 +0100 Subject: [PATCH 532/823] Examples: Apple: Fixed filenames in OSX xcode project. --- .../imguiex.xcodeproj/project.pbxproj | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/examples/apple_example/imguiex.xcodeproj/project.pbxproj b/examples/apple_example/imguiex.xcodeproj/project.pbxproj index be43fb60cc24..3e5b07894224 100644 --- a/examples/apple_example/imguiex.xcodeproj/project.pbxproj +++ b/examples/apple_example/imguiex.xcodeproj/project.pbxproj @@ -17,8 +17,8 @@ 1A1A0F331CB3A0E10090F036 /* imgui_demo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 197E1E881B89443600E3FE6A /* imgui_demo.cpp */; }; 1A1A0F341CB3A0EC0090F036 /* debug_hud.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5891B2E6A5500C130BA /* debug_hud.cpp */; }; 1A1A0F481CB3A2E50090F036 /* main.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A1A0F391CB3A1B20090F036 /* main.cpp */; }; - 1A1A0F4A1CB3A5070090F036 /* imgui_impl_glfw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A1A0F371CB3A1B20090F036 /* imgui_impl_glfw.cpp */; }; - 1A1A0F4E1CB3C54D0090F036 /* libglfw3.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 1A1A0F4D1CB3C54D0090F036 /* libglfw3.dylib */; }; + 1A1A0F4A1CB3A5070090F036 /* imgui_impl_glfw_gl2.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A1A0F371CB3A1B20090F036 /* imgui_impl_glfw_gl2.cpp */; }; + 1A1A0F4E1CB3C54D0090F036 /* libglfw.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 1A1A0F4D1CB3C54D0090F036 /* libglfw.dylib */; }; 6D1E39171B35EEF10017B40F /* uSynergy.c in Sources */ = {isa = PBXBuildFile; fileRef = 6D1E39151B35EEF10017B40F /* uSynergy.c */; }; 6D2FC55A1B2E632000C130BA /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC5591B2E632000C130BA /* main.m */; }; 6D2FC55D1B2E632000C130BA /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 6D2FC55C1B2E632000C130BA /* AppDelegate.m */; }; @@ -43,10 +43,10 @@ 1A1A0F221CB39FB50090F036 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 1A1A0F271CB39FB50090F036 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 1A1A0F2C1CB39FB50090F036 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 1A1A0F371CB3A1B20090F036 /* imgui_impl_glfw.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = imgui_impl_glfw.cpp; sourceTree = ""; }; - 1A1A0F381CB3A1B20090F036 /* imgui_impl_glfw.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = imgui_impl_glfw.h; sourceTree = ""; }; + 1A1A0F371CB3A1B20090F036 /* imgui_impl_glfw_gl2.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = imgui_impl_glfw_gl2.cpp; sourceTree = ""; }; + 1A1A0F381CB3A1B20090F036 /* imgui_impl_glfw_gl2.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = imgui_impl_glfw_gl2.h; sourceTree = ""; }; 1A1A0F391CB3A1B20090F036 /* main.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = main.cpp; sourceTree = ""; }; - 1A1A0F4D1CB3C54D0090F036 /* libglfw3.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libglfw3.dylib; path = /usr/local/lib/libglfw3.dylib; sourceTree = ""; }; + 1A1A0F4D1CB3C54D0090F036 /* libglfw.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libglfw.dylib; path = /usr/local/lib/libglfw.dylib; sourceTree = ""; }; 6D1E39151B35EEF10017B40F /* uSynergy.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = uSynergy.c; sourceTree = ""; }; 6D1E39161B35EEF10017B40F /* uSynergy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = uSynergy.h; sourceTree = ""; }; 6D2FC5541B2E632000C130BA /* imguiex-ios.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "imguiex-ios.app"; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -77,7 +77,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 1A1A0F4E1CB3C54D0090F036 /* libglfw3.dylib in Frameworks */, + 1A1A0F4E1CB3C54D0090F036 /* libglfw.dylib in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -96,7 +96,7 @@ 1A1A0F201CB39FB50090F036 /* imguiex-osx */ = { isa = PBXGroup; children = ( - 1A1A0F4D1CB3C54D0090F036 /* libglfw3.dylib */, + 1A1A0F4D1CB3C54D0090F036 /* libglfw.dylib */, 1A1A0F351CB3A1B20090F036 /* opengl2_example */, 1A1A0F211CB39FB50090F036 /* AppDelegate.h */, 1A1A0F221CB39FB50090F036 /* AppDelegate.m */, @@ -117,8 +117,8 @@ 1A1A0F351CB3A1B20090F036 /* opengl2_example */ = { isa = PBXGroup; children = ( - 1A1A0F371CB3A1B20090F036 /* imgui_impl_glfw.cpp */, - 1A1A0F381CB3A1B20090F036 /* imgui_impl_glfw.h */, + 1A1A0F371CB3A1B20090F036 /* imgui_impl_glfw_gl2.cpp */, + 1A1A0F381CB3A1B20090F036 /* imgui_impl_glfw_gl2.h */, 1A1A0F391CB3A1B20090F036 /* main.cpp */, ); name = opengl2_example; @@ -307,7 +307,7 @@ 1A1A0F481CB3A2E50090F036 /* main.cpp in Sources */, 1A1A0F321CB3A0DE0090F036 /* uSynergy.c in Sources */, 1A1A0F231CB39FB50090F036 /* AppDelegate.m in Sources */, - 1A1A0F4A1CB3A5070090F036 /* imgui_impl_glfw.cpp in Sources */, + 1A1A0F4A1CB3A5070090F036 /* imgui_impl_glfw_gl2.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; From ddff378daf86c8806f04d31c2e0e092330983a3f Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 29 Jan 2018 00:38:00 +0100 Subject: [PATCH 533/823] Examples: Synced Makefile comments. Added build/ folder into git ignore list/ --- examples/.gitignore | 2 +- examples/opengl2_example/Makefile | 12 ++++++++---- examples/opengl3_example/Makefile | 13 +++++++------ examples/sdl_opengl3_example/Makefile | 13 +++++++------ 4 files changed, 23 insertions(+), 17 deletions(-) diff --git a/examples/.gitignore b/examples/.gitignore index 9516dc7f661d..127854990063 100644 --- a/examples/.gitignore +++ b/examples/.gitignore @@ -1,4 +1,4 @@ -## Visual Studio files +build/* Debug/* Release/* ipch/* diff --git a/examples/opengl2_example/Makefile b/examples/opengl2_example/Makefile index f10c59a8d03d..ea96af4496ee 100644 --- a/examples/opengl2_example/Makefile +++ b/examples/opengl2_example/Makefile @@ -2,10 +2,13 @@ # Cross Platform Makefile # Compatible with MSYS2/MINGW, Ubuntu 14.04.1 and Mac OS X # -# -# if you using Mac OS X: -# You'll need glfw -# http://www.glfw.org +# You will need GLFW (http://www.glfw.org): +# Linux: +# apt-get install libglfw-dev +# Mac OS X: +# brew install glfw +# MSYS2: +# pacman -S --noconfirm --needed mingw-w64-x86_64-toolchain mingw-w64-x86_64-glfw # #CXX = g++ @@ -46,6 +49,7 @@ ifeq ($(findstring MINGW,$(UNAME_S)),MINGW) CFLAGS = $(CXXFLAGS) endif + .cpp.o: $(CXX) $(CXXFLAGS) -c -o $@ $< diff --git a/examples/opengl3_example/Makefile b/examples/opengl3_example/Makefile index 32343ed235f1..63eaf75c3c68 100644 --- a/examples/opengl3_example/Makefile +++ b/examples/opengl3_example/Makefile @@ -2,12 +2,13 @@ # Cross Platform Makefile # Compatible with MSYS2/MINGW, Ubuntu 14.04.1 and Mac OS X # -# -# You will need GLFW (http://www.glfw.org) -# -# apt-get install libglfw-dev # Linux -# brew install glfw # Mac OS X -# pacman -S --noconfirm --needed mingw-w64-x86_64-toolchain mingw-w64-x86_64-glfw # MSYS2 +# You will need GLFW (http://www.glfw.org): +# Linux: +# apt-get install libglfw-dev +# Mac OS X: +# brew install glfw +# MSYS2: +# pacman -S --noconfirm --needed mingw-w64-x86_64-toolchain mingw-w64-x86_64-glfw # #CXX = g++ diff --git a/examples/sdl_opengl3_example/Makefile b/examples/sdl_opengl3_example/Makefile index 364ca1239250..b454bebd4b0d 100644 --- a/examples/sdl_opengl3_example/Makefile +++ b/examples/sdl_opengl3_example/Makefile @@ -2,12 +2,13 @@ # Cross Platform Makefile # Compatible with MSYS2/MINGW, Ubuntu 14.04.1 and Mac OS X # -# -# You will need SDL2 (http://www.libsdl.org) -# -# apt-get install libsdl2-dev # Linux -# brew install sdl2 # Mac OS X -# pacman -S mingw-w64-i686-SDL # MSYS2 +# You will need SDL2 (http://www.libsdl.org): +# Linux: +# apt-get install libsdl2-dev +# Mac OS X: +# brew install sdl2 +# MSYS2: +# pacman -S mingw-w64-i686-SDL # #CXX = g++ From 3cdd2096ec3998aef478a66feb1bb700de69b0d4 Mon Sep 17 00:00:00 2001 From: Omar Cornut Date: Mon, 29 Jan 2018 00:48:21 +0100 Subject: [PATCH 534/823] Examples: Use Clang in old Makefile. --- examples/opengl2_example/Makefile | 1 + examples/opengl3_example/Makefile | 1 + examples/sdl_opengl3_example/Makefile | 1 + 3 files changed, 3 insertions(+) diff --git a/examples/opengl2_example/Makefile b/examples/opengl2_example/Makefile index ea96af4496ee..e00891baa0f4 100644 --- a/examples/opengl2_example/Makefile +++ b/examples/opengl2_example/Makefile @@ -12,6 +12,7 @@ # #CXX = g++ +CXX = clang++ EXE = opengl2_example OBJS = main.o imgui_impl_glfw_gl2.o diff --git a/examples/opengl3_example/Makefile b/examples/opengl3_example/Makefile index 63eaf75c3c68..881c9bd1932c 100644 --- a/examples/opengl3_example/Makefile +++ b/examples/opengl3_example/Makefile @@ -12,6 +12,7 @@ # #CXX = g++ +CXX = clang++ EXE = opengl3_example OBJS = main.o imgui_impl_glfw_gl3.o diff --git a/examples/sdl_opengl3_example/Makefile b/examples/sdl_opengl3_example/Makefile index b454bebd4b0d..06e4d880f3f8 100644 --- a/examples/sdl_opengl3_example/Makefile +++ b/examples/sdl_opengl3_example/Makefile @@ -12,6 +12,7 @@ # #CXX = g++ +CXX = clang++ EXE = sdl_opengl3_example OBJS = main.o imgui_impl_sdl_gl3.o From 91d77be36e2067ce51c64262d0df1efa53e0d470 Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 29 Jan 2018 00:55:16 +0100 Subject: [PATCH 535/823] Examples: Makefile leave CXX alone, instead leave commented out options. (nb: codeship doesn't seem have clang++) --- examples/opengl2_example/Makefile | 2 +- examples/opengl3_example/Makefile | 2 +- examples/sdl_opengl3_example/Makefile | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/opengl2_example/Makefile b/examples/opengl2_example/Makefile index e00891baa0f4..b0ee3152de1b 100644 --- a/examples/opengl2_example/Makefile +++ b/examples/opengl2_example/Makefile @@ -12,7 +12,7 @@ # #CXX = g++ -CXX = clang++ +#CXX = clang++ EXE = opengl2_example OBJS = main.o imgui_impl_glfw_gl2.o diff --git a/examples/opengl3_example/Makefile b/examples/opengl3_example/Makefile index 881c9bd1932c..133c0a64e0e7 100644 --- a/examples/opengl3_example/Makefile +++ b/examples/opengl3_example/Makefile @@ -12,7 +12,7 @@ # #CXX = g++ -CXX = clang++ +#CXX = clang++ EXE = opengl3_example OBJS = main.o imgui_impl_glfw_gl3.o diff --git a/examples/sdl_opengl3_example/Makefile b/examples/sdl_opengl3_example/Makefile index 06e4d880f3f8..45f6a6631405 100644 --- a/examples/sdl_opengl3_example/Makefile +++ b/examples/sdl_opengl3_example/Makefile @@ -12,7 +12,7 @@ # #CXX = g++ -CXX = clang++ +#CXX = clang++ EXE = sdl_opengl3_example OBJS = main.o imgui_impl_sdl_gl3.o From 6a25a8720ac27573225643a1188d8a49b4ad614e Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 29 Jan 2018 14:38:46 +0100 Subject: [PATCH 536/823] Examples: Using #include "imgui.h" instead of appear correct-er as per standard? xcode+clang are very nitpicky there. --- examples/allegro5_example/imgui_impl_a5.cpp | 2 +- examples/allegro5_example/main.cpp | 2 +- examples/directx10_example/main.cpp | 2 +- examples/directx11_example/imgui_impl_dx11.cpp | 2 +- examples/directx11_example/main.cpp | 2 +- examples/directx9_example/imgui_impl_dx9.cpp | 2 +- examples/directx9_example/main.cpp | 2 +- examples/marmalade_example/imgui_impl_marmalade.cpp | 2 +- examples/marmalade_example/main.cpp | 2 +- examples/null_example/main.cpp | 2 +- examples/opengl2_example/imgui_impl_glfw_gl2.cpp | 2 +- examples/opengl2_example/main.cpp | 2 +- examples/opengl3_example/imgui_impl_glfw_gl3.cpp | 2 +- examples/opengl3_example/main.cpp | 2 +- examples/sdl_opengl2_example/imgui_impl_sdl_gl2.cpp | 2 +- examples/sdl_opengl2_example/main.cpp | 2 +- examples/sdl_opengl3_example/main.cpp | 2 +- examples/vulkan_example/imgui_impl_glfw_vulkan.cpp | 5 ++--- examples/vulkan_example/main.cpp | 5 ++--- 19 files changed, 21 insertions(+), 23 deletions(-) diff --git a/examples/allegro5_example/imgui_impl_a5.cpp b/examples/allegro5_example/imgui_impl_a5.cpp index 62f7af67296f..4269136214c9 100644 --- a/examples/allegro5_example/imgui_impl_a5.cpp +++ b/examples/allegro5_example/imgui_impl_a5.cpp @@ -12,7 +12,7 @@ #include // uint64_t #include // memcpy -#include +#include "imgui.h" #include "imgui_impl_a5.h" #include #include diff --git a/examples/allegro5_example/main.cpp b/examples/allegro5_example/main.cpp index 3c9c9770eb1c..7ecf4321397c 100644 --- a/examples/allegro5_example/main.cpp +++ b/examples/allegro5_example/main.cpp @@ -4,7 +4,7 @@ #include #include #include -#include +#include "imgui.h" #include "imgui_impl_a5.h" int main(int, char**) diff --git a/examples/directx10_example/main.cpp b/examples/directx10_example/main.cpp index 38f4054eada3..fccdda60f61f 100644 --- a/examples/directx10_example/main.cpp +++ b/examples/directx10_example/main.cpp @@ -1,7 +1,7 @@ // ImGui - standalone example application for DirectX 10 // If you are new to ImGui, see examples/README.txt and documentation at the top of imgui.cpp. -#include +#include "imgui.h" #include "imgui_impl_dx10.h" #include #include diff --git a/examples/directx11_example/imgui_impl_dx11.cpp b/examples/directx11_example/imgui_impl_dx11.cpp index 4963fc12eaa3..25742cb7af92 100644 --- a/examples/directx11_example/imgui_impl_dx11.cpp +++ b/examples/directx11_example/imgui_impl_dx11.cpp @@ -6,7 +6,7 @@ // If you are new to ImGui, see examples/README.txt and documentation at the top of imgui.cpp. // https://github.com/ocornut/imgui -#include +#include "imgui.h" #include "imgui_impl_dx11.h" // DirectX diff --git a/examples/directx11_example/main.cpp b/examples/directx11_example/main.cpp index 79e7bb169ddc..f1e3b8ac8b55 100644 --- a/examples/directx11_example/main.cpp +++ b/examples/directx11_example/main.cpp @@ -1,7 +1,7 @@ // ImGui - standalone example application for DirectX 11 // If you are new to ImGui, see examples/README.txt and documentation at the top of imgui.cpp. -#include +#include "imgui.h" #include "imgui_impl_dx11.h" #include #define DIRECTINPUT_VERSION 0x0800 diff --git a/examples/directx9_example/imgui_impl_dx9.cpp b/examples/directx9_example/imgui_impl_dx9.cpp index a4e676914ce4..b47a840b6ec9 100644 --- a/examples/directx9_example/imgui_impl_dx9.cpp +++ b/examples/directx9_example/imgui_impl_dx9.cpp @@ -6,7 +6,7 @@ // If you are new to ImGui, see examples/README.txt and documentation at the top of imgui.cpp. // https://github.com/ocornut/imgui -#include +#include "imgui.h" #include "imgui_impl_dx9.h" // DirectX diff --git a/examples/directx9_example/main.cpp b/examples/directx9_example/main.cpp index 09a109d981bc..d0323dca025b 100644 --- a/examples/directx9_example/main.cpp +++ b/examples/directx9_example/main.cpp @@ -1,7 +1,7 @@ // ImGui - standalone example application for DirectX 9 // If you are new to ImGui, see examples/README.txt and documentation at the top of imgui.cpp. -#include +#include "imgui.h" #include "imgui_impl_dx9.h" #include #define DIRECTINPUT_VERSION 0x0800 diff --git a/examples/marmalade_example/imgui_impl_marmalade.cpp b/examples/marmalade_example/imgui_impl_marmalade.cpp index 36fc8328c862..0bffb30d8bad 100644 --- a/examples/marmalade_example/imgui_impl_marmalade.cpp +++ b/examples/marmalade_example/imgui_impl_marmalade.cpp @@ -9,7 +9,7 @@ // Copyright (C) 2015 by Giovanni Zito // This file is part of ImGui -#include +#include "imgui.h" #include "imgui_impl_marmalade.h" #include diff --git a/examples/marmalade_example/main.cpp b/examples/marmalade_example/main.cpp index 2b5edb77f78d..338c469cd500 100644 --- a/examples/marmalade_example/main.cpp +++ b/examples/marmalade_example/main.cpp @@ -4,7 +4,7 @@ // Copyright (C) 2015 by Giovanni Zito // This file is part of ImGui -#include +#include "imgui.h" #include "imgui_impl_marmalade.h" #include diff --git a/examples/null_example/main.cpp b/examples/null_example/main.cpp index 04c1bda40702..3dd41b0e6e45 100644 --- a/examples/null_example/main.cpp +++ b/examples/null_example/main.cpp @@ -1,5 +1,5 @@ // ImGui - null/dummy example application (compile and link imgui with no inputs, no outputs) -#include +#include "imgui.h" #include int main(int, char**) diff --git a/examples/opengl2_example/imgui_impl_glfw_gl2.cpp b/examples/opengl2_example/imgui_impl_glfw_gl2.cpp index e5fe2f47bcb0..27052b60d70f 100644 --- a/examples/opengl2_example/imgui_impl_glfw_gl2.cpp +++ b/examples/opengl2_example/imgui_impl_glfw_gl2.cpp @@ -15,7 +15,7 @@ // If you are new to ImGui, see examples/README.txt and documentation at the top of imgui.cpp. // https://github.com/ocornut/imgui -#include +#include "imgui.h" #include "imgui_impl_glfw_gl2.h" // GLFW diff --git a/examples/opengl2_example/main.cpp b/examples/opengl2_example/main.cpp index 6359f5b6253f..01eba4fbbd28 100644 --- a/examples/opengl2_example/main.cpp +++ b/examples/opengl2_example/main.cpp @@ -6,7 +6,7 @@ // **Prefer using the code in the opengl3_example/ folder** // See imgui_impl_glfw.cpp for details. -#include +#include "imgui.h" #include "imgui_impl_glfw_gl2.h" #include #include diff --git a/examples/opengl3_example/imgui_impl_glfw_gl3.cpp b/examples/opengl3_example/imgui_impl_glfw_gl3.cpp index a71fc515dab5..f02692b2af55 100644 --- a/examples/opengl3_example/imgui_impl_glfw_gl3.cpp +++ b/examples/opengl3_example/imgui_impl_glfw_gl3.cpp @@ -8,7 +8,7 @@ // If you are new to ImGui, see examples/README.txt and documentation at the top of imgui.cpp. // https://github.com/ocornut/imgui -#include +#include "imgui.h" #include "imgui_impl_glfw_gl3.h" // GL3W/GLFW diff --git a/examples/opengl3_example/main.cpp b/examples/opengl3_example/main.cpp index 6beb855dc4f0..26de8ca23dd0 100644 --- a/examples/opengl3_example/main.cpp +++ b/examples/opengl3_example/main.cpp @@ -3,7 +3,7 @@ // (GLFW is a cross-platform general purpose library for handling windows, inputs, OpenGL/Vulkan graphics context creation, etc.) // (GL3W is a helper library to access OpenGL functions since there is no standard header to access modern OpenGL functions easily. Alternatives are GLEW, Glad, etc.) -#include +#include "imgui.h" #include "imgui_impl_glfw_gl3.h" #include #include // This example is using gl3w to access OpenGL functions (because it is small). You may use glew/glad/glLoadGen/etc. whatever already works for you. diff --git a/examples/sdl_opengl2_example/imgui_impl_sdl_gl2.cpp b/examples/sdl_opengl2_example/imgui_impl_sdl_gl2.cpp index 76def29c3af8..801c433f08f8 100644 --- a/examples/sdl_opengl2_example/imgui_impl_sdl_gl2.cpp +++ b/examples/sdl_opengl2_example/imgui_impl_sdl_gl2.cpp @@ -18,7 +18,7 @@ #include #include #include -#include +#include "imgui.h" #include "imgui_impl_sdl_gl2.h" // Data diff --git a/examples/sdl_opengl2_example/main.cpp b/examples/sdl_opengl2_example/main.cpp index 21b567a835e9..bc475647939a 100644 --- a/examples/sdl_opengl2_example/main.cpp +++ b/examples/sdl_opengl2_example/main.cpp @@ -6,7 +6,7 @@ // **Prefer using the code in the sdl_opengl3_example/ folder** // See imgui_impl_sdl.cpp for details. -#include +#include "imgui.h" #include "imgui_impl_sdl_gl2.h" #include #include diff --git a/examples/sdl_opengl3_example/main.cpp b/examples/sdl_opengl3_example/main.cpp index 7ee60389c417..6321181dfe6d 100644 --- a/examples/sdl_opengl3_example/main.cpp +++ b/examples/sdl_opengl3_example/main.cpp @@ -3,7 +3,7 @@ // (SDL is a cross-platform general purpose library for handling windows, inputs, OpenGL/Vulkan graphics context creation, etc.) // (GL3W is a helper library to access OpenGL functions since there is no standard header to access modern OpenGL functions easily. Alternatives are GLEW, Glad, etc.) -#include +#include "imgui.h" #include "imgui_impl_sdl_gl3.h" #include #include // This example is using gl3w to access OpenGL functions (because it is small). You may use glew/glad/glLoadGen/etc. whatever already works for you. diff --git a/examples/vulkan_example/imgui_impl_glfw_vulkan.cpp b/examples/vulkan_example/imgui_impl_glfw_vulkan.cpp index 080d57d3ea87..3748b504bb47 100644 --- a/examples/vulkan_example/imgui_impl_glfw_vulkan.cpp +++ b/examples/vulkan_example/imgui_impl_glfw_vulkan.cpp @@ -6,7 +6,8 @@ // If you are new to ImGui, see examples/README.txt and documentation at the top of imgui.cpp. // https://github.com/ocornut/imgui -#include +#include "imgui.h" +#include "imgui_impl_glfw_vulkan.h" // GLFW #define GLFW_INCLUDE_NONE @@ -19,8 +20,6 @@ #include #endif -#include "imgui_impl_glfw_vulkan.h" - // GLFW Data static GLFWwindow* g_Window = NULL; static double g_Time = 0.0f; diff --git a/examples/vulkan_example/main.cpp b/examples/vulkan_example/main.cpp index 6c4ef33fe28b..75b08d225312 100644 --- a/examples/vulkan_example/main.cpp +++ b/examples/vulkan_example/main.cpp @@ -1,7 +1,8 @@ // ImGui - standalone example application for Glfw + Vulkan, using programmable pipeline // If you are new to ImGui, see examples/README.txt and documentation at the top of imgui.cpp. -#include +#include "imgui.h" +#include "imgui_impl_glfw_vulkan.h" #include // printf, fprintf #include // abort @@ -9,8 +10,6 @@ #define GLFW_INCLUDE_VULKAN #include -#include "imgui_impl_glfw_vulkan.h" - #define IMGUI_MAX_POSSIBLE_BACK_BUFFERS 16 #define IMGUI_UNLIMITED_FRAME_RATE //#ifdef _DEBUG From 21771adb94c92a0d73d4dd42b42d8d6e4bf9ab80 Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 29 Jan 2018 15:35:51 +0100 Subject: [PATCH 537/823] Nav: Debug overlay uses default font. (#787) --- imgui.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/imgui.cpp b/imgui.cpp index c8add8ced606..d4c7835e634c 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2198,7 +2198,7 @@ static bool NavScoreItem(ImRect cand) ImFormatString(buf, IM_ARRAYSIZE(buf), "dbox (%.2f,%.2f->%.4f) dcen (%.2f,%.2f->%.4f) d (%.2f,%.2f->%.4f) nav %c, quad %c", dbx, dby, dist_box, dcx, dcy, dist_center, dax, day, dist_axial, "WENS"[g.NavMoveDir], "WENS"[quadrant]); g.OverlayDrawList.AddRect(cand.Min, cand.Max, IM_COL32(255,255,0,200)); g.OverlayDrawList.AddRectFilled(cand.Max-ImVec2(4,4), cand.Max+ImGui::CalcTextSize(buf)+ImVec2(4,4), IM_COL32(40,0,0,150)); - g.OverlayDrawList.AddText(cand.Max, ~0U, buf); + g.OverlayDrawList.AddText(g.IO.FontDefault, 13.0f, cand.Max, ~0U, buf); } #endif From c8b9b2c6bdc7710221d163dd49a7a787cba7a483 Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 29 Jan 2018 15:46:41 +0100 Subject: [PATCH 538/823] Nav: Mouse hovering selectable / menu items only activate them if they are on the active NavLayer. (#787) --- imgui.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/imgui.cpp b/imgui.cpp index d4c7835e634c..7a4ee90205a4 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -10600,7 +10600,7 @@ bool ImGui::Selectable(const char* label, bool selected, ImGuiSelectableFlags fl // Hovering selectable with mouse updates NavId accordingly so navigation can be resumed with gamepad/keyboard (this doesn't happen on most widgets) if (pressed || hovered)// && (g.IO.MouseDelta.x != 0.0f || g.IO.MouseDelta.y != 0.0f)) - if (!g.NavDisableMouseHover && g.NavWindow == window) + if (!g.NavDisableMouseHover && g.NavWindow == window && g.NavLayer == window->DC.NavLayerActiveMask) { g.NavDisableHighlight = true; SetNavID(id, window->DC.NavLayerCurrent); From 4654040bcbe58bd55af5512297524afb71ddfc79 Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 29 Jan 2018 17:35:36 +0100 Subject: [PATCH 539/823] Nav: Comments, added enum to clarify NavForward code. (#787) --- imgui.cpp | 19 ++++++++++--------- imgui_internal.h | 13 ++++++++++--- 2 files changed, 20 insertions(+), 12 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 7a4ee90205a4..9c7e4a830c5b 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2896,12 +2896,12 @@ static void ImGui::NavUpdate() } // When a forwarded move request failed, we restore the highlight that we disabled during the forward frame - if (g.NavMoveRequestForwardStep == 2) + if (g.NavMoveRequestForward == ImGuiNavForward_ForwardResult) { IM_ASSERT(g.NavMoveRequest); if (g.NavMoveResultId == 0) g.NavDisableHighlight = false; - g.NavMoveRequestForwardStep = 0; + g.NavMoveRequestForward = ImGuiNavForward_None; } // Apply application mouse position movement, after we had a chance to process move request result. @@ -2993,7 +2993,7 @@ static void ImGui::NavUpdate() // Initiate directional inputs request const int allowed_dir_flags = (g.ActiveId == 0) ? ~0 : g.ActiveIdAllowNavDirFlags; - if (g.NavMoveRequestForwardStep == 0) + if (g.NavMoveRequestForward == ImGuiNavForward_None) { g.NavMoveDir = ImGuiDir_None; if (g.NavWindow && !g.NavWindowingTarget && allowed_dir_flags && !(g.NavWindow->Flags & ImGuiWindowFlags_NoNavInputs)) @@ -3006,9 +3006,10 @@ static void ImGui::NavUpdate() } else { + // Forwarding previous request (which has been modified, e.g. wrap around menus rewrite the requests with a starting rectangle at the other side of the window) IM_ASSERT(g.NavMoveDir != ImGuiDir_None); - IM_ASSERT(g.NavMoveRequestForwardStep == 1); - g.NavMoveRequestForwardStep = 2; + IM_ASSERT(g.NavMoveRequestForward == ImGuiNavForward_Forwarding); + g.NavMoveRequestForward = ImGuiNavForward_ForwardResult; } if (g.NavMoveDir != ImGuiDir_None) @@ -4821,9 +4822,9 @@ static void NavProcessMoveRequestWrapAround(ImGuiWindow* window) { ImGuiContext& g = *GImGui; if (g.NavMoveRequest && g.NavWindow == window && g.NavMoveResultId == 0) - if ((g.NavMoveDir == ImGuiDir_Up || g.NavMoveDir == ImGuiDir_Down) && g.NavMoveRequestForwardStep == 0 && g.NavLayer == 0) + if ((g.NavMoveDir == ImGuiDir_Up || g.NavMoveDir == ImGuiDir_Down) && g.NavMoveRequestForward == ImGuiNavForward_None && g.NavLayer == 0) { - g.NavMoveRequestForwardStep = 1; + g.NavMoveRequestForward = ImGuiNavForward_Forwarding; NavMoveRequestCancel(); g.NavWindow->NavRectRel[0].Min.y = g.NavWindow->NavRectRel[0].Max.y = ((g.NavMoveDir == ImGuiDir_Up) ? ImMax(window->SizeFull.y, window->SizeContents.y) : 0.0f) - window->Scroll.y; } @@ -10860,7 +10861,7 @@ void ImGui::EndMenuBar() ImGuiWindow* nav_earliest_child = g.NavWindow; while (nav_earliest_child->ParentWindow && (nav_earliest_child->ParentWindow->Flags & ImGuiWindowFlags_ChildMenu)) nav_earliest_child = nav_earliest_child->ParentWindow; - if (nav_earliest_child->ParentWindow == window && nav_earliest_child->DC.ParentLayoutType == ImGuiLayoutType_Horizontal && g.NavMoveRequestForwardStep == 0) + if (nav_earliest_child->ParentWindow == window && nav_earliest_child->DC.ParentLayoutType == ImGuiLayoutType_Horizontal && g.NavMoveRequestForward == ImGuiNavForward_None) { // To do so we claim focus back, restore NavId and then process the movement request for yet another frame. // This involve a one-frame delay which isn't very problematic in this situation. We could remove it by scoring in advance for multiple window (probably not worth the hassle/cost) @@ -10869,7 +10870,7 @@ void ImGui::EndMenuBar() SetNavIDAndMoveMouse(window->NavLastIds[1], 1, window->NavRectRel[1]); g.NavLayer = 1; g.NavDisableHighlight = true; // Hide highlight for the current frame so we don't see the intermediary selection. - g.NavMoveRequestForwardStep = 1; + g.NavMoveRequestForward = ImGuiNavForward_Forwarding; NavMoveRequestCancel(); } } diff --git a/imgui_internal.h b/imgui_internal.h index c958f33e66d7..75cabcf6342f 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -292,6 +292,13 @@ enum ImGuiNavDirSourceFlags_ ImGuiNavDirSourceFlags_PadLStick = 1 << 2 }; +enum ImGuiNavForward +{ + ImGuiNavForward_None, + ImGuiNavForward_Forwarding, + ImGuiNavForward_ForwardResult +}; + // 2D axis aligned bounding-box // NB: we can't rely on ImVec2 math operators being available here struct IMGUI_API ImRect @@ -610,11 +617,11 @@ struct ImGuiContext bool NavInitResultExplicit; // Whether the result was explicitly requested with SetItemDefaultFocus() bool NavMoveFromClampedRefRect; // Set by manual scrolling, if we scroll to a point where NavId isn't visible we reset navigation from visible items bool NavMoveRequest; // Move request for this frame - int NavMoveRequestForwardStep; // 0: no forward, 1: forward request, 2: forward result (this is used to navigate sibling parent menus from a child menu) + ImGuiNavForward NavMoveRequestForward; // No forward / Forwarding / ForwardResult (this is used to navigate sibling parent menus from a child menu) ImGuiDir NavMoveDir; // Direction of the move request (left/right/up/down) ImGuiDir NavMoveDirLast; // Direction of the previous move request ImGuiID NavMoveResultId; // Best move request candidate - ImGuiID NavMoveResultParentId; // + ImGuiID NavMoveResultParentId; // Best move request candidate window->IDStack.back() - to compare context float NavMoveResultDistBox; // Best move request candidate box distance to current NavId float NavMoveResultDistCenter; // Best move request candidate center distance to current NavId float NavMoveResultDistAxial; @@ -729,7 +736,7 @@ struct ImGuiContext NavInitResultExplicit = false; NavMoveFromClampedRefRect = false; NavMoveRequest = false; - NavMoveRequestForwardStep = 0; + NavMoveRequestForward = ImGuiNavForward_None; NavMoveDir = NavMoveDirLast = ImGuiDir_None; NavMoveResultId = 0; NavMoveResultParentId = 0; From 1cf38d0334c4837ba7ab9d9b6e5c6e215a146871 Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 29 Jan 2018 18:12:32 +0100 Subject: [PATCH 540/823] Internals: Nav: Renamed ImGuiNavForward enum (#787) --- imgui.cpp | 10 +++++----- imgui_internal.h | 6 +++--- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 9c7e4a830c5b..e2f515f8e008 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2896,7 +2896,7 @@ static void ImGui::NavUpdate() } // When a forwarded move request failed, we restore the highlight that we disabled during the forward frame - if (g.NavMoveRequestForward == ImGuiNavForward_ForwardResult) + if (g.NavMoveRequestForward == ImGuiNavForward_ForwardActive) { IM_ASSERT(g.NavMoveRequest); if (g.NavMoveResultId == 0) @@ -3008,8 +3008,8 @@ static void ImGui::NavUpdate() { // Forwarding previous request (which has been modified, e.g. wrap around menus rewrite the requests with a starting rectangle at the other side of the window) IM_ASSERT(g.NavMoveDir != ImGuiDir_None); - IM_ASSERT(g.NavMoveRequestForward == ImGuiNavForward_Forwarding); - g.NavMoveRequestForward = ImGuiNavForward_ForwardResult; + IM_ASSERT(g.NavMoveRequestForward == ImGuiNavForward_ForwardQueued); + g.NavMoveRequestForward = ImGuiNavForward_ForwardActive; } if (g.NavMoveDir != ImGuiDir_None) @@ -4824,7 +4824,7 @@ static void NavProcessMoveRequestWrapAround(ImGuiWindow* window) if (g.NavMoveRequest && g.NavWindow == window && g.NavMoveResultId == 0) if ((g.NavMoveDir == ImGuiDir_Up || g.NavMoveDir == ImGuiDir_Down) && g.NavMoveRequestForward == ImGuiNavForward_None && g.NavLayer == 0) { - g.NavMoveRequestForward = ImGuiNavForward_Forwarding; + g.NavMoveRequestForward = ImGuiNavForward_ForwardQueued; NavMoveRequestCancel(); g.NavWindow->NavRectRel[0].Min.y = g.NavWindow->NavRectRel[0].Max.y = ((g.NavMoveDir == ImGuiDir_Up) ? ImMax(window->SizeFull.y, window->SizeContents.y) : 0.0f) - window->Scroll.y; } @@ -10870,7 +10870,7 @@ void ImGui::EndMenuBar() SetNavIDAndMoveMouse(window->NavLastIds[1], 1, window->NavRectRel[1]); g.NavLayer = 1; g.NavDisableHighlight = true; // Hide highlight for the current frame so we don't see the intermediary selection. - g.NavMoveRequestForward = ImGuiNavForward_Forwarding; + g.NavMoveRequestForward = ImGuiNavForward_ForwardQueued; NavMoveRequestCancel(); } } diff --git a/imgui_internal.h b/imgui_internal.h index 75cabcf6342f..2713aa56d997 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -295,8 +295,8 @@ enum ImGuiNavDirSourceFlags_ enum ImGuiNavForward { ImGuiNavForward_None, - ImGuiNavForward_Forwarding, - ImGuiNavForward_ForwardResult + ImGuiNavForward_ForwardQueued, + ImGuiNavForward_ForwardActive }; // 2D axis aligned bounding-box @@ -617,7 +617,7 @@ struct ImGuiContext bool NavInitResultExplicit; // Whether the result was explicitly requested with SetItemDefaultFocus() bool NavMoveFromClampedRefRect; // Set by manual scrolling, if we scroll to a point where NavId isn't visible we reset navigation from visible items bool NavMoveRequest; // Move request for this frame - ImGuiNavForward NavMoveRequestForward; // No forward / Forwarding / ForwardResult (this is used to navigate sibling parent menus from a child menu) + ImGuiNavForward NavMoveRequestForward; // None / ForwardQueued / ForwardActive (this is used to navigate sibling parent menus from a child menu) ImGuiDir NavMoveDir; // Direction of the move request (left/right/up/down) ImGuiDir NavMoveDirLast; // Direction of the previous move request ImGuiID NavMoveResultId; // Best move request candidate From 72485a5d0443e0ed0c8464f04a44a3d832a402b8 Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 29 Jan 2018 18:28:46 +0100 Subject: [PATCH 541/823] Nav: Refactor NavMoveResult** flags into ImGuiNavMoveResult structure as we are going to want two instances of it. (#787) (+1 squashed commits) + store window inside result. --- imgui.cpp | 58 ++++++++++++++++++++++++++---------------------- imgui_internal.h | 23 +++++++++++-------- 2 files changed, 45 insertions(+), 36 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index e2f515f8e008..cfa2d8e7dfb5 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2132,7 +2132,7 @@ static float NavScoreItemDistInterval(float a0, float a1, float b0, float b1) } // Scoring function for directional navigation. Based on https://gist.github.com/rygorous/6981057 -static bool NavScoreItem(ImRect cand) +static bool NavScoreItem(ImGuiNavMoveResult* result, ImRect cand) { ImGuiContext& g = *GImGui; ImGuiWindow* window = g.NavWindow; @@ -2207,21 +2207,21 @@ static bool NavScoreItem(ImRect cand) if (quadrant == g.NavMoveDir) { // Does it beat the current best candidate? - if (dist_box < g.NavMoveResultDistBox) + if (dist_box < result->DistBox) { - g.NavMoveResultDistBox = dist_box; - g.NavMoveResultDistCenter = dist_center; + result->DistBox = dist_box; + result->DistCenter = dist_center; return true; } - if (dist_box == g.NavMoveResultDistBox) + if (dist_box == result->DistBox) { // Try using distance between center points to break ties - if (dist_center < g.NavMoveResultDistCenter) + if (dist_center < result->DistCenter) { - g.NavMoveResultDistCenter = dist_center; + result->DistCenter = dist_center; new_best = true; } - else if (dist_center == g.NavMoveResultDistCenter) + else if (dist_center == result->DistCenter) { // Still tied! we need to be extra-careful to make sure everything gets linked properly. We consistently break ties by symbolically moving "later" items // (with higher index) to the right/downwards by an infinitesimal amount since we the current "best" button already (so it must have a lower index), @@ -2237,11 +2237,11 @@ static bool NavScoreItem(ImRect cand) // This is just to avoid buttons having no links in a particular direction when there's a suitable neighbor. you get good graphs without this too. // 2017/09/29: FIXME: This now currently only enabled inside menubars, ideally we'd disable it everywhere. Menus in particular need to catch failure. For general navigation it feels awkward. // Disabling it may however lead to disconnected graphs when nodes are very spaced out on different axis. Perhaps consider offering this as an option? - if (g.NavMoveResultDistBox == FLT_MAX && dist_axial < g.NavMoveResultDistAxial) // Check axial match + if (result->DistBox == FLT_MAX && dist_axial < result->DistAxial) // Check axial match if (g.NavLayer == 1 && !(g.NavWindow->Flags & ImGuiWindowFlags_ChildMenu)) if ((g.NavMoveDir == ImGuiDir_Left && dax < 0.0f) || (g.NavMoveDir == ImGuiDir_Right && dax > 0.0f) || (g.NavMoveDir == ImGuiDir_Up && day < 0.0f) || (g.NavMoveDir == ImGuiDir_Down && day > 0.0f)) { - g.NavMoveResultDistAxial = dist_axial; + result->DistAxial = dist_axial; new_best = true; } @@ -2288,19 +2288,21 @@ static void ImGui::NavProcessItem(ImGuiWindow* window, const ImRect& nav_bb, con // Scoring for navigation if (g.NavId != id && !(item_flags & ImGuiItemFlags_NoNav)) { + ImGuiNavMoveResult* result = &g.NavMoveResult; #if IMGUI_DEBUG_NAV_SCORING // [DEBUG] Score all items in NavWindow at all times if (!g.NavMoveRequest) g.NavMoveDir = g.NavMoveDirLast; - bool new_best = NavScoreItem(nav_bb) && g.NavMoveRequest; + bool new_best = NavScoreItem(result, nav_bb) && g.NavMoveRequest; #else - bool new_best = g.NavMoveRequest && NavScoreItem(nav_bb); + bool new_best = g.NavMoveRequest && NavScoreItem(result, nav_bb); #endif if (new_best) { - g.NavMoveResultId = id; - g.NavMoveResultParentId = window->IDStack.back(); - g.NavMoveResultRectRel = nav_bb_rel; + result->ID = id; + result->ParentID = window->IDStack.back(); + result->Window = window; + result->RectRel = nav_bb_rel; } } @@ -2881,17 +2883,18 @@ static void ImGui::NavUpdate() g.NavJustMovedToId = 0; // Process navigation move request - if (g.NavMoveRequest && g.NavMoveResultId != 0) + if (g.NavMoveRequest && g.NavMoveResult.ID != 0) { // Scroll to keep newly navigated item fully into view - IM_ASSERT(g.NavWindow); + ImGuiNavMoveResult* result = &g.NavMoveResult; + IM_ASSERT(g.NavWindow && result->Window); if (g.NavLayer == 0) - NavScrollToBringItemIntoView(g.NavWindow, g.NavMoveResultRectRel); + NavScrollToBringItemIntoView(result->Window, result->RectRel); // Apply result from previous frame navigation directional move request ClearActiveID(); - SetNavIDAndMoveMouse(g.NavMoveResultId, g.NavLayer, g.NavMoveResultRectRel); - g.NavJustMovedToId = g.NavMoveResultId; + SetNavIDAndMoveMouse(result->ID, g.NavLayer, result->RectRel); + g.NavJustMovedToId = result->ID; g.NavMoveFromClampedRefRect = false; } @@ -2899,7 +2902,7 @@ static void ImGui::NavUpdate() if (g.NavMoveRequestForward == ImGuiNavForward_ForwardActive) { IM_ASSERT(g.NavMoveRequest); - if (g.NavMoveResultId == 0) + if (g.NavMoveResult.ID == 0) g.NavDisableHighlight = false; g.NavMoveRequestForward = ImGuiNavForward_None; } @@ -3058,9 +3061,10 @@ static void ImGui::NavUpdate() } // Reset search - g.NavMoveResultId = 0; - g.NavMoveResultParentId = 0; - g.NavMoveResultDistAxial = g.NavMoveResultDistBox = g.NavMoveResultDistCenter = FLT_MAX; + ImGuiNavMoveResult* result = &g.NavMoveResult; + result->ID = result->ParentID = 0; + result->Window = NULL; + result->DistAxial = result->DistBox = result->DistCenter = FLT_MAX; // When we have manually scrolled (without using navigation) and NavId becomes out of bounds, we project its bounding box to the visible area to restart navigation within visible items if (g.NavMoveRequest && g.NavMoveFromClampedRefRect && g.NavLayer == 0) @@ -4821,7 +4825,7 @@ bool ImGui::BeginPopupModal(const char* name, bool* p_open, ImGuiWindowFlags fla static void NavProcessMoveRequestWrapAround(ImGuiWindow* window) { ImGuiContext& g = *GImGui; - if (g.NavMoveRequest && g.NavWindow == window && g.NavMoveResultId == 0) + if (g.NavMoveRequest && g.NavWindow == window && g.NavMoveResult.ID == 0) if ((g.NavMoveDir == ImGuiDir_Up || g.NavMoveDir == ImGuiDir_Down) && g.NavMoveRequestForward == ImGuiNavForward_None && g.NavLayer == 0) { g.NavMoveRequestForward = ImGuiNavForward_ForwardQueued; @@ -10856,7 +10860,7 @@ void ImGui::EndMenuBar() ImGuiContext& g = *GImGui; // Nav: When a move request within one of our child menu failed, capture the request to navigate among our siblings. - if (g.NavMoveRequest && g.NavMoveResultId == 0 && (g.NavMoveDir == ImGuiDir_Left || g.NavMoveDir == ImGuiDir_Right) && (g.NavWindow->Flags & ImGuiWindowFlags_ChildMenu)) + if (g.NavMoveRequest && g.NavMoveResult.ID == 0 && (g.NavMoveDir == ImGuiDir_Left || g.NavMoveDir == ImGuiDir_Right) && (g.NavWindow->Flags & ImGuiWindowFlags_ChildMenu)) { ImGuiWindow* nav_earliest_child = g.NavWindow; while (nav_earliest_child->ParentWindow && (nav_earliest_child->ParentWindow->Flags & ImGuiWindowFlags_ChildMenu)) @@ -11024,7 +11028,7 @@ void ImGui::EndMenu() // Nav: When a left move request within our child menu failed, close the menu ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; - if (g.NavWindow && g.NavWindow->ParentWindow == window && g.NavMoveRequest && g.NavMoveResultId == 0 && g.NavMoveDir == ImGuiDir_Left && window->DC.LayoutType == ImGuiLayoutType_Vertical) + if (g.NavWindow && g.NavWindow->ParentWindow == window && g.NavMoveRequest && g.NavMoveResult.ID == 0 && g.NavMoveDir == ImGuiDir_Left && window->DC.LayoutType == ImGuiLayoutType_Vertical) { ClosePopupToLevel(g.OpenPopupStack.Size - 1); g.NavMoveRequest = false; diff --git a/imgui_internal.h b/imgui_internal.h index 2713aa56d997..f277882cdbdb 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -504,6 +504,19 @@ struct ImDrawDataBuilder IMGUI_API void FlattenIntoSingleLayer(); }; +struct ImGuiNavMoveResult +{ + ImGuiID ID; // Best candidate + ImGuiID ParentID; // Best candidate window->IDStack.back() - to compare context + ImGuiWindow* Window; // Best candidate window + float DistBox; // Best candidate box distance to current NavId + float DistCenter; // Best candidate center distance to current NavId + float DistAxial; // Best candidate selected distance (box/center) to current NavId + ImRect RectRel; // Best candidate bounding box in window relative space + + ImGuiNavMoveResult() { ID = ParentID = 0; Window = NULL; DistBox = DistCenter = DistAxial = 0.0f; } +}; + // Storage for SetNexWindow** functions struct ImGuiNextWindowData { @@ -620,12 +633,7 @@ struct ImGuiContext ImGuiNavForward NavMoveRequestForward; // None / ForwardQueued / ForwardActive (this is used to navigate sibling parent menus from a child menu) ImGuiDir NavMoveDir; // Direction of the move request (left/right/up/down) ImGuiDir NavMoveDirLast; // Direction of the previous move request - ImGuiID NavMoveResultId; // Best move request candidate - ImGuiID NavMoveResultParentId; // Best move request candidate window->IDStack.back() - to compare context - float NavMoveResultDistBox; // Best move request candidate box distance to current NavId - float NavMoveResultDistCenter; // Best move request candidate center distance to current NavId - float NavMoveResultDistAxial; - ImRect NavMoveResultRectRel; // Best move request candidate bounding box in window relative space + ImGuiNavMoveResult NavMoveResult; // Best move request candidate // Render ImDrawData DrawData; // Main ImDrawData instance to pass render information to the user @@ -738,9 +746,6 @@ struct ImGuiContext NavMoveRequest = false; NavMoveRequestForward = ImGuiNavForward_None; NavMoveDir = NavMoveDirLast = ImGuiDir_None; - NavMoveResultId = 0; - NavMoveResultParentId = 0; - NavMoveResultDistBox = NavMoveResultDistCenter = NavMoveResultDistAxial = 0.0f; ModalWindowDarkeningRatio = 0.0f; OverlayDrawList._Data = &DrawListSharedData; From c8d8dc7f0a99a9e1ca6c03ccff93dc08e6ac8856 Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 29 Jan 2018 22:15:55 +0100 Subject: [PATCH 542/823] Nav: Internals: Renamed RootNavWindow to NavRootWindow (#787) --- imgui.cpp | 23 ++++++++++++----------- imgui_internal.h | 10 +++++----- 2 files changed, 17 insertions(+), 16 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index cfa2d8e7dfb5..e3666e88bd16 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1906,9 +1906,6 @@ ImGuiWindow::ImGuiWindow(ImGuiContext* context, const char* name) SetWindowPosAllowFlags = SetWindowSizeAllowFlags = SetWindowCollapsedAllowFlags = ImGuiCond_Always | ImGuiCond_Once | ImGuiCond_FirstUseEver | ImGuiCond_Appearing; SetWindowPosVal = SetWindowPosPivot = ImVec2(FLT_MAX, FLT_MAX); - NavLastIds[0] = NavLastIds[1] = 0; - NavRectRel[0] = NavRectRel[1] = ImRect(); - LastFrameActive = -1; ItemWidthDefault = 0.0f; FontWindowScale = 1.0f; @@ -1918,7 +1915,10 @@ ImGuiWindow::ImGuiWindow(ImGuiContext* context, const char* name) ParentWindow = NULL; RootWindow = NULL; RootNonPopupWindow = NULL; - RootNavWindow = NULL; + + NavRootWindow = NULL; + NavLastIds[0] = NavLastIds[1] = 0; + NavRectRel[0] = NavRectRel[1] = ImRect(); FocusIdxAllCounter = FocusIdxTabCounter = -1; FocusIdxAllRequestCurrent = FocusIdxTabRequestCurrent = INT_MAX; @@ -2235,7 +2235,7 @@ static bool NavScoreItem(ImGuiNavMoveResult* result, ImRect cand) // Axial check: if 'curr' has no link at all in some direction and 'cand' lies roughly in that direction, add a tentative link. This will only be kept if no "real" matches // are found, so it only augments the graph produced by the above method using extra links. (important, since it doesn't guarantee strong connectedness) // This is just to avoid buttons having no links in a particular direction when there's a suitable neighbor. you get good graphs without this too. - // 2017/09/29: FIXME: This now currently only enabled inside menubars, ideally we'd disable it everywhere. Menus in particular need to catch failure. For general navigation it feels awkward. + // 2017/09/29: FIXME: This now currently only enabled inside menu bars, ideally we'd disable it everywhere. Menus in particular need to catch failure. For general navigation it feels awkward. // Disabling it may however lead to disconnected graphs when nodes are very spaced out on different axis. Perhaps consider offering this as an option? if (result->DistBox == FLT_MAX && dist_axial < result->DistAxial) // Check axial match if (g.NavLayer == 1 && !(g.NavWindow->Flags & ImGuiWindowFlags_ChildMenu)) @@ -2333,7 +2333,7 @@ bool ImGui::ItemAdd(const ImRect& bb, ImGuiID id, const ImRect* nav_bb_arg) // it may not scale very well for windows with ten of thousands of item, but at least NavMoveRequest is only set on user interaction, aka maximum once a frame. // We could early out with "if (is_clipped && !g.NavInitRequest) return false;" but when we wouldn't be able to reach unclipped widgets. This would work if user had explicit scrolling control (e.g. mapped on a stick) window->DC.NavLayerActiveMaskNext |= window->DC.NavLayerCurrentMask; - if (g.NavWindow == window->RootNavWindow) + if (g.NavWindow == window->NavRootWindow) if (g.NavId == id || g.NavAnyRequest) NavProcessItem(window, nav_bb_arg ? *nav_bb_arg : bb, id); } @@ -2885,9 +2885,10 @@ static void ImGui::NavUpdate() // Process navigation move request if (g.NavMoveRequest && g.NavMoveResult.ID != 0) { - // Scroll to keep newly navigated item fully into view ImGuiNavMoveResult* result = &g.NavMoveResult; IM_ASSERT(g.NavWindow && result->Window); + + // Scroll to keep newly navigated item fully into view if (g.NavLayer == 0) NavScrollToBringItemIntoView(result->Window, result->RectRel); @@ -5527,9 +5528,9 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) window->RootWindow = parent_window->RootWindow; if (parent_window && !(flags & ImGuiWindowFlags_Modal) && (flags & (ImGuiWindowFlags_ChildWindow | ImGuiWindowFlags_Popup))) window->RootNonPopupWindow = parent_window->RootNonPopupWindow; - window->RootNavWindow = window; - //while (window->RootNavWindow->Flags & ImGuiWindowFlags_NavFlattened) - // window->RootNavWindow = window->RootNavWindow->ParentWindow; + window->NavRootWindow = window; + //while (window->NavRootWindow->Flags & ImGuiWindowFlags_NavFlattened) + // window->NavRootWindow = window->NavRootWindow->ParentWindow; window->Active = true; window->BeginOrderWithinParent = 0; @@ -7036,7 +7037,7 @@ void ImGui::SetItemDefaultFocus() ImGuiWindow* window = g.CurrentWindow; if (!window->Appearing) return; - if (g.NavWindow == window->RootNavWindow && (g.NavInitRequest || g.NavInitResultId != 0) && g.NavLayer == g.NavWindow->DC.NavLayerCurrent) + if (g.NavWindow == window->NavRootWindow && (g.NavInitRequest || g.NavInitResultId != 0) && g.NavLayer == g.NavWindow->DC.NavLayerCurrent) { g.NavInitRequest = false; g.NavInitResultExplicit = true; diff --git a/imgui_internal.h b/imgui_internal.h index f277882cdbdb..7328429f5b6a 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -511,7 +511,7 @@ struct ImGuiNavMoveResult ImGuiWindow* Window; // Best candidate window float DistBox; // Best candidate box distance to current NavId float DistCenter; // Best candidate center distance to current NavId - float DistAxial; // Best candidate selected distance (box/center) to current NavId + float DistAxial; ImRect RectRel; // Best candidate bounding box in window relative space ImGuiNavMoveResult() { ID = ParentID = 0; Window = NULL; DistBox = DistCenter = DistAxial = 0.0f; } @@ -921,9 +921,6 @@ struct IMGUI_API ImGuiWindow ImVec2 SetWindowPosVal; // store window position when using a non-zero Pivot (position set needs to be processed when we know the window size) ImVec2 SetWindowPosPivot; // store window pivot for positioning. ImVec2(0,0) when positioning from top-left corner; ImVec2(0.5f,0.5f) for centering; ImVec2(1,1) for bottom right. - ImGuiID NavLastIds[2]; // Last known NavId for this window, per layer (0/1) - ImRect NavRectRel[2]; // Reference rectangle, in window relative space - ImGuiDrawContext DC; // Temporary per-window data, reset at the beginning of the frame ImVector IDStack; // ID stack. ID are hashes seeded with the value at the top of the stack ImRect ClipRect; // = DrawList->clip_rect_stack.back(). Scissoring / clipping rectangle. x1, y1, x2, y2. @@ -939,7 +936,10 @@ struct IMGUI_API ImGuiWindow ImGuiWindow* ParentWindow; // If we are a child _or_ popup window, this is pointing to our parent. Otherwise NULL. ImGuiWindow* RootWindow; // Generally point to ourself. If we are a child window, this is pointing to the first non-child parent window. ImGuiWindow* RootNonPopupWindow; // Generally point to ourself. Used to display TitleBgActive color and for selecting which window to use for NavWindowing - ImGuiWindow* RootNavWindow; // Generally point to ourself. If we are a child window with the ImGuiWindowFlags_NavFlattenedChild flag, point to parent. Used to display TitleBgActive color and for selecting which window to use for NavWindowing. + + ImGuiWindow* NavRootWindow; // Generally point to ourself. If we are a child window with the NavFlattened flag, point to a parent window. + ImGuiID NavLastIds[2]; // Last known NavId for this window, per layer (0/1) + ImRect NavRectRel[2]; // Reference rectangle, in window relative space // Navigation / Focus // FIXME-NAV: Merge all this with the new Nav system, at least the request variables should be moved to ImGuiContext From 020b153d35667a97c27bdf60baad41ca08a66ddd Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 29 Jan 2018 22:51:28 +0100 Subject: [PATCH 543/823] Nav: calling NavMoveRequestCancel() more consistently when hijacking a request. Not strictly necessary. (#787) --- imgui.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index e3666e88bd16..2dba6664766a 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -7839,12 +7839,12 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l if (g.NavId == id && g.NavMoveRequest && g.NavMoveDir == ImGuiDir_Left && is_open) { toggled = true; - g.NavMoveRequest = false; + NavMoveRequestCancel(); } if (g.NavId == id && g.NavMoveRequest && g.NavMoveDir == ImGuiDir_Right && !is_open) // If there's something upcoming on the line we may want to give it the priority? { toggled = true; - g.NavMoveRequest = false; + NavMoveRequestCancel(); } if (toggled) @@ -10976,7 +10976,7 @@ bool ImGui::BeginMenu(const char* label, bool enabled) if (g.NavId == id && g.NavMoveRequest && g.NavMoveDir == ImGuiDir_Right) // Nav-Right to open { want_open = true; - g.NavMoveRequest = false; + NavMoveRequestCancel(); } } else @@ -10993,8 +10993,8 @@ bool ImGui::BeginMenu(const char* label, bool enabled) } else if (g.NavId == id && g.NavMoveRequest && g.NavMoveDir == ImGuiDir_Down) // Nav-Down to open { - g.NavMoveRequest = false; want_open = true; + NavMoveRequestCancel(); } } @@ -11032,7 +11032,7 @@ void ImGui::EndMenu() if (g.NavWindow && g.NavWindow->ParentWindow == window && g.NavMoveRequest && g.NavMoveResult.ID == 0 && g.NavMoveDir == ImGuiDir_Left && window->DC.LayoutType == ImGuiLayoutType_Vertical) { ClosePopupToLevel(g.OpenPopupStack.Size - 1); - g.NavMoveRequest = false; + NavMoveRequestCancel(); } EndPopup(); From b40dc5c4f2935cfdb68c7195745aad0bf8bc19ed Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 29 Jan 2018 22:57:17 +0100 Subject: [PATCH 544/823] Nav: NavScoreItem uses g.CurrentWindow and not g.NavWindow. This was changed as part of b3cba62b80038bd8c8fd722ba5e4e13c83bfb8bc when first trying to implement the NavFlattenedFlag. As it turns out we won't need it. Committing separately for safety. (#787) --- imgui.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/imgui.cpp b/imgui.cpp index 2dba6664766a..edd56adf05dd 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2135,7 +2135,7 @@ static float NavScoreItemDistInterval(float a0, float a1, float b0, float b1) static bool NavScoreItem(ImGuiNavMoveResult* result, ImRect cand) { ImGuiContext& g = *GImGui; - ImGuiWindow* window = g.NavWindow; + ImGuiWindow* window = g.CurrentWindow; if (g.NavLayer != window->DC.NavLayerCurrent) return false; From c851b33352b88cd512008f113bc76db363dee3d2 Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 29 Jan 2018 23:06:55 +0100 Subject: [PATCH 545/823] Nav: Added proper version of ImGuiWindowFlags_NavFlattened that handles scrolling nicely. Marked as private as I'm not happy with the name. (#787) --- imgui.cpp | 54 +++++++++++++++++++++++++++++------------------- imgui.h | 2 +- imgui_demo.cpp | 2 +- imgui_internal.h | 6 ++++-- 4 files changed, 39 insertions(+), 25 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index edd56adf05dd..965305ba7e8d 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2254,6 +2254,12 @@ static inline void NavUpdateAnyRequestFlag() g.NavAnyRequest = g.NavMoveRequest || g.NavInitRequest || IMGUI_DEBUG_NAV_SCORING; } +static bool NavMoveRequestButNoResultYet() +{ + ImGuiContext& g = *GImGui; + return g.NavMoveRequest && g.NavMoveResultLocal.ID == 0 && g.NavMoveResultOther.ID == 0; +} + static void NavMoveRequestCancel() { ImGuiContext& g = *GImGui; @@ -2288,7 +2294,7 @@ static void ImGui::NavProcessItem(ImGuiWindow* window, const ImRect& nav_bb, con // Scoring for navigation if (g.NavId != id && !(item_flags & ImGuiItemFlags_NoNav)) { - ImGuiNavMoveResult* result = &g.NavMoveResult; + ImGuiNavMoveResult* result = (window == g.NavWindow) ? &g.NavMoveResultLocal : &g.NavMoveResultOther; #if IMGUI_DEBUG_NAV_SCORING // [DEBUG] Score all items in NavWindow at all times if (!g.NavMoveRequest) @@ -2333,9 +2339,10 @@ bool ImGui::ItemAdd(const ImRect& bb, ImGuiID id, const ImRect* nav_bb_arg) // it may not scale very well for windows with ten of thousands of item, but at least NavMoveRequest is only set on user interaction, aka maximum once a frame. // We could early out with "if (is_clipped && !g.NavInitRequest) return false;" but when we wouldn't be able to reach unclipped widgets. This would work if user had explicit scrolling control (e.g. mapped on a stick) window->DC.NavLayerActiveMaskNext |= window->DC.NavLayerCurrentMask; - if (g.NavWindow == window->NavRootWindow) - if (g.NavId == id || g.NavAnyRequest) - NavProcessItem(window, nav_bb_arg ? *nav_bb_arg : bb, id); + if (g.NavId == id || g.NavAnyRequest) + if (g.NavWindow->NavRootWindow == window->NavRootWindow) + if (window == g.NavWindow || ((window->Flags | g.NavWindow->Flags) & ImGuiWindowFlags_NavFlattened)) + NavProcessItem(window, nav_bb_arg ? *nav_bb_arg : bb, id); } window->DC.LastItemId = id; @@ -2883,9 +2890,14 @@ static void ImGui::NavUpdate() g.NavJustMovedToId = 0; // Process navigation move request - if (g.NavMoveRequest && g.NavMoveResult.ID != 0) + if (g.NavMoveRequest && (g.NavMoveResultLocal.ID != 0 || g.NavMoveResultOther.ID != 0)) { - ImGuiNavMoveResult* result = &g.NavMoveResult; + // Select which result to use + ImGuiNavMoveResult* result = (g.NavMoveResultLocal.ID != 0) ? &g.NavMoveResultLocal : &g.NavMoveResultOther; + if (g.NavMoveResultOther.ID != 0 && g.NavMoveResultOther.Window->ParentWindow == g.NavWindow) // Maybe entering a flattened child? In this case solve the tie using the regular scoring rules + if ((g.NavMoveResultOther.DistBox < g.NavMoveResultLocal.DistBox) || (g.NavMoveResultOther.DistBox == g.NavMoveResultLocal.DistBox && g.NavMoveResultOther.DistCenter < g.NavMoveResultLocal.DistCenter)) + result = &g.NavMoveResultOther; + IM_ASSERT(g.NavWindow && result->Window); // Scroll to keep newly navigated item fully into view @@ -2894,6 +2906,7 @@ static void ImGui::NavUpdate() // Apply result from previous frame navigation directional move request ClearActiveID(); + g.NavWindow = result->Window; SetNavIDAndMoveMouse(result->ID, g.NavLayer, result->RectRel); g.NavJustMovedToId = result->ID; g.NavMoveFromClampedRefRect = false; @@ -2903,7 +2916,7 @@ static void ImGui::NavUpdate() if (g.NavMoveRequestForward == ImGuiNavForward_ForwardActive) { IM_ASSERT(g.NavMoveRequest); - if (g.NavMoveResult.ID == 0) + if (g.NavMoveResultLocal.ID == 0 && g.NavMoveResultOther.ID == 0) g.NavDisableHighlight = false; g.NavMoveRequestForward = ImGuiNavForward_None; } @@ -3061,11 +3074,9 @@ static void ImGui::NavUpdate() } } - // Reset search - ImGuiNavMoveResult* result = &g.NavMoveResult; - result->ID = result->ParentID = 0; - result->Window = NULL; - result->DistAxial = result->DistBox = result->DistCenter = FLT_MAX; + // Reset search results + g.NavMoveResultLocal.Clear(); + g.NavMoveResultOther.Clear(); // When we have manually scrolled (without using navigation) and NavId becomes out of bounds, we project its bounding box to the visible area to restart navigation within visible items if (g.NavMoveRequest && g.NavMoveFromClampedRefRect && g.NavLayer == 0) @@ -4826,7 +4837,7 @@ bool ImGui::BeginPopupModal(const char* name, bool* p_open, ImGuiWindowFlags fla static void NavProcessMoveRequestWrapAround(ImGuiWindow* window) { ImGuiContext& g = *GImGui; - if (g.NavMoveRequest && g.NavWindow == window && g.NavMoveResult.ID == 0) + if (g.NavWindow == window && NavMoveRequestButNoResultYet()) if ((g.NavMoveDir == ImGuiDir_Up || g.NavMoveDir == ImGuiDir_Down) && g.NavMoveRequestForward == ImGuiNavForward_None && g.NavLayer == 0) { g.NavMoveRequestForward = ImGuiNavForward_ForwardQueued; @@ -4928,7 +4939,7 @@ static bool BeginChildEx(const char* name, ImGuiID id, const ImVec2& size_arg, b g.Style.ChildBorderSize = backup_border_size; // Process navigation-in immediately so NavInit can run on first frame - if (/*!(flags & ImGuiWindowFlags_NavFlattened) &&*/ (child_window->DC.NavLayerActiveMask != 0 || child_window->DC.NavHasScroll) && g.NavActivateId == id) + if (!(flags & ImGuiWindowFlags_NavFlattened) && (child_window->DC.NavLayerActiveMask != 0 || child_window->DC.NavHasScroll) && g.NavActivateId == id) { ImGui::FocusWindow(child_window); ImGui::NavInitWindow(child_window, false); @@ -4972,7 +4983,7 @@ void ImGui::EndChild() ImGuiWindow* parent_window = GetCurrentWindow(); ImRect bb(parent_window->DC.CursorPos, parent_window->DC.CursorPos + sz); ItemSize(sz); - if (/*!(window->Flags & ImGuiWindowFlags_NavFlattened) &&*/ (window->DC.NavLayerActiveMask != 0 || window->DC.NavHasScroll)) + if (!(window->Flags & ImGuiWindowFlags_NavFlattened) && (window->DC.NavLayerActiveMask != 0 || window->DC.NavHasScroll)) { ItemAdd(bb, window->ChildId); RenderNavHighlight(bb, window->ChildId); @@ -5420,8 +5431,9 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) // Automatically disable manual moving/resizing when NoInputs is set if (flags & ImGuiWindowFlags_NoInputs) flags |= ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize; - //if (flags & ImGuiWindowFlags_NavFlattened) - // IM_ASSERT(flags & ImGuiWindowFlags_ChildWindow); + + if (flags & ImGuiWindowFlags_NavFlattened) + IM_ASSERT(flags & ImGuiWindowFlags_ChildWindow); const int current_frame = g.FrameCount; const bool first_begin_of_the_frame = (window->LastFrameActive != current_frame); @@ -5529,8 +5541,8 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) if (parent_window && !(flags & ImGuiWindowFlags_Modal) && (flags & (ImGuiWindowFlags_ChildWindow | ImGuiWindowFlags_Popup))) window->RootNonPopupWindow = parent_window->RootNonPopupWindow; window->NavRootWindow = window; - //while (window->NavRootWindow->Flags & ImGuiWindowFlags_NavFlattened) - // window->NavRootWindow = window->NavRootWindow->ParentWindow; + while (window->NavRootWindow->Flags & ImGuiWindowFlags_NavFlattened) + window->NavRootWindow = window->NavRootWindow->ParentWindow; window->Active = true; window->BeginOrderWithinParent = 0; @@ -10861,7 +10873,7 @@ void ImGui::EndMenuBar() ImGuiContext& g = *GImGui; // Nav: When a move request within one of our child menu failed, capture the request to navigate among our siblings. - if (g.NavMoveRequest && g.NavMoveResult.ID == 0 && (g.NavMoveDir == ImGuiDir_Left || g.NavMoveDir == ImGuiDir_Right) && (g.NavWindow->Flags & ImGuiWindowFlags_ChildMenu)) + if (NavMoveRequestButNoResultYet() && (g.NavMoveDir == ImGuiDir_Left || g.NavMoveDir == ImGuiDir_Right) && (g.NavWindow->Flags & ImGuiWindowFlags_ChildMenu)) { ImGuiWindow* nav_earliest_child = g.NavWindow; while (nav_earliest_child->ParentWindow && (nav_earliest_child->ParentWindow->Flags & ImGuiWindowFlags_ChildMenu)) @@ -11029,7 +11041,7 @@ void ImGui::EndMenu() // Nav: When a left move request within our child menu failed, close the menu ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; - if (g.NavWindow && g.NavWindow->ParentWindow == window && g.NavMoveRequest && g.NavMoveResult.ID == 0 && g.NavMoveDir == ImGuiDir_Left && window->DC.LayoutType == ImGuiLayoutType_Vertical) + if (g.NavWindow && g.NavWindow->ParentWindow == window && NavMoveRequestButNoResultYet() && g.NavMoveDir == ImGuiDir_Left && window->DC.LayoutType == ImGuiLayoutType_Vertical) { ClosePopupToLevel(g.OpenPopupStack.Size - 1); NavMoveRequestCancel(); diff --git a/imgui.h b/imgui.h index 24831dba9e18..8659f1d7440a 100644 --- a/imgui.h +++ b/imgui.h @@ -552,9 +552,9 @@ enum ImGuiWindowFlags_ ImGuiWindowFlags_ResizeFromAnySide = 1 << 17, // (WIP) Enable resize from any corners and borders. Your back-end needs to honor the different values of io.MouseCursor set by imgui. ImGuiWindowFlags_NoNavFocus = 1 << 18, // No focusing of this window with gamepad/keyboard navigation ImGuiWindowFlags_NoNavInputs = 1 << 19, // No gamepad/keyboard navigation within the window - //ImGuiWindowFlags_NavFlattened = 1 << 20, // Allow gamepad/keyboard navigation to cross over parent border to this child (only use on child that have no scrolling!) // [Internal] + ImGuiWindowFlags_NavFlattened = 1 << 20, // (WIP) Allow gamepad/keyboard navigation to cross over parent border to this child (only use on child that have no scrolling!) ImGuiWindowFlags_ChildWindow = 1 << 24, // Don't use! For internal use by BeginChild() ImGuiWindowFlags_Tooltip = 1 << 25, // Don't use! For internal use by BeginTooltip() ImGuiWindowFlags_Popup = 1 << 26, // Don't use! For internal use by BeginPopup() diff --git a/imgui_demo.cpp b/imgui_demo.cpp index a642e5d1d386..2746b8a0a581 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -2148,7 +2148,7 @@ void ImGui::ShowStyleEditor(ImGuiStyle* ref) ImGui::RadioButton("Alpha", &alpha_flags, ImGuiColorEditFlags_AlphaPreview); ImGui::SameLine(); ImGui::RadioButton("Both", &alpha_flags, ImGuiColorEditFlags_AlphaPreviewHalf); - ImGui::BeginChild("#colors", ImVec2(0, 300), true, ImGuiWindowFlags_AlwaysVerticalScrollbar | ImGuiWindowFlags_AlwaysHorizontalScrollbar); + ImGui::BeginChild("#colors", ImVec2(0, 300), true, ImGuiWindowFlags_AlwaysVerticalScrollbar | ImGuiWindowFlags_AlwaysHorizontalScrollbar | ImGuiWindowFlags_NavFlattened); ImGui::PushItemWidth(-160); for (int i = 0; i < ImGuiCol_COUNT; i++) { diff --git a/imgui_internal.h b/imgui_internal.h index 7328429f5b6a..7a691cb74e1a 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -514,7 +514,8 @@ struct ImGuiNavMoveResult float DistAxial; ImRect RectRel; // Best candidate bounding box in window relative space - ImGuiNavMoveResult() { ID = ParentID = 0; Window = NULL; DistBox = DistCenter = DistAxial = 0.0f; } + ImGuiNavMoveResult() { Clear(); } + void Clear() { ID = ParentID = 0; Window = NULL; DistBox = DistCenter = DistAxial = FLT_MAX; RectRel = ImRect(); } }; // Storage for SetNexWindow** functions @@ -633,7 +634,8 @@ struct ImGuiContext ImGuiNavForward NavMoveRequestForward; // None / ForwardQueued / ForwardActive (this is used to navigate sibling parent menus from a child menu) ImGuiDir NavMoveDir; // Direction of the move request (left/right/up/down) ImGuiDir NavMoveDirLast; // Direction of the previous move request - ImGuiNavMoveResult NavMoveResult; // Best move request candidate + ImGuiNavMoveResult NavMoveResultLocal; // Best move request candidate within NavWindow + ImGuiNavMoveResult NavMoveResultOther; // Best move request candidate within NavWindow's flattened hierarchy (when using the NavFlattened flag) // Render ImDrawData DrawData; // Main ImDrawData instance to pass render information to the user From bed6ef03f5821437d6c697fc0607605aa3255ae5 Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 29 Jan 2018 23:49:51 +0100 Subject: [PATCH 546/823] Nav: workaround to kindly handle ALT-TAB without detecting TAB-release on backends that clear all keys on unfocus. (#787) --- TODO.txt | 2 ++ imgui.cpp | 6 ++++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/TODO.txt b/TODO.txt index 0222bd590813..0a46c81cb1bb 100644 --- a/TODO.txt +++ b/TODO.txt @@ -238,6 +238,8 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i - focus: preserve ActiveId/focus stack state, e.g. when opening a menu and close it, previously selected InputText() focus gets restored (#622) - focus: SetKeyboardFocusHere() on with >= 0 offset could be done on same frame (else latch and modulate on beginning of next frame) - focus: unable to use SetKeyboardFocusHere() on clipped widgets. (#787) + + - inputs: we need an explicit flag about whether the imgui window is focused, to be able to distinguish focused key releases vs alt-tabbing all release behaviors. - inputs: rework IO system to be able to pass actual ordered/timestamped events. use an event queue? (~#335, #71) - inputs: support track pad style scrolling & slider edit. diff --git a/imgui.cpp b/imgui.cpp index 965305ba7e8d..5f0ec83358d9 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2780,9 +2780,11 @@ static void ImGui::NavUpdateWindowing() apply_focus_window = g.NavWindowingTarget; } - // Keyboard: Press and release ALT to toggle menu layer + // Keyboard: Press and Release ALT to toggle menu layer + // FIXME: We lack an explicit IO variable for "is the imgui window focused", so compare mouse validity to detect the common case of backend clearing releases all keys on ALT-TAB if ((g.ActiveId == 0 || g.ActiveIdAllowOverlap) && IsNavInputPressed(ImGuiNavInput_KeyMenu, ImGuiInputReadMode_Released)) - apply_toggle_layer = true; + if (IsMousePosValid(&g.IO.MousePos) == IsMousePosValid(&g.IO.MousePosPrev)) + apply_toggle_layer = true; // Move window if (g.NavWindowingTarget && !(g.NavWindowingTarget->Flags & ImGuiWindowFlags_NoMove)) From acf21ee429dc9d37ac03333e5113c6ea6fc119ac Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 30 Jan 2018 15:04:48 +0100 Subject: [PATCH 547/823] Nav: Windows with ImGuiWindowFlags_NoBringToFrontOnFocus flag aren't temporarily displayed on the front when using CTRL-TAB. (#787) --- imgui.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 5f0ec83358d9..8497bde6fe3c 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -3917,14 +3917,15 @@ void ImGui::Render() // Gather windows to render g.IO.MetricsRenderVertices = g.IO.MetricsRenderIndices = g.IO.MetricsActiveWindows = 0; g.DrawDataBuilder.Clear(); + ImGuiWindow* window_to_render_front_most = (g.NavWindowingTarget && !(g.NavWindowingTarget->Flags & ImGuiWindowFlags_NoBringToFrontOnFocus)) ? g.NavWindowingTarget : NULL; for (int n = 0; n != g.Windows.Size; n++) { ImGuiWindow* window = g.Windows[n]; - if (window->Active && window->HiddenFrames <= 0 && (window->Flags & (ImGuiWindowFlags_ChildWindow)) == 0 && window != g.NavWindowingTarget) + if (window->Active && window->HiddenFrames <= 0 && (window->Flags & (ImGuiWindowFlags_ChildWindow)) == 0 && window != window_to_render_front_most) AddWindowToDrawDataSelectLayer(window); } - if (g.NavWindowingTarget && g.NavWindowingTarget->Active && g.NavWindowingTarget->HiddenFrames <= 0) // NavWindowingTarget is always temporarily displayed as the front-most window - AddWindowToDrawDataSelectLayer(g.NavWindowingTarget); + if (window_to_render_front_most && window_to_render_front_most->Active && window_to_render_front_most->HiddenFrames <= 0) // NavWindowingTarget is always temporarily displayed as the front-most window + AddWindowToDrawDataSelectLayer(window_to_render_front_most); g.DrawDataBuilder.FlattenIntoSingleLayer(); // Draw software mouse cursor if requested From a7ad5134e5fcd8cfd95c29cd6087af767af7c4dd Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 30 Jan 2018 15:01:52 +0100 Subject: [PATCH 548/823] Nav: window that are filling the entire display/viewport gets their windowing highlight clamped within. (#787) --- imgui.cpp | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 8497bde6fe3c..af833cebba99 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -5760,13 +5760,13 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) if ((flags & ImGuiWindowFlags_Modal) != 0 && window == GetFrontMostModalRootWindow()) window->DrawList->AddRectFilled(fullscreen_rect.Min, fullscreen_rect.Max, GetColorU32(ImGuiCol_ModalWindowDarkening, g.ModalWindowDarkeningRatio)); - // Draw navigation windowing rectangle (via ImGuiKey_NavWindowing key), shows whole window selected + // Draw navigation selection/windowing rectangle background if (g.NavWindowingTarget == window) { ImRect bb = window->Rect(); bb.Expand(g.FontSize); - window->DrawList->AddRectFilled(bb.Min, bb.Max, GetColorU32(ImGuiCol_NavWindowingHighlight, g.NavWindowingHighlightAlpha * 0.25f), g.Style.WindowRounding); - window->DrawList->AddRect(bb.Min, bb.Max, GetColorU32(ImGuiCol_NavWindowingHighlight, g.NavWindowingHighlightAlpha), g.Style.WindowRounding, ~0, 3.0f); + if (!bb.Contains(viewport_rect)) // Avoid drawing if the window covers all the viewport anyway + window->DrawList->AddRectFilled(bb.Min, bb.Max, GetColorU32(ImGuiCol_NavWindowingHighlight, g.NavWindowingHighlightAlpha * 0.25f), g.Style.WindowRounding); } // Draw window + handle manual resize @@ -5839,6 +5839,16 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) window->DrawList->AddLine(title_bar_rect.GetBL() + ImVec2(style.WindowBorderSize, -1), title_bar_rect.GetBR() + ImVec2(-style.WindowBorderSize,-1), GetColorU32(ImGuiCol_Border), style.FrameBorderSize); } + // Draw navigation selection/windowing rectangle border + if (g.NavWindowingTarget == window) + { + ImRect bb = window->Rect(); + bb.Expand(g.FontSize); + if (bb.Contains(viewport_rect)) + bb.Expand(-g.FontSize - 2.0f); + window->DrawList->AddRect(bb.Min, bb.Max, GetColorU32(ImGuiCol_NavWindowingHighlight, g.NavWindowingHighlightAlpha), g.Style.WindowRounding, ~0, 3.0f); + } + // Store a backup of SizeFull which we will use next frame to decide if we need scrollbars. window->SizeFullAtLastBegin = window->SizeFull; From 38197a236dfbf15e3009cdae274043730d5f1cf8 Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 30 Jan 2018 15:07:20 +0100 Subject: [PATCH 549/823] Internals: Renaming. --- imgui.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 8a08918bc550..249c9cf18f60 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -667,7 +667,7 @@ static void SaveIniSettingsToDisk(const char* ini_filename); static void SaveIniSettingsToMemory(ImVector& out_buf); static void MarkIniSettingsDirty(ImGuiWindow* window); -static ImRect GetVisibleRect(); +static ImRect GetViewportRect(); static void CloseInactivePopups(ImGuiWindow* ref_window); static void ClosePopupToLevel(int remaining); @@ -3685,7 +3685,7 @@ ImVec2 ImGui::GetItemRectSize() return window->DC.LastItemRect.GetSize(); } -static ImRect GetVisibleRect() +static ImRect GetViewportRect() { ImGuiContext& g = *GImGui; if (g.IO.DisplayVisibleMin.x != g.IO.DisplayVisibleMax.x && g.IO.DisplayVisibleMin.y != g.IO.DisplayVisibleMax.y) @@ -4104,7 +4104,7 @@ static ImVec2 FindBestWindowPosForPopup(const ImVec2& ref_pos, const ImVec2& siz // r_avoid = the rectangle to avoid (e.g. for tooltip it is a rectangle around the mouse cursor which we want to avoid. for popups it's a small point around the cursor.) // r_outer = the visible area rectangle, minus safe area padding. If our popup size won't fit because of safe area padding we ignore it. ImVec2 safe_padding = style.DisplaySafeAreaPadding; - ImRect r_outer(GetVisibleRect()); + ImRect r_outer(GetViewportRect()); r_outer.Expand(ImVec2((size.x - r_outer.GetWidth() > safe_padding.x*2) ? -safe_padding.x : 0.0f, (size.y - r_outer.GetHeight() > safe_padding.y*2) ? -safe_padding.y : 0.0f)); ImVec2 base_pos_clamped = ImClamp(ref_pos, r_outer.Min, r_outer.Max - size); //GImGui->OverlayDrawList.AddRect(r_avoid.Min, r_avoid.Max, IM_COL32(255,0,0,255)); @@ -4779,15 +4779,15 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) window->DrawList->Clear(); window->DrawList->Flags = (g.Style.AntiAliasedLines ? ImDrawListFlags_AntiAliasedLines : 0) | (g.Style.AntiAliasedFill ? ImDrawListFlags_AntiAliasedFill : 0); window->DrawList->PushTextureID(g.Font->ContainerAtlas->TexID); - ImRect fullscreen_rect(GetVisibleRect()); + ImRect viewport_rect(GetViewportRect()); if ((flags & ImGuiWindowFlags_ChildWindow) && !(flags & ImGuiWindowFlags_Popup) && !window_is_child_tooltip) PushClipRect(parent_window->ClipRect.Min, parent_window->ClipRect.Max, true); else - PushClipRect(fullscreen_rect.Min, fullscreen_rect.Max, true); + PushClipRect(viewport_rect.Min, viewport_rect.Max, true); // Draw modal window background (darkens what is behind them) if ((flags & ImGuiWindowFlags_Modal) != 0 && window == GetFrontMostModalRootWindow()) - window->DrawList->AddRectFilled(fullscreen_rect.Min, fullscreen_rect.Max, GetColorU32(ImGuiCol_ModalWindowDarkening, g.ModalWindowDarkeningRatio)); + window->DrawList->AddRectFilled(viewport_rect.Min, viewport_rect.Max, GetColorU32(ImGuiCol_ModalWindowDarkening, g.ModalWindowDarkeningRatio)); // Draw window + handle manual resize const float window_rounding = window->WindowRounding; From a8763d14c5b06b7560170c696b5e47e5c9db971f Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 30 Jan 2018 15:07:20 +0100 Subject: [PATCH 550/823] Internals: Renaming. --- imgui.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index af833cebba99..b566e1f4ceb6 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -698,7 +698,7 @@ static void SaveIniSettingsToDisk(const char* ini_filename); static void SaveIniSettingsToMemory(ImVector& out_buf); static void MarkIniSettingsDirty(ImGuiWindow* window); -static ImRect GetVisibleRect(); +static ImRect GetViewportRect(); static void CloseInactivePopups(ImGuiWindow* ref_window); static void ClosePopupToLevel(int remaining); @@ -2629,7 +2629,7 @@ static ImVec2 NavCalcPreferredMousePos() return g.IO.MousePos; const ImRect& rect_rel = window->NavRectRel[g.NavLayer]; ImVec2 pos = g.NavWindow->Pos + ImVec2(rect_rel.Min.x + ImMin(g.Style.FramePadding.x*4, rect_rel.GetWidth()), rect_rel.Max.y - ImMin(g.Style.FramePadding.y, rect_rel.GetHeight())); - ImRect visible_rect = GetVisibleRect(); + ImRect visible_rect = GetViewportRect(); return ImFloor(ImClamp(pos, visible_rect.Min, visible_rect.Max)); // ImFloor() is important because non-integer mouse position application in backend might be lossy and result in undesirable non-zero delta. } @@ -4592,7 +4592,7 @@ ImVec2 ImGui::GetItemRectSize() return window->DC.LastItemRect.GetSize(); } -static ImRect GetVisibleRect() +static ImRect GetViewportRect() { ImGuiContext& g = *GImGui; if (g.IO.DisplayVisibleMin.x != g.IO.DisplayVisibleMax.x && g.IO.DisplayVisibleMin.y != g.IO.DisplayVisibleMax.y) @@ -5046,7 +5046,7 @@ static ImVec2 FindBestWindowPosForPopup(const ImVec2& ref_pos, const ImVec2& siz // r_avoid = the rectangle to avoid (e.g. for tooltip it is a rectangle around the mouse cursor which we want to avoid. for popups it's a small point around the cursor.) // r_outer = the visible area rectangle, minus safe area padding. If our popup size won't fit because of safe area padding we ignore it. ImVec2 safe_padding = style.DisplaySafeAreaPadding; - ImRect r_outer(GetVisibleRect()); + ImRect r_outer(GetViewportRect()); r_outer.Expand(ImVec2((size.x - r_outer.GetWidth() > safe_padding.x*2) ? -safe_padding.x : 0.0f, (size.y - r_outer.GetHeight() > safe_padding.y*2) ? -safe_padding.y : 0.0f)); ImVec2 base_pos_clamped = ImClamp(ref_pos, r_outer.Min, r_outer.Max - size); //GImGui->OverlayDrawList.AddRect(r_avoid.Min, r_avoid.Max, IM_COL32(255,0,0,255)); @@ -5750,15 +5750,15 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) window->DrawList->Clear(); window->DrawList->Flags = (g.Style.AntiAliasedLines ? ImDrawListFlags_AntiAliasedLines : 0) | (g.Style.AntiAliasedFill ? ImDrawListFlags_AntiAliasedFill : 0); window->DrawList->PushTextureID(g.Font->ContainerAtlas->TexID); - ImRect fullscreen_rect(GetVisibleRect()); + ImRect viewport_rect(GetViewportRect()); if ((flags & ImGuiWindowFlags_ChildWindow) && !(flags & ImGuiWindowFlags_Popup) && !window_is_child_tooltip) PushClipRect(parent_window->ClipRect.Min, parent_window->ClipRect.Max, true); else - PushClipRect(fullscreen_rect.Min, fullscreen_rect.Max, true); + PushClipRect(viewport_rect.Min, viewport_rect.Max, true); // Draw modal window background (darkens what is behind them) if ((flags & ImGuiWindowFlags_Modal) != 0 && window == GetFrontMostModalRootWindow()) - window->DrawList->AddRectFilled(fullscreen_rect.Min, fullscreen_rect.Max, GetColorU32(ImGuiCol_ModalWindowDarkening, g.ModalWindowDarkeningRatio)); + window->DrawList->AddRectFilled(viewport_rect.Min, viewport_rect.Max, GetColorU32(ImGuiCol_ModalWindowDarkening, g.ModalWindowDarkeningRatio)); // Draw navigation selection/windowing rectangle background if (g.NavWindowingTarget == window) From 1ed7bce3edf213c00632995929b0fc01bd5c4227 Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 30 Jan 2018 18:29:53 +0100 Subject: [PATCH 551/823] Nav: Removed old unused code. (#787) --- imgui.cpp | 9 --------- 1 file changed, 9 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index b566e1f4ceb6..1e0b6f634c26 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -3839,15 +3839,6 @@ void ImGui::EndFrame() g.ActiveIdClickOffset = g.IO.MousePos - g.HoveredRootWindow->Pos; if (!(g.HoveredWindow->Flags & ImGuiWindowFlags_NoMove) && !(g.HoveredRootWindow->Flags & ImGuiWindowFlags_NoMove)) g.MovingWindow = g.HoveredWindow; - - // FIXME-NAV: This never execute because of the FocusWindow call above, however we may want this behavior? - /* - if (g.NavWindow != g.HoveredWindow) - { - g.NavRefRectRel = ImRect(g.IO.MousePos - g.HoveredWindow->Pos, g.IO.MousePos - g.HoveredWindow->Pos); //ImRect(0,0,0,0); - g.NavDisableHighlight = true; - } - */ } else if (g.NavWindow != NULL && GetFrontMostModalRootWindow() == NULL) { From 9fc6f5907b7cfe70df4d1ebd81eff15f27c3d5a1 Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 30 Jan 2018 18:34:32 +0100 Subject: [PATCH 552/823] Nav: Fixed NavRectRel being cleared for one frame when restoring layer 0 with Alt/Menu key or Escape. Maybe was inconsequential. (#787) --- imgui.cpp | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 1e0b6f634c26..92cefa962c33 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2248,6 +2248,16 @@ static bool NavScoreItem(ImGuiNavMoveResult* result, ImRect cand) return new_best; } +static void NavRestoreLayer(int layer) +{ + ImGuiContext& g = *GImGui; + g.NavLayer = layer; + if (layer == 0 && g.NavWindow->NavLastIds[0] != 0) + SetNavIDAndMoveMouse(g.NavWindow->NavLastIds[0], layer, g.NavWindow->NavRectRel[0]); + else + ImGui::NavInitWindow(g.NavWindow, true); +} + static inline void NavUpdateAnyRequestFlag() { ImGuiContext& g = *GImGui; @@ -2825,13 +2835,9 @@ static void ImGui::NavUpdateWindowing() { if ((g.NavWindow->DC.NavLayerActiveMask & (1 << 1)) == 0 && (g.NavWindow->RootWindow->DC.NavLayerActiveMask & (1 << 1)) != 0) FocusWindow(g.NavWindow->RootWindow); - g.NavLayer = (g.NavWindow->DC.NavLayerActiveMask & (1 << 1)) ? (g.NavLayer ^ 1) : 0; g.NavDisableHighlight = false; g.NavDisableMouseHover = true; - if (g.NavLayer == 0 && g.NavWindow->NavLastIds[0] != 0) - SetNavIDAndMoveMouse(g.NavWindow->NavLastIds[0], g.NavLayer, ImRect()); - else - NavInitWindow(g.NavWindow, true); + NavRestoreLayer((g.NavWindow->DC.NavLayerActiveMask & (1 << 1)) ? (g.NavLayer ^ 1) : 0); } } @@ -2971,11 +2977,7 @@ static void ImGui::NavUpdate() else if (g.NavLayer != 0) { // Leave the "menu" layer - g.NavLayer = 0; - if (g.NavWindow->NavLastIds[0]) - SetNavIDAndMoveMouse(g.NavWindow->NavLastIds[0], g.NavLayer, ImRect()); - else - NavInitWindow(g.NavWindow, true); + NavRestoreLayer(0); } else { From 22f7de0fbdeed04f6279f505d79ed03efa536f2b Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 30 Jan 2018 19:20:20 +0100 Subject: [PATCH 553/823] Nav: Updated TODO list. --- TODO.txt | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/TODO.txt b/TODO.txt index 0a46c81cb1bb..f0ef26b9f92a 100644 --- a/TODO.txt +++ b/TODO.txt @@ -229,10 +229,13 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i - font: fix AddRemapChar() to work before font has been built. - font: (api breaking) removed "TTF" from symbol names. also because it now supports OTF. -!- nav/keyboard: tooltip & combo boxes are messing up / not honoring keyboard tabbing. - nav: integrate navigation branch into master. (#787) + - nav: Menu/Esc on a menu restore layer 0 but lose child window position. + - nav: Esc on a flattened child + - nav: menus: allow pressing Menu to leave a sub-menu. - nav: integrate/design keyboard controls. - - nav: once tab should go through most/all widgets (in submission order?) + - nav: simulate right-click or context activation? (SHIFT+F10) + - nav: tabs should go through most/all widgets (in submission order?) - nav: currently cannot access menubar of a child window with Alt/menu key. - nav: esc/enter default behavior for popups, e.g. be able to mark an "ok" or "cancel" button that would get triggered by those keys. - focus: preserve ActiveId/focus stack state, e.g. when opening a menu and close it, previously selected InputText() focus gets restored (#622) From bd579e5429d4907549eb1bd8600d435c2b5cae06 Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 30 Jan 2018 20:07:12 +0100 Subject: [PATCH 554/823] Nav: Removed io.NavUsable --> io.NavActive, io.NavActive --> io.NavVisible. (#787). NavActive takes account of NavFlags enable flags. --- imgui.cpp | 12 ++++++------ imgui.h | 4 ++-- imgui_demo.cpp | 2 +- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 92cefa962c33..3b9753dddef1 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -221,8 +221,8 @@ - For gamepad use, the easiest approach is to go all-or-nothing, with a buttons combo that toggle your inputs between imgui and your game/application. Sharing inputs in a more advanced or granular way between imgui and your game/application may be tricky and requires further work on imgui. For more advanced uses, you may want to use: - - io.NavUsable: true when a window is focused and it doesn't have the ImGuiWindowFlags_NoNavInputs flag set. - - io.NavActive: true when the navigation cursor is visible (and usually goes false when mouse is used). + - io.NavActive: true when a window is focused and it doesn't have the ImGuiWindowFlags_NoNavInputs flag set. + - io.NavVisible: true when the navigation cursor is visible (and usually goes false when mouse is used). - query focus information with IsWindowFocused(), IsAnyWindowFocused(), IsAnyItemFocused() functions. The reality is more complex than what those flags can express. Please discuss your issues and usage scenario in the thread above! As we head toward more keyboard-oriented development this aspect will need to be improved. @@ -2281,7 +2281,7 @@ static void NavMoveRequestCancel() static void ImGui::NavProcessItem(ImGuiWindow* window, const ImRect& nav_bb, const ImGuiID id) { ImGuiContext& g = *GImGui; - //if (!g.IO.NavUsable) // [2017/10/06] Removed this possibly redundant test but I am not sure of all the side-effects yet. Some of the feature here will need to work regardless of using a _NoNavInputs flag. + //if (!g.IO.NavActive) // [2017/10/06] Removed this possibly redundant test but I am not sure of all the side-effects yet. Some of the feature here will need to work regardless of using a _NoNavInputs flag. // return; const ImGuiItemFlags item_flags = window->DC.ItemFlags; @@ -2947,8 +2947,8 @@ static void ImGui::NavUpdate() NavUpdateWindowing(); // Set output flags for user application - g.IO.NavUsable = g.NavWindow && !(g.NavWindow->Flags & ImGuiWindowFlags_NoNavInputs); - g.IO.NavActive = (g.IO.NavUsable && g.NavId != 0 && !g.NavDisableHighlight) || (g.NavWindowingTarget != NULL) || g.NavInitRequest; + g.IO.NavActive = (g.IO.NavFlags & (ImGuiNavFlags_EnableGamepad | ImGuiNavFlags_EnableKeyboard)) && g.NavWindow && !(g.NavWindow->Flags & ImGuiWindowFlags_NoNavInputs); + g.IO.NavVisible = (g.IO.NavActive && g.NavId != 0 && !g.NavDisableHighlight) || (g.NavWindowingTarget != NULL) || g.NavInitRequest; // Process NavCancel input (to close a popup, get back to parent, clear focus) if (IsNavInputPressed(ImGuiNavInput_PadCancel, ImGuiInputReadMode_Pressed)) @@ -13017,7 +13017,7 @@ void ImGui::ShowMetricsWindow(bool* p_open) ImGui::Text("ActiveId: 0x%08X/0x%08X (%.2f sec), ActiveIdSource: %s", g.ActiveId, g.ActiveIdPreviousFrame, g.ActiveIdTimer, input_source_names[g.ActiveIdSource]); ImGui::Text("ActiveIdWindow: '%s'", g.ActiveIdWindow ? g.ActiveIdWindow->Name : "NULL"); ImGui::Text("NavWindow: '%s', NavId: 0x%08X, NavLayer: %d", g.NavWindow ? g.NavWindow->Name : "NULL", g.NavId, g.NavLayer); - ImGui::Text("NavUsable: %d, NavActive: %d", g.IO.NavUsable, g.IO.NavActive); + ImGui::Text("NavActive: %d, NavVisible: %d", g.IO.NavActive, g.IO.NavVisible); ImGui::Text("NavActivateId: 0x%08X, NavInputId: 0x%08X", g.NavActivateId, g.NavInputId); ImGui::Text("NavDisableHighlight: %d, NavDisableMouseHover: %d", g.NavDisableHighlight, g.NavDisableMouseHover); ImGui::Text("DragDrop: %d, SourceId = 0x%08X, Payload \"%s\" (%d bytes)", g.DragDropActive, g.DragDropPayload.SourceId, g.DragDropPayload.DataType, g.DragDropPayload.DataSize); diff --git a/imgui.h b/imgui.h index 8659f1d7440a..9a1fc5e1a5fe 100644 --- a/imgui.h +++ b/imgui.h @@ -1016,8 +1016,8 @@ struct ImGuiIO bool WantCaptureKeyboard; // When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application. This is set by ImGui when it wants to use your keyboard inputs. bool WantTextInput; // Mobile/console: when io.WantTextInput is true, you may display an on-screen keyboard. This is set by ImGui when it wants textual keyboard input to happen (e.g. when a InputText widget is active). bool WantMoveMouse; // MousePos has been altered, back-end should reposition mouse on next frame. Set only when ImGuiNavFlags_MoveMouse flag is enabled in io.NavFlags. - bool NavUsable; // Directional navigation is currently allowed (will handle ImGuiKey_NavXXX events) ~ a window is focused and it doesn't use the ImGuiWindowFlags_NoNavInputs flag. - bool NavActive; // Directional navigation is active/visible and currently allowed (will handle ImGuiKey_NavXXX events). + bool NavActive; // Directional navigation is currently allowed (will handle ImGuiKey_NavXXX events) = a window is focused and it doesn't use the ImGuiWindowFlags_NoNavInputs flag. + bool NavVisible; // Directional navigation is visible and allowed (will handle ImGuiKey_NavXXX events). float Framerate; // Application framerate estimation, in frame per second. Solely for convenience. Rolling average estimation based on IO.DeltaTime over 120 frames int MetricsAllocs; // Number of active memory allocations int MetricsRenderVertices; // Vertices output during last call to Render() diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 2746b8a0a581..06e8f71192a6 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -1818,7 +1818,7 @@ void ImGui::ShowDemoWindow(bool* p_open) ImGui::Text("Keys release:"); for (int i = 0; i < IM_ARRAYSIZE(io.KeysDown); i++) if (ImGui::IsKeyReleased(i)) { ImGui::SameLine(); ImGui::Text("%d", i); } ImGui::Text("Keys mods: %s%s%s%s", io.KeyCtrl ? "CTRL " : "", io.KeyShift ? "SHIFT " : "", io.KeyAlt ? "ALT " : "", io.KeySuper ? "SUPER " : ""); - ImGui::Text("NavUsable: %d, NavActive: %d", io.NavUsable, io.NavActive); + ImGui::Text("NavActive: %d, NavVisible: %d", io.NavActive, io.NavVisible); ImGui::Text("NavInputs down:"); for (int i = 0; i < IM_ARRAYSIZE(io.NavInputs); i++) if (io.NavInputs[i] > 0.0f) { ImGui::SameLine(); ImGui::Text("[%d] %.2f", i, io.NavInputs[i]); } ImGui::Text("NavInputs pressed:"); for (int i = 0; i < IM_ARRAYSIZE(io.NavInputs); i++) if (io.NavInputsDownDuration[i] == 0.0f) { ImGui::SameLine(); ImGui::Text("[%d]", i); } ImGui::Text("NavInputs duration:"); for (int i = 0; i < IM_ARRAYSIZE(io.NavInputs); i++) if (io.NavInputsDownDuration[i] >= 0.0f) { ImGui::SameLine(); ImGui::Text("[%d] %.2f", i, io.NavInputsDownDuration[i]); } From bebe03db0515b80ea108c363b2ef1fd89c573c16 Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 30 Jan 2018 21:17:27 +0100 Subject: [PATCH 555/823] Metrics: Minor formatting tweaks --- imgui.cpp | 8 ++++---- imgui_demo.cpp | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 249c9cf18f60..a16b0216de80 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -11677,7 +11677,7 @@ void ImGui::ShowMetricsWindow(bool* p_open) ImGui::Text("%d vertices, %d indices (%d triangles)", ImGui::GetIO().MetricsRenderVertices, ImGui::GetIO().MetricsRenderIndices, ImGui::GetIO().MetricsRenderIndices / 3); ImGui::Text("%d allocations", ImGui::GetIO().MetricsAllocs); static bool show_clip_rects = true; - ImGui::Checkbox("Show clipping rectangles when hovering an ImDrawCmd", &show_clip_rects); + ImGui::Checkbox("Show clipping rectangles when hovering draw commands", &show_clip_rects); ImGui::Separator(); struct Funcs @@ -11710,7 +11710,7 @@ void ImGui::ShowMetricsWindow(bool* p_open) continue; } ImDrawIdx* idx_buffer = (draw_list->IdxBuffer.Size > 0) ? draw_list->IdxBuffer.Data : NULL; - bool pcmd_node_open = ImGui::TreeNode((void*)(pcmd - draw_list->CmdBuffer.begin()), "Draw %-4d %s vtx, tex = %p, clip_rect = (%.0f,%.0f)..(%.0f,%.0f)", pcmd->ElemCount, draw_list->IdxBuffer.Size > 0 ? "indexed" : "non-indexed", pcmd->TextureId, pcmd->ClipRect.x, pcmd->ClipRect.y, pcmd->ClipRect.z, pcmd->ClipRect.w); + bool pcmd_node_open = ImGui::TreeNode((void*)(pcmd - draw_list->CmdBuffer.begin()), "Draw %4d %s vtx, tex 0x%p, clip_rect (%4.0f,%4.0f)-(%4.0f,%4.0f)", pcmd->ElemCount, draw_list->IdxBuffer.Size > 0 ? "indexed" : "non-indexed", pcmd->TextureId, pcmd->ClipRect.x, pcmd->ClipRect.y, pcmd->ClipRect.z, pcmd->ClipRect.w); if (show_clip_rects && ImGui::IsItemHovered()) { ImRect clip_rect = pcmd->ClipRect; @@ -11735,7 +11735,7 @@ void ImGui::ShowMetricsWindow(bool* p_open) { ImDrawVert& v = draw_list->VtxBuffer[idx_buffer ? idx_buffer[vtx_i] : vtx_i]; triangles_pos[n] = v.pos; - buf_p += ImFormatString(buf_p, (int)(buf_end - buf_p), "%s %04d { pos = (%8.2f,%8.2f), uv = (%.6f,%.6f), col = %08X }\n", (n == 0) ? "vtx" : " ", vtx_i, v.pos.x, v.pos.y, v.uv.x, v.uv.y, v.col); + buf_p += ImFormatString(buf_p, (int)(buf_end - buf_p), "%s %04d: pos (%8.2f,%8.2f), uv (%.6f,%.6f), col %08X\n", (n == 0) ? "vtx" : " ", vtx_i, v.pos.x, v.pos.y, v.uv.x, v.uv.y, v.col); } ImGui::Selectable(buf, false); if (ImGui::IsItemHovered()) @@ -11793,7 +11793,7 @@ void ImGui::ShowMetricsWindow(bool* p_open) } ImGui::TreePop(); } - if (ImGui::TreeNode("Basic state")) + if (ImGui::TreeNode("Internal state")) { ImGui::Text("HoveredWindow: '%s'", g.HoveredWindow ? g.HoveredWindow->Name : "NULL"); ImGui::Text("HoveredRootWindow: '%s'", g.HoveredRootWindow ? g.HoveredRootWindow->Name : "NULL"); diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 9c49281fb848..8fb10149e296 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -94,7 +94,7 @@ static void ShowHelpMarker(const char* desc) if (ImGui::IsItemHovered()) { ImGui::BeginTooltip(); - ImGui::PushTextWrapPos(450.0f); + ImGui::PushTextWrapPos(ImGui::GetFontSize() * 35.0f); ImGui::TextUnformatted(desc); ImGui::PopTextWrapPos(); ImGui::EndTooltip(); From 955d86199fd7216dcc51a82951ebc8be6da560a7 Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 30 Jan 2018 23:55:23 +0100 Subject: [PATCH 556/823] Examples: Tweaks formatting. --- examples/directx10_example/main.cpp | 30 ++++++++++++++--------------- examples/directx11_example/main.cpp | 30 ++++++++++++++--------------- 2 files changed, 28 insertions(+), 32 deletions(-) diff --git a/examples/directx10_example/main.cpp b/examples/directx10_example/main.cpp index fccdda60f61f..3e57d797a96b 100644 --- a/examples/directx10_example/main.cpp +++ b/examples/directx10_example/main.cpp @@ -39,22 +39,20 @@ HRESULT CreateDeviceD3D(HWND hWnd) { // Setup swap chain DXGI_SWAP_CHAIN_DESC sd; - { - ZeroMemory(&sd, sizeof(sd)); - sd.BufferCount = 2; - sd.BufferDesc.Width = 0; - sd.BufferDesc.Height = 0; - sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; - sd.BufferDesc.RefreshRate.Numerator = 60; - sd.BufferDesc.RefreshRate.Denominator = 1; - sd.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH; - sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; - sd.OutputWindow = hWnd; - sd.SampleDesc.Count = 1; - sd.SampleDesc.Quality = 0; - sd.Windowed = TRUE; - sd.SwapEffect = DXGI_SWAP_EFFECT_DISCARD; - } + ZeroMemory(&sd, sizeof(sd)); + sd.BufferCount = 2; + sd.BufferDesc.Width = 0; + sd.BufferDesc.Height = 0; + sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + sd.BufferDesc.RefreshRate.Numerator = 60; + sd.BufferDesc.RefreshRate.Denominator = 1; + sd.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH; + sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; + sd.OutputWindow = hWnd; + sd.SampleDesc.Count = 1; + sd.SampleDesc.Quality = 0; + sd.Windowed = TRUE; + sd.SwapEffect = DXGI_SWAP_EFFECT_DISCARD; UINT createDeviceFlags = 0; //createDeviceFlags |= D3D10_CREATE_DEVICE_DEBUG; diff --git a/examples/directx11_example/main.cpp b/examples/directx11_example/main.cpp index f1e3b8ac8b55..852bb199507e 100644 --- a/examples/directx11_example/main.cpp +++ b/examples/directx11_example/main.cpp @@ -39,22 +39,20 @@ HRESULT CreateDeviceD3D(HWND hWnd) { // Setup swap chain DXGI_SWAP_CHAIN_DESC sd; - { - ZeroMemory(&sd, sizeof(sd)); - sd.BufferCount = 2; - sd.BufferDesc.Width = 0; - sd.BufferDesc.Height = 0; - sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; - sd.BufferDesc.RefreshRate.Numerator = 60; - sd.BufferDesc.RefreshRate.Denominator = 1; - sd.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH; - sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; - sd.OutputWindow = hWnd; - sd.SampleDesc.Count = 1; - sd.SampleDesc.Quality = 0; - sd.Windowed = TRUE; - sd.SwapEffect = DXGI_SWAP_EFFECT_DISCARD; - } + ZeroMemory(&sd, sizeof(sd)); + sd.BufferCount = 2; + sd.BufferDesc.Width = 0; + sd.BufferDesc.Height = 0; + sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + sd.BufferDesc.RefreshRate.Numerator = 60; + sd.BufferDesc.RefreshRate.Denominator = 1; + sd.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH; + sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; + sd.OutputWindow = hWnd; + sd.SampleDesc.Count = 1; + sd.SampleDesc.Quality = 0; + sd.Windowed = TRUE; + sd.SwapEffect = DXGI_SWAP_EFFECT_DISCARD; UINT createDeviceFlags = 0; //createDeviceFlags |= D3D11_CREATE_DEVICE_DEBUG; From 596b6d6de236010d05f0a0ba30c8a9ad714de8c6 Mon Sep 17 00:00:00 2001 From: omar Date: Wed, 31 Jan 2018 00:03:11 +0100 Subject: [PATCH 557/823] Style: Enable window border by default. (#707) --- imgui.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/imgui.cpp b/imgui.cpp index a16b0216de80..5629f55377bd 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -724,7 +724,7 @@ ImGuiStyle::ImGuiStyle() Alpha = 1.0f; // Global alpha applies to everything in ImGui WindowPadding = ImVec2(8,8); // Padding within a window WindowRounding = 7.0f; // Radius of window corners rounding. Set to 0.0f to have rectangular windows - WindowBorderSize = 0.0f; // Thickness of border around windows. Generally set to 0.0f or 1.0f. Other values not well tested. + WindowBorderSize = 1.0f; // Thickness of border around windows. Generally set to 0.0f or 1.0f. Other values not well tested. WindowMinSize = ImVec2(32,32); // Minimum window size WindowTitleAlign = ImVec2(0.0f,0.5f);// Alignment for title bar text ChildRounding = 0.0f; // Radius of child window corners rounding. Set to 0.0f to have rectangular child windows From cca9c3e3dadfe38c69ce4f78eb2ff239ee9a16de Mon Sep 17 00:00:00 2001 From: omar Date: Wed, 31 Jan 2018 00:15:47 +0100 Subject: [PATCH 558/823] Examples: Using Dark theme by default. (#707). Tweaked demo code. --- examples/allegro5_example/main.cpp | 30 ++++++++++++++++--------- examples/directx10_example/main.cpp | 30 ++++++++++++++++--------- examples/directx11_example/main.cpp | 30 ++++++++++++++++--------- examples/directx9_example/main.cpp | 30 ++++++++++++++++--------- examples/marmalade_example/main.cpp | 30 ++++++++++++++++--------- examples/opengl2_example/main.cpp | 30 ++++++++++++++++--------- examples/opengl3_example/main.cpp | 30 ++++++++++++++++--------- examples/sdl_opengl2_example/main.cpp | 32 +++++++++++++++++---------- examples/sdl_opengl3_example/main.cpp | 30 ++++++++++++++++--------- examples/vulkan_example/main.cpp | 30 ++++++++++++++++--------- imgui_demo.cpp | 2 +- 11 files changed, 192 insertions(+), 112 deletions(-) diff --git a/examples/allegro5_example/main.cpp b/examples/allegro5_example/main.cpp index 7ecf4321397c..256415adb537 100644 --- a/examples/allegro5_example/main.cpp +++ b/examples/allegro5_example/main.cpp @@ -26,8 +26,8 @@ int main(int, char**) ImGui_ImplA5_Init(display); // Setup style - ImGui::StyleColorsClassic(); - //ImGui::StyleColorsDark(); + ImGui::StyleColorsDark(); + //ImGui::StyleColorsClassic(); // Load Fonts // - If no fonts are loaded, dear imgui will use the default font. You can also load multiple fonts and use ImGui::PushFont()/PopFont() to select them. @@ -76,25 +76,33 @@ int main(int, char**) // Tip: if we don't call ImGui::Begin()/ImGui::End() the widgets automatically appears in a window called "Debug". { static float f = 0.0f; - ImGui::Text("Hello, world!"); // Some text (you can use a format string too) - ImGui::SliderFloat("float", &f, 0.0f, 1.0f); // Edit 1 float as a slider from 0.0f to 1.0f - ImGui::ColorEdit3("clear color", (float*)&clear_color); // Edit 3 floats as a color - if (ImGui::Button("Demo Window")) // Use buttons to toggle our bools. We could use Checkbox() as well. - show_demo_window ^= 1; - if (ImGui::Button("Another Window")) - show_another_window ^= 1; + static int counter = 0; + ImGui::Text("Hello, world!"); // Display some text (you can use a format string too) + ImGui::SliderFloat("float", &f, 0.0f, 1.0f); // Edit 1 float using a slider from 0.0f to 1.0f + ImGui::ColorEdit3("clear color", (float*)&clear_color); // Edit 3 floats representing a color + + ImGui::Checkbox("Demo Window", &show_demo_window); // Edit bools storing our windows open/close state + ImGui::Checkbox("Another Window", &show_another_window); + + if (ImGui::Button("Button")) // Buttons return true when clicked (NB: most widgets return true when edited/activated) + counter++; + ImGui::SameLine(); + ImGui::Text("counter = %d", counter); + ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate); } - // 2. Show another simple window. In most cases you will use an explicit Begin/End pair to name the window. + // 2. Show another simple window. In most cases you will use an explicit Begin/End pair to name your windows. if (show_another_window) { ImGui::Begin("Another Window", &show_another_window); ImGui::Text("Hello from another window!"); + if (ImGui::Button("Close Me")) + show_another_window = false; ImGui::End(); } - // 3. Show the ImGui demo window. Most of the sample code is in ImGui::ShowDemoWindow(). + // 3. Show the ImGui demo window. Most of the sample code is in ImGui::ShowDemoWindow(). Read its code to learn more about Dear ImGui! if (show_demo_window) { ImGui::SetNextWindowPos(ImVec2(650, 20), ImGuiCond_FirstUseEver); // Normally user code doesn't need/want to call this because positions are saved in .ini file anyway. Here we just want to make the demo initial state a bit more friendly! diff --git a/examples/directx10_example/main.cpp b/examples/directx10_example/main.cpp index 3e57d797a96b..1bb42c729df1 100644 --- a/examples/directx10_example/main.cpp +++ b/examples/directx10_example/main.cpp @@ -123,8 +123,8 @@ int main(int, char**) ImGui_ImplDX10_Init(hwnd, g_pd3dDevice); // Setup style - ImGui::StyleColorsClassic(); - //ImGui::StyleColorsDark(); + ImGui::StyleColorsDark(); + //ImGui::StyleColorsClassic(); // Load Fonts // - If no fonts are loaded, dear imgui will use the default font. You can also load multiple fonts and use ImGui::PushFont()/PopFont() to select them. @@ -167,25 +167,33 @@ int main(int, char**) // Tip: if we don't call ImGui::Begin()/ImGui::End() the widgets automatically appears in a window called "Debug". { static float f = 0.0f; - ImGui::Text("Hello, world!"); // Some text (you can use a format string too) - ImGui::SliderFloat("float", &f, 0.0f, 1.0f); // Edit 1 float as a slider from 0.0f to 1.0f - ImGui::ColorEdit3("clear color", (float*)&clear_color); // Edit 3 floats as a color - if (ImGui::Button("Demo Window")) // Use buttons to toggle our bools. We could use Checkbox() as well. - show_demo_window ^= 1; - if (ImGui::Button("Another Window")) - show_another_window ^= 1; + static int counter = 0; + ImGui::Text("Hello, world!"); // Display some text (you can use a format string too) + ImGui::SliderFloat("float", &f, 0.0f, 1.0f); // Edit 1 float using a slider from 0.0f to 1.0f + ImGui::ColorEdit3("clear color", (float*)&clear_color); // Edit 3 floats representing a color + + ImGui::Checkbox("Demo Window", &show_demo_window); // Edit bools storing our windows open/close state + ImGui::Checkbox("Another Window", &show_another_window); + + if (ImGui::Button("Button")) // Buttons return true when clicked (NB: most widgets return true when edited/activated) + counter++; + ImGui::SameLine(); + ImGui::Text("counter = %d", counter); + ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate); } - // 2. Show another simple window. In most cases you will use an explicit Begin/End pair to name the window. + // 2. Show another simple window. In most cases you will use an explicit Begin/End pair to name your windows. if (show_another_window) { ImGui::Begin("Another Window", &show_another_window); ImGui::Text("Hello from another window!"); + if (ImGui::Button("Close Me")) + show_another_window = false; ImGui::End(); } - // 3. Show the ImGui demo window. Most of the sample code is in ImGui::ShowDemoWindow(). + // 3. Show the ImGui demo window. Most of the sample code is in ImGui::ShowDemoWindow(). Read its code to learn more about Dear ImGui! if (show_demo_window) { ImGui::SetNextWindowPos(ImVec2(650, 20), ImGuiCond_FirstUseEver); // Normally user code doesn't need/want to call this because positions are saved in .ini file anyway. Here we just want to make the demo initial state a bit more friendly! diff --git a/examples/directx11_example/main.cpp b/examples/directx11_example/main.cpp index 852bb199507e..10db035d4212 100644 --- a/examples/directx11_example/main.cpp +++ b/examples/directx11_example/main.cpp @@ -126,8 +126,8 @@ int main(int, char**) ImGui_ImplDX11_Init(hwnd, g_pd3dDevice, g_pd3dDeviceContext); // Setup style - ImGui::StyleColorsClassic(); - //ImGui::StyleColorsDark(); + ImGui::StyleColorsDark(); + //ImGui::StyleColorsClassic(); // Load Fonts // - If no fonts are loaded, dear imgui will use the default font. You can also load multiple fonts and use ImGui::PushFont()/PopFont() to select them. @@ -170,25 +170,33 @@ int main(int, char**) // Tip: if we don't call ImGui::Begin()/ImGui::End() the widgets automatically appears in a window called "Debug". { static float f = 0.0f; - ImGui::Text("Hello, world!"); // Some text (you can use a format string too) - ImGui::SliderFloat("float", &f, 0.0f, 1.0f); // Edit 1 float as a slider from 0.0f to 1.0f - ImGui::ColorEdit3("clear color", (float*)&clear_color); // Edit 3 floats as a color - if (ImGui::Button("Demo Window")) // Use buttons to toggle our bools. We could use Checkbox() as well. - show_demo_window ^= 1; - if (ImGui::Button("Another Window")) - show_another_window ^= 1; + static int counter = 0; + ImGui::Text("Hello, world!"); // Display some text (you can use a format string too) + ImGui::SliderFloat("float", &f, 0.0f, 1.0f); // Edit 1 float using a slider from 0.0f to 1.0f + ImGui::ColorEdit3("clear color", (float*)&clear_color); // Edit 3 floats representing a color + + ImGui::Checkbox("Demo Window", &show_demo_window); // Edit bools storing our windows open/close state + ImGui::Checkbox("Another Window", &show_another_window); + + if (ImGui::Button("Button")) // Buttons return true when clicked (NB: most widgets return true when edited/activated) + counter++; + ImGui::SameLine(); + ImGui::Text("counter = %d", counter); + ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate); } - // 2. Show another simple window. In most cases you will use an explicit Begin/End pair to name the window. + // 2. Show another simple window. In most cases you will use an explicit Begin/End pair to name your windows. if (show_another_window) { ImGui::Begin("Another Window", &show_another_window); ImGui::Text("Hello from another window!"); + if (ImGui::Button("Close Me")) + show_another_window = false; ImGui::End(); } - // 3. Show the ImGui demo window. Most of the sample code is in ImGui::ShowDemoWindow(). + // 3. Show the ImGui demo window. Most of the sample code is in ImGui::ShowDemoWindow(). Read its code to learn more about Dear ImGui! if (show_demo_window) { ImGui::SetNextWindowPos(ImVec2(650, 20), ImGuiCond_FirstUseEver); // Normally user code doesn't need/want to call this because positions are saved in .ini file anyway. Here we just want to make the demo initial state a bit more friendly! diff --git a/examples/directx9_example/main.cpp b/examples/directx9_example/main.cpp index d0323dca025b..5a05d8828162 100644 --- a/examples/directx9_example/main.cpp +++ b/examples/directx9_example/main.cpp @@ -78,8 +78,8 @@ int main(int, char**) ImGui_ImplDX9_Init(hwnd, g_pd3dDevice); // Setup style - ImGui::StyleColorsClassic(); - //ImGui::StyleColorsDark(); + ImGui::StyleColorsDark(); + //ImGui::StyleColorsClassic(); // Load Fonts // - If no fonts are loaded, dear imgui will use the default font. You can also load multiple fonts and use ImGui::PushFont()/PopFont() to select them. @@ -124,25 +124,33 @@ int main(int, char**) // Tip: if we don't call ImGui::Begin()/ImGui::End() the widgets automatically appears in a window called "Debug". { static float f = 0.0f; - ImGui::Text("Hello, world!"); // Some text (you can use a format string too) - ImGui::SliderFloat("float", &f, 0.0f, 1.0f); // Edit 1 float as a slider from 0.0f to 1.0f - ImGui::ColorEdit3("clear color", (float*)&clear_color); // Edit 3 floats as a color - if (ImGui::Button("Demo Window")) // Use buttons to toggle our bools. We could use Checkbox() as well. - show_demo_window ^= 1; - if (ImGui::Button("Another Window")) - show_another_window ^= 1; + static int counter = 0; + ImGui::Text("Hello, world!"); // Display some text (you can use a format string too) + ImGui::SliderFloat("float", &f, 0.0f, 1.0f); // Edit 1 float using a slider from 0.0f to 1.0f + ImGui::ColorEdit3("clear color", (float*)&clear_color); // Edit 3 floats representing a color + + ImGui::Checkbox("Demo Window", &show_demo_window); // Edit bools storing our windows open/close state + ImGui::Checkbox("Another Window", &show_another_window); + + if (ImGui::Button("Button")) // Buttons return true when clicked (NB: most widgets return true when edited/activated) + counter++; + ImGui::SameLine(); + ImGui::Text("counter = %d", counter); + ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate); } - // 2. Show another simple window. In most cases you will use an explicit Begin/End pair to name the window. + // 2. Show another simple window. In most cases you will use an explicit Begin/End pair to name your windows. if (show_another_window) { ImGui::Begin("Another Window", &show_another_window); ImGui::Text("Hello from another window!"); + if (ImGui::Button("Close Me")) + show_another_window = false; ImGui::End(); } - // 3. Show the ImGui demo window. Most of the sample code is in ImGui::ShowDemoWindow(). + // 3. Show the ImGui demo window. Most of the sample code is in ImGui::ShowDemoWindow(). Read its code to learn more about Dear ImGui! if (show_demo_window) { ImGui::SetNextWindowPos(ImVec2(650, 20), ImGuiCond_FirstUseEver); // Normally user code doesn't need/want to call this because positions are saved in .ini file anyway. Here we just want to make the demo initial state a bit more friendly! diff --git a/examples/marmalade_example/main.cpp b/examples/marmalade_example/main.cpp index 338c469cd500..c47a33310a8a 100644 --- a/examples/marmalade_example/main.cpp +++ b/examples/marmalade_example/main.cpp @@ -18,8 +18,8 @@ int main(int, char**) ImGui_Marmalade_Init(true); // Setup style - ImGui::StyleColorsClassic(); - //ImGui::StyleColorsDark(); + ImGui::StyleColorsDark(); + //ImGui::StyleColorsClassic(); // Load Fonts // - If no fonts are loaded, dear imgui will use the default font. You can also load multiple fonts and use ImGui::PushFont()/PopFont() to select them. @@ -59,25 +59,33 @@ int main(int, char**) // Tip: if we don't call ImGui::Begin()/ImGui::End() the widgets automatically appears in a window called "Debug". { static float f = 0.0f; - ImGui::Text("Hello, world!"); // Some text (you can use a format string too) - ImGui::SliderFloat("float", &f, 0.0f, 1.0f); // Edit 1 float as a slider from 0.0f to 1.0f - ImGui::ColorEdit3("clear color", (float*)&clear_color); // Edit 3 floats as a color - if (ImGui::Button("Demo Window")) // Use buttons to toggle our bools. We could use Checkbox() as well. - show_demo_window ^= 1; - if (ImGui::Button("Another Window")) - show_another_window ^= 1; + static int counter = 0; + ImGui::Text("Hello, world!"); // Display some text (you can use a format string too) + ImGui::SliderFloat("float", &f, 0.0f, 1.0f); // Edit 1 float using a slider from 0.0f to 1.0f + ImGui::ColorEdit3("clear color", (float*)&clear_color); // Edit 3 floats representing a color + + ImGui::Checkbox("Demo Window", &show_demo_window); // Edit bools storing our windows open/close state + ImGui::Checkbox("Another Window", &show_another_window); + + if (ImGui::Button("Button")) // Buttons return true when clicked (NB: most widgets return true when edited/activated) + counter++; + ImGui::SameLine(); + ImGui::Text("counter = %d", counter); + ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate); } - // 2. Show another simple window. In most cases you will use an explicit Begin/End pair to name the window. + // 2. Show another simple window. In most cases you will use an explicit Begin/End pair to name your windows. if (show_another_window) { ImGui::Begin("Another Window", &show_another_window); ImGui::Text("Hello from another window!"); + if (ImGui::Button("Close Me")) + show_another_window = false; ImGui::End(); } - // 3. Show the ImGui demo window. Most of the sample code is in ImGui::ShowDemoWindow(). + // 3. Show the ImGui demo window. Most of the sample code is in ImGui::ShowDemoWindow(). Read its code to learn more about Dear ImGui! if (show_demo_window) { ImGui::SetNextWindowPos(ImVec2(650, 20), ImGuiCond_FirstUseEver); // Normally user code doesn't need/want to call this because positions are saved in .ini file anyway. Here we just want to make the demo initial state a bit more friendly! diff --git a/examples/opengl2_example/main.cpp b/examples/opengl2_example/main.cpp index 01eba4fbbd28..d676bec8dacb 100644 --- a/examples/opengl2_example/main.cpp +++ b/examples/opengl2_example/main.cpp @@ -30,8 +30,8 @@ int main(int, char**) ImGui_ImplGlfwGL2_Init(window, true); // Setup style - ImGui::StyleColorsClassic(); - //ImGui::StyleColorsDark(); + ImGui::StyleColorsDark(); + //ImGui::StyleColorsClassic(); // Load Fonts // - If no fonts are loaded, dear imgui will use the default font. You can also load multiple fonts and use ImGui::PushFont()/PopFont() to select them. @@ -67,25 +67,33 @@ int main(int, char**) // Tip: if we don't call ImGui::Begin()/ImGui::End() the widgets automatically appears in a window called "Debug". { static float f = 0.0f; - ImGui::Text("Hello, world!"); // Some text (you can use a format string too) - ImGui::SliderFloat("float", &f, 0.0f, 1.0f); // Edit 1 float as a slider from 0.0f to 1.0f - ImGui::ColorEdit3("clear color", (float*)&clear_color); // Edit 3 floats as a color - if (ImGui::Button("Demo Window")) // Use buttons to toggle our bools. We could use Checkbox() as well. - show_demo_window ^= 1; - if (ImGui::Button("Another Window")) - show_another_window ^= 1; + static int counter = 0; + ImGui::Text("Hello, world!"); // Display some text (you can use a format string too) + ImGui::SliderFloat("float", &f, 0.0f, 1.0f); // Edit 1 float using a slider from 0.0f to 1.0f + ImGui::ColorEdit3("clear color", (float*)&clear_color); // Edit 3 floats representing a color + + ImGui::Checkbox("Demo Window", &show_demo_window); // Edit bools storing our windows open/close state + ImGui::Checkbox("Another Window", &show_another_window); + + if (ImGui::Button("Button")) // Buttons return true when clicked (NB: most widgets return true when edited/activated) + counter++; + ImGui::SameLine(); + ImGui::Text("counter = %d", counter); + ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate); } - // 2. Show another simple window. In most cases you will use an explicit Begin/End pair to name the window. + // 2. Show another simple window. In most cases you will use an explicit Begin/End pair to name your windows. if (show_another_window) { ImGui::Begin("Another Window", &show_another_window); ImGui::Text("Hello from another window!"); + if (ImGui::Button("Close Me")) + show_another_window = false; ImGui::End(); } - // 3. Show the ImGui demo window. Most of the sample code is in ImGui::ShowDemoWindow(). + // 3. Show the ImGui demo window. Most of the sample code is in ImGui::ShowDemoWindow(). Read its code to learn more about Dear ImGui! if (show_demo_window) { ImGui::SetNextWindowPos(ImVec2(650, 20), ImGuiCond_FirstUseEver); // Normally user code doesn't need/want to call this because positions are saved in .ini file anyway. Here we just want to make the demo initial state a bit more friendly! diff --git a/examples/opengl3_example/main.cpp b/examples/opengl3_example/main.cpp index 26de8ca23dd0..7b9a7a993a79 100644 --- a/examples/opengl3_example/main.cpp +++ b/examples/opengl3_example/main.cpp @@ -35,8 +35,8 @@ int main(int, char**) ImGui_ImplGlfwGL3_Init(window, true); // Setup style - ImGui::StyleColorsClassic(); - //ImGui::StyleColorsDark(); + ImGui::StyleColorsDark(); + //ImGui::StyleColorsClassic(); // Load Fonts // - If no fonts are loaded, dear imgui will use the default font. You can also load multiple fonts and use ImGui::PushFont()/PopFont() to select them. @@ -72,25 +72,33 @@ int main(int, char**) // Tip: if we don't call ImGui::Begin()/ImGui::End() the widgets automatically appears in a window called "Debug". { static float f = 0.0f; - ImGui::Text("Hello, world!"); // Some text (you can use a format string too) - ImGui::SliderFloat("float", &f, 0.0f, 1.0f); // Edit 1 float as a slider from 0.0f to 1.0f - ImGui::ColorEdit3("clear color", (float*)&clear_color); // Edit 3 floats as a color - if (ImGui::Button("Demo Window")) // Use buttons to toggle our bools. We could use Checkbox() as well. - show_demo_window ^= 1; - if (ImGui::Button("Another Window")) - show_another_window ^= 1; + static int counter = 0; + ImGui::Text("Hello, world!"); // Display some text (you can use a format string too) + ImGui::SliderFloat("float", &f, 0.0f, 1.0f); // Edit 1 float using a slider from 0.0f to 1.0f + ImGui::ColorEdit3("clear color", (float*)&clear_color); // Edit 3 floats representing a color + + ImGui::Checkbox("Demo Window", &show_demo_window); // Edit bools storing our windows open/close state + ImGui::Checkbox("Another Window", &show_another_window); + + if (ImGui::Button("Button")) // Buttons return true when clicked (NB: most widgets return true when edited/activated) + counter++; + ImGui::SameLine(); + ImGui::Text("counter = %d", counter); + ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate); } - // 2. Show another simple window. In most cases you will use an explicit Begin/End pair to name the window. + // 2. Show another simple window. In most cases you will use an explicit Begin/End pair to name your windows. if (show_another_window) { ImGui::Begin("Another Window", &show_another_window); ImGui::Text("Hello from another window!"); + if (ImGui::Button("Close Me")) + show_another_window = false; ImGui::End(); } - // 3. Show the ImGui demo window. Most of the sample code is in ImGui::ShowDemoWindow(). + // 3. Show the ImGui demo window. Most of the sample code is in ImGui::ShowDemoWindow(). Read its code to learn more about Dear ImGui! if (show_demo_window) { ImGui::SetNextWindowPos(ImVec2(650, 20), ImGuiCond_FirstUseEver); // Normally user code doesn't need/want to call this because positions are saved in .ini file anyway. Here we just want to make the demo initial state a bit more friendly! diff --git a/examples/sdl_opengl2_example/main.cpp b/examples/sdl_opengl2_example/main.cpp index bc475647939a..1613660038a9 100644 --- a/examples/sdl_opengl2_example/main.cpp +++ b/examples/sdl_opengl2_example/main.cpp @@ -36,8 +36,8 @@ int main(int, char**) ImGui_ImplSdlGL2_Init(window); // Setup style - ImGui::StyleColorsClassic(); - //ImGui::StyleColorsDark(); + ImGui::StyleColorsDark(); + //ImGui::StyleColorsClassic(); // Load Fonts // - If no fonts are loaded, dear imgui will use the default font. You can also load multiple fonts and use ImGui::PushFont()/PopFont() to select them. @@ -76,29 +76,37 @@ int main(int, char**) } ImGui_ImplSdlGL2_NewFrame(window); - // 1. Show a simple window + // 1. Show a simple window. // Tip: if we don't call ImGui::Begin()/ImGui::End() the widgets automatically appears in a window called "Debug". { static float f = 0.0f; - ImGui::Text("Hello, world!"); // Some text (you can use a format string too) - ImGui::SliderFloat("float", &f, 0.0f, 1.0f); // Edit 1 float as a slider from 0.0f to 1.0f - ImGui::ColorEdit3("clear color", (float*)&clear_color); // Edit 3 floats as a color - if (ImGui::Button("Demo Window")) // Use buttons to toggle our bools. We could use Checkbox() as well. - show_demo_window ^= 1; - if (ImGui::Button("Another Window")) - show_another_window ^= 1; + static int counter = 0; + ImGui::Text("Hello, world!"); // Display some text (you can use a format string too) + ImGui::SliderFloat("float", &f, 0.0f, 1.0f); // Edit 1 float using a slider from 0.0f to 1.0f + ImGui::ColorEdit3("clear color", (float*)&clear_color); // Edit 3 floats representing a color + + ImGui::Checkbox("Demo Window", &show_demo_window); // Edit bools storing our windows open/close state + ImGui::Checkbox("Another Window", &show_another_window); + + if (ImGui::Button("Button")) // Buttons return true when clicked (NB: most widgets return true when edited/activated) + counter++; + ImGui::SameLine(); + ImGui::Text("counter = %d", counter); + ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate); } - // 2. Show another simple window. In most cases you will use an explicit Begin/End pair to name the window. + // 2. Show another simple window. In most cases you will use an explicit Begin/End pair to name your windows. if (show_another_window) { ImGui::Begin("Another Window", &show_another_window); ImGui::Text("Hello from another window!"); + if (ImGui::Button("Close Me")) + show_another_window = false; ImGui::End(); } - // 3. Show the ImGui demo window. Most of the sample code is in ImGui::ShowDemoWindow(). + // 3. Show the ImGui demo window. Most of the sample code is in ImGui::ShowDemoWindow(). Read its code to learn more about Dear ImGui! if (show_demo_window) { ImGui::SetNextWindowPos(ImVec2(650, 20), ImGuiCond_FirstUseEver); // Normally user code doesn't need/want to call this because positions are saved in .ini file anyway. Here we just want to make the demo initial state a bit more friendly! diff --git a/examples/sdl_opengl3_example/main.cpp b/examples/sdl_opengl3_example/main.cpp index 6321181dfe6d..bb3831a1a1c4 100644 --- a/examples/sdl_opengl3_example/main.cpp +++ b/examples/sdl_opengl3_example/main.cpp @@ -36,8 +36,8 @@ int main(int, char**) ImGui_ImplSdlGL3_Init(window); // Setup style - ImGui::StyleColorsClassic(); - //ImGui::StyleColorsDark(); + ImGui::StyleColorsDark(); + //ImGui::StyleColorsClassic(); // Load Fonts // - If no fonts are loaded, dear imgui will use the default font. You can also load multiple fonts and use ImGui::PushFont()/PopFont() to select them. @@ -80,25 +80,33 @@ int main(int, char**) // Tip: if we don't call ImGui::Begin()/ImGui::End() the widgets automatically appears in a window called "Debug". { static float f = 0.0f; - ImGui::Text("Hello, world!"); // Some text (you can use a format string too) - ImGui::SliderFloat("float", &f, 0.0f, 1.0f); // Edit 1 float as a slider from 0.0f to 1.0f - ImGui::ColorEdit3("clear color", (float*)&clear_color); // Edit 3 floats as a color - if (ImGui::Button("Demo Window")) // Use buttons to toggle our bools. We could use Checkbox() as well. - show_demo_window ^= 1; - if (ImGui::Button("Another Window")) - show_another_window ^= 1; + static int counter = 0; + ImGui::Text("Hello, world!"); // Display some text (you can use a format string too) + ImGui::SliderFloat("float", &f, 0.0f, 1.0f); // Edit 1 float using a slider from 0.0f to 1.0f + ImGui::ColorEdit3("clear color", (float*)&clear_color); // Edit 3 floats representing a color + + ImGui::Checkbox("Demo Window", &show_demo_window); // Edit bools storing our windows open/close state + ImGui::Checkbox("Another Window", &show_another_window); + + if (ImGui::Button("Button")) // Buttons return true when clicked (NB: most widgets return true when edited/activated) + counter++; + ImGui::SameLine(); + ImGui::Text("counter = %d", counter); + ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate); } - // 2. Show another simple window. In most cases you will use an explicit Begin/End pair to name the window. + // 2. Show another simple window. In most cases you will use an explicit Begin/End pair to name your windows. if (show_another_window) { ImGui::Begin("Another Window", &show_another_window); ImGui::Text("Hello from another window!"); + if (ImGui::Button("Close Me")) + show_another_window = false; ImGui::End(); } - // 3. Show the ImGui demo window. Most of the sample code is in ImGui::ShowDemoWindow(). + // 3. Show the ImGui demo window. Most of the sample code is in ImGui::ShowDemoWindow(). Read its code to learn more about Dear ImGui! if (show_demo_window) { ImGui::SetNextWindowPos(ImVec2(650, 20), ImGuiCond_FirstUseEver); // Normally user code doesn't need/want to call this because positions are saved in .ini file anyway. Here we just want to make the demo initial state a bit more friendly! diff --git a/examples/vulkan_example/main.cpp b/examples/vulkan_example/main.cpp index 75b08d225312..872583b0edf8 100644 --- a/examples/vulkan_example/main.cpp +++ b/examples/vulkan_example/main.cpp @@ -625,8 +625,8 @@ int main(int, char**) ImGui_ImplGlfwVulkan_Init(window, true, &init_data); // Setup style - ImGui::StyleColorsClassic(); - //ImGui::StyleColorsDark(); + ImGui::StyleColorsDark(); + //ImGui::StyleColorsClassic(); // Load Fonts // - If no fonts are loaded, dear imgui will use the default font. You can also load multiple fonts and use ImGui::PushFont()/PopFont() to select them. @@ -700,25 +700,33 @@ int main(int, char**) // Tip: if we don't call ImGui::Begin()/ImGui::End() the widgets automatically appears in a window called "Debug". { static float f = 0.0f; - ImGui::Text("Hello, world!"); // Some text (you can use a format string too) - ImGui::SliderFloat("float", &f, 0.0f, 1.0f); // Edit 1 float as a slider from 0.0f to 1.0f - ImGui::ColorEdit3("clear color", (float*)&clear_color); // Edit 3 floats as a color - if (ImGui::Button("Demo Window")) // Use buttons to toggle our bools. We could use Checkbox() as well. - show_demo_window ^= 1; - if (ImGui::Button("Another Window")) - show_another_window ^= 1; + static int counter = 0; + ImGui::Text("Hello, world!"); // Display some text (you can use a format string too) + ImGui::SliderFloat("float", &f, 0.0f, 1.0f); // Edit 1 float using a slider from 0.0f to 1.0f + ImGui::ColorEdit3("clear color", (float*)&clear_color); // Edit 3 floats representing a color + + ImGui::Checkbox("Demo Window", &show_demo_window); // Edit bools storing our windows open/close state + ImGui::Checkbox("Another Window", &show_another_window); + + if (ImGui::Button("Button")) // Buttons return true when clicked (NB: most widgets return true when edited/activated) + counter++; + ImGui::SameLine(); + ImGui::Text("counter = %d", counter); + ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate); } - // 2. Show another simple window. In most cases you will use an explicit Begin/End pair to name the window. + // 2. Show another simple window. In most cases you will use an explicit Begin/End pair to name your windows. if (show_another_window) { ImGui::Begin("Another Window", &show_another_window); ImGui::Text("Hello from another window!"); + if (ImGui::Button("Close Me")) + show_another_window = false; ImGui::End(); } - // 3. Show the ImGui demo window. Most of the sample code is in ImGui::ShowDemoWindow(). + // 3. Show the ImGui demo window. Most of the sample code is in ImGui::ShowDemoWindow(). Read its code to learn more about Dear ImGui! if (show_demo_window) { ImGui::SetNextWindowPos(ImVec2(650, 20), ImGuiCond_FirstUseEver); // Normally user code doesn't need/want to call this because positions are saved in .ini file anyway. Here we just want to make the demo initial state a bit more friendly! diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 8fb10149e296..850238351752 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -1979,7 +1979,7 @@ void ImGui::ShowDemoWindow(bool* p_open) // Here we use the simplified Combo() api that packs items into a single literal string. Useful for quick combo boxes where the choices are known locally. bool ImGui::ShowStyleSelector(const char* label) { - static int style_idx = 0; + static int style_idx = -1; if (ImGui::Combo(label, &style_idx, "Classic\0Dark\0Light\0")) { switch (style_idx) From 6c38aa2dc75d0ea66ce13617d6b13315c4e1381c Mon Sep 17 00:00:00 2001 From: omar Date: Wed, 31 Jan 2018 00:16:44 +0100 Subject: [PATCH 559/823] Examples: Apple: Tweak code and sync with other examples better (untested). --- .../imguiex-ios/GameViewController.m | 22 +++++------ .../apple_example/imguiex-ios/debug_hud.cpp | 38 +++++++++++++++---- .../apple_example/imguiex-ios/debug_hud.h | 6 +-- .../imguiex-ios/imgui_impl_ios.mm | 2 +- 4 files changed, 45 insertions(+), 23 deletions(-) diff --git a/examples/apple_example/imguiex-ios/GameViewController.m b/examples/apple_example/imguiex-ios/GameViewController.m index e902f7ac24d5..316fbd6cccf2 100644 --- a/examples/apple_example/imguiex-ios/GameViewController.m +++ b/examples/apple_example/imguiex-ios/GameViewController.m @@ -294,35 +294,33 @@ - (void)update - (void)glkView:(GLKView *)view drawInRect:(CGRect)rect { + // Start the dear imgui frame + [self.imgui newFrame]; + + // Create some UI elements + DebugHUD_DoInterface( &_hud ); + + // Render glClearColor(0.65f, 0.65f, 0.65f, 1.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - + glBindVertexArrayOES(_vertexArray); // Render the object with GLKit [self.effect prepareToDraw]; - glDrawArrays(GL_TRIANGLES, 0, 36); // Render the object again with ES2 glUseProgram(_program); - glUniformMatrix4fv(uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX], 1, 0, _modelViewProjectionMatrix.m); glUniformMatrix3fv(uniforms[UNIFORM_NORMAL_MATRIX], 1, 0, _normalMatrix.m); glUniform3f(uniforms[UNIFORM_DIFFUSE_COLOR], _hud.cubeColor1[0], _hud.cubeColor1[1], _hud.cubeColor1[2] ); - glDrawArrays(GL_TRIANGLES, 0, 36); - - [self.imgui newFrame]; - - // Now do our ImGUI UI - DebugHUD_DoInterface( &_hud ); - + self.effect.light0.diffuseColor = GLKVector4Make( _hud.cubeColor2[0], _hud.cubeColor2[1], _hud.cubeColor2[2], 1.0f); - // Now render Imgui + // Render dear imgui as the last thing in the frame if possible [self.imgui render]; - } #pragma mark - OpenGL ES 2 shader compilation diff --git a/examples/apple_example/imguiex-ios/debug_hud.cpp b/examples/apple_example/imguiex-ios/debug_hud.cpp index c81f273d187c..002d6bac45cb 100644 --- a/examples/apple_example/imguiex-ios/debug_hud.cpp +++ b/examples/apple_example/imguiex-ios/debug_hud.cpp @@ -10,7 +10,7 @@ void DebugHUD_InitDefaults( DebugHUD *hud ) { hud->show_demo_window = true; - hud->show_example_window = true; + hud->show_another_window = true; hud->rotation_speed = 15.0f; hud->cubeColor1[0] = 0.4f; @@ -26,19 +26,43 @@ void DebugHUD_InitDefaults( DebugHUD *hud ) void DebugHUD_DoInterface(DebugHUD *hud) { - if (hud->show_demo_window) + // 1. Show a simple window. + // Tip: if we don't call ImGui::Begin()/ImGui::End() the widgets automatically appears in a window called "Debug". { - ImGui::SetNextWindowPos(ImVec2(650, 20), ImGuiCond_FirstUseEver); // Normally user code doesn't need/want to call this because positions are saved in .ini file anyway. Here we just want to make the demo initial state a bit more friendly! - ImGui::ShowDemoWindow(&hud->show_demo_window ); + static float f = 0.0f; + static int counter = 0; + ImGui::Text("Hello, world!"); // Display some text (you can use a format string too) + ImGui::SliderFloat("float", &f, 0.0f, 1.0f); // Edit 1 float using a slider from 0.0f to 1.0f + ImGui::ColorEdit3("clear color", (float*)&clear_color); // Edit 3 floats representing a color + + ImGui::Checkbox("Demo Window", &hud->show_demo_window); // Edit bools storing our windows open/close state + ImGui::Checkbox("Another Window", &hud->show_another_window); + + if (ImGui::Button("Button")) // Buttons return true when clicked (NB: most widgets return true when edited/activated) + counter++; + ImGui::SameLine(); + ImGui::Text("counter = %d", counter); + + ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate); } - - if (hud->show_example_window) + + // 2. Show another simple window. In most cases you will use an explicit Begin/End pair to name your windows. + if (hud->show_another_window) { - ImGui::Begin("Another Window", &hud->show_example_window); + ImGui::Begin("Another Window", &hud-?show_another_window); ImGui::Text("Hello from another window!"); ImGui::ColorEdit3("Cube 1 Color", hud->cubeColor1); ImGui::ColorEdit3("Cube 2 Color", hud->cubeColor2); ImGui::SliderFloat("Rotation Speed", &hud->rotation_speed, 0.0f, 200.0f); + if (ImGui::Button("Close Me")) + hud->show_another_window = false; ImGui::End(); } + + // 3. Show the ImGui demo window. Most of the sample code is in ImGui::ShowDemoWindow(). Read its code to learn more about Dear ImGui! + if (hud->show_demo_window) + { + ImGui::SetNextWindowPos(ImVec2(650, 20), ImGuiCond_FirstUseEver); // Normally user code doesn't need/want to call this because positions are saved in .ini file anyway. Here we just want to make the demo initial state a bit more friendly! + ImGui::ShowDemoWindow(&hud->show_demo_window); + } } diff --git a/examples/apple_example/imguiex-ios/debug_hud.h b/examples/apple_example/imguiex-ios/debug_hud.h index 601376c3e160..89b79a411b92 100644 --- a/examples/apple_example/imguiex-ios/debug_hud.h +++ b/examples/apple_example/imguiex-ios/debug_hud.h @@ -7,7 +7,7 @@ typedef struct DebugHUD { bool show_demo_window; - bool show_example_window; + bool show_another_window; float rotation_speed; float cubeColor1[4]; float cubeColor2[4]; @@ -17,8 +17,8 @@ typedef struct DebugHUD extern "C" { #endif -void DebugHUD_InitDefaults( DebugHUD *hud ); -void DebugHUD_DoInterface( DebugHUD *hud ); +void DebugHUD_InitDefaults(DebugHUD *hud); +void DebugHUD_DoInterface(DebugHUD *hud); #if __cplusplus } diff --git a/examples/apple_example/imguiex-ios/imgui_impl_ios.mm b/examples/apple_example/imguiex-ios/imgui_impl_ios.mm index 5b56d3ca39dd..20b5b7337ffb 100644 --- a/examples/apple_example/imguiex-ios/imgui_impl_ios.mm +++ b/examples/apple_example/imguiex-ios/imgui_impl_ios.mm @@ -263,7 +263,7 @@ void ImGui_KeyboardCallback(uSynergyCookie cookie, uint16_t key, uint16_t modifiers, uSynergyBool down, uSynergyBool repeat) { int scanCode = key-1; -// printf("Synergy: keyboard callback: 0x%02X (%s)", scanCode, down?"true":"false"); + // printf("Synergy: keyboard callback: 0x%02X (%s)", scanCode, down?"true":"false"); ImGuiIO& io = ImGui::GetIO(); io.KeysDown[key] = down; io.KeyShift = (modifiers & USYNERGY_MODIFIER_SHIFT); From dd41a1650a479f55b7fea9f3af834c66e6b7ad2d Mon Sep 17 00:00:00 2001 From: omar Date: Wed, 31 Jan 2018 15:41:48 +0100 Subject: [PATCH 560/823] Comments --- imgui.h | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/imgui.h b/imgui.h index 40b95149161b..4166b603ceaa 100644 --- a/imgui.h +++ b/imgui.h @@ -840,28 +840,30 @@ enum ImGuiCond_ #endif }; +// You may modify the ImGui::GetStyle() main instance during initialization and before NewFrame(). +// During the frame, prefer using ImGui::PushStyleVar(ImGuiStyleVar_XXXX)/PopStyleVar() to alter the main style values, and ImGui::PushStyleColor(ImGuiCol_XXX)/PopStyleColor() for colors. struct ImGuiStyle { - float Alpha; // Global alpha applies to everything in ImGui - ImVec2 WindowPadding; // Padding within a window - float WindowRounding; // Radius of window corners rounding. Set to 0.0f to have rectangular windows - float WindowBorderSize; // Thickness of border around windows. Generally set to 0.0f or 1.0f. (Other values are not well tested and more CPU/GPU costly) - ImVec2 WindowMinSize; // Minimum window size + float Alpha; // Global alpha applies to everything in ImGui. + ImVec2 WindowPadding; // Padding within a window. + float WindowRounding; // Radius of window corners rounding. Set to 0.0f to have rectangular windows. + float WindowBorderSize; // Thickness of border around windows. Generally set to 0.0f or 1.0f. (Other values are not well tested and more CPU/GPU costly). + ImVec2 WindowMinSize; // Minimum window size. This is a global setting. If you want to constraint individual windows, use SetNextWindowSizeConstraints(). ImVec2 WindowTitleAlign; // Alignment for title bar text. Defaults to (0.0f,0.5f) for left-aligned,vertically centered. float ChildRounding; // Radius of child window corners rounding. Set to 0.0f to have rectangular windows. - float ChildBorderSize; // Thickness of border around child windows. Generally set to 0.0f or 1.0f. (Other values are not well tested and more CPU/GPU costly) + float ChildBorderSize; // Thickness of border around child windows. Generally set to 0.0f or 1.0f. (Other values are not well tested and more CPU/GPU costly). float PopupRounding; // Radius of popup window corners rounding. - float PopupBorderSize; // Thickness of border around popup windows. Generally set to 0.0f or 1.0f. (Other values are not well tested and more CPU/GPU costly) - ImVec2 FramePadding; // Padding within a framed rectangle (used by most widgets) + float PopupBorderSize; // Thickness of border around popup windows. Generally set to 0.0f or 1.0f. (Other values are not well tested and more CPU/GPU costly). + ImVec2 FramePadding; // Padding within a framed rectangle (used by most widgets). float FrameRounding; // Radius of frame corners rounding. Set to 0.0f to have rectangular frame (used by most widgets). - float FrameBorderSize; // Thickness of border around frames. Generally set to 0.0f or 1.0f. (Other values are not well tested and more CPU/GPU costly) - ImVec2 ItemSpacing; // Horizontal and vertical spacing between widgets/lines - ImVec2 ItemInnerSpacing; // Horizontal and vertical spacing between within elements of a composed widget (e.g. a slider and its label) + float FrameBorderSize; // Thickness of border around frames. Generally set to 0.0f or 1.0f. (Other values are not well tested and more CPU/GPU costly). + ImVec2 ItemSpacing; // Horizontal and vertical spacing between widgets/lines. + ImVec2 ItemInnerSpacing; // Horizontal and vertical spacing between within elements of a composed widget (e.g. a slider and its label). ImVec2 TouchExtraPadding; // Expand reactive bounding box for touch-based system where touch position is not accurate enough. Unfortunately we don't sort widgets so priority on overlap will always be given to the first widget. So don't grow this too much! float IndentSpacing; // Horizontal indentation when e.g. entering a tree node. Generally == (FontSize + FramePadding.x*2). - float ColumnsMinSpacing; // Minimum horizontal spacing between two columns - float ScrollbarSize; // Width of the vertical scrollbar, Height of the horizontal scrollbar - float ScrollbarRounding; // Radius of grab corners for scrollbar + float ColumnsMinSpacing; // Minimum horizontal spacing between two columns. + float ScrollbarSize; // Width of the vertical scrollbar, Height of the horizontal scrollbar. + float ScrollbarRounding; // Radius of grab corners for scrollbar. float GrabMinSize; // Minimum width/height of a grab box for slider/scrollbar. float GrabRounding; // Radius of grabs corners rounding. Set to 0.0f to have rectangular slider grabs. ImVec2 ButtonTextAlign; // Alignment of button text when button is larger than text. Defaults to (0.5f,0.5f) for horizontally+vertically centered. From cd3dd886de5dd0018a2c5cf70175d3ab377d0a5b Mon Sep 17 00:00:00 2001 From: omar Date: Wed, 31 Jan 2018 16:00:07 +0100 Subject: [PATCH 561/823] Moved extra_fonts/ to misc/fonts/. Moved .natvis file to misc/natvis/ (#1569) --- TODO.txt | 2 -- examples/allegro5_example/main.cpp | 10 +++++----- .../directx10_example/directx10_example.vcxproj | 2 +- .../directx10_example.vcxproj.filters | 2 +- examples/directx10_example/main.cpp | 10 +++++----- .../directx11_example/directx11_example.vcxproj | 2 +- .../directx11_example.vcxproj.filters | 2 +- examples/directx11_example/main.cpp | 10 +++++----- examples/directx9_example/directx9_example.vcxproj | 2 +- .../directx9_example.vcxproj.filters | 2 +- examples/directx9_example/main.cpp | 10 +++++----- examples/marmalade_example/main.cpp | 10 +++++----- examples/opengl2_example/main.cpp | 10 +++++----- examples/opengl2_example/opengl2_example.vcxproj | 2 +- .../opengl2_example/opengl2_example.vcxproj.filters | 2 +- examples/opengl3_example/main.cpp | 10 +++++----- examples/opengl3_example/opengl3_example.vcxproj | 2 +- .../opengl3_example/opengl3_example.vcxproj.filters | 2 +- examples/sdl_opengl2_example/main.cpp | 10 +++++----- examples/sdl_opengl3_example/main.cpp | 10 +++++----- examples/vulkan_example/main.cpp | 10 +++++----- imgui.cpp | 4 ++-- imgui_demo.cpp | 4 ++-- imgui_draw.cpp | 4 ++-- {extra_fonts => misc/fonts}/Cousine-Regular.ttf | Bin {extra_fonts => misc/fonts}/DroidSans.ttf | Bin {extra_fonts => misc/fonts}/Karla-Regular.ttf | Bin {extra_fonts => misc/fonts}/ProggyClean.ttf | Bin {extra_fonts => misc/fonts}/ProggyTiny.ttf | Bin {extra_fonts => misc/fonts}/README.txt | 0 {extra_fonts => misc/fonts}/Roboto-Medium.ttf | Bin .../fonts}/binary_to_compressed_c.cpp | 0 misc/natvis/README.txt | 3 +++ {examples/libs => misc/natvis}/imgui.natvis | 0 34 files changed, 69 insertions(+), 68 deletions(-) rename {extra_fonts => misc/fonts}/Cousine-Regular.ttf (100%) rename {extra_fonts => misc/fonts}/DroidSans.ttf (100%) rename {extra_fonts => misc/fonts}/Karla-Regular.ttf (100%) rename {extra_fonts => misc/fonts}/ProggyClean.ttf (100%) rename {extra_fonts => misc/fonts}/ProggyTiny.ttf (100%) rename {extra_fonts => misc/fonts}/README.txt (100%) rename {extra_fonts => misc/fonts}/Roboto-Medium.ttf (100%) rename {extra_fonts => misc/fonts}/binary_to_compressed_c.cpp (100%) create mode 100644 misc/natvis/README.txt rename {examples/libs => misc/natvis}/imgui.natvis (100%) diff --git a/TODO.txt b/TODO.txt index 3a6535a03334..89b7267810a3 100644 --- a/TODO.txt +++ b/TODO.txt @@ -248,8 +248,6 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i - misc: fix for compilation settings where stdcall isn't the default (e.g. vectorcall) (#1230) - remote: make a system like RemoteImGui first-class citizen/project (#75) - - natvis: more the imgui.natvis file in a better location. perhaps reorganize extra_fonts/? (#1569) - - demo: add vertical separator demo - demo: add virtual scrolling example? - examples: directx9: save/restore device state more thoroughly. diff --git a/examples/allegro5_example/main.cpp b/examples/allegro5_example/main.cpp index 256415adb537..b740dace1e09 100644 --- a/examples/allegro5_example/main.cpp +++ b/examples/allegro5_example/main.cpp @@ -34,14 +34,14 @@ int main(int, char**) // - AddFontFromFileTTF() will return the ImFont* so you can store it if you need to select the font among multiple. // - If the file cannot be loaded, the function will return NULL. Please handle those errors in your application (e.g. use an assertion, or display an error and quit). // - The fonts will be rasterized at a given size (w/ oversampling) and stored into a texture when calling ImFontAtlas::Build()/GetTexDataAsXXXX(), which ImGui_ImplXXXX_NewFrame below will call. - // - Read 'extra_fonts/README.txt' for more instructions and details. + // - Read 'misc/fonts/README.txt' for more instructions and details. // - Remember that in C/C++ if you want to include a backslash \ in a string literal you need to write a double backslash \\ ! //ImGuiIO& io = ImGui::GetIO(); //io.Fonts->AddFontDefault(); - //io.Fonts->AddFontFromFileTTF("../../extra_fonts/Roboto-Medium.ttf", 16.0f); - //io.Fonts->AddFontFromFileTTF("../../extra_fonts/Cousine-Regular.ttf", 15.0f); - //io.Fonts->AddFontFromFileTTF("../../extra_fonts/DroidSans.ttf", 16.0f); - //io.Fonts->AddFontFromFileTTF("../../extra_fonts/ProggyTiny.ttf", 10.0f); + //io.Fonts->AddFontFromFileTTF("../../misc/fonts/Roboto-Medium.ttf", 16.0f); + //io.Fonts->AddFontFromFileTTF("../../misc/fonts/Cousine-Regular.ttf", 15.0f); + //io.Fonts->AddFontFromFileTTF("../../misc/fonts/DroidSans.ttf", 16.0f); + //io.Fonts->AddFontFromFileTTF("../../misc/fonts/ProggyTiny.ttf", 10.0f); //ImFont* font = io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf", 18.0f, NULL, io.Fonts->GetGlyphRangesJapanese()); //IM_ASSERT(font != NULL); diff --git a/examples/directx10_example/directx10_example.vcxproj b/examples/directx10_example/directx10_example.vcxproj index 3a403518e32e..64b57ddf172a 100644 --- a/examples/directx10_example/directx10_example.vcxproj +++ b/examples/directx10_example/directx10_example.vcxproj @@ -153,7 +153,7 @@ - + diff --git a/examples/directx10_example/directx10_example.vcxproj.filters b/examples/directx10_example/directx10_example.vcxproj.filters index 5a358463eae7..aef010adf011 100644 --- a/examples/directx10_example/directx10_example.vcxproj.filters +++ b/examples/directx10_example/directx10_example.vcxproj.filters @@ -41,7 +41,7 @@ - + sources diff --git a/examples/directx10_example/main.cpp b/examples/directx10_example/main.cpp index 1bb42c729df1..aebf81f875e0 100644 --- a/examples/directx10_example/main.cpp +++ b/examples/directx10_example/main.cpp @@ -131,14 +131,14 @@ int main(int, char**) // - AddFontFromFileTTF() will return the ImFont* so you can store it if you need to select the font among multiple. // - If the file cannot be loaded, the function will return NULL. Please handle those errors in your application (e.g. use an assertion, or display an error and quit). // - The fonts will be rasterized at a given size (w/ oversampling) and stored into a texture when calling ImFontAtlas::Build()/GetTexDataAsXXXX(), which ImGui_ImplXXXX_NewFrame below will call. - // - Read 'extra_fonts/README.txt' for more instructions and details. + // - Read 'misc/fonts/README.txt' for more instructions and details. // - Remember that in C/C++ if you want to include a backslash \ in a string literal you need to write a double backslash \\ ! //ImGuiIO& io = ImGui::GetIO(); //io.Fonts->AddFontDefault(); - //io.Fonts->AddFontFromFileTTF("../../extra_fonts/Roboto-Medium.ttf", 16.0f); - //io.Fonts->AddFontFromFileTTF("../../extra_fonts/Cousine-Regular.ttf", 15.0f); - //io.Fonts->AddFontFromFileTTF("../../extra_fonts/DroidSans.ttf", 16.0f); - //io.Fonts->AddFontFromFileTTF("../../extra_fonts/ProggyTiny.ttf", 10.0f); + //io.Fonts->AddFontFromFileTTF("../../misc/fonts/Roboto-Medium.ttf", 16.0f); + //io.Fonts->AddFontFromFileTTF("../../misc/fonts/Cousine-Regular.ttf", 15.0f); + //io.Fonts->AddFontFromFileTTF("../../misc/fonts/DroidSans.ttf", 16.0f); + //io.Fonts->AddFontFromFileTTF("../../misc/fonts/ProggyTiny.ttf", 10.0f); //ImFont* font = io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf", 18.0f, NULL, io.Fonts->GetGlyphRangesJapanese()); //IM_ASSERT(font != NULL); diff --git a/examples/directx11_example/directx11_example.vcxproj b/examples/directx11_example/directx11_example.vcxproj index 347b4f007656..c07939f776b4 100644 --- a/examples/directx11_example/directx11_example.vcxproj +++ b/examples/directx11_example/directx11_example.vcxproj @@ -153,7 +153,7 @@ - + diff --git a/examples/directx11_example/directx11_example.vcxproj.filters b/examples/directx11_example/directx11_example.vcxproj.filters index a79484cc1c44..57b74dee4985 100644 --- a/examples/directx11_example/directx11_example.vcxproj.filters +++ b/examples/directx11_example/directx11_example.vcxproj.filters @@ -41,7 +41,7 @@ - + sources diff --git a/examples/directx11_example/main.cpp b/examples/directx11_example/main.cpp index 10db035d4212..ef82218d1765 100644 --- a/examples/directx11_example/main.cpp +++ b/examples/directx11_example/main.cpp @@ -134,14 +134,14 @@ int main(int, char**) // - AddFontFromFileTTF() will return the ImFont* so you can store it if you need to select the font among multiple. // - If the file cannot be loaded, the function will return NULL. Please handle those errors in your application (e.g. use an assertion, or display an error and quit). // - The fonts will be rasterized at a given size (w/ oversampling) and stored into a texture when calling ImFontAtlas::Build()/GetTexDataAsXXXX(), which ImGui_ImplXXXX_NewFrame below will call. - // - Read 'extra_fonts/README.txt' for more instructions and details. + // - Read 'misc/fonts/README.txt' for more instructions and details. // - Remember that in C/C++ if you want to include a backslash \ in a string literal you need to write a double backslash \\ ! //ImGuiIO& io = ImGui::GetIO(); //io.Fonts->AddFontDefault(); - //io.Fonts->AddFontFromFileTTF("../../extra_fonts/Roboto-Medium.ttf", 16.0f); - //io.Fonts->AddFontFromFileTTF("../../extra_fonts/Cousine-Regular.ttf", 15.0f); - //io.Fonts->AddFontFromFileTTF("../../extra_fonts/DroidSans.ttf", 16.0f); - //io.Fonts->AddFontFromFileTTF("../../extra_fonts/ProggyTiny.ttf", 10.0f); + //io.Fonts->AddFontFromFileTTF("../../misc/fonts/Roboto-Medium.ttf", 16.0f); + //io.Fonts->AddFontFromFileTTF("../../misc/fonts/Cousine-Regular.ttf", 15.0f); + //io.Fonts->AddFontFromFileTTF("../../misc/fonts/DroidSans.ttf", 16.0f); + //io.Fonts->AddFontFromFileTTF("../../misc/fonts/ProggyTiny.ttf", 10.0f); //ImFont* font = io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf", 18.0f, NULL, io.Fonts->GetGlyphRangesJapanese()); //IM_ASSERT(font != NULL); diff --git a/examples/directx9_example/directx9_example.vcxproj b/examples/directx9_example/directx9_example.vcxproj index e63bd35b57cf..89f3ae6ecc61 100644 --- a/examples/directx9_example/directx9_example.vcxproj +++ b/examples/directx9_example/directx9_example.vcxproj @@ -153,7 +153,7 @@ - + diff --git a/examples/directx9_example/directx9_example.vcxproj.filters b/examples/directx9_example/directx9_example.vcxproj.filters index b0843b3975e7..555ef06d7e1d 100644 --- a/examples/directx9_example/directx9_example.vcxproj.filters +++ b/examples/directx9_example/directx9_example.vcxproj.filters @@ -42,7 +42,7 @@ - + sources diff --git a/examples/directx9_example/main.cpp b/examples/directx9_example/main.cpp index 5a05d8828162..f40e5ef42b48 100644 --- a/examples/directx9_example/main.cpp +++ b/examples/directx9_example/main.cpp @@ -86,14 +86,14 @@ int main(int, char**) // - AddFontFromFileTTF() will return the ImFont* so you can store it if you need to select the font among multiple. // - If the file cannot be loaded, the function will return NULL. Please handle those errors in your application (e.g. use an assertion, or display an error and quit). // - The fonts will be rasterized at a given size (w/ oversampling) and stored into a texture when calling ImFontAtlas::Build()/GetTexDataAsXXXX(), which ImGui_ImplXXXX_NewFrame below will call. - // - Read 'extra_fonts/README.txt' for more instructions and details. + // - Read 'misc/fonts/README.txt' for more instructions and details. // - Remember that in C/C++ if you want to include a backslash \ in a string literal you need to write a double backslash \\ ! //ImGuiIO& io = ImGui::GetIO(); //io.Fonts->AddFontDefault(); - //io.Fonts->AddFontFromFileTTF("../../extra_fonts/Roboto-Medium.ttf", 16.0f); - //io.Fonts->AddFontFromFileTTF("../../extra_fonts/Cousine-Regular.ttf", 15.0f); - //io.Fonts->AddFontFromFileTTF("../../extra_fonts/DroidSans.ttf", 16.0f); - //io.Fonts->AddFontFromFileTTF("../../extra_fonts/ProggyTiny.ttf", 10.0f); + //io.Fonts->AddFontFromFileTTF("../../misc/fonts/Roboto-Medium.ttf", 16.0f); + //io.Fonts->AddFontFromFileTTF("../../misc/fonts/Cousine-Regular.ttf", 15.0f); + //io.Fonts->AddFontFromFileTTF("../../misc/fonts/DroidSans.ttf", 16.0f); + //io.Fonts->AddFontFromFileTTF("../../misc/fonts/ProggyTiny.ttf", 10.0f); //ImFont* font = io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf", 18.0f, NULL, io.Fonts->GetGlyphRangesJapanese()); //IM_ASSERT(font != NULL); diff --git a/examples/marmalade_example/main.cpp b/examples/marmalade_example/main.cpp index c47a33310a8a..58c2182bfb64 100644 --- a/examples/marmalade_example/main.cpp +++ b/examples/marmalade_example/main.cpp @@ -26,14 +26,14 @@ int main(int, char**) // - AddFontFromFileTTF() will return the ImFont* so you can store it if you need to select the font among multiple. // - If the file cannot be loaded, the function will return NULL. Please handle those errors in your application (e.g. use an assertion, or display an error and quit). // - The fonts will be rasterized at a given size (w/ oversampling) and stored into a texture when calling ImFontAtlas::Build()/GetTexDataAsXXXX(), which ImGui_ImplXXXX_NewFrame below will call. - // - Read 'extra_fonts/README.txt' for more instructions and details. + // - Read 'misc/fonts/README.txt' for more instructions and details. // - Remember that in C/C++ if you want to include a backslash \ in a string literal you need to write a double backslash \\ ! //ImGuiIO& io = ImGui::GetIO(); //io.Fonts->AddFontDefault(); - //io.Fonts->AddFontFromFileTTF("../../extra_fonts/Roboto-Medium.ttf", 16.0f); - //io.Fonts->AddFontFromFileTTF("../../extra_fonts/Cousine-Regular.ttf", 15.0f); - //io.Fonts->AddFontFromFileTTF("../../extra_fonts/DroidSans.ttf", 16.0f); - //io.Fonts->AddFontFromFileTTF("../../extra_fonts/ProggyTiny.ttf", 10.0f); + //io.Fonts->AddFontFromFileTTF("../../misc/fonts/Roboto-Medium.ttf", 16.0f); + //io.Fonts->AddFontFromFileTTF("../../misc/fonts/Cousine-Regular.ttf", 15.0f); + //io.Fonts->AddFontFromFileTTF("../../misc/fonts/DroidSans.ttf", 16.0f); + //io.Fonts->AddFontFromFileTTF("../../misc/fonts/ProggyTiny.ttf", 10.0f); //ImFont* font = io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf", 18.0f, NULL, io.Fonts->GetGlyphRangesJapanese()); //IM_ASSERT(font != NULL); diff --git a/examples/opengl2_example/main.cpp b/examples/opengl2_example/main.cpp index d676bec8dacb..89d41c378e67 100644 --- a/examples/opengl2_example/main.cpp +++ b/examples/opengl2_example/main.cpp @@ -38,14 +38,14 @@ int main(int, char**) // - AddFontFromFileTTF() will return the ImFont* so you can store it if you need to select the font among multiple. // - If the file cannot be loaded, the function will return NULL. Please handle those errors in your application (e.g. use an assertion, or display an error and quit). // - The fonts will be rasterized at a given size (w/ oversampling) and stored into a texture when calling ImFontAtlas::Build()/GetTexDataAsXXXX(), which ImGui_ImplXXXX_NewFrame below will call. - // - Read 'extra_fonts/README.txt' for more instructions and details. + // - Read 'misc/fonts/README.txt' for more instructions and details. // - Remember that in C/C++ if you want to include a backslash \ in a string literal you need to write a double backslash \\ ! //ImGuiIO& io = ImGui::GetIO(); //io.Fonts->AddFontDefault(); - //io.Fonts->AddFontFromFileTTF("../../extra_fonts/Roboto-Medium.ttf", 16.0f); - //io.Fonts->AddFontFromFileTTF("../../extra_fonts/Cousine-Regular.ttf", 15.0f); - //io.Fonts->AddFontFromFileTTF("../../extra_fonts/DroidSans.ttf", 16.0f); - //io.Fonts->AddFontFromFileTTF("../../extra_fonts/ProggyTiny.ttf", 10.0f); + //io.Fonts->AddFontFromFileTTF("../../misc/fonts/Roboto-Medium.ttf", 16.0f); + //io.Fonts->AddFontFromFileTTF("../../misc/fonts/Cousine-Regular.ttf", 15.0f); + //io.Fonts->AddFontFromFileTTF("../../misc/fonts/DroidSans.ttf", 16.0f); + //io.Fonts->AddFontFromFileTTF("../../misc/fonts/ProggyTiny.ttf", 10.0f); //ImFont* font = io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf", 18.0f, NULL, io.Fonts->GetGlyphRangesJapanese()); //IM_ASSERT(font != NULL); diff --git a/examples/opengl2_example/opengl2_example.vcxproj b/examples/opengl2_example/opengl2_example.vcxproj index bf1a3ed4ea6f..3756748d32ce 100644 --- a/examples/opengl2_example/opengl2_example.vcxproj +++ b/examples/opengl2_example/opengl2_example.vcxproj @@ -163,7 +163,7 @@ - + diff --git a/examples/opengl2_example/opengl2_example.vcxproj.filters b/examples/opengl2_example/opengl2_example.vcxproj.filters index 35fd6ffaf119..0c85d9fa380d 100644 --- a/examples/opengl2_example/opengl2_example.vcxproj.filters +++ b/examples/opengl2_example/opengl2_example.vcxproj.filters @@ -42,7 +42,7 @@ - + sources diff --git a/examples/opengl3_example/main.cpp b/examples/opengl3_example/main.cpp index 7b9a7a993a79..6bf6401723d4 100644 --- a/examples/opengl3_example/main.cpp +++ b/examples/opengl3_example/main.cpp @@ -43,14 +43,14 @@ int main(int, char**) // - AddFontFromFileTTF() will return the ImFont* so you can store it if you need to select the font among multiple. // - If the file cannot be loaded, the function will return NULL. Please handle those errors in your application (e.g. use an assertion, or display an error and quit). // - The fonts will be rasterized at a given size (w/ oversampling) and stored into a texture when calling ImFontAtlas::Build()/GetTexDataAsXXXX(), which ImGui_ImplXXXX_NewFrame below will call. - // - Read 'extra_fonts/README.txt' for more instructions and details. + // - Read 'misc/fonts/README.txt' for more instructions and details. // - Remember that in C/C++ if you want to include a backslash \ in a string literal you need to write a double backslash \\ ! //ImGuiIO& io = ImGui::GetIO(); //io.Fonts->AddFontDefault(); - //io.Fonts->AddFontFromFileTTF("../../extra_fonts/Roboto-Medium.ttf", 16.0f); - //io.Fonts->AddFontFromFileTTF("../../extra_fonts/Cousine-Regular.ttf", 15.0f); - //io.Fonts->AddFontFromFileTTF("../../extra_fonts/DroidSans.ttf", 16.0f); - //io.Fonts->AddFontFromFileTTF("../../extra_fonts/ProggyTiny.ttf", 10.0f); + //io.Fonts->AddFontFromFileTTF("../../misc/fonts/Roboto-Medium.ttf", 16.0f); + //io.Fonts->AddFontFromFileTTF("../../misc/fonts/Cousine-Regular.ttf", 15.0f); + //io.Fonts->AddFontFromFileTTF("../../misc/fonts/DroidSans.ttf", 16.0f); + //io.Fonts->AddFontFromFileTTF("../../misc/fonts/ProggyTiny.ttf", 10.0f); //ImFont* font = io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf", 18.0f, NULL, io.Fonts->GetGlyphRangesJapanese()); //IM_ASSERT(font != NULL); diff --git a/examples/opengl3_example/opengl3_example.vcxproj b/examples/opengl3_example/opengl3_example.vcxproj index 2a78226f736d..e3a9c82047b1 100644 --- a/examples/opengl3_example/opengl3_example.vcxproj +++ b/examples/opengl3_example/opengl3_example.vcxproj @@ -166,7 +166,7 @@ - + diff --git a/examples/opengl3_example/opengl3_example.vcxproj.filters b/examples/opengl3_example/opengl3_example.vcxproj.filters index c743ace31979..0170ab469332 100644 --- a/examples/opengl3_example/opengl3_example.vcxproj.filters +++ b/examples/opengl3_example/opengl3_example.vcxproj.filters @@ -54,7 +54,7 @@ - + sources diff --git a/examples/sdl_opengl2_example/main.cpp b/examples/sdl_opengl2_example/main.cpp index 1613660038a9..10e66e8083ba 100644 --- a/examples/sdl_opengl2_example/main.cpp +++ b/examples/sdl_opengl2_example/main.cpp @@ -44,14 +44,14 @@ int main(int, char**) // - AddFontFromFileTTF() will return the ImFont* so you can store it if you need to select the font among multiple. // - If the file cannot be loaded, the function will return NULL. Please handle those errors in your application (e.g. use an assertion, or display an error and quit). // - The fonts will be rasterized at a given size (w/ oversampling) and stored into a texture when calling ImFontAtlas::Build()/GetTexDataAsXXXX(), which ImGui_ImplXXXX_NewFrame below will call. - // - Read 'extra_fonts/README.txt' for more instructions and details. + // - Read 'misc/fonts/README.txt' for more instructions and details. // - Remember that in C/C++ if you want to include a backslash \ in a string literal you need to write a double backslash \\ ! //ImGuiIO& io = ImGui::GetIO(); //io.Fonts->AddFontDefault(); - //io.Fonts->AddFontFromFileTTF("../../extra_fonts/Roboto-Medium.ttf", 16.0f); - //io.Fonts->AddFontFromFileTTF("../../extra_fonts/Cousine-Regular.ttf", 15.0f); - //io.Fonts->AddFontFromFileTTF("../../extra_fonts/DroidSans.ttf", 16.0f); - //io.Fonts->AddFontFromFileTTF("../../extra_fonts/ProggyTiny.ttf", 10.0f); + //io.Fonts->AddFontFromFileTTF("../../misc/fonts/Roboto-Medium.ttf", 16.0f); + //io.Fonts->AddFontFromFileTTF("../../misc/fonts/Cousine-Regular.ttf", 15.0f); + //io.Fonts->AddFontFromFileTTF("../../misc/fonts/DroidSans.ttf", 16.0f); + //io.Fonts->AddFontFromFileTTF("../../misc/fonts/ProggyTiny.ttf", 10.0f); //ImFont* font = io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf", 18.0f, NULL, io.Fonts->GetGlyphRangesJapanese()); //IM_ASSERT(font != NULL); diff --git a/examples/sdl_opengl3_example/main.cpp b/examples/sdl_opengl3_example/main.cpp index bb3831a1a1c4..2d7e85977bd6 100644 --- a/examples/sdl_opengl3_example/main.cpp +++ b/examples/sdl_opengl3_example/main.cpp @@ -44,14 +44,14 @@ int main(int, char**) // - AddFontFromFileTTF() will return the ImFont* so you can store it if you need to select the font among multiple. // - If the file cannot be loaded, the function will return NULL. Please handle those errors in your application (e.g. use an assertion, or display an error and quit). // - The fonts will be rasterized at a given size (w/ oversampling) and stored into a texture when calling ImFontAtlas::Build()/GetTexDataAsXXXX(), which ImGui_ImplXXXX_NewFrame below will call. - // - Read 'extra_fonts/README.txt' for more instructions and details. + // - Read 'misc/fonts/README.txt' for more instructions and details. // - Remember that in C/C++ if you want to include a backslash \ in a string literal you need to write a double backslash \\ ! //ImGuiIO& io = ImGui::GetIO(); //io.Fonts->AddFontDefault(); - //io.Fonts->AddFontFromFileTTF("../../extra_fonts/Roboto-Medium.ttf", 16.0f); - //io.Fonts->AddFontFromFileTTF("../../extra_fonts/Cousine-Regular.ttf", 15.0f); - //io.Fonts->AddFontFromFileTTF("../../extra_fonts/DroidSans.ttf", 16.0f); - //io.Fonts->AddFontFromFileTTF("../../extra_fonts/ProggyTiny.ttf", 10.0f); + //io.Fonts->AddFontFromFileTTF("../../misc/fonts/Roboto-Medium.ttf", 16.0f); + //io.Fonts->AddFontFromFileTTF("../../misc/fonts/Cousine-Regular.ttf", 15.0f); + //io.Fonts->AddFontFromFileTTF("../../misc/fonts/DroidSans.ttf", 16.0f); + //io.Fonts->AddFontFromFileTTF("../../misc/fonts/ProggyTiny.ttf", 10.0f); //ImFont* font = io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf", 18.0f, NULL, io.Fonts->GetGlyphRangesJapanese()); //IM_ASSERT(font != NULL); diff --git a/examples/vulkan_example/main.cpp b/examples/vulkan_example/main.cpp index 872583b0edf8..41939aab0dc5 100644 --- a/examples/vulkan_example/main.cpp +++ b/examples/vulkan_example/main.cpp @@ -633,14 +633,14 @@ int main(int, char**) // - AddFontFromFileTTF() will return the ImFont* so you can store it if you need to select the font among multiple. // - If the file cannot be loaded, the function will return NULL. Please handle those errors in your application (e.g. use an assertion, or display an error and quit). // - The fonts will be rasterized at a given size (w/ oversampling) and stored into a texture when calling ImFontAtlas::Build()/GetTexDataAsXXXX(), which ImGui_ImplXXXX_NewFrame below will call. - // - Read 'extra_fonts/README.txt' for more instructions and details. + // - Read 'misc/fonts/README.txt' for more instructions and details. // - Remember that in C/C++ if you want to include a backslash \ in a string literal you need to write a double backslash \\ ! //ImGuiIO& io = ImGui::GetIO(); //io.Fonts->AddFontDefault(); - //io.Fonts->AddFontFromFileTTF("../../extra_fonts/Roboto-Medium.ttf", 16.0f); - //io.Fonts->AddFontFromFileTTF("../../extra_fonts/Cousine-Regular.ttf", 15.0f); - //io.Fonts->AddFontFromFileTTF("../../extra_fonts/DroidSans.ttf", 16.0f); - //io.Fonts->AddFontFromFileTTF("../../extra_fonts/ProggyTiny.ttf", 10.0f); + //io.Fonts->AddFontFromFileTTF("../../misc/fonts/Roboto-Medium.ttf", 16.0f); + //io.Fonts->AddFontFromFileTTF("../../misc/fonts/Cousine-Regular.ttf", 15.0f); + //io.Fonts->AddFontFromFileTTF("../../misc/fonts/DroidSans.ttf", 16.0f); + //io.Fonts->AddFontFromFileTTF("../../misc/fonts/ProggyTiny.ttf", 10.0f); //ImFont* font = io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf", 18.0f, NULL, io.Fonts->GetGlyphRangesJapanese()); //IM_ASSERT(font != NULL); diff --git a/imgui.cpp b/imgui.cpp index 5629f55377bd..45e0e2a9bc4c 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -510,11 +510,11 @@ Q: How can I easily use icons in my application? A: The most convenient and practical way is to merge an icon font such as FontAwesome inside you main font. Then you can refer to icons within your - strings. Read 'How can I load multiple fonts?' and the file 'extra_fonts/README.txt' for instructions and useful header files. + strings. Read 'How can I load multiple fonts?' and the file 'misc/fonts/README.txt' for instructions and useful header files. Q: How can I load multiple fonts? A: Use the font atlas to pack them into a single texture: - (Read extra_fonts/README.txt and the code in ImFontAtlas for more details.) + (Read misc/fonts/README.txt and the code in ImFontAtlas for more details.) ImGuiIO& io = ImGui::GetIO(); ImFont* font0 = io.Fonts->AddFontDefault(); diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 850238351752..4c2a437e460a 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -2010,7 +2010,7 @@ void ImGui::ShowFontSelector(const char* label) ShowHelpMarker( "- Load additional fonts with io.Fonts->AddFontFromFileTTF().\n" "- The font atlas is built when calling io.Fonts->GetTexDataAsXXXX() or io.Fonts->Build().\n" - "- Read FAQ and documentation in extra_fonts/ for more details.\n" + "- Read FAQ and documentation in misc/fonts/ for more details.\n" "- If you need to add/remove fonts at runtime (e.g. for DPI change), do it before calling NewFrame()."); } @@ -2137,7 +2137,7 @@ void ImGui::ShowStyleEditor(ImGuiStyle* ref) if (memcmp(&style.Colors[i], &ref->Colors[i], sizeof(ImVec4)) != 0) { // Tips: in a real user application, you may want to merge and use an icon font into the main font, so instead of "Save"/"Revert" you'd use icons. - // Read the FAQ and extra_fonts/README.txt about using icon fonts. It's really easy and super convenient! + // Read the FAQ and misc/fonts/README.txt about using icon fonts. It's really easy and super convenient! ImGui::SameLine(0.0f, style.ItemInnerSpacing.x); if (ImGui::Button("Save")) ref->Colors[i] = style.Colors[i]; ImGui::SameLine(0.0f, style.ItemInnerSpacing.x); if (ImGui::Button("Revert")) style.Colors[i] = ref->Colors[i]; } diff --git a/imgui_draw.cpp b/imgui_draw.cpp index 216cf3fd7c1f..3b331c88324a 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -1484,7 +1484,7 @@ ImFont* ImFontAtlas::AddFont(const ImFontConfig* font_cfg) return new_font_cfg.DstFont; } -// Default font TTF is compressed with stb_compress then base85 encoded (see extra_fonts/binary_to_compressed_c.cpp for encoder) +// Default font TTF is compressed with stb_compress then base85 encoded (see misc/fonts/binary_to_compressed_c.cpp for encoder) static unsigned int stb_decompress_length(unsigned char *input); static unsigned int stb_decompress(unsigned char *output, unsigned char *i, unsigned int length); static const char* GetDefaultCompressedFontDataTTFBase85(); @@ -2698,7 +2698,7 @@ void ImGui::RenderRectFilledRangeH(ImDrawList* draw_list, const ImRect& rect, Im // DEFAULT FONT DATA //----------------------------------------------------------------------------- // Compressed with stb_compress() then converted to a C array. -// Use the program in extra_fonts/binary_to_compressed_c.cpp to create the array from a TTF file. +// Use the program in misc/fonts/binary_to_compressed_c.cpp to create the array from a TTF file. // Decompression from stb.h (public domain) by Sean Barrett https://github.com/nothings/stb/blob/master/stb.h //----------------------------------------------------------------------------- diff --git a/extra_fonts/Cousine-Regular.ttf b/misc/fonts/Cousine-Regular.ttf similarity index 100% rename from extra_fonts/Cousine-Regular.ttf rename to misc/fonts/Cousine-Regular.ttf diff --git a/extra_fonts/DroidSans.ttf b/misc/fonts/DroidSans.ttf similarity index 100% rename from extra_fonts/DroidSans.ttf rename to misc/fonts/DroidSans.ttf diff --git a/extra_fonts/Karla-Regular.ttf b/misc/fonts/Karla-Regular.ttf similarity index 100% rename from extra_fonts/Karla-Regular.ttf rename to misc/fonts/Karla-Regular.ttf diff --git a/extra_fonts/ProggyClean.ttf b/misc/fonts/ProggyClean.ttf similarity index 100% rename from extra_fonts/ProggyClean.ttf rename to misc/fonts/ProggyClean.ttf diff --git a/extra_fonts/ProggyTiny.ttf b/misc/fonts/ProggyTiny.ttf similarity index 100% rename from extra_fonts/ProggyTiny.ttf rename to misc/fonts/ProggyTiny.ttf diff --git a/extra_fonts/README.txt b/misc/fonts/README.txt similarity index 100% rename from extra_fonts/README.txt rename to misc/fonts/README.txt diff --git a/extra_fonts/Roboto-Medium.ttf b/misc/fonts/Roboto-Medium.ttf similarity index 100% rename from extra_fonts/Roboto-Medium.ttf rename to misc/fonts/Roboto-Medium.ttf diff --git a/extra_fonts/binary_to_compressed_c.cpp b/misc/fonts/binary_to_compressed_c.cpp similarity index 100% rename from extra_fonts/binary_to_compressed_c.cpp rename to misc/fonts/binary_to_compressed_c.cpp diff --git a/misc/natvis/README.txt b/misc/natvis/README.txt new file mode 100644 index 000000000000..821014e2fc1b --- /dev/null +++ b/misc/natvis/README.txt @@ -0,0 +1,3 @@ + +Natvis file to describe types in Visual Studio debugger. +You can include this in a project file, or install in Visual Studio folder. diff --git a/examples/libs/imgui.natvis b/misc/natvis/imgui.natvis similarity index 100% rename from examples/libs/imgui.natvis rename to misc/natvis/imgui.natvis From 9c8fb804ed7d1523711b1ea460a380fc665292c3 Mon Sep 17 00:00:00 2001 From: omar Date: Wed, 31 Jan 2018 17:41:26 +0100 Subject: [PATCH 562/823] Log: Comments and extraneous assets to clarify intent. (#1584) --- imgui.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 45e0e2a9bc4c..1025054557d9 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -6570,8 +6570,9 @@ void ImGui::LogToTTY(int max_depth) return; ImGuiWindow* window = g.CurrentWindow; - g.LogEnabled = true; + IM_ASSERT(g.LogFile == NULL); g.LogFile = stdout; + g.LogEnabled = true; g.LogStartDepth = window->DC.TreeDepth; if (max_depth >= 0) g.LogAutoExpandMaxDepth = max_depth; @@ -6592,6 +6593,7 @@ void ImGui::LogToFile(int max_depth, const char* filename) return; } + IM_ASSERT(g.LogFile == NULL); g.LogFile = ImFileOpen(filename, "ab"); if (!g.LogFile) { @@ -6612,8 +6614,9 @@ void ImGui::LogToClipboard(int max_depth) return; ImGuiWindow* window = g.CurrentWindow; - g.LogEnabled = true; + IM_ASSERT(g.LogFile == NULL); g.LogFile = NULL; + g.LogEnabled = true; g.LogStartDepth = window->DC.TreeDepth; if (max_depth >= 0) g.LogAutoExpandMaxDepth = max_depth; @@ -6626,7 +6629,6 @@ void ImGui::LogFinish() return; LogText(IM_NEWLINE); - g.LogEnabled = false; if (g.LogFile != NULL) { if (g.LogFile == stdout) @@ -6640,6 +6642,7 @@ void ImGui::LogFinish() SetClipboardText(g.LogClipboard->begin()); g.LogClipboard->clear(); } + g.LogEnabled = false; } // Helper to display logging buttons From e6c0b212e8119fb171913553ebd9f44ff0c0b5c1 Mon Sep 17 00:00:00 2001 From: omar Date: Wed, 31 Jan 2018 18:53:15 +0100 Subject: [PATCH 563/823] Nav: Fixed initial movement (which sends an InitRequest) from clearing NavDisableHighlight and fully enabling Nav feedbacks. (#787) NB: Setting g.NavInitResultExplicit = false on InitRequest match was added in initial commit c2cb2a6928a436b1358f5e960844c02cbab0b3ba --- imgui.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index feef6b5fee0b..58cfa3fbb2b8 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2291,7 +2291,7 @@ static void ImGui::NavProcessItem(ImGuiWindow* window, const ImRect& nav_bb, con // Even if 'ImGuiItemFlags_NoNavDefaultFocus' is on (typically collapse/close button) we record the first ResultId so they can be used as a fallback if (!(item_flags & ImGuiItemFlags_NoNavDefaultFocus)) { - g.NavInitRequest = g.NavInitResultExplicit = false; // Found a match, clear request + g.NavInitRequest = false; // Found a match, clear request NavUpdateAnyRequestFlag(); } if (g.NavInitResultId == 0 || !(item_flags & ImGuiItemFlags_NoNavDefaultFocus)) @@ -2887,10 +2887,11 @@ static void ImGui::NavUpdate() { // Apply result from previous navigation init request (will typically select the first item, unless SetItemDefaultFocus() has been called) IM_ASSERT(g.NavWindow); - SetNavID(g.NavInitResultId, g.NavLayer); + if (g.NavInitResultExplicit) + SetNavIDAndMoveMouse(g.NavInitResultId, g.NavLayer, g.NavInitResultRectRel); + else + SetNavID(g.NavInitResultId, g.NavLayer); g.NavWindow->NavRectRel[g.NavLayer] = g.NavInitResultRectRel; - if (g.NavDisableMouseHover) - g.NavMousePosDirty = true; } g.NavInitRequest = false; g.NavInitResultExplicit = false; From 38d45ee73f47a70ca1f9a81522a36d493ab1bf30 Mon Sep 17 00:00:00 2001 From: omar Date: Wed, 31 Jan 2018 19:13:20 +0100 Subject: [PATCH 564/823] Demo: Tweaked the Child demos, added a menu bar to the second child to test some navigation functions. --- imgui_demo.cpp | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 9e92634fbe02..852123fdf7d8 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -1056,7 +1056,6 @@ void ImGui::ShowDemoWindow(bool* p_open) static bool disable_mouse_wheel = false; ImGui::Checkbox("Disable Mouse Wheel", &disable_mouse_wheel); - ImGui::Text("Without border"); static int line = 50; bool goto_line = ImGui::Button("Goto"); ImGui::SameLine(); @@ -1083,8 +1082,16 @@ void ImGui::ShowDemoWindow(bool* p_open) // Child 2: rounded border { ImGui::PushStyleVar(ImGuiStyleVar_ChildRounding, 5.0f); - ImGui::BeginChild("Child2", ImVec2(0,300), true, (disable_mouse_wheel ? ImGuiWindowFlags_NoScrollWithMouse : 0)); - ImGui::Text("With border"); + ImGui::BeginChild("Child2", ImVec2(0,300), true, (disable_mouse_wheel ? ImGuiWindowFlags_NoScrollWithMouse : 0) | ImGuiWindowFlags_MenuBar); + if (ImGui::BeginMenuBar()) + { + if (ImGui::BeginMenu("Menu")) + { + ShowExampleMenuFile(); + ImGui::EndMenu(); + } + ImGui::EndMenuBar(); + } ImGui::Columns(2); for (int i = 0; i < 100; i++) { From aa2dda7610a5c21daa905a26b8adec805b01a140 Mon Sep 17 00:00:00 2001 From: omar Date: Wed, 31 Jan 2018 21:06:47 +0100 Subject: [PATCH 565/823] Nav: Tweak code to be easier to follow + updated todo list after clarifying an issue. --- TODO.txt | 4 ++-- imgui.cpp | 13 +++++++------ 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/TODO.txt b/TODO.txt index 8f4701108b17..05a8875ed97a 100644 --- a/TODO.txt +++ b/TODO.txt @@ -235,8 +235,8 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i - nav: menus: allow pressing Menu to leave a sub-menu. - nav: integrate/design keyboard controls. - nav: simulate right-click or context activation? (SHIFT+F10) - - nav: tabs should go through most/all widgets (in submission order?) - - nav: currently cannot access menubar of a child window with Alt/menu key. + - nav: tabs should go through most/all widgets (in submission order?). + - nav: cannot access menubar of a flattened child window with Alt/menu key (not a very common use case..). - nav: esc/enter default behavior for popups, e.g. be able to mark an "ok" or "cancel" button that would get triggered by those keys. - focus: preserve ActiveId/focus stack state, e.g. when opening a menu and close it, previously selected InputText() focus gets restored (#622) - focus: SetKeyboardFocusHere() on with >= 0 offset could be done on same frame (else latch and modulate on beginning of next frame) diff --git a/imgui.cpp b/imgui.cpp index 58cfa3fbb2b8..372029ba12ff 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2289,16 +2289,16 @@ static void ImGui::NavProcessItem(ImGuiWindow* window, const ImRect& nav_bb, con if (g.NavInitRequest && g.NavLayer == window->DC.NavLayerCurrent) { // Even if 'ImGuiItemFlags_NoNavDefaultFocus' is on (typically collapse/close button) we record the first ResultId so they can be used as a fallback + if (!(item_flags & ImGuiItemFlags_NoNavDefaultFocus) || g.NavInitResultId == 0) + { + g.NavInitResultId = id; + g.NavInitResultRectRel = nav_bb_rel; + } if (!(item_flags & ImGuiItemFlags_NoNavDefaultFocus)) { g.NavInitRequest = false; // Found a match, clear request NavUpdateAnyRequestFlag(); } - if (g.NavInitResultId == 0 || !(item_flags & ImGuiItemFlags_NoNavDefaultFocus)) - { - g.NavInitResultId = id; - g.NavInitResultRectRel = nav_bb_rel; - } } // Scoring for navigation @@ -13017,7 +13017,8 @@ void ImGui::ShowMetricsWindow(bool* p_open) ImGui::Text("HoveredId: 0x%08X/0x%08X (%.2f sec)", g.HoveredId, g.HoveredIdPreviousFrame, g.HoveredIdTimer); // Data is "in-flight" so depending on when the Metrics window is called we may see current frame information or not ImGui::Text("ActiveId: 0x%08X/0x%08X (%.2f sec), ActiveIdSource: %s", g.ActiveId, g.ActiveIdPreviousFrame, g.ActiveIdTimer, input_source_names[g.ActiveIdSource]); ImGui::Text("ActiveIdWindow: '%s'", g.ActiveIdWindow ? g.ActiveIdWindow->Name : "NULL"); - ImGui::Text("NavWindow: '%s', NavId: 0x%08X, NavLayer: %d", g.NavWindow ? g.NavWindow->Name : "NULL", g.NavId, g.NavLayer); + ImGui::Text("NavWindow: '%s'", g.NavWindow ? g.NavWindow->Name : "NULL"); + ImGui::Text("NavId: 0x%08X, NavLayer: %d", g.NavId, g.NavLayer); ImGui::Text("NavActive: %d, NavVisible: %d", g.IO.NavActive, g.IO.NavVisible); ImGui::Text("NavActivateId: 0x%08X, NavInputId: 0x%08X", g.NavActivateId, g.NavInputId); ImGui::Text("NavDisableHighlight: %d, NavDisableMouseHover: %d", g.NavDisableHighlight, g.NavDisableMouseHover); From 76d8af40369a8f32be1de52c5c1fc1cbf8591354 Mon Sep 17 00:00:00 2001 From: omar Date: Wed, 31 Jan 2018 21:25:52 +0100 Subject: [PATCH 566/823] Nav: when browsing a window that has no activable items (scroll only) we keep a highlight on the child. (#787) --- imgui.cpp | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 372029ba12ff..937619ca32bb 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -4960,7 +4960,8 @@ bool ImGui::BeginChild(ImGuiID id, const ImVec2& size_arg, bool border, ImGuiWin void ImGui::EndChild() { - ImGuiWindow* window = GetCurrentWindow(); + ImGuiContext& g = *GImGui; + ImGuiWindow* window = g.CurrentWindow; IM_ASSERT(window->Flags & ImGuiWindowFlags_ChildWindow); // Mismatched BeginChild()/EndChild() callss if (window->BeginCount > 1) @@ -4977,13 +4978,18 @@ void ImGui::EndChild() sz.y = ImMax(4.0f, sz.y); End(); - ImGuiWindow* parent_window = GetCurrentWindow(); + ImGuiWindow* parent_window = g.CurrentWindow; ImRect bb(parent_window->DC.CursorPos, parent_window->DC.CursorPos + sz); + ItemSize(sz); - if (!(window->Flags & ImGuiWindowFlags_NavFlattened) && (window->DC.NavLayerActiveMask != 0 || window->DC.NavHasScroll)) + if ((window->DC.NavLayerActiveMask != 0 || window->DC.NavHasScroll) && !(window->Flags & ImGuiWindowFlags_NavFlattened)) { ItemAdd(bb, window->ChildId); RenderNavHighlight(bb, window->ChildId); + + // When browsing a window that has no activable items (scroll only) we keep a highlight on the child + if (window->DC.NavLayerActiveMask == 0 && window == g.NavWindow) + RenderNavHighlight(ImRect(bb.Min - ImVec2(2,2), bb.Max + ImVec2(2,2)), g.NavId, ImGuiNavHighlightFlags_TypeThin); } else { From dbdbf01b9f735ccf53f7e767e54ff12867eb617b Mon Sep 17 00:00:00 2001 From: omar Date: Wed, 31 Jan 2018 19:13:20 +0100 Subject: [PATCH 567/823] Demo: Tweaked the Child demos, added a menu bar to the second child to test some navigation functions. --- imgui_demo.cpp | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 4c2a437e460a..b7c699480639 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -1051,9 +1051,10 @@ void ImGui::ShowDemoWindow(bool* p_open) if (ImGui::TreeNode("Child regions")) { static bool disable_mouse_wheel = false; + static bool disable_menu = false; ImGui::Checkbox("Disable Mouse Wheel", &disable_mouse_wheel); + ImGui::Checkbox("Disable Menu", &disable_menu); - ImGui::Text("Without border"); static int line = 50; bool goto_line = ImGui::Button("Goto"); ImGui::SameLine(); @@ -1080,8 +1081,16 @@ void ImGui::ShowDemoWindow(bool* p_open) // Child 2: rounded border { ImGui::PushStyleVar(ImGuiStyleVar_ChildRounding, 5.0f); - ImGui::BeginChild("Child2", ImVec2(0,300), true, (disable_mouse_wheel ? ImGuiWindowFlags_NoScrollWithMouse : 0)); - ImGui::Text("With border"); + ImGui::BeginChild("Child2", ImVec2(0,300), true, (disable_mouse_wheel ? ImGuiWindowFlags_NoScrollWithMouse : 0) | (disable_menu ? 0 : ImGuiWindowFlags_MenuBar)); + if (!disable_menu && ImGui::BeginMenuBar()) + { + if (ImGui::BeginMenu("Menu")) + { + ShowExampleMenuFile(); + ImGui::EndMenu(); + } + ImGui::EndMenuBar(); + } ImGui::Columns(2); for (int i = 0; i < 100; i++) { From 9bc5c089b6c351b821bbd672f3c002b9b53ead03 Mon Sep 17 00:00:00 2001 From: omar Date: Wed, 31 Jan 2018 22:14:33 +0100 Subject: [PATCH 568/823] Internal: Avoid needlessly bringing parent of front-most child back to front. This is mostly to reduce flicker/confusion in Metrics when traversing windows. We could aim at separating the child windows from non-child windows at some point. --- imgui.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/imgui.cpp b/imgui.cpp index 1025054557d9..f0414555c5a3 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -5161,7 +5161,8 @@ void ImGui::Scrollbar(ImGuiLayoutType direction) void ImGui::BringWindowToFront(ImGuiWindow* window) { ImGuiContext& g = *GImGui; - if (g.Windows.back() == window) + ImGuiWindow* current_front_window = g.Windows.back(); + if (current_front_window == window || current_front_window->RootWindow == window) return; for (int i = g.Windows.Size - 2; i >= 0; i--) // We can ignore the front most window if (g.Windows[i] == window) From 7b22a91578800e115b5d3feacaa89707d80ab788 Mon Sep 17 00:00:00 2001 From: omar Date: Thu, 1 Feb 2018 00:08:13 +0100 Subject: [PATCH 569/823] Nav / Slider: Fixed reaching edge of integer slider with navigation input, bug introduced on January 25 in Nav branch 10a4a77b27d598bf10fb617e4180488eaf0adc2a. (#787) --- imgui.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/imgui.cpp b/imgui.cpp index ac12e3fff266..ebbd75225f30 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -8457,10 +8457,11 @@ bool ImGui::SliderBehavior(const ImRect& frame_bb, ImGuiID id, float* v, float v } if (IsNavInputDown(ImGuiNavInput_PadTweakFast)) delta *= 10.0f; - clicked_t = ImSaturate(clicked_t + delta); set_new_value = true; if ((clicked_t >= 1.0f && delta > 0.0f) || (clicked_t <= 0.0f && delta < 0.0f)) // This is to avoid applying the saturation when already past the limits set_new_value = false; + else + clicked_t = ImSaturate(clicked_t + delta); } } else From bdd868704f8cf92384847f98a5e354f511a296e1 Mon Sep 17 00:00:00 2001 From: omar Date: Thu, 1 Feb 2018 00:50:42 +0100 Subject: [PATCH 570/823] Nav: Child window is restored on focus when returning to layer 0 or refocusing. This is a little experimental and potentially error-prone right now. (#787, vaguely relate to ~#727) Ideally we should maintain a non-sorted last-focused list that include childs windows. --- TODO.txt | 1 - imgui.cpp | 46 ++++++++++++++++++++++++++++++++++++++-------- imgui_internal.h | 1 + 3 files changed, 39 insertions(+), 9 deletions(-) diff --git a/TODO.txt b/TODO.txt index 05a8875ed97a..a483594f6f3e 100644 --- a/TODO.txt +++ b/TODO.txt @@ -230,7 +230,6 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i - font: (api breaking) removed "TTF" from symbol names. also because it now supports OTF. - nav: integrate navigation branch into master. (#787) - - nav: Menu/Esc on a menu restore layer 0 but lose child window position. - nav: Esc on a flattened child - nav: menus: allow pressing Menu to leave a sub-menu. - nav: integrate/design keyboard controls. diff --git a/imgui.cpp b/imgui.cpp index ebbd75225f30..fc4e042039f1 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1919,6 +1919,7 @@ ImGuiWindow::ImGuiWindow(ImGuiContext* context, const char* name) NavRootWindow = NULL; NavLastIds[0] = NavLastIds[1] = 0; NavRectRel[0] = NavRectRel[1] = ImRect(); + NavLastChildNavWindow = NULL; FocusIdxAllCounter = FocusIdxTabCounter = -1; FocusIdxAllRequestCurrent = FocusIdxTabRequestCurrent = INT_MAX; @@ -1983,7 +1984,7 @@ static void SetNavID(ImGuiID id, int nav_layer) IM_ASSERT(g.NavWindow); IM_ASSERT(nav_layer == 0 || nav_layer == 1); g.NavId = id; - g.NavWindow->NavLastIds[nav_layer] = g.NavId; + g.NavWindow->NavLastIds[nav_layer] = id; } static void SetNavIDAndMoveMouse(ImGuiID id, int nav_layer, const ImRect& rect_rel) @@ -2248,10 +2249,22 @@ static bool NavScoreItem(ImGuiNavMoveResult* result, ImRect cand) return new_best; } +// Call when we are expected to land on Layer 0 after FocusWindow() +static ImGuiWindow* NavRestoreLastChildNavWindow(ImGuiWindow* window) +{ + ImGuiWindow* child_window = window->NavLastChildNavWindow; + if (child_window == NULL) + return window; + window->NavLastChildNavWindow = NULL; + return child_window; +} + static void NavRestoreLayer(int layer) { ImGuiContext& g = *GImGui; g.NavLayer = layer; + if (layer == 0) + g.NavWindow = NavRestoreLastChildNavWindow(g.NavWindow); if (layer == 0 && g.NavWindow->NavLastIds[0] != 0) SetNavIDAndMoveMouse(g.NavWindow->NavLastIds[0], layer, g.NavWindow->NavRectRel[0]); else @@ -2819,6 +2832,7 @@ static void ImGui::NavUpdateWindowing() { g.NavDisableHighlight = false; g.NavDisableMouseHover = true; + apply_focus_window = NavRestoreLastChildNavWindow(apply_focus_window); FocusWindow(apply_focus_window); if (apply_focus_window->NavLastIds[0] == 0) NavInitWindow(apply_focus_window, false); @@ -2833,8 +2847,14 @@ static void ImGui::NavUpdateWindowing() // Apply menu/layer toggle if (apply_toggle_layer && g.NavWindow) { + // FIXME-NAV: Iterate parent windows to find first one with an active menu layer, instead of aiming at root window immediately if ((g.NavWindow->DC.NavLayerActiveMask & (1 << 1)) == 0 && (g.NavWindow->RootWindow->DC.NavLayerActiveMask & (1 << 1)) != 0) - FocusWindow(g.NavWindow->RootWindow); + { + ImGuiWindow* old_nav_window = g.NavWindow; + ImGuiWindow* new_nav_window = g.NavWindow->RootWindow; + FocusWindow(new_nav_window); + new_nav_window->NavLastChildNavWindow = old_nav_window; + } g.NavDisableHighlight = false; g.NavDisableMouseHover = true; NavRestoreLayer((g.NavWindow->DC.NavLayerActiveMask & (1 << 1)) ? (g.NavLayer ^ 1) : 0); @@ -2945,6 +2965,12 @@ static void ImGui::NavUpdate() g.NavJustTabbedId = 0; IM_ASSERT(g.NavLayer == 0 || g.NavLayer == 1); + // Store our return window (for returning from Layer 1 to Layer 0) and clear it as soon as we step back in our own Layer 0 + if (g.NavWindow && g.NavWindow != g.NavWindow->RootWindow) + g.NavWindow->RootWindow->NavLastChildNavWindow = g.NavWindow; + if (g.NavWindow && g.NavWindow->NavLastChildNavWindow != NULL && g.NavLayer == 0) + g.NavWindow->NavLastChildNavWindow = NULL; + NavUpdateWindowing(); // Set output flags for user application @@ -4731,10 +4757,10 @@ static ImGuiWindow* GetFrontMostModalRootWindow() static void ClosePopupToLevel(int remaining) { ImGuiContext& g = *GImGui; - if (remaining > 0) - ImGui::FocusWindow(g.OpenPopupStack[remaining-1].Window); - else - ImGui::FocusWindow(g.OpenPopupStack[0].ParentWindow); + ImGuiWindow* focus_window = (remaining > 0) ? g.OpenPopupStack[remaining-1].Window : g.OpenPopupStack[0].ParentWindow; + if (g.NavLayer == 0) + focus_window = NavRestoreLastChildNavWindow(focus_window); + ImGui::FocusWindow(focus_window); g.OpenPopupStack.resize(remaining); } @@ -6210,9 +6236,11 @@ void ImGui::FocusWindow(ImGuiWindow* window) g.NavId = window ? window->NavLastIds[0] : 0; // Restore NavId g.NavIdIsAlive = false; g.NavLayer = 0; + g.NavWindow = window; if (window && g.NavDisableMouseHover) g.NavMousePosDirty = true; - g.NavWindow = window; + if (window && window->NavLastChildNavWindow != NULL) + window->NavLastChildNavWindow = NULL; } // Passing NULL allow to disable keyboard focus @@ -6239,7 +6267,8 @@ void ImGui::FocusFrontMostActiveWindow(ImGuiWindow* ignore_window) for (int i = g.Windows.Size - 1; i >= 0; i--) if (g.Windows[i] != ignore_window && g.Windows[i]->WasActive && !(g.Windows[i]->Flags & ImGuiWindowFlags_ChildWindow)) { - FocusWindow(g.Windows[i]); + ImGuiWindow* focus_window = NavRestoreLastChildNavWindow(g.Windows[i]); + FocusWindow(focus_window); return; } } @@ -12994,6 +13023,7 @@ void ImGui::ShowMetricsWindow(bool* p_open) ImGui::BulletText("Scroll: (%.2f/%.2f,%.2f/%.2f)", window->Scroll.x, GetScrollMaxX(window), window->Scroll.y, GetScrollMaxY(window)); ImGui::BulletText("Active: %d, WriteAccessed: %d", window->Active, window->WriteAccessed); ImGui::BulletText("NavLastIds: 0x%08X,0x%08X, NavLayerActiveMask: %X", window->NavLastIds[0], window->NavLastIds[1], window->DC.NavLayerActiveMask); + ImGui::BulletText("NavLastChildNavWindow: %s", window->NavLastChildNavWindow ? window->NavLastChildNavWindow->Name : "NULL"); ImGui::BulletText("NavRectRel[0]: (%.1f,%.1f)(%.1f,%.1f)", window->NavRectRel[0].Min.x, window->NavRectRel[0].Min.y, window->NavRectRel[0].Max.x, window->NavRectRel[0].Max.y); if (window->RootWindow != window) NodeWindow(window->RootWindow, "RootWindow"); if (window->DC.ChildWindows.Size > 0) NodeWindows(window->DC.ChildWindows, "ChildWindows"); diff --git a/imgui_internal.h b/imgui_internal.h index 7a691cb74e1a..23e6cfc02181 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -940,6 +940,7 @@ struct IMGUI_API ImGuiWindow ImGuiWindow* RootNonPopupWindow; // Generally point to ourself. Used to display TitleBgActive color and for selecting which window to use for NavWindowing ImGuiWindow* NavRootWindow; // Generally point to ourself. If we are a child window with the NavFlattened flag, point to a parent window. + ImGuiWindow* NavLastChildNavWindow; // When going to the menu bar, we remember the child window we came from. (This could probably be made implicit if we kept g.Windows sorted by last focused including child window.) ImGuiID NavLastIds[2]; // Last known NavId for this window, per layer (0/1) ImRect NavRectRel[2]; // Reference rectangle, in window relative space From 8cc2dbc3bded49f7b3707b949e61966fce50af66 Mon Sep 17 00:00:00 2001 From: omar Date: Thu, 1 Feb 2018 14:56:56 +0100 Subject: [PATCH 571/823] Internals: Nav: Extracted code into IsWindowNavFocusable(). (#787) --- imgui.cpp | 14 +++++++++----- imgui_internal.h | 1 + 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index fc4e042039f1..6ef58a6273cb 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2669,11 +2669,8 @@ static ImGuiWindow* FindWindowNavigable(int i_start, int i_stop, int dir) // FIX { ImGuiContext& g = *GImGui; for (int i = i_start; i >= 0 && i < g.Windows.Size && i != i_stop; i += dir) - { - ImGuiWindow* window = g.Windows[i]; - if (window->Active && window == window->RootNonPopupWindow && (!(window->Flags & ImGuiWindowFlags_NoNavFocus) || window == g.NavWindow)) - return window; - } + if (ImGui::IsWindowNavFocusable(g.Windows[i])) + return g.Windows[i]; return NULL; } @@ -6650,6 +6647,13 @@ bool ImGui::IsWindowFocused(ImGuiFocusedFlags flags) } } +// Can we focus this window with CTRL+TAB (or PadMenu + PadFocusPrev/PadFocusNext) +bool ImGui::IsWindowNavFocusable(ImGuiWindow* window) +{ + ImGuiContext& g = *GImGui; + return window->Active && window == window->RootNonPopupWindow && (!(window->Flags & ImGuiWindowFlags_NoNavFocus) || window == g.NavWindow); +} + float ImGui::GetWindowWidth() { ImGuiWindow* window = GImGui->CurrentWindow; diff --git a/imgui_internal.h b/imgui_internal.h index 23e6cfc02181..a44eba4f4895 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -1001,6 +1001,7 @@ namespace ImGui IMGUI_API void BringWindowToFront(ImGuiWindow* window); IMGUI_API void BringWindowToBack(ImGuiWindow* window); IMGUI_API bool IsWindowChildOf(ImGuiWindow* window, ImGuiWindow* potential_parent); + IMGUI_API bool IsWindowNavFocusable(ImGuiWindow* window); IMGUI_API void Initialize(); From ef2c3bcdee9af118a1345488dad53dd7bf04bec1 Mon Sep 17 00:00:00 2001 From: omar Date: Thu, 1 Feb 2018 18:02:55 +0100 Subject: [PATCH 572/823] Nav: Fixed InitRequest leaking when changing window (repro was to navigate inside File->Options->[Child] then press Left and notice how we would land on parent window on the fist item after the current one). (#787) --- imgui.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/imgui.cpp b/imgui.cpp index 6ef58a6273cb..daf39ec7b473 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -6238,6 +6238,8 @@ void ImGui::FocusWindow(ImGuiWindow* window) g.NavMousePosDirty = true; if (window && window->NavLastChildNavWindow != NULL) window->NavLastChildNavWindow = NULL; + if (g.NavInitRequest) + g.NavInitRequest = false; } // Passing NULL allow to disable keyboard focus From fd6d8863f77c87d642d1a6108f061a0315d2daf0 Mon Sep 17 00:00:00 2001 From: omar Date: Thu, 1 Feb 2018 18:19:36 +0100 Subject: [PATCH 573/823] Nav: SetFocusID() clears NavInitRequest for consistency (repro would a same frame interaction / race condition). (#787) --- imgui.cpp | 5 +++-- imgui_internal.h | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index daf39ec7b473..e9795c8d891e 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2027,6 +2027,8 @@ void ImGui::SetFocusID(ImGuiID id, ImGuiWindow* window) // Assume that SetFocusID() is called in the context where its NavLayer is the current layer, which is the case everywhere we call it. const int nav_layer = window->DC.NavLayerCurrent; + if (g.NavWindow != window) + g.NavInitRequest = false; g.NavId = id; g.NavWindow = window; g.NavLayer = nav_layer; @@ -6238,8 +6240,7 @@ void ImGui::FocusWindow(ImGuiWindow* window) g.NavMousePosDirty = true; if (window && window->NavLastChildNavWindow != NULL) window->NavLastChildNavWindow = NULL; - if (g.NavInitRequest) - g.NavInitRequest = false; + g.NavInitRequest = false; } // Passing NULL allow to disable keyboard focus diff --git a/imgui_internal.h b/imgui_internal.h index a44eba4f4895..0c93de71a2d8 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -621,7 +621,7 @@ struct ImGuiContext int NavLayer; // Layer we are navigating on. For now the system is hard-coded for 0=main contents and 1=menu/title bar, may expose layers later. int NavIdTabCounter; // == NavWindow->DC.FocusIdxTabCounter at time of NavId processing bool NavIdIsAlive; // Nav widget has been seen this frame ~~ NavRefRectRel is valid - bool NavMousePosDirty; + bool NavMousePosDirty; // When set we will update mouse position if (NavFlags & ImGuiNavFlags_MoveMouse) if set bool NavDisableHighlight; // When user starts using mouse, we hide gamepad/keyboard highlight (nb: but they are still available, which is why NavDisableHighlight isn't always != NavDisableMouseHover) bool NavDisableMouseHover; // When user starts using gamepad/keyboard, we hide mouse hovering highlight until mouse is touched again. bool NavAnyRequest; // ~~ NavMoveRequest || NavInitRequest From 5812d0b75108a21f2436e668d140bda59154a8ac Mon Sep 17 00:00:00 2001 From: omar Date: Thu, 1 Feb 2018 18:29:30 +0100 Subject: [PATCH 574/823] Nav: Using CTRL+TAB / PadFocusNext/Prev to Focus a window closes the previous window popups. (#787) --- imgui.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/imgui.cpp b/imgui.cpp index e9795c8d891e..e3b41300ebc6 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2832,6 +2832,7 @@ static void ImGui::NavUpdateWindowing() g.NavDisableHighlight = false; g.NavDisableMouseHover = true; apply_focus_window = NavRestoreLastChildNavWindow(apply_focus_window); + CloseInactivePopups(apply_focus_window); FocusWindow(apply_focus_window); if (apply_focus_window->NavLastIds[0] == 0) NavInitWindow(apply_focus_window, false); From 07163804df6312590900bc2d3d6edd412fc0dee6 Mon Sep 17 00:00:00 2001 From: omar Date: Thu, 1 Feb 2018 18:31:41 +0100 Subject: [PATCH 575/823] Internals: Renamed CloseInactivePopups() to a better ClosePopupsOverWindow(). Exposed in imgui_internal.h --- imgui.cpp | 11 +++++------ imgui_internal.h | 1 + 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index f0414555c5a3..9d8755771db7 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -669,7 +669,6 @@ static void MarkIniSettingsDirty(ImGuiWindow* window); static ImRect GetViewportRect(); -static void CloseInactivePopups(ImGuiWindow* ref_window); static void ClosePopupToLevel(int remaining); static ImGuiWindow* GetFrontMostModalRootWindow(); @@ -2549,7 +2548,7 @@ void ImGui::NewFrame() // But in order to allow the user to call NewFrame() multiple times without calling Render(), we are doing an explicit clear. g.CurrentWindowStack.resize(0); g.CurrentPopupStack.resize(0); - CloseInactivePopups(g.NavWindow); + ClosePopupsOverWindow(g.NavWindow); // Create implicit window - we will only render it if the user has added something to it. // We don't use "Debug" to avoid colliding with user trying to create a "Debug" window with custom flags. @@ -3000,7 +2999,7 @@ void ImGui::EndFrame() } // With right mouse button we close popups without changing focus - // (The left mouse button path calls FocusWindow which will lead NewFrame->CloseInactivePopups to trigger) + // (The left mouse button path calls FocusWindow which will lead NewFrame->ClosePopupsOverWindow to trigger) if (g.IO.MouseClicked[1]) { // Find the top-most window between HoveredWindow and the front most Modal Window. @@ -3017,7 +3016,7 @@ void ImGui::EndFrame() if (window == g.HoveredWindow) hovered_window_above_modal = true; } - CloseInactivePopups(hovered_window_above_modal ? g.HoveredWindow : modal); + ClosePopupsOverWindow(hovered_window_above_modal ? g.HoveredWindow : modal); } } } @@ -3772,7 +3771,7 @@ void ImGui::OpenPopupEx(ImGuiID id) else g.OpenPopupStack[current_stack_size] = popup_ref; - // When reopening a popup we first refocus its parent, otherwise if its parent is itself a popup it would get closed by CloseInactivePopups(). + // When reopening a popup we first refocus its parent, otherwise if its parent is itself a popup it would get closed by ClosePopupsOverWindow(). // This is equivalent to what ClosePopupToLevel() does. //if (g.OpenPopupStack[current_stack_size].PopupId == id) // FocusWindow(parent_window); @@ -3785,7 +3784,7 @@ void ImGui::OpenPopup(const char* str_id) OpenPopupEx(g.CurrentWindow->GetID(str_id)); } -static void CloseInactivePopups(ImGuiWindow* ref_window) +void ImGui::ClosePopupsOverWindow(ImGuiWindow* ref_window) { ImGuiContext& g = *GImGui; if (g.OpenPopupStack.empty()) diff --git a/imgui_internal.h b/imgui_internal.h index a00a88a0947a..37a31bff59b9 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -894,6 +894,7 @@ namespace ImGui IMGUI_API void OpenPopupEx(ImGuiID id); IMGUI_API void ClosePopup(ImGuiID id); + IMGUI_API void ClosePopupsOverWindow(ImGuiWindow* ref_window); IMGUI_API bool IsPopupOpen(ImGuiID id); IMGUI_API bool BeginPopupEx(ImGuiID id, ImGuiWindowFlags extra_flags); IMGUI_API void BeginTooltipEx(ImGuiWindowFlags extra_flags, bool override_previous_tooltip = true); From 95f9c74b9ae857529675489b4ce99490671dcf57 Mon Sep 17 00:00:00 2001 From: omar Date: Thu, 1 Feb 2018 19:21:44 +0100 Subject: [PATCH 576/823] Metrics: Displaying some of the important internal window flags. --- imgui.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/imgui.cpp b/imgui.cpp index 34cc18519560..a3b72926b895 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -13025,13 +13025,20 @@ void ImGui::ShowMetricsWindow(bool* p_open) { if (!ImGui::TreeNode(window, "%s '%s', %d @ 0x%p", label, window->Name, window->Active || window->WasActive, window)) return; + ImGuiWindowFlags flags = window->Flags; NodeDrawList(window, window->DrawList, "DrawList"); ImGui::BulletText("Pos: (%.1f,%.1f), Size: (%.1f,%.1f), SizeContents (%.1f,%.1f)", window->Pos.x, window->Pos.y, window->Size.x, window->Size.y, window->SizeContents.x, window->SizeContents.y); + ImGui::BulletText("Flags: 0x%08X (%s%s%s%s%s%s..)", flags, + (flags & ImGuiWindowFlags_ChildWindow) ? "Child " : "", (flags & ImGuiWindowFlags_Tooltip) ? "Tooltip " : "", (flags & ImGuiWindowFlags_Popup) ? "Popup " : "", + (flags & ImGuiWindowFlags_Modal) ? "Modal " : "", (flags & ImGuiWindowFlags_ChildMenu) ? "ChildMenu " : "", (flags & ImGuiWindowFlags_NoSavedSettings) ? "NoSavedSettings " : ""); ImGui::BulletText("Scroll: (%.2f/%.2f,%.2f/%.2f)", window->Scroll.x, GetScrollMaxX(window), window->Scroll.y, GetScrollMaxY(window)); ImGui::BulletText("Active: %d, WriteAccessed: %d", window->Active, window->WriteAccessed); ImGui::BulletText("NavLastIds: 0x%08X,0x%08X, NavLayerActiveMask: %X", window->NavLastIds[0], window->NavLastIds[1], window->DC.NavLayerActiveMask); ImGui::BulletText("NavLastChildNavWindow: %s", window->NavLastChildNavWindow ? window->NavLastChildNavWindow->Name : "NULL"); - ImGui::BulletText("NavRectRel[0]: (%.1f,%.1f)(%.1f,%.1f)", window->NavRectRel[0].Min.x, window->NavRectRel[0].Min.y, window->NavRectRel[0].Max.x, window->NavRectRel[0].Max.y); + if (window->NavRectRel[0].IsFinite()) + ImGui::BulletText("NavRectRel[0]: (%.1f,%.1f)(%.1f,%.1f)", window->NavRectRel[0].Min.x, window->NavRectRel[0].Min.y, window->NavRectRel[0].Max.x, window->NavRectRel[0].Max.y); + else + ImGui::BulletText("NavRectRel[0]: "); if (window->RootWindow != window) NodeWindow(window->RootWindow, "RootWindow"); if (window->DC.ChildWindows.Size > 0) NodeWindows(window->DC.ChildWindows, "ChildWindows"); ImGui::BulletText("Storage: %d bytes", window->StateStorage.Data.Size * (int)sizeof(ImGuiStorage::Pair)); From eb737e0a427bac0a79969a91a4bddd0486efaec0 Mon Sep 17 00:00:00 2001 From: omar Date: Thu, 1 Feb 2018 21:26:52 +0100 Subject: [PATCH 577/823] Nav: Child window is restored on focus follow up. Fix bdd868704f8cf92384847f98a5e354f511a296e1. (#787, ~#727) One visible issue was pressing Left to leave a child menu. --- imgui.cpp | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index a3b72926b895..8febc9400278 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2250,14 +2250,19 @@ static bool NavScoreItem(ImGuiNavMoveResult* result, ImRect cand) return new_best; } +static void NavSaveLastChildNavWindow(ImGuiWindow* child_window) +{ + ImGuiWindow* parent_window = child_window; + while (parent_window && (parent_window->Flags & ImGuiWindowFlags_ChildWindow) != 0 && (parent_window->Flags & (ImGuiWindowFlags_Popup | ImGuiWindowFlags_ChildMenu)) == 0) + parent_window = parent_window->ParentWindow; + if (parent_window && parent_window != child_window) + parent_window->NavLastChildNavWindow = child_window; +} + // Call when we are expected to land on Layer 0 after FocusWindow() static ImGuiWindow* NavRestoreLastChildNavWindow(ImGuiWindow* window) { - ImGuiWindow* child_window = window->NavLastChildNavWindow; - if (child_window == NULL) - return window; - window->NavLastChildNavWindow = NULL; - return child_window; + return window->NavLastChildNavWindow ? window->NavLastChildNavWindow : window; } static void NavRestoreLayer(int layer) @@ -2846,11 +2851,12 @@ static void ImGui::NavUpdateWindowing() // Apply menu/layer toggle if (apply_toggle_layer && g.NavWindow) { - // FIXME-NAV: Iterate parent windows to find first one with an active menu layer, instead of aiming at root window immediately - if ((g.NavWindow->DC.NavLayerActiveMask & (1 << 1)) == 0 && (g.NavWindow->RootWindow->DC.NavLayerActiveMask & (1 << 1)) != 0) + ImGuiWindow* new_nav_window = g.NavWindow; + while ((new_nav_window->DC.NavLayerActiveMask & (1 << 1)) == 0 && (new_nav_window->Flags & ImGuiWindowFlags_ChildWindow) != 0 && (new_nav_window->Flags & (ImGuiWindowFlags_Popup | ImGuiWindowFlags_ChildMenu)) == 0) + new_nav_window = new_nav_window->ParentWindow; + if (new_nav_window != g.NavWindow) { ImGuiWindow* old_nav_window = g.NavWindow; - ImGuiWindow* new_nav_window = g.NavWindow->RootWindow; FocusWindow(new_nav_window); new_nav_window->NavLastChildNavWindow = old_nav_window; } @@ -2965,8 +2971,8 @@ static void ImGui::NavUpdate() IM_ASSERT(g.NavLayer == 0 || g.NavLayer == 1); // Store our return window (for returning from Layer 1 to Layer 0) and clear it as soon as we step back in our own Layer 0 - if (g.NavWindow && g.NavWindow != g.NavWindow->RootWindow) - g.NavWindow->RootWindow->NavLastChildNavWindow = g.NavWindow; + if (g.NavWindow) + NavSaveLastChildNavWindow(g.NavWindow); if (g.NavWindow && g.NavWindow->NavLastChildNavWindow != NULL && g.NavLayer == 0) g.NavWindow->NavLastChildNavWindow = NULL; @@ -6238,8 +6244,6 @@ void ImGui::FocusWindow(ImGuiWindow* window) g.NavWindow = window; if (window && g.NavDisableMouseHover) g.NavMousePosDirty = true; - if (window && window->NavLastChildNavWindow != NULL) - window->NavLastChildNavWindow = NULL; g.NavInitRequest = false; } From 5c9ea4d53a864e412d01be3a0a9ac36062b0d5c7 Mon Sep 17 00:00:00 2001 From: omar Date: Thu, 1 Feb 2018 21:33:23 +0100 Subject: [PATCH 578/823] Nav: Fixed press Left on sub-menu when parent wasn't a menu - we were just checking at the wrong level. (#787) --- imgui.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/imgui.cpp b/imgui.cpp index 8febc9400278..01b9d0f886da 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -11099,7 +11099,7 @@ void ImGui::EndMenu() // Nav: When a left move request within our child menu failed, close the menu ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; - if (g.NavWindow && g.NavWindow->ParentWindow == window && NavMoveRequestButNoResultYet() && g.NavMoveDir == ImGuiDir_Left && window->DC.LayoutType == ImGuiLayoutType_Vertical) + if (g.NavWindow == window && g.NavMoveDir == ImGuiDir_Left && NavMoveRequestButNoResultYet() && window->DC.LayoutType == ImGuiLayoutType_Vertical) { ClosePopupToLevel(g.OpenPopupStack.Size - 1); NavMoveRequestCancel(); From c7b7b181b5ae1253bbbb3a6bf0ff6241ebaad5bb Mon Sep 17 00:00:00 2001 From: omar Date: Thu, 1 Feb 2018 22:13:25 +0100 Subject: [PATCH 579/823] Nav: CloseButton reacts when clipped. (#787) --- imgui.cpp | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 01b9d0f886da..4bec647c4db6 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -7564,17 +7564,21 @@ bool ImGui::InvisibleButton(const char* str_id, const ImVec2& size_arg) return pressed; } -// Upper-right button to close a window. +// Button to close a window bool ImGui::CloseButton(ImGuiID id, const ImVec2& pos, float radius) { - ImGuiWindow* window = GetCurrentWindow(); + ImGuiContext& g = *GImGui; + ImGuiWindow* window = g.CurrentWindow; + // We intentionally allow interaction when clipped so that a mechanical Alt,Right,Validate sequence close a window. + // (this isn't the regular behavior of buttons, but it doesn't affect the user much because navigation tends to keep items visible). const ImRect bb(pos - ImVec2(radius,radius), pos + ImVec2(radius,radius)); - if (!ItemAdd(bb, id)) // To allow navigation - return false; + bool is_clipped = !ItemAdd(bb, id); bool hovered, held; bool pressed = ButtonBehavior(bb, id, &hovered, &held); + if (is_clipped) + return pressed; // Render const ImU32 col = GetColorU32((held && hovered) ? ImGuiCol_CloseButtonActive : hovered ? ImGuiCol_CloseButtonHovered : ImGuiCol_CloseButton); @@ -7587,7 +7591,6 @@ bool ImGui::CloseButton(ImGuiID id, const ImVec2& pos, float radius) window->DrawList->AddLine(center + ImVec2(+cross_extent,+cross_extent), center + ImVec2(-cross_extent,-cross_extent), GetColorU32(ImGuiCol_Text)); window->DrawList->AddLine(center + ImVec2(+cross_extent,-cross_extent), center + ImVec2(-cross_extent,+cross_extent), GetColorU32(ImGuiCol_Text)); } - return pressed; } From 950f260a32538967e4a063c3259220013aee136e Mon Sep 17 00:00:00 2001 From: omar Date: Thu, 1 Feb 2018 22:25:25 +0100 Subject: [PATCH 580/823] Nav: Fixed Selectable/MenuItem Nav Highlight from using rounding when outer highlight stays square. (#787) --- imgui.cpp | 7 ++++--- imgui_internal.h | 3 ++- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 4bec647c4db6..fce0c566350f 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -4248,6 +4248,7 @@ void ImGui::RenderNavHighlight(const ImRect& bb, ImGuiID id, ImGuiNavHighlightFl return; ImGuiWindow* window = ImGui::GetCurrentWindow(); + float rounding = (flags & ImGuiNavHighlightFlags_NoRounding) ? 0.0f : g.Style.FrameRounding; ImRect display_rect = bb; display_rect.ClipWith(window->ClipRect); if (flags & ImGuiNavHighlightFlags_TypeDefault) @@ -4258,13 +4259,13 @@ void ImGui::RenderNavHighlight(const ImRect& bb, ImGuiID id, ImGuiNavHighlightFl bool fully_visible = window->ClipRect.Contains(display_rect); if (!fully_visible) window->DrawList->PushClipRect(display_rect.Min, display_rect.Max); - window->DrawList->AddRect(display_rect.Min + ImVec2(THICKNESS*0.5f,THICKNESS*0.5f), display_rect.Max - ImVec2(THICKNESS*0.5f,THICKNESS*0.5f), GetColorU32(ImGuiCol_NavHighlight), g.Style.FrameRounding, 0x0F, THICKNESS); + window->DrawList->AddRect(display_rect.Min + ImVec2(THICKNESS*0.5f,THICKNESS*0.5f), display_rect.Max - ImVec2(THICKNESS*0.5f,THICKNESS*0.5f), GetColorU32(ImGuiCol_NavHighlight), rounding, ImDrawCornerFlags_All, THICKNESS); if (!fully_visible) window->DrawList->PopClipRect(); } if (flags & ImGuiNavHighlightFlags_TypeThin) { - window->DrawList->AddRect(display_rect.Min, display_rect.Max, GetColorU32(ImGuiCol_NavHighlight), g.Style.FrameRounding, ~0, 1.0f); + window->DrawList->AddRect(display_rect.Min, display_rect.Max, GetColorU32(ImGuiCol_NavHighlight), rounding, ~0, 1.0f); } } @@ -10690,7 +10691,7 @@ bool ImGui::Selectable(const char* label, bool selected, ImGuiSelectableFlags fl { const ImU32 col = GetColorU32((held && hovered) ? ImGuiCol_HeaderActive : hovered ? ImGuiCol_HeaderHovered : ImGuiCol_Header); RenderFrame(bb_with_spacing.Min, bb_with_spacing.Max, col, false, 0.0f); - RenderNavHighlight(bb_with_spacing, id, ImGuiNavHighlightFlags_TypeThin); + RenderNavHighlight(bb_with_spacing, id, ImGuiNavHighlightFlags_TypeThin | ImGuiNavHighlightFlags_NoRounding); } if ((flags & ImGuiSelectableFlags_SpanAllColumns) && window->DC.ColumnsSet) diff --git a/imgui_internal.h b/imgui_internal.h index 4531f732f365..97fefb2ff9a1 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -282,7 +282,8 @@ enum ImGuiNavHighlightFlags_ { ImGuiNavHighlightFlags_TypeDefault = 1 << 0, ImGuiNavHighlightFlags_TypeThin = 1 << 1, - ImGuiNavHighlightFlags_AlwaysDraw = 1 << 2 + ImGuiNavHighlightFlags_AlwaysDraw = 1 << 2, + ImGuiNavHighlightFlags_NoRounding = 1 << 3 }; enum ImGuiNavDirSourceFlags_ From 68d3e139a74ed9d7cad4abb0f36466544ef24620 Mon Sep 17 00:00:00 2001 From: omar Date: Thu, 1 Feb 2018 22:28:58 +0100 Subject: [PATCH 581/823] Nav: When focusing a parent window while closing a popup, hide its highlight for one frame to avoid potential double highlight and flicker with the common pattern of menu items leading to the opening other windows. (#787) --- imgui.cpp | 6 +++++- imgui_internal.h | 2 ++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/imgui.cpp b/imgui.cpp index fce0c566350f..60863f3dcdcf 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -4247,6 +4247,8 @@ void ImGui::RenderNavHighlight(const ImRect& bb, ImGuiID id, ImGuiNavHighlightFl if (g.NavDisableHighlight && !(flags & ImGuiNavHighlightFlags_AlwaysDraw)) return; ImGuiWindow* window = ImGui::GetCurrentWindow(); + if (window->DC.NavHideHighlightOneFrame) + return; float rounding = (flags & ImGuiNavHighlightFlags_NoRounding) ? 0.0f : g.Style.FrameRounding; ImRect display_rect = bb; @@ -4767,6 +4769,7 @@ static void ClosePopupToLevel(int remaining) if (g.NavLayer == 0) focus_window = NavRestoreLastChildNavWindow(focus_window); ImGui::FocusWindow(focus_window); + focus_window->DC.NavHideHighlightOneFrame = true; g.OpenPopupStack.resize(remaining); } @@ -5901,9 +5904,10 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) window->DC.CursorMaxPos = window->DC.CursorStartPos; window->DC.CurrentLineHeight = window->DC.PrevLineHeight = 0.0f; window->DC.CurrentLineTextBaseOffset = window->DC.PrevLineTextBaseOffset = 0.0f; + window->DC.NavHideHighlightOneFrame = false; + window->DC.NavHasScroll = (GetScrollMaxY() > 0.0f); window->DC.NavLayerActiveMask = window->DC.NavLayerActiveMaskNext; window->DC.NavLayerActiveMaskNext = 0x00; - window->DC.NavHasScroll = (GetScrollMaxY() > 0.0f); window->DC.MenuBarAppending = false; window->DC.MenuBarOffsetX = ImMax(window->WindowPadding.x, style.ItemSpacing.x); window->DC.LogLinePosY = window->DC.CursorPos.y - 9999.0f; diff --git a/imgui_internal.h b/imgui_internal.h index 97fefb2ff9a1..37b32651455f 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -820,6 +820,7 @@ struct IMGUI_API ImGuiDrawContext ImGuiID LastItemId; ImRect LastItemRect; bool LastItemRectHoveredRect; + bool NavHideHighlightOneFrame; bool NavHasScroll; // Set when scrolling can be used (ScrollMax > 0.0f) int NavLayerCurrent; // Current layer, 0..31 (we currently only use 0..1) int NavLayerCurrentMask; // = (1 << NavLayerCurrent) used by ItemAdd prior to clipping. @@ -857,6 +858,7 @@ struct IMGUI_API ImGuiDrawContext LastItemId = 0; LastItemRect = ImRect(); LastItemRectHoveredRect = false; + NavHideHighlightOneFrame = false; NavHasScroll = false; NavLayerActiveMask = NavLayerActiveMaskNext = 0x00; NavLayerCurrent = 0; From 942c1407109577acfd19d9f8539d03a7882b8c71 Mon Sep 17 00:00:00 2001 From: omar Date: Thu, 1 Feb 2018 22:32:52 +0100 Subject: [PATCH 582/823] CloseButton: Fixed cross positioning. --- imgui.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/imgui.cpp b/imgui.cpp index 60863f3dcdcf..bb0b62d63303 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -7587,12 +7587,13 @@ bool ImGui::CloseButton(ImGuiID id, const ImVec2& pos, float radius) // Render const ImU32 col = GetColorU32((held && hovered) ? ImGuiCol_CloseButtonActive : hovered ? ImGuiCol_CloseButtonHovered : ImGuiCol_CloseButton); - const ImVec2 center = bb.GetCenter(); + ImVec2 center = bb.GetCenter(); window->DrawList->AddCircleFilled(center, ImMax(2.0f, radius), col, 12); const float cross_extent = (radius * 0.7071f) - 1.0f; if (hovered) { + center -= ImVec2(0.5f, 0.5f); window->DrawList->AddLine(center + ImVec2(+cross_extent,+cross_extent), center + ImVec2(-cross_extent,-cross_extent), GetColorU32(ImGuiCol_Text)); window->DrawList->AddLine(center + ImVec2(+cross_extent,-cross_extent), center + ImVec2(-cross_extent,+cross_extent), GetColorU32(ImGuiCol_Text)); } From c4fc87950897ca5f0a1861c4f3d2a60d1f2f331a Mon Sep 17 00:00:00 2001 From: omar Date: Thu, 1 Feb 2018 22:32:52 +0100 Subject: [PATCH 583/823] CloseButton: Fixed cross positioning. --- imgui.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/imgui.cpp b/imgui.cpp index 9d8755771db7..fe71f4f06eaf 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -6458,12 +6458,13 @@ bool ImGui::CloseButton(ImGuiID id, const ImVec2& pos, float radius) // Render const ImU32 col = GetColorU32((held && hovered) ? ImGuiCol_CloseButtonActive : hovered ? ImGuiCol_CloseButtonHovered : ImGuiCol_CloseButton); - const ImVec2 center = bb.GetCenter(); + ImVec2 center = bb.GetCenter(); window->DrawList->AddCircleFilled(center, ImMax(2.0f, radius), col, 12); const float cross_extent = (radius * 0.7071f) - 1.0f; if (hovered) { + center -= ImVec2(0.5f, 0.5f); window->DrawList->AddLine(center + ImVec2(+cross_extent,+cross_extent), center + ImVec2(-cross_extent,-cross_extent), GetColorU32(ImGuiCol_Text)); window->DrawList->AddLine(center + ImVec2(+cross_extent,-cross_extent), center + ImVec2(-cross_extent,+cross_extent), GetColorU32(ImGuiCol_Text)); } From efbd8cebe7bd7a410bc8e15fb45de22936bb4a39 Mon Sep 17 00:00:00 2001 From: omar Date: Thu, 1 Feb 2018 22:43:37 +0100 Subject: [PATCH 584/823] Nav: Comments (#787) --- TODO.txt | 3 +++ imgui.cpp | 15 ++++++++------- imgui_demo.cpp | 2 +- 3 files changed, 12 insertions(+), 8 deletions(-) diff --git a/TODO.txt b/TODO.txt index a483594f6f3e..6f6ab7cc3457 100644 --- a/TODO.txt +++ b/TODO.txt @@ -157,6 +157,7 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i - tooltip: allow tooltips with timers? or general timer policy? (instaneous vs timed) - menus: calling BeginMenu() twice with a same name doesn't append as Begin() does for regular windows (#1207) + - menus: menu bars inside modals windows are acting weird. - statusbar: add a per-window status bar helper similar to what menubar does. - shortcuts: local-style shortcut api, e.g. parse "&Save" - shortcuts,menus: global-style shortcut api e.g. "Save (CTRL+S)" -> explicit flag for recursing into closed menu @@ -230,6 +231,7 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i - font: (api breaking) removed "TTF" from symbol names. also because it now supports OTF. - nav: integrate navigation branch into master. (#787) + - nav: Left within a tree node block as a fallback. - nav: Esc on a flattened child - nav: menus: allow pressing Menu to leave a sub-menu. - nav: integrate/design keyboard controls. @@ -237,6 +239,7 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i - nav: tabs should go through most/all widgets (in submission order?). - nav: cannot access menubar of a flattened child window with Alt/menu key (not a very common use case..). - nav: esc/enter default behavior for popups, e.g. be able to mark an "ok" or "cancel" button that would get triggered by those keys. + - nav: when activating a button that changes label (without a static ID) or disappear, can we somehow automatically recover into a nearest highlight item? - focus: preserve ActiveId/focus stack state, e.g. when opening a menu and close it, previously selected InputText() focus gets restored (#622) - focus: SetKeyboardFocusHere() on with >= 0 offset could be done on same frame (else latch and modulate on beginning of next frame) - focus: unable to use SetKeyboardFocusHere() on clipped widgets. (#787) diff --git a/imgui.cpp b/imgui.cpp index bb0b62d63303..bd0ec45aad03 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -211,26 +211,27 @@ USING GAMEPAD/KEYBOARD NAVIGATION [BETA] - - Gamepad/keyboard navigation support is available, currently in Beta with some issues. Your feedback and bug reports are welcome. + - Gamepad/keyboard navigation support is now available. Your feedback and bug reports are greatly welcome! - See https://github.com/ocornut/imgui/issues/787 discussion thread and ask questions there. - - The current primary focus is to support game controllers. - - Consider emulating a mouse cursor with DualShock4 touch pad or a spare analog stick as a mouse-emulation fallback. - - Consider using Synergy host (on your computer) + uSynergy.c (in your console/tablet/phone app) to use PC mouse/keyboard. + - The initial focus was to support game controllers, but keyboard is becoming increasingly and decently usable. - Your inputs are passed to imgui by filling the io.NavInputs[] array. See 'enum ImGuiNavInput_' in imgui.h for a description of available inputs. + - Please refer to the examples/ application for suggested keyboard and gamepad mapping. + - PS4 users: Consider emulating a mouse cursor with DualShock4 touch pad or a spare analog stick as a mouse-emulation fallback. + - Consoles/Tablet/Phone users: Consider using Synergy host (on your computer) + uSynergy.c (in your console/tablet/phone app) to use your PC mouse/keyboard. - The ImGuiNavFlags_EnableGamepad and ImGuiNavFlags_EnableKeyboard flags of io.NavFlags are only here to instruct your binding whether to find inputs. - For gamepad use, the easiest approach is to go all-or-nothing, with a buttons combo that toggle your inputs between imgui and your game/application. Sharing inputs in a more advanced or granular way between imgui and your game/application may be tricky and requires further work on imgui. For more advanced uses, you may want to use: - io.NavActive: true when a window is focused and it doesn't have the ImGuiWindowFlags_NoNavInputs flag set. - io.NavVisible: true when the navigation cursor is visible (and usually goes false when mouse is used). - - query focus information with IsWindowFocused(), IsAnyWindowFocused(), IsAnyItemFocused() functions. + - query focus information with e.g. IsWindowFocused(), IsItemFocused() etc. functions. The reality is more complex than what those flags can express. Please discuss your issues and usage scenario in the thread above! As we head toward more keyboard-oriented development this aspect will need to be improved. - On a TV/console system where readability may be lower or mouse inputs may be awkward, you may want to set the ImGuiNavFlags_MoveMouse flag in io.NavFlags. - Enabling ImGuiNavFlags_MoveMouse instructs dear imgui to move your mouse cursor along when navigation movement. + Enabling ImGuiNavFlags_MoveMouse instructs dear imgui to move your mouse cursor along with navigation movement. When enabled, the NewFrame() functions may alter 'io.MousePos' and set 'io.WantMoveMouse' to notify you that it did so. When that happens your back-end NEEDS to move the OS or underlying mouse cursor on the next frame. Some of the binding in examples/ do that. - (Important: It you set the ImGuiNavFlags_MoveMouse flag but don't honor 'io.WantMoveMouse' properly, imgui will misbehave as it will think your mouse is moving back and forth.) + (If you set the ImGuiNavFlags_MoveMouse flag but don't honor 'io.WantMoveMouse' properly, imgui will misbehave as it will see your mouse as moving back and forth.) (In a setup when you may not have easy control over the mouse cursor, e.g. uSynergy.c doesn't expose moving remote mouse cursor, you may want to set a boolean to ignore your other external mouse positions until the external source is moved again.) diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 2de0f63208c6..3af5399bae5e 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -1533,7 +1533,7 @@ void ImGui::ShowDemoWindow(bool* p_open) ImGui::OpenPopup("Delete?"); if (ImGui::BeginPopupModal("Delete?", NULL, ImGuiWindowFlags_AlwaysAutoResize)) { - ImGui::Text("All those beautiful files will be deleted.\nThis operation cannot be undone!\n\n"); + ImGui::Text("All those beautiful files will be deleted.\nThis operation cannot be undone!\n\n"); ImGui::Separator(); //static int dummy_i = 0; From 96ddfbc97342c8c4750cf66a05cae285afc26e6f Mon Sep 17 00:00:00 2001 From: omar Date: Thu, 1 Feb 2018 23:36:22 +0100 Subject: [PATCH 585/823] Nav: Modal windows can't be closed with Nav PadCancel. (#787) --- imgui.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/imgui.cpp b/imgui.cpp index bd0ec45aad03..a1ab36ebcffd 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -3005,7 +3005,8 @@ static void ImGui::NavUpdate() else if (g.OpenPopupStack.Size > 0) { // Close open popup/menu - ClosePopupToLevel(g.OpenPopupStack.Size - 1); + if (!(g.OpenPopupStack.back().Window->Flags & ImGuiWindowFlags_Modal)) + ClosePopupToLevel(g.OpenPopupStack.Size - 1); } else if (g.NavLayer != 0) { From 6a83a9152fe5ee6c59948099a6a2805ae1ae958f Mon Sep 17 00:00:00 2001 From: omar Date: Thu, 1 Feb 2018 23:39:02 +0100 Subject: [PATCH 586/823] Natvis: Showing some flags for ImGuiWindow. --- misc/natvis/imgui.natvis | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/misc/natvis/imgui.natvis b/misc/natvis/imgui.natvis index 38c676c757f8..48b20426e385 100644 --- a/misc/natvis/imgui.natvis +++ b/misc/natvis/imgui.natvis @@ -33,8 +33,7 @@ - {{Name={Name,s}}} - {{Name={Name,s}} Inactive} + {{Name={Name,s} Active {(Active||WasActive)?1:0,d} Child {(Flags & 0x01000000)?1:0,d} Popup {(Flags & 0x04000000)?1:0,d}} \ No newline at end of file From 91209382002eb9bd36c0dc8c91f83e755bfc9844 Mon Sep 17 00:00:00 2001 From: omar Date: Thu, 1 Feb 2018 23:53:00 +0100 Subject: [PATCH 587/823] Nav: Revert 5c9ea4d53a864e412d01be3a0a9ac36062b0d5c7 with comments. (#787) --- imgui.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index a1ab36ebcffd..a62fe7824aad 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -11107,10 +11107,12 @@ bool ImGui::BeginMenu(const char* label, bool enabled) void ImGui::EndMenu() { - // Nav: When a left move request within our child menu failed, close the menu + // Nav: When a left move request _within our child menu_ failed, close the menu. + // A menu doesn't close itself because EndMenuBar() wants the catch the last Left<>Right inputs. + // However it means that with the current code, a BeginMenu() from outside another menu or a menu-bar won't be closable with the Left direction. ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; - if (g.NavWindow == window && g.NavMoveDir == ImGuiDir_Left && NavMoveRequestButNoResultYet() && window->DC.LayoutType == ImGuiLayoutType_Vertical) + if (g.NavWindow && g.NavWindow->ParentWindow == window && g.NavMoveDir == ImGuiDir_Left && NavMoveRequestButNoResultYet() && window->DC.LayoutType == ImGuiLayoutType_Vertical) { ClosePopupToLevel(g.OpenPopupStack.Size - 1); NavMoveRequestCancel(); From ce9d7baaba09df15ca8afc54baef1cff15ae72ee Mon Sep 17 00:00:00 2001 From: omar Date: Fri, 2 Feb 2018 17:47:05 +0100 Subject: [PATCH 588/823] Nav: TreeNode: Added ImGuiTreeNodeFlags_NavCloseFromChild flag, allow closing a TreeNode() from any of child. The explicit flag is not great, perhaps allowing some form of inheritance would help. (#787, #1079) --- imgui.cpp | 22 +++++++++++++++++++++- imgui.h | 1 + imgui_internal.h | 2 ++ 3 files changed, 24 insertions(+), 1 deletion(-) diff --git a/imgui.cpp b/imgui.cpp index a62fe7824aad..210132a747a7 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -5924,6 +5924,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) window->DC.TextWrapPosStack.resize(0); window->DC.ColumnsSet = NULL; window->DC.TreeDepth = 0; + window->DC.TreeDepthMayCloseOnPop = 0x00; window->DC.StateStorage = &window->StateStorage; window->DC.GroupStack.resize(0); window->MenuColumns.Update(3, style.ItemSpacing.x, window_just_activated_by_user); @@ -7883,6 +7884,13 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l // (Ideally we'd want to add a flag for the user to specify if we want the hit test to be done up to the right side of the content or not) const ImRect interact_bb = display_frame ? bb : ImRect(bb.Min.x, bb.Min.y, bb.Min.x + text_width + style.ItemSpacing.x*2, bb.Max.y); bool is_open = TreeNodeBehaviorIsOpen(id, flags); + + // Store a flag for the current depth to tell if we will allow closing this node when navigating one of its child. + // For this purpose we essentially compare if g.NavIdIsAlive went from 0 to 1 between TreeNode() and TreePop(). + // This is currently only support 32 level deep and we are fine with (1 << Depth) overflowing into a zero. + if (is_open && !g.NavIdIsAlive && (flags & ImGuiTreeNodeFlags_NavCloseFromChild) && !(flags & ImGuiTreeNodeFlags_NoTreePushOnOpen)) + window->DC.TreeDepthMayCloseOnPop |= (1 << window->DC.TreeDepth); + if (!ItemAdd(interact_bb, id)) { if (is_open && !(flags & ImGuiTreeNodeFlags_NoTreePushOnOpen)) @@ -12529,9 +12537,21 @@ void ImGui::TreePushRawID(ImGuiID id) void ImGui::TreePop() { - ImGuiWindow* window = GetCurrentWindow(); + ImGuiContext& g = *GImGui; + ImGuiWindow* window = g.CurrentWindow; Unindent(); + window->DC.TreeDepth--; + if (g.NavMoveDir == ImGuiDir_Left && g.NavWindow == window && NavMoveRequestButNoResultYet()) + if (g.NavIdIsAlive && (window->DC.TreeDepthMayCloseOnPop & (1 << window->DC.TreeDepth))) + { + ImGuiID id = window->IDStack.back(); + window->DC.StateStorage->SetBool(id, false); + SetNavID(id, g.NavLayer); + NavMoveRequestCancel(); + } + window->DC.TreeDepthMayCloseOnPop &= (1 << window->DC.TreeDepth) - 1; + PopID(); } diff --git a/imgui.h b/imgui.h index 5238b8c9fff5..d441497ca16e 100644 --- a/imgui.h +++ b/imgui.h @@ -602,6 +602,7 @@ enum ImGuiTreeNodeFlags_ ImGuiTreeNodeFlags_FramePadding = 1 << 10, // Use FramePadding (even for an unframed text node) to vertically align text baseline to regular widget height. Equivalent to calling AlignTextToFramePadding(). //ImGuITreeNodeFlags_SpanAllAvailWidth = 1 << 11, // FIXME: TODO: Extend hit box horizontally even if not framed //ImGuiTreeNodeFlags_NoScrollOnOpen = 1 << 12, // FIXME: TODO: Disable automatic scroll on TreePop() if node got just open and contents is not visible + ImGuiTreeNodeFlags_NavCloseFromChild = 1 << 13, // (WIP) Nav: left direction may close this TreeNode() when focusing on any child (items submitted between TreeNode and TreePop) ImGuiTreeNodeFlags_CollapsingHeader = ImGuiTreeNodeFlags_Framed | ImGuiTreeNodeFlags_NoAutoOpenOnLog // Obsolete names (will be removed) diff --git a/imgui_internal.h b/imgui_internal.h index 37b32651455f..9b6bc742f902 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -817,6 +817,7 @@ struct IMGUI_API ImGuiDrawContext float PrevLineTextBaseOffset; float LogLinePosY; int TreeDepth; + ImU32 TreeDepthMayCloseOnPop; // Store a copy of !g.NavIdIsAlive for TreeDepth 0..31 ImGuiID LastItemId; ImRect LastItemRect; bool LastItemRectHoveredRect; @@ -855,6 +856,7 @@ struct IMGUI_API ImGuiDrawContext CurrentLineTextBaseOffset = PrevLineTextBaseOffset = 0.0f; LogLinePosY = -1.0f; TreeDepth = 0; + TreeDepthMayCloseOnPop = 0x00; LastItemId = 0; LastItemRect = ImRect(); LastItemRectHoveredRect = false; From 648de2fc00e7960c89aac7a8826aea758d6894a5 Mon Sep 17 00:00:00 2001 From: omar Date: Fri, 2 Feb 2018 18:38:18 +0100 Subject: [PATCH 589/823] Nav: Press Left on a child with ImGuiTreeNodeFlags_NavCloseFromChild moves you to parent node instead of closing it immediately. More standard. (#787, #1079) --- imgui.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 210132a747a7..a0e7e2c4df88 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -12545,9 +12545,7 @@ void ImGui::TreePop() if (g.NavMoveDir == ImGuiDir_Left && g.NavWindow == window && NavMoveRequestButNoResultYet()) if (g.NavIdIsAlive && (window->DC.TreeDepthMayCloseOnPop & (1 << window->DC.TreeDepth))) { - ImGuiID id = window->IDStack.back(); - window->DC.StateStorage->SetBool(id, false); - SetNavID(id, g.NavLayer); + SetNavID(window->IDStack.back(), g.NavLayer); NavMoveRequestCancel(); } window->DC.TreeDepthMayCloseOnPop &= (1 << window->DC.TreeDepth) - 1; From 147ec8d1e2a0935082207aeab254df7039bd29c5 Mon Sep 17 00:00:00 2001 From: omar Date: Sun, 4 Feb 2018 12:17:35 +0100 Subject: [PATCH 590/823] Style Added style.MouseCursorScale, may remove (#939). --- imgui.cpp | 13 ++++++++----- imgui.h | 1 + 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index fe71f4f06eaf..9dd9eb77880c 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -774,6 +774,7 @@ void ImGuiStyle::ScaleAllSizes(float scale_factor) GrabRounding = ImFloor(GrabRounding * scale_factor); DisplayWindowPadding = ImFloor(DisplayWindowPadding * scale_factor); DisplaySafeAreaPadding = ImFloor(DisplaySafeAreaPadding * scale_factor); + MouseCursorScale = ImFloor(MouseCursorScale * scale_factor); } ImGuiIO::ImGuiIO() @@ -3073,11 +3074,12 @@ void ImGui::Render() { const ImVec2 pos = g.IO.MousePos - offset; const ImTextureID tex_id = g.IO.Fonts->TexID; + const float sc = g.Style.MouseCursorScale; g.OverlayDrawList.PushTextureID(tex_id); - g.OverlayDrawList.AddImage(tex_id, pos+ImVec2(1,0), pos+ImVec2(1,0) + size, uv[2], uv[3], IM_COL32(0,0,0,48)); // Shadow - g.OverlayDrawList.AddImage(tex_id, pos+ImVec2(2,0), pos+ImVec2(2,0) + size, uv[2], uv[3], IM_COL32(0,0,0,48)); // Shadow - g.OverlayDrawList.AddImage(tex_id, pos, pos + size, uv[2], uv[3], IM_COL32(0,0,0,255)); // Black border - g.OverlayDrawList.AddImage(tex_id, pos, pos + size, uv[0], uv[1], IM_COL32(255,255,255,255)); // White fill + g.OverlayDrawList.AddImage(tex_id, pos + ImVec2(1,0)*sc, pos+ImVec2(1,0)*sc + size*sc, uv[2], uv[3], IM_COL32(0,0,0,48)); // Shadow + g.OverlayDrawList.AddImage(tex_id, pos + ImVec2(2,0)*sc, pos+ImVec2(2,0)*sc + size*sc, uv[2], uv[3], IM_COL32(0,0,0,48)); // Shadow + g.OverlayDrawList.AddImage(tex_id, pos, pos + size*sc, uv[2], uv[3], IM_COL32(0,0,0,255)); // Black border + g.OverlayDrawList.AddImage(tex_id, pos, pos + size*sc, uv[0], uv[1], IM_COL32(255,255,255,255)); // White fill g.OverlayDrawList.PopTextureID(); } if (!g.OverlayDrawList.VtxBuffer.empty()) @@ -4723,8 +4725,9 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) // Position tooltip (always follows mouse) if ((flags & ImGuiWindowFlags_Tooltip) != 0 && !window_pos_set_by_api && !window_is_child_tooltip) { + float sc = g.Style.MouseCursorScale; ImVec2 ref_pos = g.IO.MousePos; - ImRect rect_to_avoid(ref_pos.x - 16, ref_pos.y - 8, ref_pos.x + 24, ref_pos.y + 24); // FIXME: Completely hard-coded. Store boxes in mouse cursor data? Scale? Center on cursor hit-point? + ImRect rect_to_avoid(ref_pos.x - 16, ref_pos.y - 8, ref_pos.x + 24 * sc, ref_pos.y + 24 * sc); // FIXME: Hard-coded based on mouse cursor shape expectation. Exact dimension not very important. window->PosFloat = FindBestWindowPosForPopup(ref_pos, window->Size, &window->AutoPosLastDirection, rect_to_avoid); if (window->AutoPosLastDirection == ImGuiDir_None) window->PosFloat = ref_pos + ImVec2(2,2); // If there's not enough room, for tooltip we prefer avoiding the cursor at all cost even if it means that part of the tooltip won't be visible. diff --git a/imgui.h b/imgui.h index 4166b603ceaa..5c436c023abb 100644 --- a/imgui.h +++ b/imgui.h @@ -869,6 +869,7 @@ struct ImGuiStyle ImVec2 ButtonTextAlign; // Alignment of button text when button is larger than text. Defaults to (0.5f,0.5f) for horizontally+vertically centered. ImVec2 DisplayWindowPadding; // Window positions are clamped to be visible within the display area by at least this amount. Only covers regular windows. ImVec2 DisplaySafeAreaPadding; // If you cannot see the edge of your screen (e.g. on a TV) increase the safe area padding. Covers popups/tooltips as well regular windows. + float MouseCursorScale; // Scale software rendered mouse cursor (when io.MouseDrawCursor is enabled). May be removed later. bool AntiAliasedLines; // Enable anti-aliasing on lines/borders. Disable if you are really tight on CPU/GPU. bool AntiAliasedFill; // Enable anti-aliasing on filled shapes (rounded rectangles, circles, etc.) float CurveTessellationTol; // Tessellation tolerance when using PathBezierCurveTo() without a specific number of segments. Decrease for highly tessellated curves (higher quality, more polygons), increase to reduce quality. From e9a617b22ad11117ae5e2e580f7d8d824949776c Mon Sep 17 00:00:00 2001 From: omar Date: Sun, 4 Feb 2018 12:35:17 +0100 Subject: [PATCH 591/823] Moved imgui_freetype from imgui_club (#618) --- misc/freetype/imgui_freetype.cpp | 369 +++++++++++++++++++++++++++++++ misc/freetype/imgui_freetype.h | 31 +++ 2 files changed, 400 insertions(+) create mode 100644 misc/freetype/imgui_freetype.cpp create mode 100644 misc/freetype/imgui_freetype.h diff --git a/misc/freetype/imgui_freetype.cpp b/misc/freetype/imgui_freetype.cpp new file mode 100644 index 000000000000..968d7f17de51 --- /dev/null +++ b/misc/freetype/imgui_freetype.cpp @@ -0,0 +1,369 @@ +// Wrapper to use Freetype (instead of stb_truetype) for Dear ImGui +// Get latest version at http://www.github.com/ocornut/imgui_club +// Original code by @Vuhdo (Aleksei Skriabin) + +// Changelog: +// - v0.50: (2017/08/16) imported from https://github.com/Vuhdo/imgui_freetype, updated for latest changes in ImFontAtlas, minor tweaks. +// - v0.51: (2017/08/26) cleanup, optimizations, support for ImFontConfig::RasterizerFlags, ImFontConfig::RasterizerMultiply. +// - v0.52: (2017/09/26) fixes for imgui internal changes +// - v0.53: (2017/10/22) minor inconsequential change to match change in master (removed an unnecessary statement) +// - v0.54: (2018/01/22) fix for addition of ImFontAtlas::TexUvscale member + +// Todo/Bugs: +// - Font size has lots of waste. +// - FreeType's memory allocator is not overridden. + +#include "imgui_freetype.h" +#include "imgui_internal.h" // ImMin,ImMax,ImFontAtlasBuild*, +#include +#include +#include FT_FREETYPE_H +#include FT_GLYPH_H +#include FT_SYNTHESIS_H + +#ifdef _MSC_VER +#pragma warning (disable: 4505) // unreferenced local function has been removed (stb stuff) +#endif + +#if defined(__GNUC__) +#pragma GCC diagnostic ignored "-Wunused-function" // warning: 'xxxx' defined but not used +#endif + +namespace +{ + // Glyph metrics: + // -------------- + // + // xmin xmax + // | | + // |<-------- width -------->| + // | | + // | +-------------------------+----------------- ymax + // | | ggggggggg ggggg | ^ ^ + // | | g:::::::::ggg::::g | | | + // | | g:::::::::::::::::g | | | + // | | g::::::ggggg::::::gg | | | + // | | g:::::g g:::::g | | | + // offsetX -|-------->| g:::::g g:::::g | offsetY | + // | | g:::::g g:::::g | | | + // | | g::::::g g:::::g | | | + // | | g:::::::ggggg:::::g | | | + // | | g::::::::::::::::g | | height + // | | gg::::::::::::::g | | | + // baseline ---*---------|---- gggggggg::::::g-----*-------- | + // / | | g:::::g | | + // origin | | gggggg g:::::g | | + // | | g:::::gg gg:::::g | | + // | | g::::::ggg:::::::g | | + // | | gg:::::::::::::g | | + // | | ggg::::::ggg | | + // | | gggggg | v + // | +-------------------------+----------------- ymin + // | | + // |------------- advanceX ----------->| + + /// A structure that describe a glyph. + struct GlyphInfo + { + float Width; // Glyph's width in pixels. + float Height; // Glyph's height in pixels. + float OffsetX; // The distance from the origin ("pen position") to the left of the glyph. + float OffsetY; // The distance from the origin to the top of the glyph. This is usually a value < 0. + float AdvanceX; // The distance from the origin to the origin of the next glyph. This is usually a value > 0. + }; + + // Font parameters and metrics. + struct FontInfo + { + uint32_t PixelHeight; // Size this font was generated with. + float Ascender; // The pixel extents above the baseline in pixels (typically positive). + float Descender; // The extents below the baseline in pixels (typically negative). + float LineSpacing; // The baseline-to-baseline distance. Note that it usually is larger than the sum of the ascender and descender taken as absolute values. There is also no guarantee that no glyphs extend above or below subsequent baselines when using this distance. Think of it as a value the designer of the font finds appropriate. + float LineGap; // The spacing in pixels between one row's descent and the next row's ascent. + float MaxAdvanceWidth; // This field gives the maximum horizontal cursor advance for all glyphs in the font. + }; + + // FreeType glyph rasterizer. + // NB: No ctor/dtor, explicitly call Init()/Shutdown() + struct FreeTypeFont + { + bool Init(const ImFontConfig& cfg, unsigned int extra_user_flags); // Initialize from an external data buffer. Doesn't copy data, and you must ensure it stays valid up to this object lifetime. + void Shutdown(); + void SetPixelHeight(int pixel_height); // Change font pixel size. All following calls to RasterizeGlyph() will use this size + + bool CalcGlyphInfo(uint32_t codepoint, GlyphInfo& glyph_info, FT_Glyph& ft_glyph, FT_BitmapGlyph& ft_bitmap); + void BlitGlyph(FT_BitmapGlyph ft_bitmap, uint8_t* dst, uint32_t dst_pitch, unsigned char* multiply_table = NULL); + + // [Internals] + FontInfo Info; // Font descriptor of the current font. + unsigned int UserFlags; // = ImFontConfig::RasterizerFlags + FT_Library FreetypeLibrary; + FT_Face FreetypeFace; + FT_Int32 FreetypeLoadFlags; + }; + + // From SDL_ttf: Handy routines for converting from fixed point + #define FT_CEIL(X) (((X + 63) & -64) / 64) + + bool FreeTypeFont::Init(const ImFontConfig& cfg, unsigned int extra_user_flags) + { + // FIXME: substitute allocator + FT_Error error = FT_Init_FreeType(&FreetypeLibrary); + if (error != 0) + return false; + error = FT_New_Memory_Face(FreetypeLibrary, (uint8_t*)cfg.FontData, (uint32_t)cfg.FontDataSize, (uint32_t)cfg.FontNo, &FreetypeFace); + if (error != 0) + return false; + error = FT_Select_Charmap(FreetypeFace, FT_ENCODING_UNICODE); + if (error != 0) + return false; + + memset(&Info, 0, sizeof(Info)); + SetPixelHeight((uint32_t)cfg.SizePixels); + + // Convert to freetype flags (nb: Bold and Oblique are processed separately) + UserFlags = cfg.RasterizerFlags | extra_user_flags; + FreetypeLoadFlags = FT_LOAD_NO_BITMAP; + if (UserFlags & ImGuiFreeType::NoHinting) FreetypeLoadFlags |= FT_LOAD_NO_HINTING; + if (UserFlags & ImGuiFreeType::NoAutoHint) FreetypeLoadFlags |= FT_LOAD_NO_AUTOHINT; + if (UserFlags & ImGuiFreeType::ForceAutoHint) FreetypeLoadFlags |= FT_LOAD_FORCE_AUTOHINT; + if (UserFlags & ImGuiFreeType::LightHinting) + FreetypeLoadFlags |= FT_LOAD_TARGET_LIGHT; + else if (UserFlags & ImGuiFreeType::MonoHinting) + FreetypeLoadFlags |= FT_LOAD_TARGET_MONO; + else + FreetypeLoadFlags |= FT_LOAD_TARGET_NORMAL; + + return true; + } + + void FreeTypeFont::Shutdown() + { + if (FreetypeFace) + { + FT_Done_Face(FreetypeFace); + FreetypeFace = NULL; + FT_Done_FreeType(FreetypeLibrary); + FreetypeLibrary = NULL; + } + } + + void FreeTypeFont::SetPixelHeight(int pixel_height) + { + // I'm not sure how to deal with font sizes properly. + // As far as I understand, currently ImGui assumes that the 'pixel_height' is a maximum height of an any given glyph, + // i.e. it's the sum of font's ascender and descender. Seems strange to me. + FT_Size_RequestRec req; + req.type = FT_SIZE_REQUEST_TYPE_REAL_DIM; + req.width = 0; + req.height = (uint32_t)pixel_height * 64; + req.horiResolution = 0; + req.vertResolution = 0; + FT_Request_Size(FreetypeFace, &req); + + // update font info + FT_Size_Metrics metrics = FreetypeFace->size->metrics; + Info.PixelHeight = (uint32_t)pixel_height; + Info.Ascender = (float)FT_CEIL(metrics.ascender); + Info.Descender = (float)FT_CEIL(metrics.descender); + Info.LineSpacing = (float)FT_CEIL(metrics.height); + Info.LineGap = (float)FT_CEIL(metrics.height - metrics.ascender + metrics.descender); + Info.MaxAdvanceWidth = (float)FT_CEIL(metrics.max_advance); + } + + bool FreeTypeFont::CalcGlyphInfo(uint32_t codepoint, GlyphInfo &glyph_info, FT_Glyph& ft_glyph, FT_BitmapGlyph& ft_bitmap) + { + uint32_t glyph_index = FT_Get_Char_Index(FreetypeFace, codepoint); + FT_Error error = FT_Load_Glyph(FreetypeFace, glyph_index, FreetypeLoadFlags); + if (error) + return false; + + // Need an outline for this to work + FT_GlyphSlot slot = FreetypeFace->glyph; + IM_ASSERT(slot->format == FT_GLYPH_FORMAT_OUTLINE); + + if (UserFlags & ImGuiFreeType::Bold) + FT_GlyphSlot_Embolden(slot); + if (UserFlags & ImGuiFreeType::Oblique) + FT_GlyphSlot_Oblique(slot); + + // Retrieve the glyph + error = FT_Get_Glyph(slot, &ft_glyph); + if (error != 0) + return false; + + // Rasterize + error = FT_Glyph_To_Bitmap(&ft_glyph, FT_RENDER_MODE_NORMAL, NULL, true); + if (error != 0) + return false; + + ft_bitmap = (FT_BitmapGlyph)ft_glyph; + glyph_info.AdvanceX = (float)FT_CEIL(slot->advance.x); + glyph_info.OffsetX = (float)ft_bitmap->left; + glyph_info.OffsetY = -(float)ft_bitmap->top; + glyph_info.Width = (float)ft_bitmap->bitmap.width; + glyph_info.Height = (float)ft_bitmap->bitmap.rows; + + return true; + } + + void FreeTypeFont::BlitGlyph(FT_BitmapGlyph ft_bitmap, uint8_t* dst, uint32_t dst_pitch, unsigned char* multiply_table) + { + IM_ASSERT(ft_bitmap != NULL); + + const uint32_t w = ft_bitmap->bitmap.width; + const uint32_t h = ft_bitmap->bitmap.rows; + const uint8_t* src = ft_bitmap->bitmap.buffer; + const uint32_t src_pitch = ft_bitmap->bitmap.pitch; + + if (multiply_table == NULL) + { + for (uint32_t y = 0; y < h; y++, src += src_pitch, dst += dst_pitch) + memcpy(dst, src, w); + } + else + { + for (uint32_t y = 0; y < h; y++, src += src_pitch, dst += dst_pitch) + for (uint32_t x = 0; x < w; x++) + dst[x] = multiply_table[src[x]]; + } + } +} + +#define STBRP_ASSERT(x) IM_ASSERT(x) +#define STBRP_STATIC +#define STB_RECT_PACK_IMPLEMENTATION +#include "stb_rect_pack.h" + +bool ImGuiFreeType::BuildFontAtlas(ImFontAtlas* atlas, unsigned int extra_flags) +{ + IM_ASSERT(atlas->ConfigData.Size > 0); + IM_ASSERT(atlas->TexGlyphPadding == 1); // Not supported + + ImFontAtlasBuildRegisterDefaultCustomRects(atlas); + + atlas->TexID = NULL; + atlas->TexWidth = atlas->TexHeight = 0; + atlas->TexUvScale = ImVec2(0.0f, 0.0f); + atlas->TexUvWhitePixel = ImVec2(0.0f, 0.0f); + atlas->ClearTexData(); + + ImVector fonts; + fonts.resize(atlas->ConfigData.Size); + + ImVec2 max_glyph_size(1.0f, 1.0f); + + // Count glyphs/ranges, initialize font + int total_glyphs_count = 0; + int total_ranges_count = 0; + for (int input_i = 0; input_i < atlas->ConfigData.Size; input_i++) + { + ImFontConfig& cfg = atlas->ConfigData[input_i]; + FreeTypeFont& font_face = fonts[input_i]; + IM_ASSERT(cfg.DstFont && (!cfg.DstFont->IsLoaded() || cfg.DstFont->ContainerAtlas == atlas)); + + if (!font_face.Init(cfg, extra_flags)) + return false; + + max_glyph_size.x = ImMax(max_glyph_size.x, font_face.Info.MaxAdvanceWidth); + max_glyph_size.y = ImMax(max_glyph_size.y, font_face.Info.Ascender - font_face.Info.Descender); + + if (!cfg.GlyphRanges) + cfg.GlyphRanges = atlas->GetGlyphRangesDefault(); + for (const ImWchar* in_range = cfg.GlyphRanges; in_range[0] && in_range[ 1 ]; in_range += 2, total_ranges_count++) + total_glyphs_count += (in_range[1] - in_range[0]) + 1; + } + + // We need a width for the skyline algorithm. Using a dumb heuristic here to decide of width. User can override TexDesiredWidth and TexGlyphPadding if they wish. + // Width doesn't really matter much, but some API/GPU have texture size limitations and increasing width can decrease height. + atlas->TexWidth = (atlas->TexDesiredWidth > 0) ? atlas->TexDesiredWidth : (total_glyphs_count > 4000) ? 4096 : (total_glyphs_count > 2000) ? 2048 : (total_glyphs_count > 1000) ? 1024 : 512; + + // We don't do the original first pass to determine texture height, but just rough estimate. + // Looks ugly inaccurate and excessive, but AFAIK with FreeType we actually need to render glyphs to get exact sizes. + // Alternatively, we could just render all glyphs into a big shadow buffer, get their sizes, do the rectangle packing and just copy back from the + // shadow buffer to the texture buffer. Will give us an accurate texture height, but eat a lot of temp memory. Probably no one will notice.) + const int total_rects = total_glyphs_count + atlas->CustomRects.size(); + float min_rects_per_row = ceilf((atlas->TexWidth / (max_glyph_size.x + 1.0f))); + float min_rects_per_column = ceilf(total_rects / min_rects_per_row); + atlas->TexHeight = (int)(min_rects_per_column * (max_glyph_size.y + 1.0f)); + + // Create texture + atlas->TexHeight = ImUpperPowerOfTwo(atlas->TexHeight); + atlas->TexUvScale = ImVec2(1.0f / atlas->TexWidth, 1.0f / atlas->TexHeight); + atlas->TexPixelsAlpha8 = (unsigned char*)ImGui::MemAlloc(atlas->TexWidth * atlas->TexHeight); + memset(atlas->TexPixelsAlpha8, 0, atlas->TexWidth * atlas->TexHeight); + + // Start packing + ImVector pack_nodes; + pack_nodes.resize(total_rects); + stbrp_context context; + stbrp_init_target(&context, atlas->TexWidth, atlas->TexHeight, pack_nodes.Data, total_rects); + + // Pack our extra data rectangles first, so it will be on the upper-left corner of our texture (UV will have small values). + ImFontAtlasBuildPackCustomRects(atlas, &context); + + // Render characters, setup ImFont and glyphs for runtime + for (int input_i = 0; input_i < atlas->ConfigData.Size; input_i++) + { + ImFontConfig& cfg = atlas->ConfigData[input_i]; + FreeTypeFont& font_face = fonts[input_i]; + ImFont* dst_font = cfg.DstFont; + + const float ascent = font_face.Info.Ascender; + const float descent = font_face.Info.Descender; + ImFontAtlasBuildSetupFont(atlas, dst_font, &cfg, ascent, descent); + const float off_x = cfg.GlyphOffset.x; + const float off_y = cfg.GlyphOffset.y + (float)(int)(dst_font->Ascent + 0.5f); + + bool multiply_enabled = (cfg.RasterizerMultiply != 1.0f); + unsigned char multiply_table[256]; + if (multiply_enabled) + ImFontAtlasBuildMultiplyCalcLookupTable(multiply_table, cfg.RasterizerMultiply); + + for (const ImWchar* in_range = cfg.GlyphRanges; in_range[0] && in_range[1]; in_range += 2) + { + for (uint32_t codepoint = in_range[0]; codepoint <= in_range[1]; ++codepoint) + { + if (cfg.MergeMode && dst_font->FindGlyph((unsigned short)codepoint)) + continue; + + FT_Glyph ft_glyph = NULL; + FT_BitmapGlyph ft_glyph_bitmap = NULL; // NB: will point to bitmap within FT_Glyph + GlyphInfo glyph_info; + if (!font_face.CalcGlyphInfo(codepoint, glyph_info, ft_glyph, ft_glyph_bitmap)) + continue; + + // Pack rectangle + stbrp_rect rect; + rect.w = (uint16_t)glyph_info.Width + 1; // Account for texture filtering + rect.h = (uint16_t)glyph_info.Height + 1; + stbrp_pack_rects(&context, &rect, 1); + + // Copy rasterized pixels to main texture + uint8_t* blit_dst = atlas->TexPixelsAlpha8 + rect.y * atlas->TexWidth + rect.x; + font_face.BlitGlyph(ft_glyph_bitmap, blit_dst, atlas->TexWidth, multiply_enabled ? multiply_table : NULL); + FT_Done_Glyph(ft_glyph); + + // Register glyph + dst_font->AddGlyph((ImWchar)codepoint, + glyph_info.OffsetX + off_x, + glyph_info.OffsetY + off_y, + glyph_info.OffsetX + off_x + glyph_info.Width, + glyph_info.OffsetY + off_y + glyph_info.Height, + rect.x / (float)atlas->TexWidth, + rect.y / (float)atlas->TexHeight, + (rect.x + glyph_info.Width) / (float)atlas->TexWidth, + (rect.y + glyph_info.Height) / (float)atlas->TexHeight, + glyph_info.AdvanceX); + } + } + } + + // Cleanup + for (int n = 0; n < fonts.Size; n++) + fonts[n].Shutdown(); + + ImFontAtlasBuildFinish(atlas); + + return true; +} diff --git a/misc/freetype/imgui_freetype.h b/misc/freetype/imgui_freetype.h new file mode 100644 index 000000000000..f82dbc3b4db0 --- /dev/null +++ b/misc/freetype/imgui_freetype.h @@ -0,0 +1,31 @@ +// Wrapper to use Freetype (instead of stb_truetype) for Dear ImGui +// Original code by @Vuhdo +// Get latest version at http://www.github.com/ocornut/imgui_club + +#pragma once + +#include "imgui.h" // IMGUI_API, ImFontAtlas + +namespace ImGuiFreeType +{ + // Hinting greatly impacts visuals (and glyph sizes). + // When disabled, FreeType generates blurrier glyphs, more or less matches the stb's output. + // The Default hinting mode usually looks good, but may distort glyphs in an unusual way. + // The Light hinting mode generates fuzzier glyphs but better matches Microsoft's rasterizer. + + // You can set those flags on a per font basis in ImFontConfig::RasterizerFlags. + // Use the 'extra_flags' parameter of BuildFontAtlas() to force a flag on all your fonts. + enum RasterizerFlags + { + // By default, hinting is enabled and the font's native hinter is preferred over the auto-hinter. + NoHinting = 1 << 0, // Disable hinting. This generally generates 'blurrier' bitmap glyphs when the glyph are rendered in any of the anti-aliased modes. + NoAutoHint = 1 << 1, // Disable auto-hinter. + ForceAutoHint = 1 << 2, // Indicates that the auto-hinter is preferred over the font's native hinter. + LightHinting = 1 << 3, // A lighter hinting algorithm for gray-level modes. Many generated glyphs are fuzzier but better resemble their original shape. This is achieved by snapping glyphs to the pixel grid only vertically (Y-axis), as is done by Microsoft's ClearType and Adobe's proprietary font renderer. This preserves inter-glyph spacing in horizontal text. + MonoHinting = 1 << 4, // Strong hinting algorithm that should only be used for monochrome output. + Bold = 1 << 5, // Styling: Should we artificially embolden the font? + Oblique = 1 << 6, // Styling: Should we slant the font, emulating italic style? + }; + + IMGUI_API bool BuildFontAtlas(ImFontAtlas* atlas, unsigned int extra_flags = 0); +} From 7b005bd7dec7f75e7a786da4ba35378565d547b9 Mon Sep 17 00:00:00 2001 From: omar Date: Sun, 4 Feb 2018 12:44:31 +0100 Subject: [PATCH 592/823] imgui_freetype: Documentation, tweaks. (#618) --- misc/fonts/README.txt | 4 +- misc/freetype/README.md | 126 +++++++++++++++++++++++++++++++ misc/freetype/imgui_freetype.cpp | 11 +-- misc/freetype/imgui_freetype.h | 14 ++-- 4 files changed, 140 insertions(+), 15 deletions(-) create mode 100644 misc/freetype/README.md diff --git a/misc/fonts/README.txt b/misc/fonts/README.txt index 2287f6eaab08..a3774ca77c1f 100644 --- a/misc/fonts/README.txt +++ b/misc/fonts/README.txt @@ -120,9 +120,7 @@ In this document: Dear Imgui uses stb_truetype.h to rasterize fonts (with optional oversampling). This technique and implementation are not ideal for fonts rendered at _small sizes_, which may appear a little blurry. - There is an implementation of the ImFontAtlas builder using FreeType that you can use: - - https://github.com/ocornut/imgui_club + There is an implementation of the ImFontAtlas builder using FreeType that you can use in the misc/freetype/ folder. FreeType supports auto-hinting which tends to improve the readability of small fonts. Note that this code currently creates textures that are unoptimally too large (could be fixed with some work) diff --git a/misc/freetype/README.md b/misc/freetype/README.md new file mode 100644 index 000000000000..8b5d01d43f0b --- /dev/null +++ b/misc/freetype/README.md @@ -0,0 +1,126 @@ +# imgui_freetype + +This is an attempt to replace stb_truetype (the default imgui's font rasterizer) with FreeType. +Currently not optimal and probably has some limitations or bugs. +By [Vuhdo](https://github.com/Vuhdo) (Aleksei Skriabin). Improvements by @mikesart. Maintained by @ocornut. + +**Usage** +1. Get latest FreeType binaries or build yourself. +2. Add imgui_freetype.h/cpp alongside your imgui sources. +3. Include imgui_freetype.h after imgui.h. +4. Call ImGuiFreeType::BuildFontAtlas() *BEFORE* calling ImFontAtlas::GetTexDataAsRGBA32() or ImFontAtlas::Build() (so normal Build() won't be called): + +```cpp +// See ImGuiFreeType::RasterizationFlags +unsigned int flags = ImGuiFreeType::DisableHinting; +ImGuiFreeType::BuildFontAtlas(io.Fonts, flags); +io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); +``` + +**Test code Usage** +```cpp +#include "misc/freetype/imgui_freetype.h" +#include "misc/freetype/imgui_freetype.cpp" + +// Load various small fonts +ImGuiIO& io = ImGui::GetIO(); +io.Fonts->AddFontFromFileTTF("../../misc/fonts/Roboto-Medium.ttf", 13.0f); +io.Fonts->AddFontFromFileTTF("../../misc/fonts/Cousine-Regular.ttf", 13.0f); +io.Fonts->AddFontDefault(); + +FreeTypeTest freetype_test; + +// Main Loop +while (true) +{ + if (freetype_test.UpdateRebuild()) + { + // REUPLOAD FONT TEXTURE TO GPU + // e.g ImGui_ImplGlfwGL3_InvalidateDeviceObjects() + ImGui_ImplGlfwGL3_CreateDeviceObjects() + } + ImGui::NewFrame(); + freetype_test.ShowFreetypeOptionsWindow(); + ... + } +} +``` + +**Test code** +```cpp +#include "misc/freetype/imgui_freetype.h" +#include "misc/freetype/imgui_freetype.cpp" + +struct FreeTypeTest +{ + enum FontBuildMode + { + FontBuildMode_FreeType, + FontBuildMode_Stb, + }; + + FontBuildMode BuildMode; + bool WantRebuild; + float FontsMultiply; + unsigned int FontsFlags; + + FreeTypeTest() + { + BuildMode = FontBuildMode_FreeType; + WantRebuild = true; + FontsMultiply = 1.0f; + FontsFlags = 0; + } + + // Call _BEFORE_ NewFrame() + bool UpdateRebuild() + { + if (!WantRebuild) + return false; + ImGuiIO& io = ImGui::GetIO(); + for (int n = 0; n < io.Fonts->Fonts.Size; n++) + { + io.Fonts->Fonts[n]->ConfigData->RasterizerMultiply = FontsMultiply; + io.Fonts->Fonts[n]->ConfigData->RasterizerFlags = (BuildMode == FontBuildMode_FreeType) ? FontsFlags : 0x00; + } + if (BuildMode == FontBuildMode_FreeType) + ImGuiFreeType::BuildFontAtlas(io.Fonts, FontsFlags); + else if (BuildMode == FontBuildMode_Stb) + io.Fonts->Build(); + WantRebuild = false; + return true; + } + + // Call to draw interface + void ShowFreetypeOptionsWindow() + { + ImGui::Begin("FreeType Options"); + ImGui::ShowFontSelector("Fonts"); + WantRebuild |= ImGui::RadioButton("FreeType", (int*)&BuildMode, FontBuildMode_FreeType); + ImGui::SameLine(); + WantRebuild |= ImGui::RadioButton("Stb (Default)", (int*)&BuildMode, FontBuildMode_Stb); + WantRebuild |= ImGui::DragFloat("Multiply", &FontsMultiply, 0.001f, 0.0f, 2.0f); + if (BuildMode == FontBuildMode_FreeType) + { + WantRebuild |= ImGui::CheckboxFlags("NoHinting", &FontsFlags, ImGuiFreeType::NoHinting); + WantRebuild |= ImGui::CheckboxFlags("NoAutoHint", &FontsFlags, ImGuiFreeType::NoAutoHint); + WantRebuild |= ImGui::CheckboxFlags("ForceAutoHint", &FontsFlags, ImGuiFreeType::ForceAutoHint); + WantRebuild |= ImGui::CheckboxFlags("LightHinting", &FontsFlags, ImGuiFreeType::LightHinting); + WantRebuild |= ImGui::CheckboxFlags("MonoHinting", &FontsFlags, ImGuiFreeType::MonoHinting); + WantRebuild |= ImGui::CheckboxFlags("Bold", &FontsFlags, ImGuiFreeType::Bold); + WantRebuild |= ImGui::CheckboxFlags("Oblique", &FontsFlags, ImGuiFreeType::Oblique); + } + ImGui::End(); + } +}; +``` + +**Known issues** +- Output texture has excessive resolution (lots of vertical waste) +- FreeType's memory allocator is not overridden. + +**Obligatory comparison screenshots** + +Using Windows built-in segoeui.ttf font. Open in new browser tabs, view at 1080p+. + +![freetype rasterizer](https://raw.githubusercontent.com/wiki/ocornut/imgui_club/images/freetype_20170817.png) + diff --git a/misc/freetype/imgui_freetype.cpp b/misc/freetype/imgui_freetype.cpp index 968d7f17de51..9a04ed89e008 100644 --- a/misc/freetype/imgui_freetype.cpp +++ b/misc/freetype/imgui_freetype.cpp @@ -1,16 +1,17 @@ // Wrapper to use Freetype (instead of stb_truetype) for Dear ImGui -// Get latest version at http://www.github.com/ocornut/imgui_club -// Original code by @Vuhdo (Aleksei Skriabin) +// Get latest version at https://github.com/ocornut/imgui/tree/master/misc/freetype +// Original code by @Vuhdo (Aleksei Skriabin). Improvements by @mikesart. Maintained by @ocornut // Changelog: -// - v0.50: (2017/08/16) imported from https://github.com/Vuhdo/imgui_freetype, updated for latest changes in ImFontAtlas, minor tweaks. +// - v0.50: (2017/08/16) imported from https://github.com/Vuhdo/imgui_freetype into http://www.github.com/ocornut/imgui_club, updated for latest changes in ImFontAtlas, minor tweaks. // - v0.51: (2017/08/26) cleanup, optimizations, support for ImFontConfig::RasterizerFlags, ImFontConfig::RasterizerMultiply. // - v0.52: (2017/09/26) fixes for imgui internal changes // - v0.53: (2017/10/22) minor inconsequential change to match change in master (removed an unnecessary statement) // - v0.54: (2018/01/22) fix for addition of ImFontAtlas::TexUvscale member +// - v0.55: (2018/02/04) moved to main imgui repository (away from http://www.github.com/ocornut/imgui_club) -// Todo/Bugs: -// - Font size has lots of waste. +// TODO: +// - Output texture has excessive resolution (lots of vertical waste) // - FreeType's memory allocator is not overridden. #include "imgui_freetype.h" diff --git a/misc/freetype/imgui_freetype.h b/misc/freetype/imgui_freetype.h index f82dbc3b4db0..b8062bf715b2 100644 --- a/misc/freetype/imgui_freetype.h +++ b/misc/freetype/imgui_freetype.h @@ -1,6 +1,6 @@ // Wrapper to use Freetype (instead of stb_truetype) for Dear ImGui -// Original code by @Vuhdo -// Get latest version at http://www.github.com/ocornut/imgui_club +// Get latest version at https://github.com/ocornut/imgui/tree/master/misc/freetype +// Original code by @Vuhdo (Aleksei Skriabin), maintained by @ocornut #pragma once @@ -8,10 +8,10 @@ namespace ImGuiFreeType { - // Hinting greatly impacts visuals (and glyph sizes). - // When disabled, FreeType generates blurrier glyphs, more or less matches the stb's output. - // The Default hinting mode usually looks good, but may distort glyphs in an unusual way. - // The Light hinting mode generates fuzzier glyphs but better matches Microsoft's rasterizer. + // Hinting greatly impacts visuals (and glyph sizes). + // When disabled, FreeType generates blurrier glyphs, more or less matches the stb's output. + // The Default hinting mode usually looks good, but may distort glyphs in an unusual way. + // The Light hinting mode generates fuzzier glyphs but better matches Microsoft's rasterizer. // You can set those flags on a per font basis in ImFontConfig::RasterizerFlags. // Use the 'extra_flags' parameter of BuildFontAtlas() to force a flag on all your fonts. @@ -24,7 +24,7 @@ namespace ImGuiFreeType LightHinting = 1 << 3, // A lighter hinting algorithm for gray-level modes. Many generated glyphs are fuzzier but better resemble their original shape. This is achieved by snapping glyphs to the pixel grid only vertically (Y-axis), as is done by Microsoft's ClearType and Adobe's proprietary font renderer. This preserves inter-glyph spacing in horizontal text. MonoHinting = 1 << 4, // Strong hinting algorithm that should only be used for monochrome output. Bold = 1 << 5, // Styling: Should we artificially embolden the font? - Oblique = 1 << 6, // Styling: Should we slant the font, emulating italic style? + Oblique = 1 << 6 // Styling: Should we slant the font, emulating italic style? }; IMGUI_API bool BuildFontAtlas(ImFontAtlas* atlas, unsigned int extra_flags = 0); From e2654a097bd88e0190a5ebf50fe23fba574516e0 Mon Sep 17 00:00:00 2001 From: omar Date: Sun, 4 Feb 2018 18:30:37 +0100 Subject: [PATCH 593/823] ImRect: added IsInverted() helper. --- imgui_internal.h | 1 + 1 file changed, 1 insertion(+) diff --git a/imgui_internal.h b/imgui_internal.h index 9b6bc742f902..c012f3805828 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -332,6 +332,7 @@ struct IMGUI_API ImRect void ClipWithFull(const ImRect& r) { Min = ImClamp(Min, r.Min, r.Max); Max = ImClamp(Max, r.Min, r.Max); } // Full version, ensure both points are fully clipped. void Floor() { Min.x = (float)(int)Min.x; Min.y = (float)(int)Min.y; Max.x = (float)(int)Max.x; Max.y = (float)(int)Max.y; } void FixInverted() { if (Min.x > Max.x) ImSwap(Min.x, Max.x); if (Min.y > Max.y) ImSwap(Min.y, Max.y); } + bool IsInverted() const { return Min.x > Max.x || Min.y > Max.y; } bool IsFinite() const { return Min.x != FLT_MAX; } }; From 66ff820eaaebabe99aa89428af82c3fb3e32873a Mon Sep 17 00:00:00 2001 From: omar Date: Sun, 4 Feb 2018 18:30:46 +0100 Subject: [PATCH 594/823] Nav: Ensure g.NavScoringRectScreen is always finite and not inverted. (#787) --- imgui.cpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 70d39e985e0e..24cfe986b326 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2130,8 +2130,10 @@ static ImGuiDir NavScoreItemGetQuadrant(float dx, float dy) static float NavScoreItemDistInterval(float a0, float a1, float b0, float b1) { - if (a1 < b0) return a1 - b0; - if (b1 < a0) return a0 - b1; + if (a1 < b0) + return a1 - b0; + if (b1 < a0) + return a0 - b1; return 0.0f; } @@ -3133,9 +3135,11 @@ static void ImGui::NavUpdate() } // For scoring we use a single segment on the left side our current item bounding box (not touching the edge to avoid box overlap with zero-spaced items) - g.NavScoringRectScreen = g.NavWindow ? ImRect(g.NavWindow->Pos + g.NavWindow->NavRectRel[g.NavLayer].Min, g.NavWindow->Pos + g.NavWindow->NavRectRel[g.NavLayer].Max) : ImRect(); + ImRect nav_rect_rel = (g.NavWindow && g.NavWindow->NavRectRel[g.NavLayer].IsFinite()) ? g.NavWindow->NavRectRel[g.NavLayer] : ImRect(0,0,0,0); + g.NavScoringRectScreen = g.NavWindow ? ImRect(g.NavWindow->Pos + nav_rect_rel.Min, g.NavWindow->Pos + nav_rect_rel.Max) : GetViewportRect(); g.NavScoringRectScreen.Min.x = ImMin(g.NavScoringRectScreen.Min.x + 1.0f, g.NavScoringRectScreen.Max.x); g.NavScoringRectScreen.Max.x = g.NavScoringRectScreen.Min.x; + IM_ASSERT(!g.NavScoringRectScreen.IsInverted()); // Ensure if we have a finite, non-inverted bounding box here will allows us to remove extraneous fabsf() calls in NavScoreItem(). //g.OverlayDrawList.AddRect(g.NavScoringRectScreen.Min, g.NavScoringRectScreen.Max, IM_COL32(255,200,0,255)); // [DEBUG] #if IMGUI_DEBUG_NAV_RECTS if (g.NavWindow) { for (int layer = 0; layer < 2; layer++) g.OverlayDrawList.AddRect(g.NavWindow->Pos + g.NavWindow->NavRectRel[layer].Min, g.NavWindow->Pos + g.NavWindow->NavRectRel[layer].Max, IM_COL32(255,200,0,255)); } // [DEBUG] From 4786321754cf2c69dc6a0a1e803d18a726ce05ef Mon Sep 17 00:00:00 2001 From: Gerry Hernandez Date: Sun, 4 Feb 2018 21:47:08 -0500 Subject: [PATCH 595/823] Fix iOS code; fixes entire XCode build for Apple example --- .gitignore | 1 + examples/apple_example/imguiex-ios/debug_hud.cpp | 9 +++++++-- examples/apple_example/imguiex-ios/debug_hud.h | 1 + 3 files changed, 9 insertions(+), 2 deletions(-) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 000000000000..5761abcfdf0c --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +*.o diff --git a/examples/apple_example/imguiex-ios/debug_hud.cpp b/examples/apple_example/imguiex-ios/debug_hud.cpp index 002d6bac45cb..28722b56de2c 100644 --- a/examples/apple_example/imguiex-ios/debug_hud.cpp +++ b/examples/apple_example/imguiex-ios/debug_hud.cpp @@ -22,6 +22,11 @@ void DebugHUD_InitDefaults( DebugHUD *hud ) hud->cubeColor2[1] = 0.4f; hud->cubeColor2[2] = 0.4f; hud->cubeColor2[3] = 1.0f; + + hud->clearColor[0] = 0.45f; + hud->clearColor[1] = 0.55f; + hud->clearColor[2] = 0.60f; + hud->clearColor[3] = 1.00f; } void DebugHUD_DoInterface(DebugHUD *hud) @@ -33,7 +38,7 @@ void DebugHUD_DoInterface(DebugHUD *hud) static int counter = 0; ImGui::Text("Hello, world!"); // Display some text (you can use a format string too) ImGui::SliderFloat("float", &f, 0.0f, 1.0f); // Edit 1 float using a slider from 0.0f to 1.0f - ImGui::ColorEdit3("clear color", (float*)&clear_color); // Edit 3 floats representing a color + ImGui::ColorEdit3("clear color", hud->clearColor); // Edit 3 floats representing a color ImGui::Checkbox("Demo Window", &hud->show_demo_window); // Edit bools storing our windows open/close state ImGui::Checkbox("Another Window", &hud->show_another_window); @@ -49,7 +54,7 @@ void DebugHUD_DoInterface(DebugHUD *hud) // 2. Show another simple window. In most cases you will use an explicit Begin/End pair to name your windows. if (hud->show_another_window) { - ImGui::Begin("Another Window", &hud-?show_another_window); + ImGui::Begin("Another Window", &hud->show_another_window); ImGui::Text("Hello from another window!"); ImGui::ColorEdit3("Cube 1 Color", hud->cubeColor1); ImGui::ColorEdit3("Cube 2 Color", hud->cubeColor2); diff --git a/examples/apple_example/imguiex-ios/debug_hud.h b/examples/apple_example/imguiex-ios/debug_hud.h index 89b79a411b92..4ef535729cb8 100644 --- a/examples/apple_example/imguiex-ios/debug_hud.h +++ b/examples/apple_example/imguiex-ios/debug_hud.h @@ -11,6 +11,7 @@ typedef struct DebugHUD float rotation_speed; float cubeColor1[4]; float cubeColor2[4]; + float clearColor[4]; } DebugHUD; #if __cplusplus From a33b86dac7bd44826ca02616c9573dd330d2764f Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 5 Feb 2018 09:14:33 +0100 Subject: [PATCH 596/823] Removed root .gitignore. (#1594) --- .gitignore | 1 - 1 file changed, 1 deletion(-) delete mode 100644 .gitignore diff --git a/.gitignore b/.gitignore deleted file mode 100644 index 5761abcfdf0c..000000000000 --- a/.gitignore +++ /dev/null @@ -1 +0,0 @@ -*.o From cf6b39600bfbceb0c404cb8607b49f30a8fdc4e6 Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 5 Feb 2018 11:21:06 +0100 Subject: [PATCH 597/823] imgui_freetype: comments about correct blending and sRGB (#618, #578) --- misc/freetype/README.md | 6 ++++++ misc/freetype/imgui_freetype.cpp | 6 ++++++ 2 files changed, 12 insertions(+) diff --git a/misc/freetype/README.md b/misc/freetype/README.md index 8b5d01d43f0b..ad0e4d3b3bd3 100644 --- a/misc/freetype/README.md +++ b/misc/freetype/README.md @@ -17,6 +17,12 @@ ImGuiFreeType::BuildFontAtlas(io.Fonts, flags); io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); ``` +**Gamma Correct Blending** +FreeType assumes blending in linear space rather than gamma space. +See FreeType note for [FT_Render_Glyph](https://www.freetype.org/freetype2/docs/reference/ft2-base_interface.html#FT_Render_Glyph). +For correct results you need to be using sRGB and convert to linear space in the pixel shader output. +The default imgui styles will be impacted by this change (alpha values will need tweaking). + **Test code Usage** ```cpp #include "misc/freetype/imgui_freetype.h" diff --git a/misc/freetype/imgui_freetype.cpp b/misc/freetype/imgui_freetype.cpp index 9a04ed89e008..9e373c7dd8c0 100644 --- a/misc/freetype/imgui_freetype.cpp +++ b/misc/freetype/imgui_freetype.cpp @@ -10,6 +10,12 @@ // - v0.54: (2018/01/22) fix for addition of ImFontAtlas::TexUvscale member // - v0.55: (2018/02/04) moved to main imgui repository (away from http://www.github.com/ocornut/imgui_club) +// Gamma Correct Blending: +// FreeType assumes blending in linear space rather than gamma space. +// See https://www.freetype.org/freetype2/docs/reference/ft2-base_interface.html#FT_Render_Glyph +// For correct results you need to be using sRGB and convert to linear space in the pixel shader output. +// The default imgui styles will be impacted by this change (alpha values will need tweaking). + // TODO: // - Output texture has excessive resolution (lots of vertical waste) // - FreeType's memory allocator is not overridden. From 223be68d7759c0eda5acae06de1663b3e64ea196 Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 5 Feb 2018 00:05:13 +0100 Subject: [PATCH 598/823] Nav: Debugging stuff. --- imgui.cpp | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 24cfe986b326..3686c5e42d43 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2198,14 +2198,25 @@ static bool NavScoreItem(ImGuiNavMoveResult* result, ImRect cand) } #if IMGUI_DEBUG_NAV_SCORING + char buf[128]; if (ImGui::IsMouseHoveringRect(cand.Min, cand.Max)) { - char buf[128]; - ImFormatString(buf, IM_ARRAYSIZE(buf), "dbox (%.2f,%.2f->%.4f) dcen (%.2f,%.2f->%.4f) d (%.2f,%.2f->%.4f) nav %c, quad %c", dbx, dby, dist_box, dcx, dcy, dist_center, dax, day, dist_axial, "WENS"[g.NavMoveDir], "WENS"[quadrant]); + ImFormatString(buf, IM_ARRAYSIZE(buf), "dbox (%.2f,%.2f->%.4f)\ndcen (%.2f,%.2f->%.4f)\nd (%.2f,%.2f->%.4f)\nnav %c, quadrant %c", dbx, dby, dist_box, dcx, dcy, dist_center, dax, day, dist_axial, "WENS"[g.NavMoveDir], "WENS"[quadrant]); + g.OverlayDrawList.AddRect(curr.Min, curr.Max, IM_COL32(255, 200, 0, 100)); g.OverlayDrawList.AddRect(cand.Min, cand.Max, IM_COL32(255,255,0,200)); g.OverlayDrawList.AddRectFilled(cand.Max-ImVec2(4,4), cand.Max+ImGui::CalcTextSize(buf)+ImVec2(4,4), IM_COL32(40,0,0,150)); g.OverlayDrawList.AddText(g.IO.FontDefault, 13.0f, cand.Max, ~0U, buf); } + else if (g.IO.KeyCtrl) // Hold to preview score in matching quadrant. Press C to rotate. + { + if (IsKeyPressedMap(ImGuiKey_C)) { g.NavMoveDirLast = (ImGuiDir)((g.NavMoveDirLast + 1) & 3); g.IO.KeysDownDuration[g.IO.KeyMap[ImGuiKey_C]] = 0.01f; } + if (quadrant == g.NavMoveDir) + { + ImFormatString(buf, IM_ARRAYSIZE(buf), "%.0f/%.0f", dist_box, dist_center); + g.OverlayDrawList.AddRectFilled(cand.Min, cand.Max, IM_COL32(255, 0, 0, 200)); + g.OverlayDrawList.AddText(g.IO.FontDefault, 13.0f, cand.Min, IM_COL32(255, 255, 255, 255), buf); + } + } #endif // Is it in the quadrant we're interesting in moving to? From 2081fc15b51f5218f3e20845a1b9b49707b93a76 Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 5 Feb 2018 12:46:13 +0100 Subject: [PATCH 599/823] Added assert in BeginChild(ImGuiId id). --- imgui.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/imgui.cpp b/imgui.cpp index 3686c5e42d43..e337c97b7622 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -3009,8 +3009,8 @@ static void ImGui::NavUpdate() // Exit child window ImGuiWindow* child_window = g.NavWindow; ImGuiWindow* parent_window = g.NavWindow->ParentWindow; - FocusWindow(parent_window); IM_ASSERT(child_window->ChildId != 0); + FocusWindow(parent_window); SetNavID(child_window->ChildId, 0); g.NavIdIsAlive = false; if (g.NavDisableMouseHover) @@ -5009,6 +5009,7 @@ bool ImGui::BeginChild(const char* str_id, const ImVec2& size_arg, bool border, bool ImGui::BeginChild(ImGuiID id, const ImVec2& size_arg, bool border, ImGuiWindowFlags extra_flags) { + IM_ASSERT(id != 0); return BeginChildEx(NULL, id, size_arg, border, extra_flags); } From bed55a41e1e5ef2242d2f1a3a1d93254ffd1953b Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 5 Feb 2018 14:51:28 +0100 Subject: [PATCH 600/823] Internals: ImRect: Added IsInverted() helper. --- imgui_internal.h | 1 + 1 file changed, 1 insertion(+) diff --git a/imgui_internal.h b/imgui_internal.h index 37a31bff59b9..f904cbcf7768 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -285,6 +285,7 @@ struct IMGUI_API ImRect void ClipWithFull(const ImRect& r) { Min = ImClamp(Min, r.Min, r.Max); Max = ImClamp(Max, r.Min, r.Max); } // Full version, ensure both points are fully clipped. void Floor() { Min.x = (float)(int)Min.x; Min.y = (float)(int)Min.y; Max.x = (float)(int)Max.x; Max.y = (float)(int)Max.y; } void FixInverted() { if (Min.x > Max.x) ImSwap(Min.x, Max.x); if (Min.y > Max.y) ImSwap(Min.y, Max.y); } + bool IsInverted() const { return Min.x > Max.x || Min.y > Max.y; } bool IsFinite() const { return Min.x != FLT_MAX; } }; From 3f297e74e4f25c6307a49a1c50348708c7a332f4 Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 5 Feb 2018 14:52:28 +0100 Subject: [PATCH 601/823] Merging the minor/shallow changes from Navigation branch. --- imgui.cpp | 53 +++++++++++++++++++++++++++-------------------------- 1 file changed, 27 insertions(+), 26 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 9dd9eb77880c..536580698eb2 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -23,7 +23,7 @@ - ISSUES & TODO LIST - FREQUENTLY ASKED QUESTIONS (FAQ), TIPS - How can I help? - - How can I dipslay an image? What is ImTextureID, how does it works? + - How can I display an image? What is ImTextureID, how does it works? - How can I have multiple widgets with the same label? Can I have widget without a label? (Yes). A primer on labels and the ID stack. - How can I tell when Dear ImGui wants my mouse/keyboard inputs VS when I can pass them to my application? - How can I load a different font than the default? @@ -2135,9 +2135,8 @@ bool ImGui::FocusableItemRegister(ImGuiWindow* window, ImGuiID id, bool tab_stop if (window->FocusIdxAllCounter == window->FocusIdxAllRequestCurrent) return true; - if (allow_keyboard_focus) - if (window->FocusIdxTabCounter == window->FocusIdxTabRequestCurrent) - return true; + if (allow_keyboard_focus && window->FocusIdxTabCounter == window->FocusIdxTabRequestCurrent) + return true; return false; } @@ -3831,10 +3830,8 @@ static ImGuiWindow* GetFrontMostModalRootWindow() static void ClosePopupToLevel(int remaining) { ImGuiContext& g = *GImGui; - if (remaining > 0) - ImGui::FocusWindow(g.OpenPopupStack[remaining-1].Window); - else - ImGui::FocusWindow(g.OpenPopupStack[0].ParentWindow); + ImGuiWindow* focus_window = (remaining > 0) ? g.OpenPopupStack[remaining-1].Window : g.OpenPopupStack[0].ParentWindow; + ImGui::FocusWindow(focus_window); g.OpenPopupStack.resize(remaining); } @@ -4029,12 +4026,14 @@ bool ImGui::BeginChild(const char* str_id, const ImVec2& size_arg, bool border, bool ImGui::BeginChild(ImGuiID id, const ImVec2& size_arg, bool border, ImGuiWindowFlags extra_flags) { + IM_ASSERT(id != 0); return BeginChildEx(NULL, id, size_arg, border, extra_flags); } void ImGui::EndChild() { - ImGuiWindow* window = GetCurrentWindow(); + ImGuiContext& g = *GImGui; + ImGuiWindow* window = g.CurrentWindow; IM_ASSERT(window->Flags & ImGuiWindowFlags_ChildWindow); // Mismatched BeginChild()/EndChild() callss if (window->BeginCount > 1) @@ -4051,7 +4050,7 @@ void ImGui::EndChild() sz.y = ImMax(4.0f, sz.y); End(); - ImGuiWindow* parent_window = GetCurrentWindow(); + ImGuiWindow* parent_window = g.CurrentWindow; ImRect bb(parent_window->DC.CursorPos, parent_window->DC.CursorPos + sz); ItemSize(sz); ItemAdd(bb, 0); @@ -4473,6 +4472,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) // Automatically disable manual moving/resizing when NoInputs is set if (flags & ImGuiWindowFlags_NoInputs) flags |= ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize; + //if (flags & ImGuiWindowFlags_NavFlattened) // IM_ASSERT(flags & ImGuiWindowFlags_ChildWindow); @@ -4578,9 +4578,9 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) window->RootWindow = parent_window->RootWindow; if (parent_window && !(flags & ImGuiWindowFlags_Modal) && (flags & (ImGuiWindowFlags_ChildWindow | ImGuiWindowFlags_Popup))) window->RootNonPopupWindow = parent_window->RootNonPopupWindow; - //window->RootNavWindow = window; - //while (window->RootNavWindow->Flags & ImGuiWindowFlags_NavFlattened) - // window->RootNavWindow = window->RootNavWindow->ParentWindow; + //window->NavRootWindow = window; + //while (window->NavRootWindow->Flags & ImGuiWindowFlags_NavFlattened) + // window->NavRootWindow = window->NavRootWindow->ParentWindow; window->Active = true; window->BeginOrderWithinParent = 0; @@ -4796,12 +4796,13 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) const float window_border_size = window->WindowBorderSize; ImRect title_bar_rect = window->TitleBarRect(); const bool window_is_focused = want_focus || (g.NavWindow && window->RootNonPopupWindow == g.NavWindow->RootNonPopupWindow); + ImU32 title_bar_col = GetColorU32(window->Collapsed ? ImGuiCol_TitleBgCollapsed : window_is_focused ? ImGuiCol_TitleBgActive : ImGuiCol_TitleBg); if (window->Collapsed) { // Title bar only float backup_border_size = style.FrameBorderSize; g.Style.FrameBorderSize = window->WindowBorderSize; - RenderFrame(title_bar_rect.Min, title_bar_rect.Max, GetColorU32(ImGuiCol_TitleBgCollapsed), true, window_rounding); + RenderFrame(title_bar_rect.Min, title_bar_rect.Max, title_bar_col, true, window_rounding); g.Style.FrameBorderSize = backup_border_size; } else @@ -4817,7 +4818,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) // Title bar if (!(flags & ImGuiWindowFlags_NoTitleBar)) - window->DrawList->AddRectFilled(title_bar_rect.Min, title_bar_rect.Max, GetColorU32(window_is_focused ? ImGuiCol_TitleBgActive : ImGuiCol_TitleBg), window_rounding, ImDrawCornerFlags_Top); + window->DrawList->AddRectFilled(title_bar_rect.Min, title_bar_rect.Max, title_bar_col, window_rounding, ImDrawCornerFlags_Top); // Menu bar if (flags & ImGuiWindowFlags_MenuBar) @@ -6449,7 +6450,7 @@ bool ImGui::InvisibleButton(const char* str_id, const ImVec2& size_arg) return pressed; } -// Upper-right button to close a window. +// Button to close a window bool ImGui::CloseButton(ImGuiID id, const ImVec2& pos, float radius) { ImGuiWindow* window = GetCurrentWindow(); @@ -6471,7 +6472,6 @@ bool ImGui::CloseButton(ImGuiID id, const ImVec2& pos, float radius) window->DrawList->AddLine(center + ImVec2(+cross_extent,+cross_extent), center + ImVec2(-cross_extent,-cross_extent), GetColorU32(ImGuiCol_Text)); window->DrawList->AddLine(center + ImVec2(+cross_extent,-cross_extent), center + ImVec2(-cross_extent,+cross_extent), GetColorU32(ImGuiCol_Text)); } - return pressed; } @@ -7647,14 +7647,11 @@ bool ImGui::DragBehavior(const ImRect& frame_bb, ImGuiID id, float* v, float v_s float adjust_delta = 0.0f; if (IsMousePosValid()) { - //if (g.ActiveIdSource == ImGuiInputSource_Mouse) - { - adjust_delta = mouse_drag_delta.x - g.DragLastMouseDelta.x; - if (g.IO.KeyShift && g.DragSpeedScaleFast >= 0.0f) - adjust_delta *= g.DragSpeedScaleFast; - if (g.IO.KeyAlt && g.DragSpeedScaleSlow >= 0.0f) - adjust_delta *= g.DragSpeedScaleSlow; - } + adjust_delta = mouse_drag_delta.x - g.DragLastMouseDelta.x; + if (g.IO.KeyShift && g.DragSpeedScaleFast >= 0.0f) + adjust_delta *= g.DragSpeedScaleFast; + if (g.IO.KeyAlt && g.DragSpeedScaleSlow >= 0.0f) + adjust_delta *= g.DragSpeedScaleSlow; g.DragLastMouseDelta.x = mouse_drag_delta.x; } adjust_delta *= v_speed; @@ -9786,7 +9783,7 @@ bool ImGui::BeginMenu(const char* label, bool enabled) g.NavWindow = backed_nav_window; bool want_open = false, want_close = false; - if (window->DC.LayoutType != ImGuiLayoutType_Horizontal) // (window->Flags & (ImGuiWindowFlags_Popup|ImGuiWindowFlags_ChildMenu)) + if (window->DC.LayoutType == ImGuiLayoutType_Vertical) // (window->Flags & (ImGuiWindowFlags_Popup|ImGuiWindowFlags_ChildMenu)) { // Implement http://bjk5.com/post/44698559168/breaking-down-amazons-mega-dropdown to avoid using timers, so menus feels more reactive. bool moving_within_opened_triangle = false; @@ -11771,8 +11768,12 @@ void ImGui::ShowMetricsWindow(bool* p_open) { if (!ImGui::TreeNode(window, "%s '%s', %d @ 0x%p", label, window->Name, window->Active || window->WasActive, window)) return; + ImGuiWindowFlags flags = window->Flags; NodeDrawList(window, window->DrawList, "DrawList"); ImGui::BulletText("Pos: (%.1f,%.1f), Size: (%.1f,%.1f), SizeContents (%.1f,%.1f)", window->Pos.x, window->Pos.y, window->Size.x, window->Size.y, window->SizeContents.x, window->SizeContents.y); + ImGui::BulletText("Flags: 0x%08X (%s%s%s%s%s%s..)", flags, + (flags & ImGuiWindowFlags_ChildWindow) ? "Child " : "", (flags & ImGuiWindowFlags_Tooltip) ? "Tooltip " : "", (flags & ImGuiWindowFlags_Popup) ? "Popup " : "", + (flags & ImGuiWindowFlags_Modal) ? "Modal " : "", (flags & ImGuiWindowFlags_ChildMenu) ? "ChildMenu " : "", (flags & ImGuiWindowFlags_NoSavedSettings) ? "NoSavedSettings " : ""); ImGui::BulletText("Scroll: (%.2f/%.2f,%.2f/%.2f)", window->Scroll.x, GetScrollMaxX(window), window->Scroll.y, GetScrollMaxY(window)); ImGui::BulletText("Active: %d, WriteAccessed: %d", window->Active, window->WriteAccessed); if (window->RootWindow != window) NodeWindow(window->RootWindow, "RootWindow"); From 8ad88f725c075782cab4849ac1d4389885e3ab22 Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 5 Feb 2018 14:53:07 +0100 Subject: [PATCH 602/823] Nav: Minor tidying up. (#787) --- imgui.cpp | 7 +++---- imgui.h | 1 + imgui_demo.cpp | 2 +- imgui_internal.h | 20 ++++++++++---------- 4 files changed, 15 insertions(+), 15 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index e337c97b7622..0da2d40a3a6e 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -5035,7 +5035,6 @@ void ImGui::EndChild() ImGuiWindow* parent_window = g.CurrentWindow; ImRect bb(parent_window->DC.CursorPos, parent_window->DC.CursorPos + sz); - ItemSize(sz); if ((window->DC.NavLayerActiveMask != 0 || window->DC.NavHasScroll) && !(window->Flags & ImGuiWindowFlags_NavFlattened)) { @@ -6265,13 +6264,13 @@ void ImGui::FocusWindow(ImGuiWindow* window) if (g.NavWindow != window) { - g.NavId = window ? window->NavLastIds[0] : 0; // Restore NavId - g.NavIdIsAlive = false; - g.NavLayer = 0; g.NavWindow = window; if (window && g.NavDisableMouseHover) g.NavMousePosDirty = true; g.NavInitRequest = false; + g.NavId = window ? window->NavLastIds[0] : 0; // Restore NavId + g.NavIdIsAlive = false; + g.NavLayer = 0; } // Passing NULL allow to disable keyboard focus diff --git a/imgui.h b/imgui.h index 9a80026c6e8b..61ff2c695093 100644 --- a/imgui.h +++ b/imgui.h @@ -455,6 +455,7 @@ namespace ImGui IMGUI_API void StyleColorsLight(ImGuiStyle* dst = NULL); // Focus, Activation + // (Prefer using "SetItemDefaultFocus()" over "if (IsWindowAppearing()) SetScrollHere()" when applicable, to make your code more forward compatible when navigation branch is merged) IMGUI_API void SetItemDefaultFocus(); // make last item the default focused item of a window. Please use instead of "if (IsWindowAppearing()) SetScrollHere()" to signify "default item". IMGUI_API void SetKeyboardFocusHere(int offset = 0); // focus keyboard on the next widget. Use positive 'offset' to access sub components of a multiple component widget. Use -1 to access previous widget. diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 3af5399bae5e..0893cba40340 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -2730,7 +2730,7 @@ struct ExampleAppConsole // Demonstrate keeping focus on the input box ImGui::SetItemDefaultFocus(); - if (reclaim_focus) //|| ImGui::IsItemHovered()) + if (reclaim_focus) ImGui::SetKeyboardFocusHere(-1); // Auto focus previous widget ImGui::End(); diff --git a/imgui_internal.h b/imgui_internal.h index c012f3805828..4cf1d7c6e30f 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -247,6 +247,16 @@ enum ImGuiDataType ImGuiDataType_Float2 }; +enum ImGuiDir +{ + ImGuiDir_None = -1, + ImGuiDir_Left = 0, + ImGuiDir_Right = 1, + ImGuiDir_Up = 2, + ImGuiDir_Down = 3, + ImGuiDir_Count_ +}; + enum ImGuiInputSource { ImGuiInputSource_None = 0, @@ -268,16 +278,6 @@ enum ImGuiInputReadMode ImGuiInputReadMode_RepeatFast }; -enum ImGuiDir -{ - ImGuiDir_None = -1, - ImGuiDir_Left = 0, - ImGuiDir_Right = 1, - ImGuiDir_Up = 2, - ImGuiDir_Down = 3, - ImGuiDir_Count_ -}; - enum ImGuiNavHighlightFlags_ { ImGuiNavHighlightFlags_TypeDefault = 1 << 0, From 1dedbf80916968528028dba83e2aa5f328690815 Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 5 Feb 2018 15:07:25 +0100 Subject: [PATCH 603/823] Style: Fixed missing style.MouseCursorScale initialization (#939), messed up original commit badly. --- imgui.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/imgui.cpp b/imgui.cpp index 536580698eb2..d047b4b044bb 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -745,6 +745,7 @@ ImGuiStyle::ImGuiStyle() ButtonTextAlign = ImVec2(0.5f,0.5f);// Alignment of button text when button is larger than text. DisplayWindowPadding = ImVec2(22,22); // Window positions are clamped to be visible within the display area by at least this amount. Only covers regular windows. DisplaySafeAreaPadding = ImVec2(4,4); // If you cannot see the edge of your screen (e.g. on a TV) increase the safe area padding. Covers popups/tooltips as well regular windows. + MouseCursorScale = 1.0f; // Scale software rendered mouse cursor (when io.MouseDrawCursor is enabled). May be removed later. AntiAliasedLines = true; // Enable anti-aliasing on lines/borders. Disable if you are really short on CPU/GPU. AntiAliasedFill = true; // Enable anti-aliasing on filled shapes (rounded rectangles, circles, etc.) CurveTessellationTol = 1.25f; // Tessellation tolerance when using PathBezierCurveTo() without a specific number of segments. Decrease for highly tessellated curves (higher quality, more polygons), increase to reduce quality. From 11d0fc8220675e88e117f509e888ed6b7e8c97c6 Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 5 Feb 2018 15:10:07 +0100 Subject: [PATCH 604/823] Tooltip: BeginTooltip() sets NoInputs flag. --- imgui.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index d047b4b044bb..20ee693e5eb7 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -3708,7 +3708,7 @@ void ImGui::BeginTooltipEx(ImGuiWindowFlags extra_flags, bool override_previous_ window->HiddenFrames = 1; ImFormatString(window_name, IM_ARRAYSIZE(window_name), "##Tooltip_%02d", ++g.TooltipOverrideCount); } - ImGuiWindowFlags flags = ImGuiWindowFlags_Tooltip|ImGuiWindowFlags_NoTitleBar|ImGuiWindowFlags_NoMove|ImGuiWindowFlags_NoResize|ImGuiWindowFlags_NoSavedSettings|ImGuiWindowFlags_AlwaysAutoResize; + ImGuiWindowFlags flags = ImGuiWindowFlags_Tooltip|ImGuiWindowFlags_NoInputs|ImGuiWindowFlags_NoTitleBar|ImGuiWindowFlags_NoMove|ImGuiWindowFlags_NoResize|ImGuiWindowFlags_NoSavedSettings|ImGuiWindowFlags_AlwaysAutoResize; Begin(window_name, NULL, flags | extra_flags); } @@ -11384,7 +11384,7 @@ bool ImGui::BeginDragDropSource(ImGuiDragDropFlags flags, int mouse_button) //PushStyleVar(ImGuiStyleVar_Alpha, g.Style.Alpha * 0.60f); // This is better but e.g ColorButton with checkboard has issue with transparent colors :( SetNextWindowPos(g.IO.MousePos); PushStyleColor(ImGuiCol_PopupBg, GetStyleColorVec4(ImGuiCol_PopupBg) * ImVec4(1.0f, 1.0f, 1.0f, 0.6f)); - BeginTooltipEx(ImGuiWindowFlags_NoInputs); + BeginTooltip(); } if (!(flags & ImGuiDragDropFlags_SourceNoDisableHover) && !(flags & ImGuiDragDropFlags_SourceExtern)) From 5c83b55d0491f4349fbebc26b6b4add9f43febf4 Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 5 Feb 2018 15:49:35 +0100 Subject: [PATCH 605/823] Nav: Added ImGuiWindowFlags_NoNav shortcut, comments. (#787) --- imgui.h | 7 ++++--- imgui_demo.cpp | 6 +++--- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/imgui.h b/imgui.h index 61ff2c695093..cf45f1a5e498 100644 --- a/imgui.h +++ b/imgui.h @@ -551,11 +551,12 @@ enum ImGuiWindowFlags_ ImGuiWindowFlags_AlwaysHorizontalScrollbar=1<< 15, // Always show horizontal scrollbar (even if ContentSize.x < Size.x) ImGuiWindowFlags_AlwaysUseWindowPadding = 1 << 16, // Ensure child windows without border uses style.WindowPadding (ignored by default for non-bordered child windows, because more convenient) ImGuiWindowFlags_ResizeFromAnySide = 1 << 17, // (WIP) Enable resize from any corners and borders. Your back-end needs to honor the different values of io.MouseCursor set by imgui. - ImGuiWindowFlags_NoNavFocus = 1 << 18, // No focusing of this window with gamepad/keyboard navigation - ImGuiWindowFlags_NoNavInputs = 1 << 19, // No gamepad/keyboard navigation within the window + ImGuiWindowFlags_NoNavInputs = 1 << 18, // No gamepad/keyboard navigation within the window + ImGuiWindowFlags_NoNavFocus = 1 << 19, // No focusing toward this window with gamepad/keyboard navigation (e.g. skipped by CTRL+TAB) + ImGuiWindowFlags_NoNav = ImGuiWindowFlags_NoNavInputs | ImGuiWindowFlags_NoNavFocus, // [Internal] - ImGuiWindowFlags_NavFlattened = 1 << 20, // (WIP) Allow gamepad/keyboard navigation to cross over parent border to this child (only use on child that have no scrolling!) + ImGuiWindowFlags_NavFlattened = 1 << 23, // (WIP) Allow gamepad/keyboard navigation to cross over parent border to this child (only use on child that have no scrolling!) ImGuiWindowFlags_ChildWindow = 1 << 24, // Don't use! For internal use by BeginChild() ImGuiWindowFlags_Tooltip = 1 << 25, // Don't use! For internal use by BeginTooltip() ImGuiWindowFlags_Popup = 1 << 26, // Don't use! For internal use by BeginPopup() diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 0893cba40340..014709182831 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -184,7 +184,7 @@ void ImGui::ShowDemoWindow(bool* p_open) if (no_move) window_flags |= ImGuiWindowFlags_NoMove; if (no_resize) window_flags |= ImGuiWindowFlags_NoResize; if (no_collapse) window_flags |= ImGuiWindowFlags_NoCollapse; - if (no_nav) window_flags |= ImGuiWindowFlags_NoNavInputs; + if (no_nav) window_flags |= ImGuiWindowFlags_NoNav; if (no_close) p_open = NULL; // Don't pass our bool* to Begin ImGui::SetNextWindowSize(ImVec2(550,680), ImGuiCond_FirstUseEver); @@ -1802,6 +1802,7 @@ void ImGui::ShowDemoWindow(bool* p_open) ImGui::Text("WantCaptureKeyboard: %d", io.WantCaptureKeyboard); ImGui::Text("WantTextInput: %d", io.WantTextInput); ImGui::Text("WantMoveMouse: %d", io.WantMoveMouse); + ImGui::Text("NavActive: %d, NavVisible: %d", io.NavActive, io.NavVisible); ImGui::Checkbox("io.MouseDrawCursor", &io.MouseDrawCursor); ImGui::SameLine(); ShowHelpMarker("Request ImGui to render a mouse cursor for you in software. Note that a mouse cursor rendered via your application GPU rendering path will feel more laggy than hardware cursor, but will be more in sync with your other visuals.\n\nSome desktop applications may use both kinds of cursors (e.g. enable software cursor only when resizing/dragging something)."); @@ -1827,7 +1828,6 @@ void ImGui::ShowDemoWindow(bool* p_open) ImGui::Text("Keys release:"); for (int i = 0; i < IM_ARRAYSIZE(io.KeysDown); i++) if (ImGui::IsKeyReleased(i)) { ImGui::SameLine(); ImGui::Text("%d", i); } ImGui::Text("Keys mods: %s%s%s%s", io.KeyCtrl ? "CTRL " : "", io.KeyShift ? "SHIFT " : "", io.KeyAlt ? "ALT " : "", io.KeySuper ? "SUPER " : ""); - ImGui::Text("NavActive: %d, NavVisible: %d", io.NavActive, io.NavVisible); ImGui::Text("NavInputs down:"); for (int i = 0; i < IM_ARRAYSIZE(io.NavInputs); i++) if (io.NavInputs[i] > 0.0f) { ImGui::SameLine(); ImGui::Text("[%d] %.2f", i, io.NavInputs[i]); } ImGui::Text("NavInputs pressed:"); for (int i = 0; i < IM_ARRAYSIZE(io.NavInputs); i++) if (io.NavInputsDownDuration[i] == 0.0f) { ImGui::SameLine(); ImGui::Text("[%d]", i); } ImGui::Text("NavInputs duration:"); for (int i = 0; i < IM_ARRAYSIZE(io.NavInputs); i++) if (io.NavInputsDownDuration[i] >= 0.0f) { ImGui::SameLine(); ImGui::Text("[%d] %.2f", i, io.NavInputsDownDuration[i]); } @@ -2432,7 +2432,7 @@ static void ShowExampleAppFixedOverlay(bool* p_open) ImVec2 window_pos_pivot = ImVec2((corner & 1) ? 1.0f : 0.0f, (corner & 2) ? 1.0f : 0.0f); ImGui::SetNextWindowPos(window_pos, ImGuiCond_Always, window_pos_pivot); ImGui::SetNextWindowBgAlpha(0.3f); // Transparent background - if (ImGui::Begin("Example: Fixed Overlay", p_open, ImGuiWindowFlags_NoTitleBar|ImGuiWindowFlags_NoResize|ImGuiWindowFlags_AlwaysAutoResize|ImGuiWindowFlags_NoMove|ImGuiWindowFlags_NoSavedSettings|ImGuiWindowFlags_NoFocusOnAppearing|ImGuiWindowFlags_NoNavFocus|ImGuiWindowFlags_NoNavInputs)) + if (ImGui::Begin("Example: Fixed Overlay", p_open, ImGuiWindowFlags_NoTitleBar|ImGuiWindowFlags_NoResize|ImGuiWindowFlags_AlwaysAutoResize|ImGuiWindowFlags_NoMove|ImGuiWindowFlags_NoSavedSettings|ImGuiWindowFlags_NoFocusOnAppearing|ImGuiWindowFlags_NoNav)) { ImGui::Text("Simple overlay\nin the corner of the screen.\n(right-click to change position)"); ImGui::Separator(); From 92ee6b1185676a90bd7f805cdfe020b2deaaf927 Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 5 Feb 2018 16:02:21 +0100 Subject: [PATCH 606/823] Nav: Sets io.WantCaptureKeyboard when navigation is active. This is a little agressive but probably the best default and also a good way to get feedback. Added ImGuiNavFlags_NoCaptureKeyboard to disable this behavior. Comments. (#787) --- imgui.cpp | 6 +++++- imgui.h | 6 ++++-- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 436b559a413d..93547e963b47 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -3347,7 +3347,7 @@ void ImGui::NewFrame() g.ModalWindowDarkeningRatio = 0.0f; } - // Update the WantCaptureMouse/WantCAptureKeyboard flags, so user can capture/discard the inputs away from the rest of their application. + // Update the WantCaptureMouse/WantCaptureKeyboard flags, so user can capture/discard the inputs away from the rest of their application. // When clicking outside of a window we assume the click is owned by the application and won't request capture. We need to track click ownership. int mouse_earliest_button_down = -1; bool mouse_any_down = false; @@ -3365,10 +3365,14 @@ void ImGui::NewFrame() g.IO.WantCaptureMouse = (g.WantCaptureMouseNextFrame != 0); else g.IO.WantCaptureMouse = (mouse_avail_to_imgui && (g.HoveredWindow != NULL || mouse_any_down)) || (!g.OpenPopupStack.empty()); + if (g.WantCaptureKeyboardNextFrame != -1) g.IO.WantCaptureKeyboard = (g.WantCaptureKeyboardNextFrame != 0); else g.IO.WantCaptureKeyboard = (g.ActiveId != 0) || (modal_window != NULL); + if (g.IO.NavActive && (g.IO.NavFlags & ImGuiNavFlags_EnableKeyboard) && !(g.IO.NavFlags & ImGuiNavFlags_NoCaptureKeyboard)) + g.IO.WantCaptureKeyboard = true; + g.IO.WantTextInput = (g.WantTextInputNextFrame != -1) ? (g.WantTextInputNextFrame != 0) : 0; g.MouseCursor = ImGuiMouseCursor_Arrow; g.WantCaptureMouseNextFrame = g.WantCaptureKeyboardNextFrame = g.WantTextInputNextFrame = -1; diff --git a/imgui.h b/imgui.h index cf45f1a5e498..9aab0a7ef408 100644 --- a/imgui.h +++ b/imgui.h @@ -726,7 +726,8 @@ enum ImGuiNavInput_ ImGuiNavInput_PadTweakSlow, // slower tweaks // e.g. L-trigger, analog ImGuiNavInput_PadTweakFast, // faster tweaks // e.g. R-trigger, analog // Keyboard Mapping - // [BETA] You can map keyboard keys on the gamepad mapping for most inputs. Will add specialized keyboard mappings as we add features. + // [BETA] To use keyboard control you currently need to map keys to those gamepad inputs: PadActivate (Enter), PadCancel (Escape), PadInput (Enter). + // Will add specialized keyboard mappings as we add features and clarify the input interface. ImGuiNavInput_KeyMenu, // toggle menu // e.g. ALT ImGuiNavInput_KeyLeft, // move left // e.g. Arrow keys ImGuiNavInput_KeyRight, // move right @@ -740,7 +741,8 @@ enum ImGuiNavFlags_ { ImGuiNavFlags_EnableGamepad = 1 << 0, // Master gamepad navigation enable flag. This is mostly to instruct your imgui binding whether to fill in gamepad navigation inputs. ImGuiNavFlags_EnableKeyboard = 1 << 1, // Master keyboard navigation enable flag. This is mostly to instruct your imgui binding whether to fill in keyboard navigation inputs. - ImGuiNavFlags_MoveMouse = 1 << 2 // Request navigation to allow move the mouse cursor. May be useful on TV/console systems where moving a virtual mouse is awkward. Will update io.MousePos and set io.WantMoveMouse=true. If enabled you MUST honor io.WantMoveMouse requests in your binding, otherwise ImGui will react as if the mouse is jumping around back and forth. + ImGuiNavFlags_MoveMouse = 1 << 2, // Request navigation to allow moving the mouse cursor. May be useful on TV/console systems where moving a virtual mouse is awkward. Will update io.MousePos and set io.WantMoveMouse=true. If enabled you MUST honor io.WantMoveMouse requests in your binding, otherwise ImGui will react as if the mouse is jumping around back and forth. + ImGuiNavFlags_NoCaptureKeyboard = 1 << 3 // Do not set the io.WantCaptureKeyboard flag with io.NavActive is set. }; // Enumeration for PushStyleColor() / PopStyleColor() From f35734c9250ec920a05b0328b5d157c3342027c6 Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 5 Feb 2018 17:02:30 +0100 Subject: [PATCH 607/823] Nav: Debugging code. (#787) --- imgui.cpp | 6 ++++++ imgui_internal.h | 2 ++ 2 files changed, 8 insertions(+) diff --git a/imgui.cpp b/imgui.cpp index 93547e963b47..58c879d66372 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2147,6 +2147,7 @@ static bool NavScoreItem(ImGuiNavMoveResult* result, ImRect cand) return false; const ImRect& curr = g.NavScoringRectScreen; // Current modified source rect (NB: we've applied Max.x = Min.x in NavUpdate() to inhibit the effect of having varied item width) + g.NavScoringCount++; // We perform scoring on items bounding box clipped by their parent window on the other axis (clipping on our movement axis would give us equal scores for all clipped items) if (g.NavMoveDir == ImGuiDir_Left || g.NavMoveDir == ImGuiDir_Right) @@ -2923,6 +2924,10 @@ static void ImGui::NavUpdate() ImGuiContext& g = *GImGui; g.IO.WantMoveMouse = false; +#if 0 + if (g.NavScoringCount > 0) printf("[%05d] NavScoringCount %d for '%s' layer %d (Init:%d, Move:%d)\n", g.FrameCount, g.NavScoringCount, g.NavWindow ? g.NavWindow->Name : "NULL", g.NavLayer, g.NavInitRequest || g.NavInitResultId != 0, g.NavMoveRequest); +#endif + // Process navigation init request (select first/default focus) if (g.NavInitResultId != 0 && (!g.NavDisableHighlight || g.NavInitResultExplicit)) { @@ -3153,6 +3158,7 @@ static void ImGui::NavUpdate() g.NavScoringRectScreen.Max.x = g.NavScoringRectScreen.Min.x; IM_ASSERT(!g.NavScoringRectScreen.IsInverted()); // Ensure if we have a finite, non-inverted bounding box here will allows us to remove extraneous fabsf() calls in NavScoreItem(). //g.OverlayDrawList.AddRect(g.NavScoringRectScreen.Min, g.NavScoringRectScreen.Max, IM_COL32(255,200,0,255)); // [DEBUG] + g.NavScoringCount = 0; #if IMGUI_DEBUG_NAV_RECTS if (g.NavWindow) { for (int layer = 0; layer < 2; layer++) g.OverlayDrawList.AddRect(g.NavWindow->Pos + g.NavWindow->NavRectRel[layer].Min, g.NavWindow->Pos + g.NavWindow->NavRectRel[layer].Max, IM_COL32(255,200,0,255)); } // [DEBUG] if (g.NavWindow) { ImU32 col = (g.NavWindow->HiddenFrames <= 0) ? IM_COL32(255,0,255,255) : IM_COL32(255,0,0,255); ImVec2 p = NavCalcPreferredMousePos(); char buf[32]; ImFormatString(buf, 32, "%d", g.NavLayer); g.OverlayDrawList.AddCircleFilled(p, 3.0f, col); g.OverlayDrawList.AddText(NULL, 13.0f, p + ImVec2(8,-4), col, buf); } diff --git a/imgui_internal.h b/imgui_internal.h index 4cf1d7c6e30f..027726e7afdd 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -615,6 +615,7 @@ struct ImGuiContext ImGuiID NavNextActivateId; // Set by ActivateItem(), queued until next frame ImGuiID NavJustMovedToId; // Just navigated to this id (result of a successfully MoveRequest) ImRect NavScoringRectScreen; // Rectangle used for scoring, in screen space. Based of window->DC.NavRefRectRel[], modified for directional navigation scoring. + int NavScoringCount; // Metrics for debugging ImGuiWindow* NavWindowingTarget; // When selecting a window (holding Menu+FocusPrev/Next, or equivalent of CTRL-TAB) this window is temporarily displayed front-most. float NavWindowingHighlightTimer; float NavWindowingHighlightAlpha; @@ -732,6 +733,7 @@ struct ImGuiContext NavId = NavActivateId = NavActivateDownId = NavInputId = 0; NavJustTabbedId = NavJustMovedToId = NavNextActivateId = 0; NavScoringRectScreen = ImRect(); + NavScoringCount = 0; NavWindowingTarget = NULL; NavWindowingHighlightTimer = NavWindowingHighlightAlpha = 0.0f; NavWindowingToggleLayer = false; From fb7cf4a475f216dc9e41f68fbd75772d8ec8a0db Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 5 Feb 2018 18:25:03 +0100 Subject: [PATCH 608/823] Nav: Removed old unnecessary ifdefs. --- imgui.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 58c879d66372..b9e5b0691ff5 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -7653,9 +7653,7 @@ bool ImGui::ArrowButton(ImGuiID id, ImGuiDir dir, ImVec2 padding, ImGuiButtonFla bool pressed = ButtonBehavior(bb, id, &hovered, &held, flags); const ImU32 col = GetColorU32((hovered && held) ? ImGuiCol_ButtonActive : hovered ? ImGuiCol_ButtonHovered : ImGuiCol_Button); -#ifdef IMGUI_HAS_NAV RenderNavHighlight(bb, id); -#endif RenderFrame(bb.Min, bb.Max, col, true, style.FrameRounding); RenderTriangle(bb.Min + padding, dir, 1.0f); @@ -12011,9 +12009,7 @@ bool ImGui::SplitterBehavior(ImGuiID id, const ImRect& bb, ImGuiAxis axis, float ImGuiWindow* window = g.CurrentWindow; const ImGuiItemFlags item_flags_backup = window->DC.ItemFlags; -#ifdef IMGUI_HAS_NAV window->DC.ItemFlags |= ImGuiItemFlags_NoNav | ImGuiItemFlags_NoNavDefaultFocus; -#endif bool add = ItemAdd(bb, id); window->DC.ItemFlags = item_flags_backup; if (!add) From e5e3cc617eacab072422aba91009cf4f3d0f47b1 Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 5 Feb 2018 19:07:26 +0100 Subject: [PATCH 609/823] Nav: Maintaining a NavActivatePressedId field that widget can conveniently use along with NavActivateDownId. --- imgui.cpp | 21 ++++++++++++--------- imgui_internal.h | 7 ++++--- 2 files changed, 16 insertions(+), 12 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index b9e5b0691ff5..4e8816aefdfe 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -3042,28 +3042,31 @@ static void ImGui::NavUpdate() } } - g.NavActivateId = g.NavActivateDownId = g.NavInputId = 0; - if (g.NavId != 0 && !g.NavDisableHighlight && !g.NavWindowingTarget) + // Process manual activation request + g.NavActivateId = g.NavActivateDownId = g.NavActivatePressedId = g.NavInputId = 0; + if (g.NavId != 0 && !g.NavDisableHighlight && !g.NavWindowingTarget && g.NavWindow && !(g.NavWindow->Flags & ImGuiWindowFlags_NoNavInputs)) { - if (g.ActiveId == 0 && IsNavInputPressed(ImGuiNavInput_PadActivate, ImGuiInputReadMode_Pressed)) + bool activate_down = IsNavInputDown(ImGuiNavInput_PadActivate); + bool activate_pressed = activate_down && IsNavInputPressed(ImGuiNavInput_PadActivate, ImGuiInputReadMode_Pressed); + if (g.ActiveId == 0 && activate_pressed) g.NavActivateId = g.NavId; - if ((g.ActiveId == 0 || g.ActiveId == g.NavId) && IsNavInputDown(ImGuiNavInput_PadActivate)) + if ((g.ActiveId == 0 || g.ActiveId == g.NavId) && activate_down) g.NavActivateDownId = g.NavId; + if ((g.ActiveId == 0 || g.ActiveId == g.NavId) && activate_pressed) + g.NavActivatePressedId = g.NavId; + if (g.ActiveId == 0 && IsNavInputPressed(ImGuiNavInput_PadInput, ImGuiInputReadMode_Pressed)) g.NavInputId = g.NavId; } if (g.NavWindow && (g.NavWindow->Flags & ImGuiWindowFlags_NoNavInputs)) - { - g.NavActivateId = g.NavActivateDownId = g.NavInputId = 0; g.NavDisableHighlight = true; - } if (g.NavActivateId != 0) IM_ASSERT(g.NavActivateDownId == g.NavActivateId); g.NavMoveRequest = false; - // Process explicit activation request + // Process programmatic activation request if (g.NavNextActivateId != 0) - g.NavActivateId = g.NavActivateDownId = g.NavInputId = g.NavNextActivateId; + g.NavActivateId = g.NavActivateDownId = g.NavActivatePressedId = g.NavInputId = g.NavNextActivateId; g.NavNextActivateId = 0; // Initiate directional inputs request diff --git a/imgui_internal.h b/imgui_internal.h index 027726e7afdd..785b68079e9d 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -608,8 +608,9 @@ struct ImGuiContext // Navigation data (for gamepad/keyboard) ImGuiWindow* NavWindow; // Focused window for navigation. Could be called 'FocusWindow' ImGuiID NavId; // Focused item for navigation - ImGuiID NavActivateId; // ~~ IsNavInputPressed(ImGuiNavInput_PadActivate) ? NavId : 0, also set when calling ActivateItem() - ImGuiID NavActivateDownId; // ~~ IsNavInputPressed(ImGuiNavInput_PadActivate) ? NavId : 0 + ImGuiID NavActivateId; // ~~ (g.ActiveId == 0) && IsNavInputPressed(ImGuiNavInput_PadActivate) ? NavId : 0, also set when calling ActivateItem() + ImGuiID NavActivateDownId; // ~~ IsNavInputDown(ImGuiNavInput_PadActivate) ? NavId : 0 + ImGuiID NavActivatePressedId; // ~~ IsNavInputPressed(ImGuiNavInput_PadActivate) ? NavId : 0 ImGuiID NavInputId; // ~~ IsNavInputPressed(ImGuiNavInput_PadInput) ? NavId : 0 ImGuiID NavJustTabbedId; // Just tabbed to this id. ImGuiID NavNextActivateId; // Set by ActivateItem(), queued until next frame @@ -730,7 +731,7 @@ struct ImGuiContext NextTreeNodeOpenCond = 0; NavWindow = NULL; - NavId = NavActivateId = NavActivateDownId = NavInputId = 0; + NavId = NavActivateId = NavActivateDownId = NavActivatePressedId = NavInputId = 0; NavJustTabbedId = NavJustMovedToId = NavNextActivateId = 0; NavScoringRectScreen = ImRect(); NavScoringCount = 0; From 4932303e62e529f4b12eca97b2b0466d30824351 Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 5 Feb 2018 20:15:31 +0100 Subject: [PATCH 610/823] Nav: DragBehavior: Tweaks (to take the noise out of the next commit). --- imgui.cpp | 114 +++++++++++++++++++++++++++--------------------------- 1 file changed, 57 insertions(+), 57 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 4e8816aefdfe..ae6c9c29dc00 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -8852,73 +8852,73 @@ bool ImGui::DragBehavior(const ImRect& frame_bb, ImGuiID id, float* v, float v_s // Process clicking on the drag if (g.ActiveId == id) { - if (g.IO.MouseDown[0] || g.NavActivateDownId == id) + if (g.ActiveIdSource == ImGuiInputSource_Mouse && !g.IO.MouseDown[0]) + ClearActiveID(); + else if (g.ActiveIdSource == ImGuiInputSource_Nav && g.NavActivateDownId != id) + ClearActiveID(); + } + if (g.ActiveId == id) + { + if (g.ActiveIdIsJustActivated) { - if (g.ActiveIdIsJustActivated) - { - // Lock current value on click - g.DragCurrentValue = *v; - g.DragLastMouseDelta = ImVec2(0.f, 0.f); - } + // Lock current value on click + g.DragCurrentValue = *v; + g.DragLastMouseDelta = ImVec2(0.f, 0.f); + } - if (v_speed == 0.0f && (v_max - v_min) != 0.0f && (v_max - v_min) < FLT_MAX) - v_speed = (v_max - v_min) * g.DragSpeedDefaultRatio; + if (v_speed == 0.0f && (v_max - v_min) != 0.0f && (v_max - v_min) < FLT_MAX) + v_speed = (v_max - v_min) * g.DragSpeedDefaultRatio; - float v_cur = g.DragCurrentValue; - const ImVec2 mouse_drag_delta = GetMouseDragDelta(0, 1.0f); - float adjust_delta = 0.0f; - if (g.ActiveIdSource == ImGuiInputSource_Mouse && IsMousePosValid()) - { - adjust_delta = mouse_drag_delta.x - g.DragLastMouseDelta.x; - if (g.IO.KeyShift && g.DragSpeedScaleFast >= 0.0f) - adjust_delta *= g.DragSpeedScaleFast; - if (g.IO.KeyAlt && g.DragSpeedScaleSlow >= 0.0f) - adjust_delta *= g.DragSpeedScaleSlow; - g.DragLastMouseDelta.x = mouse_drag_delta.x; - } - if (g.ActiveIdSource == ImGuiInputSource_Nav) - { - adjust_delta = GetNavInputAmount2d(ImGuiNavDirSourceFlags_Keyboard|ImGuiNavDirSourceFlags_PadDPad, ImGuiInputReadMode_RepeatFast, 1.0f/10.0f, 10.0f).x; - if (v_min < v_max && ((v_cur >= v_max && adjust_delta > 0.0f) || (v_cur <= v_min && adjust_delta < 0.0f))) // This is to avoid applying the saturation when already past the limits - adjust_delta = 0.0f; - v_speed = ImMax(v_speed, GetMinimumStepAtDecimalPrecision(decimal_precision)); - } - adjust_delta *= v_speed; + float v_cur = g.DragCurrentValue; + const ImVec2 mouse_drag_delta = GetMouseDragDelta(0, 1.0f); + float adjust_delta = 0.0f; + if (g.ActiveIdSource == ImGuiInputSource_Mouse && IsMousePosValid()) + { + adjust_delta = mouse_drag_delta.x - g.DragLastMouseDelta.x; + if (g.IO.KeyShift && g.DragSpeedScaleFast >= 0.0f) + adjust_delta *= g.DragSpeedScaleFast; + if (g.IO.KeyAlt && g.DragSpeedScaleSlow >= 0.0f) + adjust_delta *= g.DragSpeedScaleSlow; + g.DragLastMouseDelta.x = mouse_drag_delta.x; + } + if (g.ActiveIdSource == ImGuiInputSource_Nav) + { + adjust_delta = GetNavInputAmount2d(ImGuiNavDirSourceFlags_Keyboard|ImGuiNavDirSourceFlags_PadDPad, ImGuiInputReadMode_RepeatFast, 1.0f/10.0f, 10.0f).x; + if (v_min < v_max && ((v_cur >= v_max && adjust_delta > 0.0f) || (v_cur <= v_min && adjust_delta < 0.0f))) // This is to avoid applying the saturation when already past the limits + adjust_delta = 0.0f; + v_speed = ImMax(v_speed, GetMinimumStepAtDecimalPrecision(decimal_precision)); + } + adjust_delta *= v_speed; - if (fabsf(adjust_delta) > 0.0f) + if (fabsf(adjust_delta) > 0.0f) + { + if (fabsf(power - 1.0f) > 0.001f) { - if (fabsf(power - 1.0f) > 0.001f) - { - // Logarithmic curve on both side of 0.0 - float v0_abs = v_cur >= 0.0f ? v_cur : -v_cur; - float v0_sign = v_cur >= 0.0f ? 1.0f : -1.0f; - float v1 = powf(v0_abs, 1.0f / power) + (adjust_delta * v0_sign); - float v1_abs = v1 >= 0.0f ? v1 : -v1; - float v1_sign = v1 >= 0.0f ? 1.0f : -1.0f; // Crossed sign line - v_cur = powf(v1_abs, power) * v0_sign * v1_sign; // Reapply sign - } - else - { - v_cur += adjust_delta; - } - - // Clamp - if (v_min < v_max) - v_cur = ImClamp(v_cur, v_min, v_max); - g.DragCurrentValue = v_cur; + // Logarithmic curve on both side of 0.0 + float v0_abs = v_cur >= 0.0f ? v_cur : -v_cur; + float v0_sign = v_cur >= 0.0f ? 1.0f : -1.0f; + float v1 = powf(v0_abs, 1.0f / power) + (adjust_delta * v0_sign); + float v1_abs = v1 >= 0.0f ? v1 : -v1; + float v1_sign = v1 >= 0.0f ? 1.0f : -1.0f; // Crossed sign line + v_cur = powf(v1_abs, power) * v0_sign * v1_sign; // Reapply sign } - - // Round to user desired precision, then apply - v_cur = RoundScalar(v_cur, decimal_precision); - if (*v != v_cur) + else { - *v = v_cur; - value_changed = true; + v_cur += adjust_delta; } + + // Clamp + if (v_min < v_max) + v_cur = ImClamp(v_cur, v_min, v_max); + g.DragCurrentValue = v_cur; } - else + + // Round to user desired precision, then apply + v_cur = RoundScalar(v_cur, decimal_precision); + if (*v != v_cur) { - ClearActiveID(); + *v = v_cur; + value_changed = true; } } From fb9fecea5ecf3759d33b2a5f1d439b6cd12d8f98 Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 5 Feb 2018 20:16:38 +0100 Subject: [PATCH 611/823] Nav: Sliders and Drags are toggle activated instead of requiring user to cross Cross/Space. (#787) --- imgui.cpp | 49 +++++++++++++++++++++++++++++-------------------- 1 file changed, 29 insertions(+), 20 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index ae6c9c29dc00..bb78b9a5ff66 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -3054,8 +3054,7 @@ static void ImGui::NavUpdate() g.NavActivateDownId = g.NavId; if ((g.ActiveId == 0 || g.ActiveId == g.NavId) && activate_pressed) g.NavActivatePressedId = g.NavId; - - if (g.ActiveId == 0 && IsNavInputPressed(ImGuiNavInput_PadInput, ImGuiInputReadMode_Pressed)) + if ((g.ActiveId == 0 || g.ActiveId == g.NavId) && IsNavInputPressed(ImGuiNavInput_PadInput, ImGuiInputReadMode_Pressed)) g.NavInputId = g.NavId; } if (g.NavWindow && (g.NavWindow->Flags & ImGuiWindowFlags_NoNavInputs)) @@ -8512,25 +8511,36 @@ bool ImGui::SliderBehavior(const ImRect& frame_bb, ImGuiID id, float* v, float v linear_zero_pos = v_min < 0.0f ? 1.0f : 0.0f; } - // Process clicking on the slider + // Process interacting with the slider bool value_changed = false; if (g.ActiveId == id) { bool set_new_value = false; float clicked_t = 0.0f; - if (g.ActiveIdSource == ImGuiInputSource_Mouse && g.IO.MouseDown[0]) + if (g.ActiveIdSource == ImGuiInputSource_Mouse) { - const float mouse_abs_pos = is_horizontal ? g.IO.MousePos.x : g.IO.MousePos.y; - clicked_t = (slider_usable_sz > 0.0f) ? ImClamp((mouse_abs_pos - slider_usable_pos_min) / slider_usable_sz, 0.0f, 1.0f) : 0.0f; - if (!is_horizontal) - clicked_t = 1.0f - clicked_t; - set_new_value = true; + if (!g.IO.MouseDown[0]) + { + ClearActiveID(); + } + else + { + const float mouse_abs_pos = is_horizontal ? g.IO.MousePos.x : g.IO.MousePos.y; + clicked_t = (slider_usable_sz > 0.0f) ? ImClamp((mouse_abs_pos - slider_usable_pos_min) / slider_usable_sz, 0.0f, 1.0f) : 0.0f; + if (!is_horizontal) + clicked_t = 1.0f - clicked_t; + set_new_value = true; + } } - else if (g.ActiveIdSource == ImGuiInputSource_Nav && g.NavActivateDownId == id) + else if (g.ActiveIdSource == ImGuiInputSource_Nav) { - const ImVec2 delta2 = GetNavInputAmount2d(ImGuiNavDirSourceFlags_Keyboard|ImGuiNavDirSourceFlags_PadDPad, ImGuiInputReadMode_RepeatFast, 0.0f, 0.0f); + const ImVec2 delta2 = GetNavInputAmount2d(ImGuiNavDirSourceFlags_Keyboard | ImGuiNavDirSourceFlags_PadDPad, ImGuiInputReadMode_RepeatFast, 0.0f, 0.0f); float delta = is_horizontal ? delta2.x : -delta2.y; - if (delta != 0.0f) + if (g.NavActivatePressedId == id && !g.ActiveIdIsJustActivated) + { + ClearActiveID(); + } + else if (delta != 0.0f) { clicked_t = SliderBehaviorCalcRatioFromValue(*v, v_min, v_max, power, linear_zero_pos); if (decimal_precision == 0 && !is_non_linear) @@ -8555,10 +8565,6 @@ bool ImGui::SliderBehavior(const ImRect& frame_bb, ImGuiID id, float* v, float v clicked_t = ImSaturate(clicked_t + delta); } } - else - { - ClearActiveID(); - } if (set_new_value) { @@ -8651,11 +8657,12 @@ bool ImGui::SliderFloat(const char* label, float* v, float v_min, float v_max, c // Tabbing or CTRL-clicking on Slider turns it into an input box bool start_text_input = false; const bool tab_focus_requested = FocusableItemRegister(window, id); - if (tab_focus_requested || (hovered && g.IO.MouseClicked[0]) || g.NavActivateId == id || g.NavInputId == id) + if (tab_focus_requested || (hovered && g.IO.MouseClicked[0]) || g.NavActivateId == id || (g.NavInputId == id && g.ScalarAsInputTextId != id)) { SetActiveID(id, window); SetFocusID(id, window); FocusWindow(window); + g.ActiveIdAllowNavDirFlags = (1 << ImGuiDir_Up) | (1 << ImGuiDir_Down); if (tab_focus_requested || g.IO.KeyCtrl || g.NavInputId == id) { start_text_input = true; @@ -8708,6 +8715,7 @@ bool ImGui::VSliderFloat(const char* label, const ImVec2& size, float* v, float SetActiveID(id, window); SetFocusID(id, window); FocusWindow(window); + g.ActiveIdAllowNavDirFlags = (1 << ImGuiDir_Left) | (1 << ImGuiDir_Right); } // Actual slider behavior + render grab @@ -8849,12 +8857,12 @@ bool ImGui::DragBehavior(const ImRect& frame_bb, ImGuiID id, float* v, float v_s bool value_changed = false; - // Process clicking on the drag + // Process interacting with the drag if (g.ActiveId == id) { if (g.ActiveIdSource == ImGuiInputSource_Mouse && !g.IO.MouseDown[0]) ClearActiveID(); - else if (g.ActiveIdSource == ImGuiInputSource_Nav && g.NavActivateDownId != id) + else if (g.ActiveIdSource == ImGuiInputSource_Nav && g.NavActivatePressedId == id && !g.ActiveIdIsJustActivated) ClearActiveID(); } if (g.ActiveId == id) @@ -8956,11 +8964,12 @@ bool ImGui::DragFloat(const char* label, float* v, float v_speed, float v_min, f // Tabbing or CTRL-clicking on Drag turns it into an input box bool start_text_input = false; const bool tab_focus_requested = FocusableItemRegister(window, id); - if (tab_focus_requested || (hovered && (g.IO.MouseClicked[0] || g.IO.MouseDoubleClicked[0])) || g.NavActivateId == id || g.NavInputId == id) + if (tab_focus_requested || (hovered && (g.IO.MouseClicked[0] || g.IO.MouseDoubleClicked[0])) || g.NavActivateId == id || (g.NavInputId == id && g.ScalarAsInputTextId != id)) { SetActiveID(id, window); SetFocusID(id, window); FocusWindow(window); + g.ActiveIdAllowNavDirFlags = (1 << ImGuiDir_Up) | (1 << ImGuiDir_Down); if (tab_focus_requested || g.IO.KeyCtrl || g.IO.MouseDoubleClicked[0] || g.NavInputId == id) { start_text_input = true; From 73d493c780443ca72f312df7aa7c4c76aefe4e12 Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 5 Feb 2018 20:34:11 +0100 Subject: [PATCH 612/823] Examples: Organized header files to make available features more visible. --- examples/allegro5_example/imgui_impl_a5.cpp | 10 +++++----- examples/allegro5_example/imgui_impl_a5.h | 9 ++++++--- examples/directx10_example/imgui_impl_dx10.cpp | 4 +++- examples/directx10_example/imgui_impl_dx10.h | 4 +++- examples/directx11_example/imgui_impl_dx11.cpp | 5 ++++- examples/directx11_example/imgui_impl_dx11.h | 5 ++++- examples/directx9_example/imgui_impl_dx9.cpp | 4 +++- examples/directx9_example/imgui_impl_dx9.h | 4 +++- examples/marmalade_example/imgui_impl_marmalade.cpp | 4 +++- examples/marmalade_example/imgui_impl_marmalade.h | 4 +++- examples/opengl2_example/imgui_impl_glfw_gl2.cpp | 4 +++- examples/opengl2_example/imgui_impl_glfw_gl2.h | 4 +++- examples/opengl3_example/imgui_impl_glfw_gl3.cpp | 6 +++++- examples/opengl3_example/imgui_impl_glfw_gl3.h | 6 +++++- examples/sdl_opengl2_example/imgui_impl_sdl_gl2.cpp | 4 +++- examples/sdl_opengl2_example/imgui_impl_sdl_gl2.h | 4 +++- examples/sdl_opengl3_example/imgui_impl_sdl_gl3.cpp | 4 +++- examples/sdl_opengl3_example/imgui_impl_sdl_gl3.h | 4 +++- examples/vulkan_example/imgui_impl_glfw_vulkan.cpp | 4 +++- examples/vulkan_example/imgui_impl_glfw_vulkan.h | 4 +++- 20 files changed, 71 insertions(+), 26 deletions(-) diff --git a/examples/allegro5_example/imgui_impl_a5.cpp b/examples/allegro5_example/imgui_impl_a5.cpp index 4269136214c9..1eb118e60a38 100644 --- a/examples/allegro5_example/imgui_impl_a5.cpp +++ b/examples/allegro5_example/imgui_impl_a5.cpp @@ -1,14 +1,14 @@ // ImGui Allegro 5 bindings -// In this binding, ImTextureID is used to store a 'ALLEGRO_BITMAP*' texture identifier. Read the FAQ about ImTextureID in imgui.cpp. -// TODO: -// - Clipboard is not supported. +// Implemented features: +// [X] User texture binding. Use 'ALLEGRO_BITMAP*' as ImTextureID. Read the FAQ about ImTextureID in imgui.cpp. +// Missing features: +// [ ] Clipboard support via al_set_clipboard_text/al_clipboard_has_text. // You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this. // If you use this binding you'll need to call 4 functions: ImGui_ImplXXXX_Init(), ImGui_ImplXXXX_NewFrame(), ImGui::Render() and ImGui_ImplXXXX_Shutdown(). // If you are new to ImGui, see examples/README.txt and documentation at the top of imgui.cpp. -// https://github.com/ocornut/imgui -// by @birthggd +// https://github.com/ocornut/imgui, Original code by @birthggd #include // uint64_t #include // memcpy diff --git a/examples/allegro5_example/imgui_impl_a5.h b/examples/allegro5_example/imgui_impl_a5.h index b7439fef9d15..7f1644353e58 100644 --- a/examples/allegro5_example/imgui_impl_a5.h +++ b/examples/allegro5_example/imgui_impl_a5.h @@ -1,11 +1,14 @@ // ImGui Allegro 5 bindings -// In this binding, ImTextureID is used to store a 'ALLEGRO_BITMAP*' texture identifier. Read the FAQ about ImTextureID in imgui.cpp. + +// Implemented features: +// [X] User texture binding. Use 'ALLEGRO_BITMAP*' as ImTextureID. Read the FAQ about ImTextureID in imgui.cpp. +// Missing features: +// [ ] Clipboard support via al_set_clipboard_text/al_clipboard_has_text. // You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this. // If you use this binding you'll need to call 4 functions: ImGui_ImplXXXX_Init(), ImGui_ImplXXXX_NewFrame(), ImGui::Render() and ImGui_ImplXXXX_Shutdown(). // If you are new to ImGui, see examples/README.txt and documentation at the top of imgui.cpp. -// https://github.com/ocornut/imgui -// by @birthggd +// https://github.com/ocornut/imgui, Original code by @birthggd #pragma once diff --git a/examples/directx10_example/imgui_impl_dx10.cpp b/examples/directx10_example/imgui_impl_dx10.cpp index 14a47c4af52b..e3080f9c41dd 100644 --- a/examples/directx10_example/imgui_impl_dx10.cpp +++ b/examples/directx10_example/imgui_impl_dx10.cpp @@ -1,5 +1,7 @@ // ImGui Win32 + DirectX10 binding -// In this binding, ImTextureID is used to store a 'ID3D10ShaderResourceView*' texture identifier. Read the FAQ about ImTextureID in imgui.cpp. + +// Implemented features: +// [X] User texture binding. Use 'ID3D10ShaderResourceView*' as ImTextureID. Read the FAQ about ImTextureID in imgui.cpp. // You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this. // If you use this binding you'll need to call 4 functions: ImGui_ImplXXXX_Init(), ImGui_ImplXXXX_NewFrame(), ImGui::Render() and ImGui_ImplXXXX_Shutdown(). diff --git a/examples/directx10_example/imgui_impl_dx10.h b/examples/directx10_example/imgui_impl_dx10.h index 38a03a27e3b5..604b7b63016c 100644 --- a/examples/directx10_example/imgui_impl_dx10.h +++ b/examples/directx10_example/imgui_impl_dx10.h @@ -1,5 +1,7 @@ // ImGui Win32 + DirectX10 binding -// In this binding, ImTextureID is used to store a 'ID3D10ShaderResourceView*' texture identifier. Read the FAQ about ImTextureID in imgui.cpp. + +// Implemented features: +// [X] User texture binding. Use 'ID3D10ShaderResourceView*' as ImTextureID. Read the FAQ about ImTextureID in imgui.cpp. // You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this. // If you use this binding you'll need to call 4 functions: ImGui_ImplXXXX_Init(), ImGui_ImplXXXX_NewFrame(), ImGui::Render() and ImGui_ImplXXXX_Shutdown(). diff --git a/examples/directx11_example/imgui_impl_dx11.cpp b/examples/directx11_example/imgui_impl_dx11.cpp index 67b8a9eeb12e..fbcfd953a0c7 100644 --- a/examples/directx11_example/imgui_impl_dx11.cpp +++ b/examples/directx11_example/imgui_impl_dx11.cpp @@ -1,5 +1,8 @@ // ImGui Win32 + DirectX11 binding -// In this binding, ImTextureID is used to store a 'ID3D11ShaderResourceView*' texture identifier. Read the FAQ about ImTextureID in imgui.cpp. + +// Implemented features: +// [X] User texture binding. Use 'ID3D11ShaderResourceView*' as ImTextureID. Read the FAQ about ImTextureID in imgui.cpp. +// [X] Keyboard navigation mapping. Enable with 'io.NavFlags |= ImGuiNavFlags_EnableKeyboard'. // You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this. // If you use this binding you'll need to call 4 functions: ImGui_ImplXXXX_Init(), ImGui_ImplXXXX_NewFrame(), ImGui::Render() and ImGui_ImplXXXX_Shutdown(). diff --git a/examples/directx11_example/imgui_impl_dx11.h b/examples/directx11_example/imgui_impl_dx11.h index 36066746d0a4..fc2b6bdb89c8 100644 --- a/examples/directx11_example/imgui_impl_dx11.h +++ b/examples/directx11_example/imgui_impl_dx11.h @@ -1,5 +1,8 @@ // ImGui Win32 + DirectX11 binding -// In this binding, ImTextureID is used to store a 'ID3D11ShaderResourceView*' texture identifier. Read the FAQ about ImTextureID in imgui.cpp. + +// Implemented features: +// [X] User texture binding. Use 'ID3D11ShaderResourceView*' as ImTextureID. Read the FAQ about ImTextureID in imgui.cpp. +// [X] Keyboard navigation mapping. Enable with 'io.NavFlags |= ImGuiNavFlags_EnableKeyboard'. // You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this. // If you use this binding you'll need to call 4 functions: ImGui_ImplXXXX_Init(), ImGui_ImplXXXX_NewFrame(), ImGui::Render() and ImGui_ImplXXXX_Shutdown(). diff --git a/examples/directx9_example/imgui_impl_dx9.cpp b/examples/directx9_example/imgui_impl_dx9.cpp index b47a840b6ec9..8e0808fdee68 100644 --- a/examples/directx9_example/imgui_impl_dx9.cpp +++ b/examples/directx9_example/imgui_impl_dx9.cpp @@ -1,5 +1,7 @@ // ImGui Win32 + DirectX9 binding -// In this binding, ImTextureID is used to store a 'LPDIRECT3DTEXTURE9' texture identifier. Read the FAQ about ImTextureID in imgui.cpp. + +// Implemented features: +// [X] User texture binding. Use 'LPDIRECT3DTEXTURE9' as ImTextureID. Read the FAQ about ImTextureID in imgui.cpp. // You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this. // If you use this binding you'll need to call 4 functions: ImGui_ImplXXXX_Init(), ImGui_ImplXXXX_NewFrame(), ImGui::Render() and ImGui_ImplXXXX_Shutdown(). diff --git a/examples/directx9_example/imgui_impl_dx9.h b/examples/directx9_example/imgui_impl_dx9.h index acaed5318b34..41fa743dace5 100644 --- a/examples/directx9_example/imgui_impl_dx9.h +++ b/examples/directx9_example/imgui_impl_dx9.h @@ -1,5 +1,7 @@ // ImGui Win32 + DirectX9 binding -// In this binding, ImTextureID is used to store a 'LPDIRECT3DTEXTURE9' texture identifier. Read the FAQ about ImTextureID in imgui.cpp. + +// Implemented features: +// [X] User texture binding. Use 'LPDIRECT3DTEXTURE9' as ImTextureID. Read the FAQ about ImTextureID in imgui.cpp. // You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this. // If you use this binding you'll need to call 4 functions: ImGui_ImplXXXX_Init(), ImGui_ImplXXXX_NewFrame(), ImGui::Render() and ImGui_ImplXXXX_Shutdown(). diff --git a/examples/marmalade_example/imgui_impl_marmalade.cpp b/examples/marmalade_example/imgui_impl_marmalade.cpp index 0bffb30d8bad..e8d60af96110 100644 --- a/examples/marmalade_example/imgui_impl_marmalade.cpp +++ b/examples/marmalade_example/imgui_impl_marmalade.cpp @@ -1,5 +1,7 @@ // ImGui Marmalade binding with IwGx -// In this binding, ImTextureID is used to store a 'CIwTexture*' texture identifier. Read the FAQ about ImTextureID in imgui.cpp. + +// Implemented features: +// [X] User texture binding. Use 'CIwTexture*' as ImTextureID. Read the FAQ about ImTextureID in imgui.cpp. // You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this. // If you use this binding you'll need to call 4 functions: ImGui_ImplXXXX_Init(), ImGui_ImplXXXX_NewFrame(), ImGui::Render() and ImGui_ImplXXXX_Shutdown(). diff --git a/examples/marmalade_example/imgui_impl_marmalade.h b/examples/marmalade_example/imgui_impl_marmalade.h index 5342cb7e0ba9..79b5e50a3918 100644 --- a/examples/marmalade_example/imgui_impl_marmalade.h +++ b/examples/marmalade_example/imgui_impl_marmalade.h @@ -1,5 +1,7 @@ // ImGui Marmalade binding with IwGx -// In this binding, ImTextureID is used to store a 'CIwTexture*' texture identifier. Read the FAQ about ImTextureID in imgui.cpp. + +// Implemented features: +// [X] User texture binding. Use 'CIwTexture*' as ImTextureID. Read the FAQ about ImTextureID in imgui.cpp. // You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this. // If you use this binding you'll need to call 4 functions: ImGui_ImplXXXX_Init(), ImGui_ImplXXXX_NewFrame(), ImGui::Render() and ImGui_ImplXXXX_Shutdown(). diff --git a/examples/opengl2_example/imgui_impl_glfw_gl2.cpp b/examples/opengl2_example/imgui_impl_glfw_gl2.cpp index 27052b60d70f..954fbcde4cf6 100644 --- a/examples/opengl2_example/imgui_impl_glfw_gl2.cpp +++ b/examples/opengl2_example/imgui_impl_glfw_gl2.cpp @@ -1,7 +1,9 @@ // ImGui GLFW binding with OpenGL (legacy, fixed pipeline) -// In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp. // (GLFW is a cross-platform general purpose library for handling windows, inputs, OpenGL/Vulkan graphics context creation, etc.) +// Implemented features: +// [X] User texture binding. Cast 'GLuint' OpenGL texture identifier as void*/ImTextureID. Read the FAQ about ImTextureID in imgui.cpp. + // **DO NOT USE THIS CODE IF YOUR CODE/ENGINE IS USING MODERN OPENGL (SHADERS, VBO, VAO, etc.)** // **Prefer using the code in the opengl3_example/ folder** // This code is mostly provided as a reference to learn how ImGui integration works, because it is shorter to read. diff --git a/examples/opengl2_example/imgui_impl_glfw_gl2.h b/examples/opengl2_example/imgui_impl_glfw_gl2.h index d04a84fa8a21..91d1e0873421 100644 --- a/examples/opengl2_example/imgui_impl_glfw_gl2.h +++ b/examples/opengl2_example/imgui_impl_glfw_gl2.h @@ -1,7 +1,9 @@ // ImGui GLFW binding with OpenGL (legacy, fixed pipeline) -// In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp. // (GLFW is a cross-platform general purpose library for handling windows, inputs, OpenGL/Vulkan graphics context creation, etc.) +// Implemented features: +// [X] User texture binding. Cast 'GLuint' OpenGL texture identifier as void*/ImTextureID. Read the FAQ about ImTextureID in imgui.cpp. + // **DO NOT USE THIS CODE IF YOUR CODE/ENGINE IS USING MODERN OPENGL (SHADERS, VBO, VAO, etc.)** // **Prefer using the code in the opengl3_example/ folder** // See imgui_impl_glfw.cpp for details. diff --git a/examples/opengl3_example/imgui_impl_glfw_gl3.cpp b/examples/opengl3_example/imgui_impl_glfw_gl3.cpp index 0b8e5d8300f5..dcd40772c833 100644 --- a/examples/opengl3_example/imgui_impl_glfw_gl3.cpp +++ b/examples/opengl3_example/imgui_impl_glfw_gl3.cpp @@ -1,8 +1,12 @@ // ImGui GLFW binding with OpenGL3 + shaders -// In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp. // (GLFW is a cross-platform general purpose library for handling windows, inputs, OpenGL/Vulkan graphics context creation, etc.) // (GL3W is a helper library to access OpenGL functions since there is no standard header to access modern OpenGL functions easily. Alternatives are GLEW, Glad, etc.) +// Implemented features: +// [X] User texture binding. Cast 'GLuint' OpenGL texture identifier as void*/ImTextureID. Read the FAQ about ImTextureID in imgui.cpp. +// [X] Keyboard navigation mapping. Enable with 'io.NavFlags |= ImGuiNavFlags_EnableKeyboard'. +// [X] Gamepad navigation mapping. Enable with 'io.NavFlags |= ImGuiNavFlags_EnableGamepad'. + // You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this. // If you use this binding you'll need to call 4 functions: ImGui_ImplXXXX_Init(), ImGui_ImplXXXX_NewFrame(), ImGui::Render() and ImGui_ImplXXXX_Shutdown(). // If you are new to ImGui, see examples/README.txt and documentation at the top of imgui.cpp. diff --git a/examples/opengl3_example/imgui_impl_glfw_gl3.h b/examples/opengl3_example/imgui_impl_glfw_gl3.h index 5f3043988e60..e7a4c2f650db 100644 --- a/examples/opengl3_example/imgui_impl_glfw_gl3.h +++ b/examples/opengl3_example/imgui_impl_glfw_gl3.h @@ -1,8 +1,12 @@ // ImGui GLFW binding with OpenGL3 + shaders -// In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp. // (GLFW is a cross-platform general purpose library for handling windows, inputs, OpenGL/Vulkan graphics context creation, etc.) // (GL3W is a helper library to access OpenGL functions since there is no standard header to access modern OpenGL functions easily. Alternatives are GLEW, Glad, etc.) +// Implemented features: +// [X] User texture binding. Cast 'GLuint' OpenGL texture identifier as void*/ImTextureID. Read the FAQ about ImTextureID in imgui.cpp. +// [X] Keyboard navigation mapping. Enable with 'io.NavFlags |= ImGuiNavFlags_EnableKeyboard'. +// [X] Gamepad navigation mapping. Enable with 'io.NavFlags |= ImGuiNavFlags_EnableGamepad'. + // You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this. // If you use this binding you'll need to call 4 functions: ImGui_ImplXXXX_Init(), ImGui_ImplXXXX_NewFrame(), ImGui::Render() and ImGui_ImplXXXX_Shutdown(). // If you are new to ImGui, see examples/README.txt and documentation at the top of imgui.cpp. diff --git a/examples/sdl_opengl2_example/imgui_impl_sdl_gl2.cpp b/examples/sdl_opengl2_example/imgui_impl_sdl_gl2.cpp index 801c433f08f8..83597d06b774 100644 --- a/examples/sdl_opengl2_example/imgui_impl_sdl_gl2.cpp +++ b/examples/sdl_opengl2_example/imgui_impl_sdl_gl2.cpp @@ -1,7 +1,9 @@ // ImGui SDL2 binding with OpenGL (legacy, fixed pipeline) -// In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp. // (SDL is a cross-platform general purpose library for handling windows, inputs, OpenGL/Vulkan graphics context creation, etc.) +// Implemented features: +// [X] User texture binding. Cast 'GLuint' OpenGL texture identifier as void*/ImTextureID. Read the FAQ about ImTextureID in imgui.cpp. + // **DO NOT USE THIS CODE IF YOUR CODE/ENGINE IS USING MODERN OPENGL (SHADERS, VBO, VAO, etc.)** // **Prefer using the code in the sdl_opengl3_example/ folder** // This code is mostly provided as a reference to learn how ImGui integration works, because it is shorter to read. diff --git a/examples/sdl_opengl2_example/imgui_impl_sdl_gl2.h b/examples/sdl_opengl2_example/imgui_impl_sdl_gl2.h index 32d7bc0e99ce..915ae52d7545 100644 --- a/examples/sdl_opengl2_example/imgui_impl_sdl_gl2.h +++ b/examples/sdl_opengl2_example/imgui_impl_sdl_gl2.h @@ -1,7 +1,9 @@ // ImGui SDL2 binding with OpenGL (legacy, fixed pipeline) -// In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp. // (SDL is a cross-platform general purpose library for handling windows, inputs, OpenGL/Vulkan graphics context creation, etc.) +// Implemented features: +// [X] User texture binding. Cast 'GLuint' OpenGL texture identifier as void*/ImTextureID. Read the FAQ about ImTextureID in imgui.cpp. + // **DO NOT USE THIS CODE IF YOUR CODE/ENGINE IS USING MODERN OPENGL (SHADERS, VBO, VAO, etc.)** // **Prefer using the code in the sdl_opengl3_example/ folder** // See imgui_impl_sdl.cpp for details. diff --git a/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.cpp b/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.cpp index 35d9cdde1313..c94bcdeaf737 100644 --- a/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.cpp +++ b/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.cpp @@ -1,8 +1,10 @@ // ImGui SDL2 binding with OpenGL3 -// In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp. // (SDL is a cross-platform general purpose library for handling windows, inputs, OpenGL/Vulkan graphics context creation, etc.) // (GL3W is a helper library to access OpenGL functions since there is no standard header to access modern OpenGL functions easily. Alternatives are GLEW, Glad, etc.) +// Implemented features: +// [X] User texture binding. Cast 'GLuint' OpenGL texture identifier as void*/ImTextureID. Read the FAQ about ImTextureID in imgui.cpp. + // You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this. // If you use this binding you'll need to call 4 functions: ImGui_ImplXXXX_Init(), ImGui_ImplXXXX_NewFrame(), ImGui::Render() and ImGui_ImplXXXX_Shutdown(). // If you are new to ImGui, see examples/README.txt and documentation at the top of imgui.cpp. diff --git a/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.h b/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.h index 543818664685..3f76e294223c 100644 --- a/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.h +++ b/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.h @@ -1,8 +1,10 @@ // ImGui SDL2 binding with OpenGL3 -// In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp. // (SDL is a cross-platform general purpose library for handling windows, inputs, OpenGL/Vulkan graphics context creation, etc.) // (GL3W is a helper library to access OpenGL functions since there is no standard header to access modern OpenGL functions easily. Alternatives are GLEW, Glad, etc.) +// Implemented features: +// [X] User texture binding. Cast 'GLuint' OpenGL texture identifier as void*/ImTextureID. Read the FAQ about ImTextureID in imgui.cpp. + // You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this. // If you use this binding you'll need to call 4 functions: ImGui_ImplXXXX_Init(), ImGui_ImplXXXX_NewFrame(), ImGui::Render() and ImGui_ImplXXXX_Shutdown(). // If you are new to ImGui, see examples/README.txt and documentation at the top of imgui.cpp. diff --git a/examples/vulkan_example/imgui_impl_glfw_vulkan.cpp b/examples/vulkan_example/imgui_impl_glfw_vulkan.cpp index 3748b504bb47..3edf20970944 100644 --- a/examples/vulkan_example/imgui_impl_glfw_vulkan.cpp +++ b/examples/vulkan_example/imgui_impl_glfw_vulkan.cpp @@ -1,5 +1,7 @@ // ImGui GLFW binding with Vulkan + shaders -// FIXME: Changes of ImTextureID aren't supported by this binding! Please, someone add it! + +// Missing features: +// [ ] User texture binding. Changes of ImTextureID aren't supported by this binding! See https://github.com/ocornut/imgui/pull/914 // You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this. // If you use this binding you'll need to call 5 functions: ImGui_ImplXXXX_Init(), ImGui_ImplXXX_CreateFontsTexture(), ImGui_ImplXXXX_NewFrame(), ImGui_ImplXXXX_Render() and ImGui_ImplXXXX_Shutdown(). diff --git a/examples/vulkan_example/imgui_impl_glfw_vulkan.h b/examples/vulkan_example/imgui_impl_glfw_vulkan.h index 0e5c96a87d76..766a9595444a 100644 --- a/examples/vulkan_example/imgui_impl_glfw_vulkan.h +++ b/examples/vulkan_example/imgui_impl_glfw_vulkan.h @@ -1,5 +1,7 @@ // ImGui GLFW binding with Vulkan + shaders -// FIXME: Changes of ImTextureID aren't supported by this binding! Please, someone add it! + +// Missing features: +// [ ] User texture binding. Changes of ImTextureID aren't supported by this binding! See https://github.com/ocornut/imgui/pull/914 // You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this. // If you use this binding you'll need to call 5 functions: ImGui_ImplXXXX_Init(), ImGui_ImplXXX_CreateFontsTexture(), ImGui_ImplXXXX_NewFrame(), ImGui_ImplXXXX_Render() and ImGui_ImplXXXX_Shutdown(). From 60fb7d31fde0dad94c48e5a2839acf09a10c5cf0 Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 5 Feb 2018 22:35:29 +0100 Subject: [PATCH 613/823] Examples: SDL2: Enabling vsync. Using scancode consistently, fixed keyboard weirdness. --- .../imgui_impl_sdl_gl2.cpp | 26 ++++++++++--------- examples/sdl_opengl2_example/main.cpp | 1 + .../imgui_impl_sdl_gl3.cpp | 26 ++++++++++--------- examples/sdl_opengl3_example/main.cpp | 1 + 4 files changed, 30 insertions(+), 24 deletions(-) diff --git a/examples/sdl_opengl2_example/imgui_impl_sdl_gl2.cpp b/examples/sdl_opengl2_example/imgui_impl_sdl_gl2.cpp index 801c433f08f8..a641ec198143 100644 --- a/examples/sdl_opengl2_example/imgui_impl_sdl_gl2.cpp +++ b/examples/sdl_opengl2_example/imgui_impl_sdl_gl2.cpp @@ -152,7 +152,8 @@ bool ImGui_ImplSdlGL2_ProcessEvent(SDL_Event* event) case SDL_KEYDOWN: case SDL_KEYUP: { - int key = event->key.keysym.sym & ~SDLK_SCANCODE_MASK; + int key = event->key.keysym.scancode; + IM_ASSERT(key >= 0 && key < IM_ARRAYSIZE(io.KeysDown)); io.KeysDown[key] = (event->type == SDL_KEYDOWN); io.KeyShift = ((SDL_GetModState() & KMOD_SHIFT) != 0); io.KeyCtrl = ((SDL_GetModState() & KMOD_CTRL) != 0); @@ -203,8 +204,9 @@ void ImGui_ImplSdlGL2_InvalidateDeviceObjects() bool ImGui_ImplSdlGL2_Init(SDL_Window* window) { + // Keyboard mapping. ImGui will use those indices to peek into the io.KeyDown[] array. ImGuiIO& io = ImGui::GetIO(); - io.KeyMap[ImGuiKey_Tab] = SDLK_TAB; // Keyboard mapping. ImGui will use those indices to peek into the io.KeyDown[] array. + io.KeyMap[ImGuiKey_Tab] = SDL_SCANCODE_TAB; io.KeyMap[ImGuiKey_LeftArrow] = SDL_SCANCODE_LEFT; io.KeyMap[ImGuiKey_RightArrow] = SDL_SCANCODE_RIGHT; io.KeyMap[ImGuiKey_UpArrow] = SDL_SCANCODE_UP; @@ -214,16 +216,16 @@ bool ImGui_ImplSdlGL2_Init(SDL_Window* window) io.KeyMap[ImGuiKey_Home] = SDL_SCANCODE_HOME; io.KeyMap[ImGuiKey_End] = SDL_SCANCODE_END; io.KeyMap[ImGuiKey_Insert] = SDL_SCANCODE_INSERT; - io.KeyMap[ImGuiKey_Delete] = SDLK_DELETE; - io.KeyMap[ImGuiKey_Backspace] = SDLK_BACKSPACE; - io.KeyMap[ImGuiKey_Enter] = SDLK_RETURN; - io.KeyMap[ImGuiKey_Escape] = SDLK_ESCAPE; - io.KeyMap[ImGuiKey_A] = SDLK_a; - io.KeyMap[ImGuiKey_C] = SDLK_c; - io.KeyMap[ImGuiKey_V] = SDLK_v; - io.KeyMap[ImGuiKey_X] = SDLK_x; - io.KeyMap[ImGuiKey_Y] = SDLK_y; - io.KeyMap[ImGuiKey_Z] = SDLK_z; + io.KeyMap[ImGuiKey_Delete] = SDL_SCANCODE_DELETE; + io.KeyMap[ImGuiKey_Backspace] = SDL_SCANCODE_BACKSPACE; + io.KeyMap[ImGuiKey_Enter] = SDL_SCANCODE_RETURN; + io.KeyMap[ImGuiKey_Escape] = SDL_SCANCODE_ESCAPE; + io.KeyMap[ImGuiKey_A] = SDL_SCANCODE_A; + io.KeyMap[ImGuiKey_C] = SDL_SCANCODE_C; + io.KeyMap[ImGuiKey_V] = SDL_SCANCODE_V; + io.KeyMap[ImGuiKey_X] = SDL_SCANCODE_X; + io.KeyMap[ImGuiKey_Y] = SDL_SCANCODE_Y; + io.KeyMap[ImGuiKey_Z] = SDL_SCANCODE_Z; io.RenderDrawListsFn = ImGui_ImplSdlGL2_RenderDrawLists; // Alternatively you can set this to NULL and call ImGui::GetDrawData() after ImGui::Render() to get the same ImDrawData pointer. io.SetClipboardTextFn = ImGui_ImplSdlGL2_SetClipboardText; diff --git a/examples/sdl_opengl2_example/main.cpp b/examples/sdl_opengl2_example/main.cpp index 10e66e8083ba..becf841a278d 100644 --- a/examples/sdl_opengl2_example/main.cpp +++ b/examples/sdl_opengl2_example/main.cpp @@ -31,6 +31,7 @@ int main(int, char**) SDL_GetCurrentDisplayMode(0, ¤t); SDL_Window *window = SDL_CreateWindow("ImGui SDL2+OpenGL example", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 1280, 720, SDL_WINDOW_OPENGL|SDL_WINDOW_RESIZABLE); SDL_GLContext glcontext = SDL_GL_CreateContext(window); + SDL_GL_SetSwapInterval(1); // Enable vsync // Setup ImGui binding ImGui_ImplSdlGL2_Init(window); diff --git a/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.cpp b/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.cpp index 35d9cdde1313..8368e4af24b8 100644 --- a/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.cpp +++ b/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.cpp @@ -174,7 +174,8 @@ bool ImGui_ImplSdlGL3_ProcessEvent(SDL_Event* event) case SDL_KEYDOWN: case SDL_KEYUP: { - int key = event->key.keysym.sym & ~SDLK_SCANCODE_MASK; + int key = event->key.keysym.scancode; + IM_ASSERT(key >= 0 && key < IM_ARRAYSIZE(io.KeysDown)); io.KeysDown[key] = (event->type == SDL_KEYDOWN); io.KeyShift = ((SDL_GetModState() & KMOD_SHIFT) != 0); io.KeyCtrl = ((SDL_GetModState() & KMOD_CTRL) != 0); @@ -314,8 +315,9 @@ void ImGui_ImplSdlGL3_InvalidateDeviceObjects() bool ImGui_ImplSdlGL3_Init(SDL_Window* window) { + // Keyboard mapping. ImGui will use those indices to peek into the io.KeyDown[] array. ImGuiIO& io = ImGui::GetIO(); - io.KeyMap[ImGuiKey_Tab] = SDLK_TAB; // Keyboard mapping. ImGui will use those indices to peek into the io.KeyDown[] array. + io.KeyMap[ImGuiKey_Tab] = SDL_SCANCODE_TAB; io.KeyMap[ImGuiKey_LeftArrow] = SDL_SCANCODE_LEFT; io.KeyMap[ImGuiKey_RightArrow] = SDL_SCANCODE_RIGHT; io.KeyMap[ImGuiKey_UpArrow] = SDL_SCANCODE_UP; @@ -325,16 +327,16 @@ bool ImGui_ImplSdlGL3_Init(SDL_Window* window) io.KeyMap[ImGuiKey_Home] = SDL_SCANCODE_HOME; io.KeyMap[ImGuiKey_End] = SDL_SCANCODE_END; io.KeyMap[ImGuiKey_Insert] = SDL_SCANCODE_INSERT; - io.KeyMap[ImGuiKey_Delete] = SDLK_DELETE; - io.KeyMap[ImGuiKey_Backspace] = SDLK_BACKSPACE; - io.KeyMap[ImGuiKey_Enter] = SDLK_RETURN; - io.KeyMap[ImGuiKey_Escape] = SDLK_ESCAPE; - io.KeyMap[ImGuiKey_A] = SDLK_a; - io.KeyMap[ImGuiKey_C] = SDLK_c; - io.KeyMap[ImGuiKey_V] = SDLK_v; - io.KeyMap[ImGuiKey_X] = SDLK_x; - io.KeyMap[ImGuiKey_Y] = SDLK_y; - io.KeyMap[ImGuiKey_Z] = SDLK_z; + io.KeyMap[ImGuiKey_Delete] = SDL_SCANCODE_DELETE; + io.KeyMap[ImGuiKey_Backspace] = SDL_SCANCODE_BACKSPACE; + io.KeyMap[ImGuiKey_Enter] = SDL_SCANCODE_RETURN; + io.KeyMap[ImGuiKey_Escape] = SDL_SCANCODE_ESCAPE; + io.KeyMap[ImGuiKey_A] = SDL_SCANCODE_A; + io.KeyMap[ImGuiKey_C] = SDL_SCANCODE_C; + io.KeyMap[ImGuiKey_V] = SDL_SCANCODE_V; + io.KeyMap[ImGuiKey_X] = SDL_SCANCODE_X; + io.KeyMap[ImGuiKey_Y] = SDL_SCANCODE_Y; + io.KeyMap[ImGuiKey_Z] = SDL_SCANCODE_Z; io.RenderDrawListsFn = ImGui_ImplSdlGL3_RenderDrawLists; // Alternatively you can set this to NULL and call ImGui::GetDrawData() after ImGui::Render() to get the same ImDrawData pointer. io.SetClipboardTextFn = ImGui_ImplSdlGL3_SetClipboardText; diff --git a/examples/sdl_opengl3_example/main.cpp b/examples/sdl_opengl3_example/main.cpp index 2d7e85977bd6..4bab49168e74 100644 --- a/examples/sdl_opengl3_example/main.cpp +++ b/examples/sdl_opengl3_example/main.cpp @@ -30,6 +30,7 @@ int main(int, char**) SDL_GetCurrentDisplayMode(0, ¤t); SDL_Window *window = SDL_CreateWindow("ImGui SDL2+OpenGL3 example", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 1280, 720, SDL_WINDOW_OPENGL|SDL_WINDOW_RESIZABLE); SDL_GLContext glcontext = SDL_GL_CreateContext(window); + SDL_GL_SetSwapInterval(1); // Enable vsync gl3wInit(); // Setup ImGui binding From fcf1c9d151c5a53ded2982ba3dc7109da071bcb4 Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 5 Feb 2018 23:09:14 +0100 Subject: [PATCH 614/823] Examples: SDL: Using SDL_GetPerformanceCounter() / SDL_GetPerformanceFrequency() to handle framerate over 1000 fps properly. Noticed bad inputs artefacts in Nav branch at 2000 fps without this. (#996) --- examples/sdl_opengl2_example/imgui_impl_sdl_gl2.cpp | 10 +++++----- examples/sdl_opengl3_example/imgui_impl_sdl_gl3.cpp | 10 +++++----- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/examples/sdl_opengl2_example/imgui_impl_sdl_gl2.cpp b/examples/sdl_opengl2_example/imgui_impl_sdl_gl2.cpp index a641ec198143..4cbe0030b34a 100644 --- a/examples/sdl_opengl2_example/imgui_impl_sdl_gl2.cpp +++ b/examples/sdl_opengl2_example/imgui_impl_sdl_gl2.cpp @@ -22,7 +22,7 @@ #include "imgui_impl_sdl_gl2.h" // Data -static double g_Time = 0.0f; +static Uint64 g_Time = 0; static bool g_MousePressed[3] = { false, false, false }; static GLuint g_FontTexture = 0; @@ -265,10 +265,10 @@ void ImGui_ImplSdlGL2_NewFrame(SDL_Window *window) io.DisplaySize = ImVec2((float)w, (float)h); io.DisplayFramebufferScale = ImVec2(w > 0 ? ((float)display_w / w) : 0, h > 0 ? ((float)display_h / h) : 0); - // Setup time step - Uint32 time = SDL_GetTicks(); - double current_time = time / 1000.0; - io.DeltaTime = g_Time > 0.0 ? (float)(current_time - g_Time) : (float)(1.0f / 60.0f); + // Setup time step (we don't use SDL_GetTicks() because it is using millisecond resolution) + static Uint64 frequency = SDL_GetPerformanceFrequency(); + Uint64 current_time = SDL_GetPerformanceCounter(); + io.DeltaTime = g_Time > 0 ? (float)((double)(current_time - g_Time) / frequency) : (float)(1.0f / 60.0f); g_Time = current_time; // Setup mouse inputs (we already got mouse wheel, keyboard keys & characters from our event handler) diff --git a/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.cpp b/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.cpp index 8368e4af24b8..6cec915238f1 100644 --- a/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.cpp +++ b/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.cpp @@ -17,7 +17,7 @@ #include // This example is using gl3w to access OpenGL functions (because it is small). You may use glew/glad/glLoadGen/etc. whatever already works for you. // Data -static double g_Time = 0.0f; +static Uint64 g_Time = 0.0f; static bool g_MousePressed[3] = { false, false, false }; static GLuint g_FontTexture = 0; static int g_ShaderHandle = 0, g_VertHandle = 0, g_FragHandle = 0; @@ -376,10 +376,10 @@ void ImGui_ImplSdlGL3_NewFrame(SDL_Window* window) io.DisplaySize = ImVec2((float)w, (float)h); io.DisplayFramebufferScale = ImVec2(w > 0 ? ((float)display_w / w) : 0, h > 0 ? ((float)display_h / h) : 0); - // Setup time step - Uint32 time = SDL_GetTicks(); - double current_time = time / 1000.0; - io.DeltaTime = g_Time > 0.0 ? (float)(current_time - g_Time) : (float)(1.0f / 60.0f); + // Setup time step (we don't use SDL_GetTicks() because it is using millisecond resolution) + static Uint64 frequency = SDL_GetPerformanceFrequency(); + Uint64 current_time = SDL_GetPerformanceCounter(); + io.DeltaTime = g_Time > 0 ? (float)((double)(current_time - g_Time) / frequency) : (float)(1.0f / 60.0f); g_Time = current_time; // Setup mouse inputs (we already got mouse wheel, keyboard keys & characters from our event handler) From 4b49f03a40a4aadfa8d586c184d098eda539f5bf Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 5 Feb 2018 23:16:40 +0100 Subject: [PATCH 615/823] Examples: SDL+GL3: Added Navigation keyboard mapping. (#787) --- .../imgui_impl_sdl_gl3.cpp | 24 +++++++++++++++++++ .../sdl_opengl3_example/imgui_impl_sdl_gl3.h | 1 + examples/sdl_opengl3_example/main.cpp | 3 ++- 3 files changed, 27 insertions(+), 1 deletion(-) diff --git a/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.cpp b/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.cpp index 06d62867ab69..0619b6ad0a39 100644 --- a/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.cpp +++ b/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.cpp @@ -4,6 +4,7 @@ // Implemented features: // [X] User texture binding. Cast 'GLuint' OpenGL texture identifier as void*/ImTextureID. Read the FAQ about ImTextureID in imgui.cpp. +// [X] Keyboard navigation mapping. Enable with 'io.NavFlags |= ImGuiNavFlags_EnableKeyboard'. // You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this. // If you use this binding you'll need to call 4 functions: ImGui_ImplXXXX_Init(), ImGui_ImplXXXX_NewFrame(), ImGui::Render() and ImGui_ImplXXXX_Shutdown(). @@ -412,6 +413,29 @@ void ImGui_ImplSdlGL3_NewFrame(SDL_Window* window) // Hide OS mouse cursor if ImGui is drawing it SDL_ShowCursor(io.MouseDrawCursor ? 0 : 1); + // Gamepad/keyboard navigation mapping [BETA] + memset(io.NavInputs, 0, sizeof(io.NavInputs)); + if (io.NavFlags & ImGuiNavFlags_EnableKeyboard) + { + // Update keyboard + // FIXME-NAV: We are still using some of the ImGuiNavInput_PadXXX enums as keyboard support is incomplete. + #define MAP_KEY(NAV_NO, KEY_NO) { if (io.KeysDown[KEY_NO]) io.NavInputs[NAV_NO] = 1.0f; } + MAP_KEY(ImGuiNavInput_KeyLeft, SDL_SCANCODE_LEFT); + MAP_KEY(ImGuiNavInput_KeyRight, SDL_SCANCODE_RIGHT); + MAP_KEY(ImGuiNavInput_KeyUp, SDL_SCANCODE_UP); + MAP_KEY(ImGuiNavInput_KeyDown, SDL_SCANCODE_DOWN); + MAP_KEY(ImGuiNavInput_KeyMenu, SDL_SCANCODE_LALT); + MAP_KEY(ImGuiNavInput_KeyMenu, SDL_SCANCODE_RALT); + MAP_KEY(ImGuiNavInput_PadActivate, SDL_SCANCODE_SPACE); + MAP_KEY(ImGuiNavInput_PadCancel, SDL_SCANCODE_ESCAPE); + MAP_KEY(ImGuiNavInput_PadInput, SDL_SCANCODE_RETURN); + MAP_KEY(ImGuiNavInput_PadTweakSlow, SDL_SCANCODE_LALT); + MAP_KEY(ImGuiNavInput_PadTweakSlow, SDL_SCANCODE_LALT); + MAP_KEY(ImGuiNavInput_PadTweakFast, SDL_SCANCODE_LSHIFT); + MAP_KEY(ImGuiNavInput_PadTweakFast, SDL_SCANCODE_RSHIFT); + #undef MAP_KEY + } + // Start the frame. This call will update the io.WantCaptureMouse, io.WantCaptureKeyboard flag that you can use to dispatch inputs (or not) to your application. ImGui::NewFrame(); } diff --git a/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.h b/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.h index 3f76e294223c..fc7e1e96ef70 100644 --- a/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.h +++ b/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.h @@ -4,6 +4,7 @@ // Implemented features: // [X] User texture binding. Cast 'GLuint' OpenGL texture identifier as void*/ImTextureID. Read the FAQ about ImTextureID in imgui.cpp. +// [X] Keyboard navigation mapping. Enable with 'io.NavFlags |= ImGuiNavFlags_EnableKeyboard'. // You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this. // If you use this binding you'll need to call 4 functions: ImGui_ImplXXXX_Init(), ImGui_ImplXXXX_NewFrame(), ImGui::Render() and ImGui_ImplXXXX_Shutdown(). diff --git a/examples/sdl_opengl3_example/main.cpp b/examples/sdl_opengl3_example/main.cpp index 4bab49168e74..7cd4ca98999f 100644 --- a/examples/sdl_opengl3_example/main.cpp +++ b/examples/sdl_opengl3_example/main.cpp @@ -34,7 +34,9 @@ int main(int, char**) gl3wInit(); // Setup ImGui binding + ImGuiIO& io = ImGui::GetIO(); (void)io; ImGui_ImplSdlGL3_Init(window); + //io.NavFlags |= ImGuiNavFlags_EnableKeyboard; // Setup style ImGui::StyleColorsDark(); @@ -47,7 +49,6 @@ int main(int, char**) // - The fonts will be rasterized at a given size (w/ oversampling) and stored into a texture when calling ImFontAtlas::Build()/GetTexDataAsXXXX(), which ImGui_ImplXXXX_NewFrame below will call. // - Read 'misc/fonts/README.txt' for more instructions and details. // - Remember that in C/C++ if you want to include a backslash \ in a string literal you need to write a double backslash \\ ! - //ImGuiIO& io = ImGui::GetIO(); //io.Fonts->AddFontDefault(); //io.Fonts->AddFontFromFileTTF("../../misc/fonts/Roboto-Medium.ttf", 16.0f); //io.Fonts->AddFontFromFileTTF("../../misc/fonts/Cousine-Regular.ttf", 15.0f); From 0c0d811859aeede5d0dca5d3d7e5026b8d5ee5a8 Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 5 Feb 2018 23:53:40 +0100 Subject: [PATCH 616/823] Nav: SetItemDefaultFocus() doesn't make the navigation cursorr highlight visible. Renamed NavInitResultExplicit to NavInitRequestFromMove. (#787) --- TODO.txt | 1 + imgui.cpp | 11 +++++------ imgui_internal.h | 4 ++-- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/TODO.txt b/TODO.txt index 6f6ab7cc3457..fe9b6ccecf98 100644 --- a/TODO.txt +++ b/TODO.txt @@ -231,6 +231,7 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i - font: (api breaking) removed "TTF" from symbol names. also because it now supports OTF. - nav: integrate navigation branch into master. (#787) + - nav: allow input system to be be more tolerant of io.DeltaTime=0.0f - nav: Left within a tree node block as a fallback. - nav: Esc on a flattened child - nav: menus: allow pressing Menu to leave a sub-menu. diff --git a/imgui.cpp b/imgui.cpp index bb78b9a5ff66..a63073b952c2 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2656,8 +2656,8 @@ void ImGui::NavInitWindow(ImGuiWindow* window, bool force_reinit) { SetNavID(0, g.NavLayer); g.NavInitRequest = true; + g.NavInitRequestFromMove = false; g.NavInitResultId = 0; - g.NavInitResultExplicit = false; g.NavInitResultRectRel = ImRect(); NavUpdateAnyRequestFlag(); } @@ -2929,18 +2929,18 @@ static void ImGui::NavUpdate() #endif // Process navigation init request (select first/default focus) - if (g.NavInitResultId != 0 && (!g.NavDisableHighlight || g.NavInitResultExplicit)) + if (g.NavInitResultId != 0 && (!g.NavDisableHighlight || g.NavInitRequestFromMove)) { // Apply result from previous navigation init request (will typically select the first item, unless SetItemDefaultFocus() has been called) IM_ASSERT(g.NavWindow); - if (g.NavInitResultExplicit) + if (g.NavInitRequestFromMove) SetNavIDAndMoveMouse(g.NavInitResultId, g.NavLayer, g.NavInitResultRectRel); else SetNavID(g.NavInitResultId, g.NavLayer); g.NavWindow->NavRectRel[g.NavLayer] = g.NavInitResultRectRel; } g.NavInitRequest = false; - g.NavInitResultExplicit = false; + g.NavInitRequestFromMove = false; g.NavInitResultId = 0; g.NavJustMovedToId = 0; @@ -3098,7 +3098,7 @@ static void ImGui::NavUpdate() // If we initiate a movement request and have no current NavId, we initiate a InitDefautRequest that will be used as a fallback if the direction fails to find a match if (g.NavMoveRequest && g.NavId == 0) { - g.NavInitRequest = g.NavInitResultExplicit = true; + g.NavInitRequest = g.NavInitRequestFromMove = true; g.NavInitResultId = 0; g.NavDisableHighlight = false; } @@ -7147,7 +7147,6 @@ void ImGui::SetItemDefaultFocus() if (g.NavWindow == window->NavRootWindow && (g.NavInitRequest || g.NavInitResultId != 0) && g.NavLayer == g.NavWindow->DC.NavLayerCurrent) { g.NavInitRequest = false; - g.NavInitResultExplicit = true; g.NavInitResultId = g.NavWindow->DC.LastItemId; g.NavInitResultRectRel = ImRect(g.NavWindow->DC.LastItemRect.Min - g.NavWindow->Pos, g.NavWindow->DC.LastItemRect.Max - g.NavWindow->Pos); NavUpdateAnyRequestFlag(); diff --git a/imgui_internal.h b/imgui_internal.h index 785b68079e9d..d2183b92b3dc 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -630,9 +630,9 @@ struct ImGuiContext bool NavDisableMouseHover; // When user starts using gamepad/keyboard, we hide mouse hovering highlight until mouse is touched again. bool NavAnyRequest; // ~~ NavMoveRequest || NavInitRequest bool NavInitRequest; // Init request for appearing window to select first item + bool NavInitRequestFromMove; ImGuiID NavInitResultId; ImRect NavInitResultRectRel; - bool NavInitResultExplicit; // Whether the result was explicitly requested with SetItemDefaultFocus() bool NavMoveFromClampedRefRect; // Set by manual scrolling, if we scroll to a point where NavId isn't visible we reset navigation from visible items bool NavMoveRequest; // Move request for this frame ImGuiNavForward NavMoveRequestForward; // None / ForwardQueued / ForwardActive (this is used to navigate sibling parent menus from a child menu) @@ -747,8 +747,8 @@ struct ImGuiContext NavDisableMouseHover = false; NavAnyRequest = false; NavInitRequest = false; + NavInitRequestFromMove = false; NavInitResultId = 0; - NavInitResultExplicit = false; NavMoveFromClampedRefRect = false; NavMoveRequest = false; NavMoveRequestForward = ImGuiNavForward_None; From ce2b8d3255fb2ff66b8ab924bf2e9022c8385740 Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 6 Feb 2018 13:16:44 +0100 Subject: [PATCH 617/823] Nav: Comments, removed extraneous parameter. --- imgui.cpp | 2 +- imgui_internal.h | 5 ++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index a63073b952c2..2890117b84fb 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -8701,7 +8701,7 @@ bool ImGui::VSliderFloat(const char* label, const ImVec2& size, float* v, float const ImRect bb(frame_bb.Min, frame_bb.Max + ImVec2(label_size.x > 0.0f ? style.ItemInnerSpacing.x + label_size.x : 0.0f, 0.0f)); ItemSize(bb, style.FramePadding.y); - if (!ItemAdd(frame_bb, id, &frame_bb)) + if (!ItemAdd(frame_bb, id)) return false; const bool hovered = ItemHoverable(frame_bb, id); diff --git a/imgui_internal.h b/imgui_internal.h index d2183b92b3dc..e17e986e8d46 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -625,7 +625,7 @@ struct ImGuiContext int NavLayer; // Layer we are navigating on. For now the system is hard-coded for 0=main contents and 1=menu/title bar, may expose layers later. int NavIdTabCounter; // == NavWindow->DC.FocusIdxTabCounter at time of NavId processing bool NavIdIsAlive; // Nav widget has been seen this frame ~~ NavRefRectRel is valid - bool NavMousePosDirty; // When set we will update mouse position if (NavFlags & ImGuiNavFlags_MoveMouse) if set + bool NavMousePosDirty; // When set we will update mouse position if (NavFlags & ImGuiNavFlags_MoveMouse) if set (NB: this not enabled by default) bool NavDisableHighlight; // When user starts using mouse, we hide gamepad/keyboard highlight (nb: but they are still available, which is why NavDisableHighlight isn't always != NavDisableMouseHover) bool NavDisableMouseHover; // When user starts using gamepad/keyboard, we hide mouse hovering highlight until mouse is touched again. bool NavAnyRequest; // ~~ NavMoveRequest || NavInitRequest @@ -636,8 +636,7 @@ struct ImGuiContext bool NavMoveFromClampedRefRect; // Set by manual scrolling, if we scroll to a point where NavId isn't visible we reset navigation from visible items bool NavMoveRequest; // Move request for this frame ImGuiNavForward NavMoveRequestForward; // None / ForwardQueued / ForwardActive (this is used to navigate sibling parent menus from a child menu) - ImGuiDir NavMoveDir; // Direction of the move request (left/right/up/down) - ImGuiDir NavMoveDirLast; // Direction of the previous move request + ImGuiDir NavMoveDir, NavMoveDirLast; // Direction of the move request (left/right/up/down), direction of the previous move request ImGuiNavMoveResult NavMoveResultLocal; // Best move request candidate within NavWindow ImGuiNavMoveResult NavMoveResultOther; // Best move request candidate within NavWindow's flattened hierarchy (when using the NavFlattened flag) From e6926d9f7c6febb64e9c8458fb8e1c0de321d576 Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 6 Feb 2018 13:34:41 +0100 Subject: [PATCH 618/823] Internals: Refactored bool LastItemRectHovered into flags. (#1597) --- imgui.cpp | 17 +++++++++-------- imgui_internal.h | 24 ++++++++++++++++-------- 2 files changed, 25 insertions(+), 16 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 20ee693e5eb7..6b107afd1a3e 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2035,13 +2035,14 @@ bool ImGui::ItemAdd(const ImRect& bb, ImGuiID id) const bool is_clipped = IsClippedEx(bb, id, false); window->DC.LastItemId = id; window->DC.LastItemRect = bb; - window->DC.LastItemRectHoveredRect = false; + window->DC.LastItemStatusFlags = 0; if (is_clipped) return false; //if (g.IO.KeyAlt) window->DrawList->AddRect(bb.Min, bb.Max, IM_COL32(255,255,0,120)); // [DEBUG] // We need to calculate this now to take account of the current clipping rectangle (as items like Selectable may change them) - window->DC.LastItemRectHoveredRect = IsMouseHoveringRect(bb.Min, bb.Max); + if (IsMouseHoveringRect(bb.Min, bb.Max)) + window->DC.LastItemStatusFlags |= ImGuiItemStatusFlags_HoveredRect; return true; } @@ -2054,7 +2055,7 @@ bool ImGui::IsItemHovered(ImGuiHoveredFlags flags) ImGuiWindow* window = g.CurrentWindow; // Test for bounding box overlap, as updated as ItemAdd() - if (!window->DC.LastItemRectHoveredRect) + if (!(window->DC.LastItemStatusFlags & ImGuiItemStatusFlags_HoveredRect)) return false; IM_ASSERT((flags & (ImGuiHoveredFlags_RootWindow | ImGuiHoveredFlags_ChildWindows)) == 0); // Flags not supported by this function @@ -4970,8 +4971,8 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) // After Begin() we fill the last item / hovered data using the title bar data. Make that a standard behavior (to allow usage of context menus on title bar only, etc.). window->DC.LastItemId = window->MoveId; + window->DC.LastItemStatusFlags = IsMouseHoveringRect(title_bar_rect.Min, title_bar_rect.Max, false) ? ImGuiItemStatusFlags_HoveredRect : 0; window->DC.LastItemRect = title_bar_rect; - window->DC.LastItemRectHoveredRect = IsMouseHoveringRect(title_bar_rect.Min, title_bar_rect.Max, false); } // Inner clipping rectangle @@ -10283,7 +10284,7 @@ bool ImGui::ColorEdit4(const char* label, float col[4], ImGuiColorEditFlags flag EndGroup(); // Drag and Drop Target - if (window->DC.LastItemRectHoveredRect && BeginDragDropTarget()) // NB: The LastItemRectHoveredRect test is merely an optional micro-optimization + if ((window->DC.LastItemStatusFlags & ImGuiItemStatusFlags_HoveredRect) && BeginDragDropTarget()) // NB: The flag test is merely an optional micro-optimization, BeginDragDropTarget() does the same test. { if (const ImGuiPayload* payload = AcceptDragDropPayload(IMGUI_PAYLOAD_TYPE_COLOR_3F)) { @@ -11337,7 +11338,7 @@ bool ImGui::BeginDragDropSource(ImGuiDragDropFlags flags, int mouse_button) // We build a throwaway ID based on current ID stack + relative AABB of items in window. // THE IDENTIFIER WON'T SURVIVE ANY REPOSITIONING OF THE WIDGET, so if your widget moves your dragging operation will be canceled. // We don't need to maintain/call ClearActiveID() as releasing the button will early out this function and trigger !ActiveIdIsAlive. - bool is_hovered = window->DC.LastItemRectHoveredRect; + bool is_hovered = (window->DC.LastItemStatusFlags & ImGuiItemStatusFlags_HoveredRect) != 0; if (!is_hovered && (g.ActiveId == 0 || g.ActiveIdWindow != window)) return false; source_id = window->DC.LastItemId = window->GetIDFromRectangle(window->DC.LastItemRect); @@ -11388,7 +11389,7 @@ bool ImGui::BeginDragDropSource(ImGuiDragDropFlags flags, int mouse_button) } if (!(flags & ImGuiDragDropFlags_SourceNoDisableHover) && !(flags & ImGuiDragDropFlags_SourceExtern)) - window->DC.LastItemRectHoveredRect = false; + window->DC.LastItemStatusFlags &= ~ImGuiItemStatusFlags_HoveredRect; return true; } @@ -11485,7 +11486,7 @@ bool ImGui::BeginDragDropTarget() return false; ImGuiWindow* window = g.CurrentWindow; - if (!window->DC.LastItemRectHoveredRect) + if (!(window->DC.LastItemStatusFlags & ImGuiItemStatusFlags_HoveredRect)) return false; if (g.HoveredWindow == NULL || window->RootWindow != g.HoveredWindow->RootWindow) return false; diff --git a/imgui_internal.h b/imgui_internal.h index f904cbcf7768..e80c5297ced9 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -45,6 +45,7 @@ struct ImGuiWindowSettings; typedef int ImGuiLayoutType; // enum: horizontal or vertical // enum ImGuiLayoutType_ typedef int ImGuiButtonFlags; // flags: for ButtonEx(), ButtonBehavior() // enum ImGuiButtonFlags_ typedef int ImGuiItemFlags; // flags: for PushItemFlag() // enum ImGuiItemFlags_ +typedef int ImGuiItemStatusFlags; // flags: storage for DC.LastItemXXX // enum ImGuiItemStatusFlags_ typedef int ImGuiSeparatorFlags; // flags: for Separator() - internal // enum ImGuiSeparatorFlags_ typedef int ImGuiSliderFlags; // flags: for SliderBehavior() // enum ImGuiSliderFlags_ @@ -216,6 +217,12 @@ enum ImGuiSeparatorFlags_ ImGuiSeparatorFlags_Vertical = 1 << 1 }; +// Storage for LastItem data +enum ImGuiItemStatusFlags_ +{ + ImGuiItemStatusFlags_HoveredRect = 1 << 0 +}; + // FIXME: this is in development, not exposed/functional as a generic feature yet. enum ImGuiLayoutType_ { @@ -673,6 +680,7 @@ struct ImGuiContext }; // Transient per-window flags, reset at the beginning of the frame. For child window, inherited from parent on first Begin(). +// This is going to be exposed in imgui.h when stabilized enough. enum ImGuiItemFlags_ { ImGuiItemFlags_AllowKeyboardFocus = 1 << 0, // true @@ -699,8 +707,8 @@ struct IMGUI_API ImGuiDrawContext float LogLinePosY; int TreeDepth; ImGuiID LastItemId; - ImRect LastItemRect; - bool LastItemRectHoveredRect; + ImGuiItemStatusFlags LastItemStatusFlags; + ImRect LastItemRect; // Interaction rect bool MenuBarAppending; float MenuBarOffsetX; ImVector ChildWindows; @@ -730,8 +738,8 @@ struct IMGUI_API ImGuiDrawContext LogLinePosY = -1.0f; TreeDepth = 0; LastItemId = 0; + LastItemStatusFlags = 0; LastItemRect = ImRect(); - LastItemRectHoveredRect = false; MenuBarAppending = false; MenuBarOffsetX = 0.0f; StateStorage = NULL; @@ -838,13 +846,13 @@ struct IMGUI_API ImGuiWindow // Backup and restore just enough data to be able to use IsItemHovered() on item A after another B in the same window has overwritten the data. struct ImGuiItemHoveredDataBackup { - ImGuiID LastItemId; - ImRect LastItemRect; - bool LastItemRectHoveredRect; + ImGuiID LastItemId; + ImGuiItemStatusFlags LastItemFlags; + ImRect LastItemRect; ImGuiItemHoveredDataBackup() { Backup(); } - void Backup() { ImGuiWindow* window = GImGui->CurrentWindow; LastItemId = window->DC.LastItemId; LastItemRect = window->DC.LastItemRect; LastItemRectHoveredRect = window->DC.LastItemRectHoveredRect; } - void Restore() const { ImGuiWindow* window = GImGui->CurrentWindow; window->DC.LastItemId = LastItemId; window->DC.LastItemRect = LastItemRect; window->DC.LastItemRectHoveredRect = LastItemRectHoveredRect; } + void Backup() { ImGuiWindow* window = GImGui->CurrentWindow; LastItemId = window->DC.LastItemId; LastItemFlags = window->DC.LastItemStatusFlags; LastItemRect = window->DC.LastItemRect; } + void Restore() const { ImGuiWindow* window = GImGui->CurrentWindow; window->DC.LastItemId = LastItemId; window->DC.LastItemStatusFlags = LastItemFlags; window->DC.LastItemRect = LastItemRect; } }; //----------------------------------------------------------------------------- From c6ba7c8231e20ea225ba466400f254b01aca7832 Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 6 Feb 2018 13:41:46 +0100 Subject: [PATCH 619/823] Internals: TreeNode: Renaming local to be more consistent with other widgets. --- imgui.cpp | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 6b107afd1a3e..a2db61ccc8f4 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -6741,12 +6741,12 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l // We vertically grow up to current line height up the typical widget height. const float text_base_offset_y = ImMax(padding.y, window->DC.CurrentLineTextBaseOffset); // Latch before ItemSize changes it const float frame_height = ImMax(ImMin(window->DC.CurrentLineHeight, g.FontSize + style.FramePadding.y*2), label_size.y + padding.y*2); - ImRect bb = ImRect(window->DC.CursorPos, ImVec2(window->Pos.x + GetContentRegionMax().x, window->DC.CursorPos.y + frame_height)); + ImRect frame_bb = ImRect(window->DC.CursorPos, ImVec2(window->Pos.x + GetContentRegionMax().x, window->DC.CursorPos.y + frame_height)); if (display_frame) { // Framed header expand a little outside the default padding - bb.Min.x -= (float)(int)(window->WindowPadding.x*0.5f) - 1; - bb.Max.x += (float)(int)(window->WindowPadding.x*0.5f) - 1; + frame_bb.Min.x -= (float)(int)(window->WindowPadding.x*0.5f) - 1; + frame_bb.Max.x += (float)(int)(window->WindowPadding.x*0.5f) - 1; } const float text_offset_x = (g.FontSize + (display_frame ? padding.x*3 : padding.x*2)); // Collapser arrow width + Spacing @@ -6755,7 +6755,7 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l // For regular tree nodes, we arbitrary allow to click past 2 worth of ItemSpacing // (Ideally we'd want to add a flag for the user to specify if we want the hit test to be done up to the right side of the content or not) - const ImRect interact_bb = display_frame ? bb : ImRect(bb.Min.x, bb.Min.y, bb.Min.x + text_width + style.ItemSpacing.x*2, bb.Max.y); + const ImRect interact_bb = display_frame ? frame_bb : ImRect(frame_bb.Min.x, frame_bb.Min.y, frame_bb.Min.x + text_width + style.ItemSpacing.x*2, frame_bb.Max.y); bool is_open = TreeNodeBehaviorIsOpen(id, flags); if (!ItemAdd(interact_bb, id)) { @@ -6796,36 +6796,36 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l // Render const ImU32 col = GetColorU32((held && hovered) ? ImGuiCol_HeaderActive : hovered ? ImGuiCol_HeaderHovered : ImGuiCol_Header); - const ImVec2 text_pos = bb.Min + ImVec2(text_offset_x, text_base_offset_y); + const ImVec2 text_pos = frame_bb.Min + ImVec2(text_offset_x, text_base_offset_y); if (display_frame) { // Framed type - RenderFrame(bb.Min, bb.Max, col, true, style.FrameRounding); - RenderTriangle(bb.Min + ImVec2(padding.x, text_base_offset_y), is_open ? ImGuiDir_Down : ImGuiDir_Right, 1.0f); + RenderFrame(frame_bb.Min, frame_bb.Max, col, true, style.FrameRounding); + RenderTriangle(frame_bb.Min + ImVec2(padding.x, text_base_offset_y), is_open ? ImGuiDir_Down : ImGuiDir_Right, 1.0f); if (g.LogEnabled) { // NB: '##' is normally used to hide text (as a library-wide feature), so we need to specify the text range to make sure the ## aren't stripped out here. const char log_prefix[] = "\n##"; const char log_suffix[] = "##"; LogRenderedText(&text_pos, log_prefix, log_prefix+3); - RenderTextClipped(text_pos, bb.Max, label, label_end, &label_size); + RenderTextClipped(text_pos, frame_bb.Max, label, label_end, &label_size); LogRenderedText(&text_pos, log_suffix+1, log_suffix+3); } else { - RenderTextClipped(text_pos, bb.Max, label, label_end, &label_size); + RenderTextClipped(text_pos, frame_bb.Max, label, label_end, &label_size); } } else { // Unframed typed for tree nodes if (hovered || (flags & ImGuiTreeNodeFlags_Selected)) - RenderFrame(bb.Min, bb.Max, col, false); + RenderFrame(frame_bb.Min, frame_bb.Max, col, false); if (flags & ImGuiTreeNodeFlags_Bullet) - RenderBullet(bb.Min + ImVec2(text_offset_x * 0.5f, g.FontSize*0.50f + text_base_offset_y)); + RenderBullet(frame_bb.Min + ImVec2(text_offset_x * 0.5f, g.FontSize*0.50f + text_base_offset_y)); else if (!(flags & ImGuiTreeNodeFlags_Leaf)) - RenderTriangle(bb.Min + ImVec2(padding.x, g.FontSize*0.15f + text_base_offset_y), is_open ? ImGuiDir_Down : ImGuiDir_Right, 0.70f); + RenderTriangle(frame_bb.Min + ImVec2(padding.x, g.FontSize*0.15f + text_base_offset_y), is_open ? ImGuiDir_Down : ImGuiDir_Right, 0.70f); if (g.LogEnabled) LogRenderedText(&text_pos, ">"); RenderText(text_pos, label, label_end, false); From b50dce54ea0afb7ccc3be479abaeb96976bcdc69 Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 6 Feb 2018 13:46:14 +0100 Subject: [PATCH 620/823] Drag and Drop: TreeNode as drop target displays rectangle over full frame. Added optional internal storage for item display rect. Will expose later. (#1597, #143) --- imgui.cpp | 17 +++++++++++------ imgui_internal.h | 13 ++++++++----- 2 files changed, 19 insertions(+), 11 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index a2db61ccc8f4..4312ed180b92 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -6757,7 +6757,11 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l // (Ideally we'd want to add a flag for the user to specify if we want the hit test to be done up to the right side of the content or not) const ImRect interact_bb = display_frame ? frame_bb : ImRect(frame_bb.Min.x, frame_bb.Min.y, frame_bb.Min.x + text_width + style.ItemSpacing.x*2, frame_bb.Max.y); bool is_open = TreeNodeBehaviorIsOpen(id, flags); - if (!ItemAdd(interact_bb, id)) + bool item_add = ItemAdd(interact_bb, id); + window->DC.LastItemStatusFlags |= ImGuiItemStatusFlags_HasDisplayRect; + window->DC.LastItemDisplayRect = frame_bb; + + if (!item_add) { if (is_open && !(flags & ImGuiTreeNodeFlags_NoTreePushOnOpen)) TreePushRawID(id); @@ -9537,7 +9541,7 @@ bool ImGui::ListBoxHeader(const char* label, const ImVec2& size_arg) ImVec2 frame_size = ImVec2(size.x, ImMax(size.y, label_size.y)); ImRect frame_bb(window->DC.CursorPos, window->DC.CursorPos + frame_size); ImRect bb(frame_bb.Min, frame_bb.Max + ImVec2(label_size.x > 0.0f ? style.ItemInnerSpacing.x + label_size.x : 0.0f, 0.0f)); - window->DC.LastItemRect = bb; + window->DC.LastItemRect = bb; // Forward storage for ListBoxFooter.. dodgy. BeginGroup(); if (label_size.x > 0) @@ -10703,9 +10707,9 @@ bool ImGui::SplitterBehavior(ImGuiID id, const ImRect& bb, ImGuiAxis axis, float #ifdef IMGUI_HAS_NAV window->DC.ItemFlags |= ImGuiItemFlags_NoNav | ImGuiItemFlags_NoNavDefaultFocus; #endif - bool add = ItemAdd(bb, id); + bool item_add = ItemAdd(bb, id); window->DC.ItemFlags = item_flags_backup; - if (!add) + if (!item_add) return false; bool hovered, held; @@ -11491,13 +11495,14 @@ bool ImGui::BeginDragDropTarget() if (g.HoveredWindow == NULL || window->RootWindow != g.HoveredWindow->RootWindow) return false; + const ImRect& display_rect = (window->DC.LastItemStatusFlags & ImGuiItemStatusFlags_HasDisplayRect) ? window->DC.LastItemDisplayRect : window->DC.LastItemRect; ImGuiID id = window->DC.LastItemId; if (id == 0) - id = window->GetIDFromRectangle(window->DC.LastItemRect); + id = window->GetIDFromRectangle(display_rect); if (g.DragDropPayload.SourceId == id) return false; - g.DragDropTargetRect = window->DC.LastItemRect; + g.DragDropTargetRect = display_rect; g.DragDropTargetId = id; return true; } diff --git a/imgui_internal.h b/imgui_internal.h index e80c5297ced9..500467722c08 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -220,7 +220,8 @@ enum ImGuiSeparatorFlags_ // Storage for LastItem data enum ImGuiItemStatusFlags_ { - ImGuiItemStatusFlags_HoveredRect = 1 << 0 + ImGuiItemStatusFlags_HoveredRect = 1 << 0, + ImGuiItemStatusFlags_HasDisplayRect = 1 << 1 }; // FIXME: this is in development, not exposed/functional as a generic feature yet. @@ -709,6 +710,7 @@ struct IMGUI_API ImGuiDrawContext ImGuiID LastItemId; ImGuiItemStatusFlags LastItemStatusFlags; ImRect LastItemRect; // Interaction rect + ImRect LastItemDisplayRect; // End-user display rect (only valid if LastItemStatusFlags & ImGuiItemStatusFlags_HasDisplayRect) bool MenuBarAppending; float MenuBarOffsetX; ImVector ChildWindows; @@ -739,7 +741,7 @@ struct IMGUI_API ImGuiDrawContext TreeDepth = 0; LastItemId = 0; LastItemStatusFlags = 0; - LastItemRect = ImRect(); + LastItemRect = LastItemDisplayRect = ImRect(); MenuBarAppending = false; MenuBarOffsetX = 0.0f; StateStorage = NULL; @@ -847,12 +849,13 @@ struct IMGUI_API ImGuiWindow struct ImGuiItemHoveredDataBackup { ImGuiID LastItemId; - ImGuiItemStatusFlags LastItemFlags; + ImGuiItemStatusFlags LastItemStatusFlags; ImRect LastItemRect; + ImRect LastItemDisplayRect; ImGuiItemHoveredDataBackup() { Backup(); } - void Backup() { ImGuiWindow* window = GImGui->CurrentWindow; LastItemId = window->DC.LastItemId; LastItemFlags = window->DC.LastItemStatusFlags; LastItemRect = window->DC.LastItemRect; } - void Restore() const { ImGuiWindow* window = GImGui->CurrentWindow; window->DC.LastItemId = LastItemId; window->DC.LastItemStatusFlags = LastItemFlags; window->DC.LastItemRect = LastItemRect; } + void Backup() { ImGuiWindow* window = GImGui->CurrentWindow; LastItemId = window->DC.LastItemId; LastItemStatusFlags = window->DC.LastItemStatusFlags; LastItemRect = window->DC.LastItemRect; LastItemDisplayRect = window->DC.LastItemDisplayRect; } + void Restore() const { ImGuiWindow* window = GImGui->CurrentWindow; window->DC.LastItemId = LastItemId; window->DC.LastItemStatusFlags = LastItemStatusFlags; window->DC.LastItemRect = LastItemRect; window->DC.LastItemDisplayRect = LastItemDisplayRect; } }; //----------------------------------------------------------------------------- From ad093966726d662359398de313dbb8e2bc1053bd Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 6 Feb 2018 16:32:51 +0100 Subject: [PATCH 621/823] ImVec2: added [] operator. This is becoming desirable for some types of code, better added sooner than later. --- imgui.h | 1 + 1 file changed, 1 insertion(+) diff --git a/imgui.h b/imgui.h index 9aab0a7ef408..4644a8adfa78 100644 --- a/imgui.h +++ b/imgui.h @@ -116,6 +116,7 @@ struct ImVec2 float x, y; ImVec2() { x = y = 0.0f; } ImVec2(float _x, float _y) { x = _x; y = _y; } + float operator[] (size_t idx) const { IM_ASSERT(idx == 0 || idx == 1); return *(&x + idx); } // We very rarely use this [] operator, thus an assert is fine. #ifdef IM_VEC2_CLASS_EXTRA // Define constructor and implicit cast operators in imconfig.h to convert back<>forth from your math types and ImVec2. IM_VEC2_CLASS_EXTRA #endif From 3b7bd4563a0b15f850bce3b0d5eefb39d8ad8006 Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 6 Feb 2018 16:32:51 +0100 Subject: [PATCH 622/823] ImVec2: added [] operator. This is becoming desirable for some types of code, better added sooner than later. --- imgui.h | 1 + 1 file changed, 1 insertion(+) diff --git a/imgui.h b/imgui.h index 5c436c023abb..3efc5978fe6b 100644 --- a/imgui.h +++ b/imgui.h @@ -113,6 +113,7 @@ struct ImVec2 float x, y; ImVec2() { x = y = 0.0f; } ImVec2(float _x, float _y) { x = _x; y = _y; } + float operator[] (size_t idx) const { IM_ASSERT(idx == 0 || idx == 1); return *(&x + idx); } // We very rarely use this [] operator, thus an assert is fine. #ifdef IM_VEC2_CLASS_EXTRA // Define constructor and implicit cast operators in imconfig.h to convert back<>forth from your math types and ImVec2. IM_VEC2_CLASS_EXTRA #endif From ed4bbc4fd4c7041f98f204ee695cfe441032a9f7 Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 6 Feb 2018 18:26:42 +0100 Subject: [PATCH 623/823] Nav: Comments, guides. --- TODO.txt | 1 + imgui.cpp | 18 +++++++++--------- imgui.h | 36 ++++++++++++++++++------------------ 3 files changed, 28 insertions(+), 27 deletions(-) diff --git a/TODO.txt b/TODO.txt index fe9b6ccecf98..939393ba6d13 100644 --- a/TODO.txt +++ b/TODO.txt @@ -238,6 +238,7 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i - nav: integrate/design keyboard controls. - nav: simulate right-click or context activation? (SHIFT+F10) - nav: tabs should go through most/all widgets (in submission order?). + - nav: when CTRL-Tab/windowing is active, the HoveredWindow detection doesn't take account of the window display re-ordering. - nav: cannot access menubar of a flattened child window with Alt/menu key (not a very common use case..). - nav: esc/enter default behavior for popups, e.g. be able to mark an "ok" or "cancel" button that would get triggered by those keys. - nav: when activating a button that changes label (without a static ID) or disappear, can we somehow automatically recover into a nearest highlight item? diff --git a/imgui.cpp b/imgui.cpp index c2e96ea286c7..6d485418d454 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -80,7 +80,8 @@ - ESCAPE to revert text to its original value. - You can apply arithmetic operators +,*,/ on numerical values. Use +- to subtract (because - would set a negative value!) - Controls are automatically adjusted for OSX to match standard OSX text editing operations. - - Gamepad/keyboard navigation are in beta-phase, see Programmer Guide below. + - Gamepad navigation: see suggested mappings in imgui.h ImGuiNavInput_ + - Keyboard navigation: see suggested mappings in imgui.h ImGuiNavInput_ PROGRAMMER GUIDE @@ -211,8 +212,7 @@ USING GAMEPAD/KEYBOARD NAVIGATION [BETA] - - Gamepad/keyboard navigation support is now available. Your feedback and bug reports are greatly welcome! - - See https://github.com/ocornut/imgui/issues/787 discussion thread and ask questions there. + - Ask questions and report issues at https://github.com/ocornut/imgui/issues/787. - The initial focus was to support game controllers, but keyboard is becoming increasingly and decently usable. - Your inputs are passed to imgui by filling the io.NavInputs[] array. See 'enum ImGuiNavInput_' in imgui.h for a description of available inputs. - Please refer to the examples/ application for suggested keyboard and gamepad mapping. @@ -221,12 +221,12 @@ - The ImGuiNavFlags_EnableGamepad and ImGuiNavFlags_EnableKeyboard flags of io.NavFlags are only here to instruct your binding whether to find inputs. - For gamepad use, the easiest approach is to go all-or-nothing, with a buttons combo that toggle your inputs between imgui and your game/application. Sharing inputs in a more advanced or granular way between imgui and your game/application may be tricky and requires further work on imgui. + When keyboard navigation is active (io.NavActive + NavFlags_EnableKeyboard), the io.WantCaptureKeyboard is set. For more advanced uses, you may want to use: - io.NavActive: true when a window is focused and it doesn't have the ImGuiWindowFlags_NoNavInputs flag set. - io.NavVisible: true when the navigation cursor is visible (and usually goes false when mouse is used). - query focus information with e.g. IsWindowFocused(), IsItemFocused() etc. functions. - The reality is more complex than what those flags can express. Please discuss your issues and usage scenario in the thread above! - As we head toward more keyboard-oriented development this aspect will need to be improved. + Please reach out if you think the game vs navigation input sharing could be improved. - On a TV/console system where readability may be lower or mouse inputs may be awkward, you may want to set the ImGuiNavFlags_MoveMouse flag in io.NavFlags. Enabling ImGuiNavFlags_MoveMouse instructs dear imgui to move your mouse cursor along with navigation movement. When enabled, the NewFrame() functions may alter 'io.MousePos' and set 'io.WantMoveMouse' to notify you that it did so. @@ -2675,7 +2675,7 @@ static ImVec2 NavCalcPreferredMousePos() const ImRect& rect_rel = window->NavRectRel[g.NavLayer]; ImVec2 pos = g.NavWindow->Pos + ImVec2(rect_rel.Min.x + ImMin(g.Style.FramePadding.x*4, rect_rel.GetWidth()), rect_rel.Max.y - ImMin(g.Style.FramePadding.y, rect_rel.GetHeight())); ImRect visible_rect = GetViewportRect(); - return ImFloor(ImClamp(pos, visible_rect.Min, visible_rect.Max)); // ImFloor() is important because non-integer mouse position application in backend might be lossy and result in undesirable non-zero delta. + return ImFloor(ImClamp(pos, visible_rect.Min, visible_rect.Max)); // ImFloor() is important because non-integer mouse position application in back-end might be lossy and result in undesirable non-zero delta. } static int FindWindowIndex(ImGuiWindow* window) // FIXME-OPT O(N) @@ -2823,7 +2823,7 @@ static void ImGui::NavUpdateWindowing() } // Keyboard: Press and Release ALT to toggle menu layer - // FIXME: We lack an explicit IO variable for "is the imgui window focused", so compare mouse validity to detect the common case of backend clearing releases all keys on ALT-TAB + // FIXME: We lack an explicit IO variable for "is the imgui window focused", so compare mouse validity to detect the common case of back-end clearing releases all keys on ALT-TAB if ((g.ActiveId == 0 || g.ActiveIdAllowOverlap) && IsNavInputPressed(ImGuiNavInput_KeyMenu, ImGuiInputReadMode_Released)) if (IsMousePosValid(&g.IO.MousePos) == IsMousePosValid(&g.IO.MousePosPrev)) apply_toggle_layer = true; @@ -4415,7 +4415,7 @@ int ImGui::GetKeyIndex(ImGuiKey imgui_key) return GImGui->IO.KeyMap[imgui_key]; } -// Note that imgui doesn't know the semantic of each entry of io.KeyDown[]. Use your own indices/enums according to how your backend/engine stored them into KeyDown[]! +// Note that imgui doesn't know the semantic of each entry of io.KeyDown[]. Use your own indices/enums according to how your back-end/engine stored them into KeyDown[]! bool ImGui::IsKeyDown(int user_key_index) { if (user_key_index < 0) return false; @@ -4536,7 +4536,7 @@ bool ImGui::IsMousePosValid(const ImVec2* mouse_pos) return mouse_pos->x >= MOUSE_INVALID && mouse_pos->y >= MOUSE_INVALID; } -// NB: This is only valid if IsMousePosValid(). Backends in theory should always keep mouse position valid when dragging even outside the client window. +// NB: This is only valid if IsMousePosValid(). Back-ends in theory should always keep mouse position valid when dragging even outside the client window. ImVec2 ImGui::GetMouseDragDelta(int button, float lock_threshold) { ImGuiContext& g = *GImGui; diff --git a/imgui.h b/imgui.h index 4644a8adfa78..136f296e6cb9 100644 --- a/imgui.h +++ b/imgui.h @@ -710,27 +710,27 @@ enum ImGuiKey_ enum ImGuiNavInput_ { // Gamepad Mapping - ImGuiNavInput_PadActivate, // press button, tweak value // e.g. Circle button - ImGuiNavInput_PadCancel, // close menu/popup/child, lose selection // e.g. Cross button - ImGuiNavInput_PadInput, // text input // e.g. Triangle button - ImGuiNavInput_PadMenu, // toggle menu, hold to: focus, move, resize // e.g. Square button - ImGuiNavInput_PadDpadLeft, // move left, resize window (with PadMenu) // e.g. D-pad directions - ImGuiNavInput_PadDpadRight, // move right - ImGuiNavInput_PadDpadUp, // move up - ImGuiNavInput_PadDpadDown, // move down - ImGuiNavInput_PadLStickLeft, // scroll up, move window (with PadMenu) // e.g. left stick directions (analog) - ImGuiNavInput_PadLStickRight, // scroll right - ImGuiNavInput_PadLStickUp, // scroll up - ImGuiNavInput_PadLStickDown, // scroll down - ImGuiNavInput_PadFocusPrev, // next window (with PadMenu) // e.g. L-trigger - ImGuiNavInput_PadFocusNext, // prev window (with PadMenu) // e.g. R-trigger - ImGuiNavInput_PadTweakSlow, // slower tweaks // e.g. L-trigger, analog - ImGuiNavInput_PadTweakFast, // faster tweaks // e.g. R-trigger, analog + ImGuiNavInput_PadActivate, // activate / open / toggle / tweak value // e.g. Circle (PS4), A (Xbox), B (Switch) + ImGuiNavInput_PadCancel, // cancel / close / exit // e.g. Cross (PS4), B (Xbox), A (Switch) + ImGuiNavInput_PadInput, // text input / on-screen keyboard // e.g. Triang.(PS4), Y (Xbox), X (Switch) + ImGuiNavInput_PadMenu, // tap: toggle menu / hold: focus, move, resize // e.g. Square (PS4), X (Xbox), Y (Switch) + ImGuiNavInput_PadDpadLeft, // move / tweak / resize window (w/ PadMenu) // e.g. D-pad Left/Right/Up/Down + ImGuiNavInput_PadDpadRight, // + ImGuiNavInput_PadDpadUp, // + ImGuiNavInput_PadDpadDown, // + ImGuiNavInput_PadLStickLeft, // scroll / move window (w/ PadMenu) // e.g. Left Analog Stick Left/Right/Up/Down + ImGuiNavInput_PadLStickRight, // + ImGuiNavInput_PadLStickUp, // + ImGuiNavInput_PadLStickDown, // + ImGuiNavInput_PadFocusPrev, // next window (w/ PadMenu) // e.g. L1 (PS4), LB (Xbox), L (Switch) + ImGuiNavInput_PadFocusNext, // prev window (w/ PadMenu) // e.g. R1 (PS4), RB (Xbox), R (Switch) + ImGuiNavInput_PadTweakSlow, // slower tweaks // e.g. L2 (PS4), LT (Xbox), ZL (Switch), Analog + ImGuiNavInput_PadTweakFast, // faster tweaks // e.g. R2 (PS4), RT (Xbox), ZR (Switch), Analog // Keyboard Mapping // [BETA] To use keyboard control you currently need to map keys to those gamepad inputs: PadActivate (Enter), PadCancel (Escape), PadInput (Enter). // Will add specialized keyboard mappings as we add features and clarify the input interface. - ImGuiNavInput_KeyMenu, // toggle menu // e.g. ALT - ImGuiNavInput_KeyLeft, // move left // e.g. Arrow keys + ImGuiNavInput_KeyMenu, // toggle menu // e.g. Alt + ImGuiNavInput_KeyLeft, // move left // e.g. Arrow keys ImGuiNavInput_KeyRight, // move right ImGuiNavInput_KeyUp, // move up ImGuiNavInput_KeyDown, // move down From 7e32fc7109995825cf7801d3b36547d5092a1c44 Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 6 Feb 2018 19:23:12 +0100 Subject: [PATCH 624/823] Nav: Toward automatically mapping keyboard input. Renamed ImGuiNavInput_PadXXX to ImGuiNavInput_XXX. Renamed ImGuiNavInput_KeyXXX to ImGuiNavInput_KeyXXX_ (internal). (#787) --- .../opengl3_example/imgui_impl_glfw_gl3.cpp | 32 +++++++------- imgui.cpp | 42 +++++++++---------- imgui.h | 42 +++++++++---------- imgui_internal.h | 8 ++-- 4 files changed, 62 insertions(+), 62 deletions(-) diff --git a/examples/opengl3_example/imgui_impl_glfw_gl3.cpp b/examples/opengl3_example/imgui_impl_glfw_gl3.cpp index dcd40772c833..7444b10bfb08 100644 --- a/examples/opengl3_example/imgui_impl_glfw_gl3.cpp +++ b/examples/opengl3_example/imgui_impl_glfw_gl3.cpp @@ -444,22 +444,22 @@ void ImGui_ImplGlfwGL3_NewFrame() int axes_count = 0, buttons_count = 0; const float* axes = glfwGetJoystickAxes(GLFW_JOYSTICK_1, &axes_count); const unsigned char* buttons = glfwGetJoystickButtons(GLFW_JOYSTICK_1, &buttons_count); - MAP_BUTTON(ImGuiNavInput_PadActivate, 0); // Cross / A - MAP_BUTTON(ImGuiNavInput_PadCancel, 1); // Circle / B - MAP_BUTTON(ImGuiNavInput_PadMenu, 2); // Square / X - MAP_BUTTON(ImGuiNavInput_PadInput, 3); // Triangle / Y - MAP_BUTTON(ImGuiNavInput_PadDpadLeft, 13); // D-Pad Left - MAP_BUTTON(ImGuiNavInput_PadDpadRight, 11); // D-Pad Right - MAP_BUTTON(ImGuiNavInput_PadDpadUp, 10); // D-Pad Up - MAP_BUTTON(ImGuiNavInput_PadDpadDown, 12); // D-Pad Down - MAP_BUTTON(ImGuiNavInput_PadFocusPrev, 4); // L Trigger - MAP_BUTTON(ImGuiNavInput_PadFocusNext, 5); // R Trigger - MAP_BUTTON(ImGuiNavInput_PadTweakSlow, 4); // L Trigger - MAP_BUTTON(ImGuiNavInput_PadTweakFast, 5); // R Trigger - MAP_ANALOG(ImGuiNavInput_PadLStickLeft, 0, -0.3f, -0.9f); - MAP_ANALOG(ImGuiNavInput_PadLStickRight,0, +0.3f, +0.9f); - MAP_ANALOG(ImGuiNavInput_PadLStickUp, 1, +0.3f, +0.9f); - MAP_ANALOG(ImGuiNavInput_PadLStickDown, 1, -0.3f, -0.9f); + MAP_BUTTON(ImGuiNavInput_Activate, 0); // Cross / A + MAP_BUTTON(ImGuiNavInput_Cancel, 1); // Circle / B + MAP_BUTTON(ImGuiNavInput_Menu, 2); // Square / X + MAP_BUTTON(ImGuiNavInput_Input, 3); // Triangle / Y + MAP_BUTTON(ImGuiNavInput_DpadLeft, 13); // D-Pad Left + MAP_BUTTON(ImGuiNavInput_DpadRight, 11); // D-Pad Right + MAP_BUTTON(ImGuiNavInput_DpadUp, 10); // D-Pad Up + MAP_BUTTON(ImGuiNavInput_DpadDown, 12); // D-Pad Down + MAP_BUTTON(ImGuiNavInput_FocusPrev, 4); // L Trigger + MAP_BUTTON(ImGuiNavInput_FocusNext, 5); // R Trigger + MAP_BUTTON(ImGuiNavInput_TweakSlow, 4); // L Trigger + MAP_BUTTON(ImGuiNavInput_TweakFast, 5); // R Trigger + MAP_ANALOG(ImGuiNavInput_LStickLeft, 0, -0.3f, -0.9f); + MAP_ANALOG(ImGuiNavInput_LStickRight,0, +0.3f, +0.9f); + MAP_ANALOG(ImGuiNavInput_LStickUp, 1, +0.3f, +0.9f); + MAP_ANALOG(ImGuiNavInput_LStickDown, 1, -0.3f, -0.9f); #undef MAP_BUTTON #undef MAP_ANALOG } diff --git a/imgui.cpp b/imgui.cpp index 6d485418d454..14dc9d65a0fa 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2739,14 +2739,14 @@ ImVec2 ImGui::GetNavInputAmount2d(ImGuiNavDirSourceFlags dir_sources, ImGuiInput { ImVec2 delta(0.0f, 0.0f); if (dir_sources & ImGuiNavDirSourceFlags_Keyboard) - delta += ImVec2(GetNavInputAmount(ImGuiNavInput_KeyRight, mode) - GetNavInputAmount(ImGuiNavInput_KeyLeft, mode), GetNavInputAmount(ImGuiNavInput_KeyDown, mode) - GetNavInputAmount(ImGuiNavInput_KeyUp, mode)); + delta += ImVec2(GetNavInputAmount(ImGuiNavInput_KeyRight_, mode) - GetNavInputAmount(ImGuiNavInput_KeyLeft_, mode), GetNavInputAmount(ImGuiNavInput_KeyDown_, mode) - GetNavInputAmount(ImGuiNavInput_KeyUp_, mode)); if (dir_sources & ImGuiNavDirSourceFlags_PadDPad) - delta += ImVec2(GetNavInputAmount(ImGuiNavInput_PadDpadRight, mode) - GetNavInputAmount(ImGuiNavInput_PadDpadLeft, mode), GetNavInputAmount(ImGuiNavInput_PadDpadDown, mode) - GetNavInputAmount(ImGuiNavInput_PadDpadUp, mode)); + delta += ImVec2(GetNavInputAmount(ImGuiNavInput_DpadRight, mode) - GetNavInputAmount(ImGuiNavInput_DpadLeft, mode), GetNavInputAmount(ImGuiNavInput_DpadDown, mode) - GetNavInputAmount(ImGuiNavInput_DpadUp, mode)); if (dir_sources & ImGuiNavDirSourceFlags_PadLStick) - delta += ImVec2(GetNavInputAmount(ImGuiNavInput_PadLStickRight, mode) - GetNavInputAmount(ImGuiNavInput_PadLStickLeft, mode), GetNavInputAmount(ImGuiNavInput_PadLStickDown, mode) - GetNavInputAmount(ImGuiNavInput_PadLStickUp, mode)); - if (slow_factor != 0.0f && IsNavInputDown(ImGuiNavInput_PadTweakSlow)) + delta += ImVec2(GetNavInputAmount(ImGuiNavInput_LStickRight, mode) - GetNavInputAmount(ImGuiNavInput_LStickLeft, mode), GetNavInputAmount(ImGuiNavInput_LStickDown, mode) - GetNavInputAmount(ImGuiNavInput_LStickUp, mode)); + if (slow_factor != 0.0f && IsNavInputDown(ImGuiNavInput_TweakSlow)) delta *= slow_factor; - if (fast_factor != 0.0f && IsNavInputDown(ImGuiNavInput_PadTweakFast)) + if (fast_factor != 0.0f && IsNavInputDown(ImGuiNavInput_TweakFast)) delta *= fast_factor; return delta; } @@ -2773,7 +2773,7 @@ static void ImGui::NavUpdateWindowing() ImGuiWindow* apply_focus_window = NULL; bool apply_toggle_layer = false; - bool start_windowing_with_gamepad = !g.NavWindowingTarget && IsNavInputPressed(ImGuiNavInput_PadMenu, ImGuiInputReadMode_Pressed); + bool start_windowing_with_gamepad = !g.NavWindowingTarget && IsNavInputPressed(ImGuiNavInput_Menu, ImGuiInputReadMode_Pressed); bool start_windowing_with_keyboard = !g.NavWindowingTarget && g.IO.KeyCtrl && IsKeyPressedMap(ImGuiKey_Tab) && (g.IO.NavFlags & ImGuiNavFlags_EnableKeyboard); if (start_windowing_with_gamepad || start_windowing_with_keyboard) if (ImGuiWindow* window = g.NavWindow ? g.NavWindow : FindWindowNavigable(g.Windows.Size - 1, -INT_MAX, -1)) @@ -2792,7 +2792,7 @@ static void ImGui::NavUpdateWindowing() g.NavWindowingHighlightAlpha = ImMax(g.NavWindowingHighlightAlpha, ImSaturate((g.NavWindowingHighlightTimer - 0.20f) / 0.05f)); // Select window to focus - const int focus_change_dir = (int)IsNavInputPressed(ImGuiNavInput_PadFocusPrev, ImGuiInputReadMode_RepeatSlow) - (int)IsNavInputPressed(ImGuiNavInput_PadFocusNext, ImGuiInputReadMode_RepeatSlow); + const int focus_change_dir = (int)IsNavInputPressed(ImGuiNavInput_FocusPrev, ImGuiInputReadMode_RepeatSlow) - (int)IsNavInputPressed(ImGuiNavInput_FocusNext, ImGuiInputReadMode_RepeatSlow); if (focus_change_dir != 0) { NavUpdateWindowingHighlightWindow(focus_change_dir); @@ -2800,7 +2800,7 @@ static void ImGui::NavUpdateWindowing() } // Single press toggles NavLayer, long press with L/R apply actual focus on release (until then the window was merely rendered front-most) - if (!IsNavInputDown(ImGuiNavInput_PadMenu)) + if (!IsNavInputDown(ImGuiNavInput_Menu)) { g.NavWindowingToggleLayer &= (g.NavWindowingHighlightAlpha < 1.0f); // Once button was held long enough we don't consider it a tap-to-toggle-layer press anymore. if (g.NavWindowingToggleLayer && g.NavWindow) @@ -2824,7 +2824,7 @@ static void ImGui::NavUpdateWindowing() // Keyboard: Press and Release ALT to toggle menu layer // FIXME: We lack an explicit IO variable for "is the imgui window focused", so compare mouse validity to detect the common case of back-end clearing releases all keys on ALT-TAB - if ((g.ActiveId == 0 || g.ActiveIdAllowOverlap) && IsNavInputPressed(ImGuiNavInput_KeyMenu, ImGuiInputReadMode_Released)) + if ((g.ActiveId == 0 || g.ActiveIdAllowOverlap) && IsNavInputPressed(ImGuiNavInput_KeyMenu_, ImGuiInputReadMode_Released)) if (IsMousePosValid(&g.IO.MousePos) == IsMousePosValid(&g.IO.MousePosPrev)) apply_toggle_layer = true; @@ -3003,7 +3003,7 @@ static void ImGui::NavUpdate() g.IO.NavVisible = (g.IO.NavActive && g.NavId != 0 && !g.NavDisableHighlight) || (g.NavWindowingTarget != NULL) || g.NavInitRequest; // Process NavCancel input (to close a popup, get back to parent, clear focus) - if (IsNavInputPressed(ImGuiNavInput_PadCancel, ImGuiInputReadMode_Pressed)) + if (IsNavInputPressed(ImGuiNavInput_Cancel, ImGuiInputReadMode_Pressed)) { if (g.ActiveId != 0) { @@ -3045,15 +3045,15 @@ static void ImGui::NavUpdate() g.NavActivateId = g.NavActivateDownId = g.NavActivatePressedId = g.NavInputId = 0; if (g.NavId != 0 && !g.NavDisableHighlight && !g.NavWindowingTarget && g.NavWindow && !(g.NavWindow->Flags & ImGuiWindowFlags_NoNavInputs)) { - bool activate_down = IsNavInputDown(ImGuiNavInput_PadActivate); - bool activate_pressed = activate_down && IsNavInputPressed(ImGuiNavInput_PadActivate, ImGuiInputReadMode_Pressed); + bool activate_down = IsNavInputDown(ImGuiNavInput_Activate); + bool activate_pressed = activate_down && IsNavInputPressed(ImGuiNavInput_Activate, ImGuiInputReadMode_Pressed); if (g.ActiveId == 0 && activate_pressed) g.NavActivateId = g.NavId; if ((g.ActiveId == 0 || g.ActiveId == g.NavId) && activate_down) g.NavActivateDownId = g.NavId; if ((g.ActiveId == 0 || g.ActiveId == g.NavId) && activate_pressed) g.NavActivatePressedId = g.NavId; - if ((g.ActiveId == 0 || g.ActiveId == g.NavId) && IsNavInputPressed(ImGuiNavInput_PadInput, ImGuiInputReadMode_Pressed)) + if ((g.ActiveId == 0 || g.ActiveId == g.NavId) && IsNavInputPressed(ImGuiNavInput_Input, ImGuiInputReadMode_Pressed)) g.NavInputId = g.NavId; } if (g.NavWindow && (g.NavWindow->Flags & ImGuiWindowFlags_NoNavInputs)) @@ -3074,10 +3074,10 @@ static void ImGui::NavUpdate() g.NavMoveDir = ImGuiDir_None; if (g.NavWindow && !g.NavWindowingTarget && allowed_dir_flags && !(g.NavWindow->Flags & ImGuiWindowFlags_NoNavInputs)) { - if ((allowed_dir_flags & (1<= 1.0f && delta > 0.0f) || (clicked_t <= 0.0f && delta < 0.0f)) // This is to avoid applying the saturation when already past the limits diff --git a/imgui.h b/imgui.h index 136f296e6cb9..2efd0d901b28 100644 --- a/imgui.h +++ b/imgui.h @@ -710,30 +710,30 @@ enum ImGuiKey_ enum ImGuiNavInput_ { // Gamepad Mapping - ImGuiNavInput_PadActivate, // activate / open / toggle / tweak value // e.g. Circle (PS4), A (Xbox), B (Switch) - ImGuiNavInput_PadCancel, // cancel / close / exit // e.g. Cross (PS4), B (Xbox), A (Switch) - ImGuiNavInput_PadInput, // text input / on-screen keyboard // e.g. Triang.(PS4), Y (Xbox), X (Switch) - ImGuiNavInput_PadMenu, // tap: toggle menu / hold: focus, move, resize // e.g. Square (PS4), X (Xbox), Y (Switch) - ImGuiNavInput_PadDpadLeft, // move / tweak / resize window (w/ PadMenu) // e.g. D-pad Left/Right/Up/Down - ImGuiNavInput_PadDpadRight, // - ImGuiNavInput_PadDpadUp, // - ImGuiNavInput_PadDpadDown, // - ImGuiNavInput_PadLStickLeft, // scroll / move window (w/ PadMenu) // e.g. Left Analog Stick Left/Right/Up/Down - ImGuiNavInput_PadLStickRight, // - ImGuiNavInput_PadLStickUp, // - ImGuiNavInput_PadLStickDown, // - ImGuiNavInput_PadFocusPrev, // next window (w/ PadMenu) // e.g. L1 (PS4), LB (Xbox), L (Switch) - ImGuiNavInput_PadFocusNext, // prev window (w/ PadMenu) // e.g. R1 (PS4), RB (Xbox), R (Switch) - ImGuiNavInput_PadTweakSlow, // slower tweaks // e.g. L2 (PS4), LT (Xbox), ZL (Switch), Analog - ImGuiNavInput_PadTweakFast, // faster tweaks // e.g. R2 (PS4), RT (Xbox), ZR (Switch), Analog + ImGuiNavInput_Activate, // activate / open / toggle / tweak value // e.g. Circle (PS4), A (Xbox), B (Switch) + ImGuiNavInput_Cancel, // cancel / close / exit // e.g. Cross (PS4), B (Xbox), A (Switch) + ImGuiNavInput_Input, // text input / on-screen keyboard // e.g. Triang.(PS4), Y (Xbox), X (Switch) + ImGuiNavInput_Menu, // tap: toggle menu / hold: focus, move, resize // e.g. Square (PS4), X (Xbox), Y (Switch) + ImGuiNavInput_DpadLeft, // move / tweak / resize window (w/ PadMenu) // e.g. D-pad Left/Right/Up/Down + ImGuiNavInput_DpadRight, // + ImGuiNavInput_DpadUp, // + ImGuiNavInput_DpadDown, // + ImGuiNavInput_LStickLeft, // scroll / move window (w/ PadMenu) // e.g. Left Analog Stick Left/Right/Up/Down + ImGuiNavInput_LStickRight, // + ImGuiNavInput_LStickUp, // + ImGuiNavInput_LStickDown, // + ImGuiNavInput_FocusPrev, // next window (w/ PadMenu) // e.g. L1 (PS4), LB (Xbox), L (Switch) + ImGuiNavInput_FocusNext, // prev window (w/ PadMenu) // e.g. R1 (PS4), RB (Xbox), R (Switch) + ImGuiNavInput_TweakSlow, // slower tweaks // e.g. L2 (PS4), LT (Xbox), ZL (Switch), Analog + ImGuiNavInput_TweakFast, // faster tweaks // e.g. R2 (PS4), RT (Xbox), ZR (Switch), Analog // Keyboard Mapping // [BETA] To use keyboard control you currently need to map keys to those gamepad inputs: PadActivate (Enter), PadCancel (Escape), PadInput (Enter). // Will add specialized keyboard mappings as we add features and clarify the input interface. - ImGuiNavInput_KeyMenu, // toggle menu // e.g. Alt - ImGuiNavInput_KeyLeft, // move left // e.g. Arrow keys - ImGuiNavInput_KeyRight, // move right - ImGuiNavInput_KeyUp, // move up - ImGuiNavInput_KeyDown, // move down + ImGuiNavInput_KeyMenu_, // toggle menu // e.g. Alt + ImGuiNavInput_KeyLeft_, // move left // e.g. Arrow keys + ImGuiNavInput_KeyRight_, // move right + ImGuiNavInput_KeyUp_, // move up + ImGuiNavInput_KeyDown_, // move down ImGuiNavInput_COUNT, }; diff --git a/imgui_internal.h b/imgui_internal.h index bbd9e48be6a4..29c2d5882a16 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -616,10 +616,10 @@ struct ImGuiContext // Navigation data (for gamepad/keyboard) ImGuiWindow* NavWindow; // Focused window for navigation. Could be called 'FocusWindow' ImGuiID NavId; // Focused item for navigation - ImGuiID NavActivateId; // ~~ (g.ActiveId == 0) && IsNavInputPressed(ImGuiNavInput_PadActivate) ? NavId : 0, also set when calling ActivateItem() - ImGuiID NavActivateDownId; // ~~ IsNavInputDown(ImGuiNavInput_PadActivate) ? NavId : 0 - ImGuiID NavActivatePressedId; // ~~ IsNavInputPressed(ImGuiNavInput_PadActivate) ? NavId : 0 - ImGuiID NavInputId; // ~~ IsNavInputPressed(ImGuiNavInput_PadInput) ? NavId : 0 + ImGuiID NavActivateId; // ~~ (g.ActiveId == 0) && IsNavInputPressed(ImGuiNavInput_Activate) ? NavId : 0, also set when calling ActivateItem() + ImGuiID NavActivateDownId; // ~~ IsNavInputDown(ImGuiNavInput_Activate) ? NavId : 0 + ImGuiID NavActivatePressedId; // ~~ IsNavInputPressed(ImGuiNavInput_Activate) ? NavId : 0 + ImGuiID NavInputId; // ~~ IsNavInputPressed(ImGuiNavInput_Input) ? NavId : 0 ImGuiID NavJustTabbedId; // Just tabbed to this id. ImGuiID NavNextActivateId; // Set by ActivateItem(), queued until next frame ImGuiID NavJustMovedToId; // Just navigated to this id (result of a successfully MoveRequest) From 057807f4a763d11477e0cc70acaf63b85b46bf77 Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 6 Feb 2018 19:29:31 +0100 Subject: [PATCH 625/823] Added ImGuiKey_Space, mapped in every examples. Will be required for navigation. (#787) --- examples/allegro5_example/imgui_impl_a5.cpp | 1 + .../imguiex-ios/imgui_impl_ios.mm | 1 + .../directx10_example/imgui_impl_dx10.cpp | 1 + .../directx11_example/imgui_impl_dx11.cpp | 1 + examples/directx9_example/imgui_impl_dx9.cpp | 1 + .../imgui_impl_marmalade.cpp | 1 + .../opengl2_example/imgui_impl_glfw_gl2.cpp | 1 + .../opengl3_example/imgui_impl_glfw_gl3.cpp | 1 + .../imgui_impl_sdl_gl2.cpp | 1 + .../imgui_impl_sdl_gl3.cpp | 1 + .../vulkan_example/imgui_impl_glfw_vulkan.cpp | 1 + imgui.h | 23 ++++++++++--------- 12 files changed, 23 insertions(+), 11 deletions(-) diff --git a/examples/allegro5_example/imgui_impl_a5.cpp b/examples/allegro5_example/imgui_impl_a5.cpp index 1eb118e60a38..81062f22eeba 100644 --- a/examples/allegro5_example/imgui_impl_a5.cpp +++ b/examples/allegro5_example/imgui_impl_a5.cpp @@ -180,6 +180,7 @@ bool ImGui_ImplA5_Init(ALLEGRO_DISPLAY* display) io.KeyMap[ImGuiKey_Insert] = ALLEGRO_KEY_INSERT; io.KeyMap[ImGuiKey_Delete] = ALLEGRO_KEY_DELETE; io.KeyMap[ImGuiKey_Backspace] = ALLEGRO_KEY_BACKSPACE; + io.KeyMap[ImGuiKey_Space] = ALLEGRO_KEY_SPACE; io.KeyMap[ImGuiKey_Enter] = ALLEGRO_KEY_ENTER; io.KeyMap[ImGuiKey_Escape] = ALLEGRO_KEY_ESCAPE; io.KeyMap[ImGuiKey_A] = ALLEGRO_KEY_A; diff --git a/examples/apple_example/imguiex-ios/imgui_impl_ios.mm b/examples/apple_example/imguiex-ios/imgui_impl_ios.mm index 20b5b7337ffb..440b586a8df1 100644 --- a/examples/apple_example/imguiex-ios/imgui_impl_ios.mm +++ b/examples/apple_example/imguiex-ios/imgui_impl_ios.mm @@ -491,6 +491,7 @@ - (void)setupImGuiHooks io.KeyMap[ImGuiKey_Insert] = kVK_Help+1; io.KeyMap[ImGuiKey_Delete] = kVK_ForwardDelete+1; io.KeyMap[ImGuiKey_Backspace] = kVK_Delete+1; + io.KeyMap[ImGuiKey_Space] = kVK_Space+1; io.KeyMap[ImGuiKey_Enter] = kVK_Return+1; io.KeyMap[ImGuiKey_Escape] = kVK_Escape+1; io.KeyMap[ImGuiKey_A] = kVK_ANSI_A+1; diff --git a/examples/directx10_example/imgui_impl_dx10.cpp b/examples/directx10_example/imgui_impl_dx10.cpp index e3080f9c41dd..7a7880907e45 100644 --- a/examples/directx10_example/imgui_impl_dx10.cpp +++ b/examples/directx10_example/imgui_impl_dx10.cpp @@ -553,6 +553,7 @@ bool ImGui_ImplDX10_Init(void* hwnd, ID3D10Device* device) io.KeyMap[ImGuiKey_Insert] = VK_INSERT; io.KeyMap[ImGuiKey_Delete] = VK_DELETE; io.KeyMap[ImGuiKey_Backspace] = VK_BACK; + io.KeyMap[ImGuiKey_Space] = VK_SPACE; io.KeyMap[ImGuiKey_Enter] = VK_RETURN; io.KeyMap[ImGuiKey_Escape] = VK_ESCAPE; io.KeyMap[ImGuiKey_A] = 'A'; diff --git a/examples/directx11_example/imgui_impl_dx11.cpp b/examples/directx11_example/imgui_impl_dx11.cpp index fbcfd953a0c7..5b7cd97d7e86 100644 --- a/examples/directx11_example/imgui_impl_dx11.cpp +++ b/examples/directx11_example/imgui_impl_dx11.cpp @@ -556,6 +556,7 @@ bool ImGui_ImplDX11_Init(void* hwnd, ID3D11Device* device, ID3D11DeviceContex io.KeyMap[ImGuiKey_Insert] = VK_INSERT; io.KeyMap[ImGuiKey_Delete] = VK_DELETE; io.KeyMap[ImGuiKey_Backspace] = VK_BACK; + io.KeyMap[ImGuiKey_Space] = VK_SPACE; io.KeyMap[ImGuiKey_Enter] = VK_RETURN; io.KeyMap[ImGuiKey_Escape] = VK_ESCAPE; io.KeyMap[ImGuiKey_A] = 'A'; diff --git a/examples/directx9_example/imgui_impl_dx9.cpp b/examples/directx9_example/imgui_impl_dx9.cpp index 8e0808fdee68..e54756d9d11c 100644 --- a/examples/directx9_example/imgui_impl_dx9.cpp +++ b/examples/directx9_example/imgui_impl_dx9.cpp @@ -272,6 +272,7 @@ bool ImGui_ImplDX9_Init(void* hwnd, IDirect3DDevice9* device) io.KeyMap[ImGuiKey_Insert] = VK_INSERT; io.KeyMap[ImGuiKey_Delete] = VK_DELETE; io.KeyMap[ImGuiKey_Backspace] = VK_BACK; + io.KeyMap[ImGuiKey_Space] = VK_SPACE; io.KeyMap[ImGuiKey_Enter] = VK_RETURN; io.KeyMap[ImGuiKey_Escape] = VK_ESCAPE; io.KeyMap[ImGuiKey_A] = 'A'; diff --git a/examples/marmalade_example/imgui_impl_marmalade.cpp b/examples/marmalade_example/imgui_impl_marmalade.cpp index e8d60af96110..2ba632faa77d 100644 --- a/examples/marmalade_example/imgui_impl_marmalade.cpp +++ b/examples/marmalade_example/imgui_impl_marmalade.cpp @@ -224,6 +224,7 @@ bool ImGui_Marmalade_Init(bool install_callbacks) io.KeyMap[ImGuiKey_Insert] = s3eKeyInsert; io.KeyMap[ImGuiKey_Delete] = s3eKeyDelete; io.KeyMap[ImGuiKey_Backspace] = s3eKeyBackspace; + io.KeyMap[ImGuiKey_Space] = s3eKeySpace; io.KeyMap[ImGuiKey_Enter] = s3eKeyEnter; io.KeyMap[ImGuiKey_Escape] = s3eKeyEsc; io.KeyMap[ImGuiKey_A] = s3eKeyA; diff --git a/examples/opengl2_example/imgui_impl_glfw_gl2.cpp b/examples/opengl2_example/imgui_impl_glfw_gl2.cpp index 954fbcde4cf6..5ac32e94ac32 100644 --- a/examples/opengl2_example/imgui_impl_glfw_gl2.cpp +++ b/examples/opengl2_example/imgui_impl_glfw_gl2.cpp @@ -217,6 +217,7 @@ bool ImGui_ImplGlfwGL2_Init(GLFWwindow* window, bool install_callbacks) io.KeyMap[ImGuiKey_Insert] = GLFW_KEY_INSERT; io.KeyMap[ImGuiKey_Delete] = GLFW_KEY_DELETE; io.KeyMap[ImGuiKey_Backspace] = GLFW_KEY_BACKSPACE; + io.KeyMap[ImGuiKey_Space] = GLFW_KEY_SPACE; io.KeyMap[ImGuiKey_Enter] = GLFW_KEY_ENTER; io.KeyMap[ImGuiKey_Escape] = GLFW_KEY_ESCAPE; io.KeyMap[ImGuiKey_A] = GLFW_KEY_A; diff --git a/examples/opengl3_example/imgui_impl_glfw_gl3.cpp b/examples/opengl3_example/imgui_impl_glfw_gl3.cpp index 7444b10bfb08..f0d2731e57d5 100644 --- a/examples/opengl3_example/imgui_impl_glfw_gl3.cpp +++ b/examples/opengl3_example/imgui_impl_glfw_gl3.cpp @@ -331,6 +331,7 @@ bool ImGui_ImplGlfwGL3_Init(GLFWwindow* window, bool install_callbacks) io.KeyMap[ImGuiKey_Insert] = GLFW_KEY_INSERT; io.KeyMap[ImGuiKey_Delete] = GLFW_KEY_DELETE; io.KeyMap[ImGuiKey_Backspace] = GLFW_KEY_BACKSPACE; + io.KeyMap[ImGuiKey_Space] = GLFW_KEY_SPACE; io.KeyMap[ImGuiKey_Enter] = GLFW_KEY_ENTER; io.KeyMap[ImGuiKey_Escape] = GLFW_KEY_ESCAPE; io.KeyMap[ImGuiKey_A] = GLFW_KEY_A; diff --git a/examples/sdl_opengl2_example/imgui_impl_sdl_gl2.cpp b/examples/sdl_opengl2_example/imgui_impl_sdl_gl2.cpp index 56776310793c..f8fd027b3e68 100644 --- a/examples/sdl_opengl2_example/imgui_impl_sdl_gl2.cpp +++ b/examples/sdl_opengl2_example/imgui_impl_sdl_gl2.cpp @@ -220,6 +220,7 @@ bool ImGui_ImplSdlGL2_Init(SDL_Window* window) io.KeyMap[ImGuiKey_Insert] = SDL_SCANCODE_INSERT; io.KeyMap[ImGuiKey_Delete] = SDL_SCANCODE_DELETE; io.KeyMap[ImGuiKey_Backspace] = SDL_SCANCODE_BACKSPACE; + io.KeyMap[ImGuiKey_Space] = SDL_SCANCODE_SPACE; io.KeyMap[ImGuiKey_Enter] = SDL_SCANCODE_RETURN; io.KeyMap[ImGuiKey_Escape] = SDL_SCANCODE_ESCAPE; io.KeyMap[ImGuiKey_A] = SDL_SCANCODE_A; diff --git a/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.cpp b/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.cpp index 0619b6ad0a39..5d42852b5f75 100644 --- a/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.cpp +++ b/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.cpp @@ -332,6 +332,7 @@ bool ImGui_ImplSdlGL3_Init(SDL_Window* window) io.KeyMap[ImGuiKey_Insert] = SDL_SCANCODE_INSERT; io.KeyMap[ImGuiKey_Delete] = SDL_SCANCODE_DELETE; io.KeyMap[ImGuiKey_Backspace] = SDL_SCANCODE_BACKSPACE; + io.KeyMap[ImGuiKey_Space] = SDL_SCANCODE_SPACE; io.KeyMap[ImGuiKey_Enter] = SDL_SCANCODE_RETURN; io.KeyMap[ImGuiKey_Escape] = SDL_SCANCODE_ESCAPE; io.KeyMap[ImGuiKey_A] = SDL_SCANCODE_A; diff --git a/examples/vulkan_example/imgui_impl_glfw_vulkan.cpp b/examples/vulkan_example/imgui_impl_glfw_vulkan.cpp index 3edf20970944..bd5eca0ecd4d 100644 --- a/examples/vulkan_example/imgui_impl_glfw_vulkan.cpp +++ b/examples/vulkan_example/imgui_impl_glfw_vulkan.cpp @@ -755,6 +755,7 @@ bool ImGui_ImplGlfwVulkan_Init(GLFWwindow* window, bool install_callbacks, Im io.KeyMap[ImGuiKey_Insert] = GLFW_KEY_INSERT; io.KeyMap[ImGuiKey_Delete] = GLFW_KEY_DELETE; io.KeyMap[ImGuiKey_Backspace] = GLFW_KEY_BACKSPACE; + io.KeyMap[ImGuiKey_Space] = GLFW_KEY_SPACE; io.KeyMap[ImGuiKey_Enter] = GLFW_KEY_ENTER; io.KeyMap[ImGuiKey_Escape] = GLFW_KEY_ESCAPE; io.KeyMap[ImGuiKey_A] = GLFW_KEY_A; diff --git a/imgui.h b/imgui.h index 2efd0d901b28..01a5ce5028bc 100644 --- a/imgui.h +++ b/imgui.h @@ -693,6 +693,7 @@ enum ImGuiKey_ ImGuiKey_Backspace, // for text edit ImGuiKey_Enter, // for text edit ImGuiKey_Escape, // for text edit + ImGuiKey_Space, ImGuiKey_A, // for text edit CTRL+A: select all ImGuiKey_C, // for text edit CTRL+C: copy ImGuiKey_V, // for text edit CTRL+V: paste @@ -999,17 +1000,17 @@ struct ImGuiIO // Input - Fill before calling NewFrame() //------------------------------------------------------------------ - ImVec2 MousePos; // Mouse position, in pixels. Set to ImVec2(-FLT_MAX,-FLT_MAX) if mouse is unavailable (on another screen, etc.) - bool MouseDown[5]; // Mouse buttons: left, right, middle + extras. ImGui itself mostly only uses left button (BeginPopupContext** are using right button). Others buttons allows us to track if the mouse is being used by your application + available to user as a convenience via IsMouse** API. - float MouseWheel; // Mouse wheel: 1 unit scrolls about 5 lines text. - float MouseWheelH; // Mouse wheel (Horizontal). Most users don't have a mouse with an horizontal wheel, may not be filled by all back ends. - bool MouseDrawCursor; // Request ImGui to draw a mouse cursor for you (if you are on a platform without a mouse cursor). - bool KeyCtrl; // Keyboard modifier pressed: Control - bool KeyShift; // Keyboard modifier pressed: Shift - bool KeyAlt; // Keyboard modifier pressed: Alt - bool KeySuper; // Keyboard modifier pressed: Cmd/Super/Windows - bool KeysDown[512]; // Keyboard keys that are pressed (ideally left in the "native" order your engine has access to keyboard keys, so you can use your own defines/enums for keys). - ImWchar InputCharacters[16+1]; // List of characters input (translated by user from keypress+keyboard state). Fill using AddInputCharacter() helper. + ImVec2 MousePos; // Mouse position, in pixels. Set to ImVec2(-FLT_MAX,-FLT_MAX) if mouse is unavailable (on another screen, etc.) + bool MouseDown[5]; // Mouse buttons: left, right, middle + extras. ImGui itself mostly only uses left button (BeginPopupContext** are using right button). Others buttons allows us to track if the mouse is being used by your application + available to user as a convenience via IsMouse** API. + float MouseWheel; // Mouse wheel: 1 unit scrolls about 5 lines text. + float MouseWheelH; // Mouse wheel (Horizontal). Most users don't have a mouse with an horizontal wheel, may not be filled by all back ends. + bool MouseDrawCursor; // Request ImGui to draw a mouse cursor for you (if you are on a platform without a mouse cursor). + bool KeyCtrl; // Keyboard modifier pressed: Control + bool KeyShift; // Keyboard modifier pressed: Shift + bool KeyAlt; // Keyboard modifier pressed: Alt + bool KeySuper; // Keyboard modifier pressed: Cmd/Super/Windows + bool KeysDown[512]; // Keyboard keys that are pressed (ideally left in the "native" order your engine has access to keyboard keys, so you can use your own defines/enums for keys). + ImWchar InputCharacters[16+1]; // List of characters input (translated by user from keypress+keyboard state). Fill using AddInputCharacter() helper. float NavInputs[ImGuiNavInput_COUNT]; // Functions From 9e3a807813eaf4e65475f0a023ba00f5f174decf Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 6 Feb 2018 19:34:09 +0100 Subject: [PATCH 626/823] Removed comments --- imgui.h | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/imgui.h b/imgui.h index 01a5ce5028bc..397756ed5bfc 100644 --- a/imgui.h +++ b/imgui.h @@ -679,21 +679,21 @@ enum ImGuiDragDropFlags_ // User fill ImGuiIO.KeyMap[] array with indices into the ImGuiIO.KeysDown[512] array enum ImGuiKey_ { - ImGuiKey_Tab, // for tabbing through fields - ImGuiKey_LeftArrow, // for text edit - ImGuiKey_RightArrow,// for text edit - ImGuiKey_UpArrow, // for text edit - ImGuiKey_DownArrow, // for text edit + ImGuiKey_Tab, + ImGuiKey_LeftArrow, + ImGuiKey_RightArrow, + ImGuiKey_UpArrow, + ImGuiKey_DownArrow, ImGuiKey_PageUp, ImGuiKey_PageDown, - ImGuiKey_Home, // for text edit - ImGuiKey_End, // for text edit - ImGuiKey_Insert, // for text edit - ImGuiKey_Delete, // for text edit - ImGuiKey_Backspace, // for text edit - ImGuiKey_Enter, // for text edit - ImGuiKey_Escape, // for text edit + ImGuiKey_Home, + ImGuiKey_End, + ImGuiKey_Insert, + ImGuiKey_Delete, + ImGuiKey_Backspace, ImGuiKey_Space, + ImGuiKey_Enter, + ImGuiKey_Escape, ImGuiKey_A, // for text edit CTRL+A: select all ImGuiKey_C, // for text edit CTRL+C: copy ImGuiKey_V, // for text edit CTRL+V: paste From 3171f90a1a31e0472d951cddc4eb8fc9b96e6421 Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 6 Feb 2018 19:54:30 +0100 Subject: [PATCH 627/823] Nav: Keyboard is now automatically mapped based on io.KeyDown[]. (#787) --- .../directx11_example/imgui_impl_dx11.cpp | 21 -------- examples/directx11_example/imgui_impl_dx11.h | 1 - .../opengl3_example/imgui_impl_glfw_gl3.cpp | 30 ++---------- .../opengl3_example/imgui_impl_glfw_gl3.h | 1 - .../imgui_impl_sdl_gl3.cpp | 24 ---------- .../sdl_opengl3_example/imgui_impl_sdl_gl3.h | 1 - imgui.cpp | 32 +++++++++++-- imgui.h | 48 ++++++++++--------- 8 files changed, 59 insertions(+), 99 deletions(-) diff --git a/examples/directx11_example/imgui_impl_dx11.cpp b/examples/directx11_example/imgui_impl_dx11.cpp index 5b7cd97d7e86..9b8c80c4f556 100644 --- a/examples/directx11_example/imgui_impl_dx11.cpp +++ b/examples/directx11_example/imgui_impl_dx11.cpp @@ -2,7 +2,6 @@ // Implemented features: // [X] User texture binding. Use 'ID3D11ShaderResourceView*' as ImTextureID. Read the FAQ about ImTextureID in imgui.cpp. -// [X] Keyboard navigation mapping. Enable with 'io.NavFlags |= ImGuiNavFlags_EnableKeyboard'. // You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this. // If you use this binding you'll need to call 4 functions: ImGui_ImplXXXX_Init(), ImGui_ImplXXXX_NewFrame(), ImGui::Render() and ImGui_ImplXXXX_Shutdown(). @@ -609,26 +608,6 @@ void ImGui_ImplDX11_NewFrame() // io.MouseDown : filled by WM_*BUTTON* events // io.MouseWheel : filled by WM_MOUSEWHEEL events - // Gamepad/keyboard navigation mapping [BETA] - memset(io.NavInputs, 0, sizeof(io.NavInputs)); - if (io.NavFlags & ImGuiNavFlags_EnableKeyboard) - { - // Update keyboard - // FIXME-NAV: We are still using some of the ImGuiNavInput_PadXXX enums as keyboard support is incomplete. - #define MAP_KEY(NAV_NO, KEY_NO) { if (io.KeysDown[KEY_NO]) io.NavInputs[NAV_NO] = 1.0f; } - MAP_KEY(ImGuiNavInput_KeyLeft, VK_LEFT); - MAP_KEY(ImGuiNavInput_KeyRight, VK_RIGHT); - MAP_KEY(ImGuiNavInput_KeyUp, VK_UP); - MAP_KEY(ImGuiNavInput_KeyDown, VK_DOWN); - MAP_KEY(ImGuiNavInput_KeyMenu, VK_MENU); - MAP_KEY(ImGuiNavInput_PadActivate, VK_SPACE); - MAP_KEY(ImGuiNavInput_PadCancel, VK_ESCAPE); - MAP_KEY(ImGuiNavInput_PadInput, VK_RETURN); - MAP_KEY(ImGuiNavInput_PadTweakFast, VK_SHIFT); - MAP_KEY(ImGuiNavInput_PadTweakSlow, VK_CONTROL); - #undef MAP_KEY - } - // Set OS mouse position if requested last frame by io.WantMoveMouse flag (used when io.NavMovesTrue is enabled by user and using directional navigation) if (io.WantMoveMouse) { diff --git a/examples/directx11_example/imgui_impl_dx11.h b/examples/directx11_example/imgui_impl_dx11.h index fc2b6bdb89c8..90bfe4fe3b5e 100644 --- a/examples/directx11_example/imgui_impl_dx11.h +++ b/examples/directx11_example/imgui_impl_dx11.h @@ -2,7 +2,6 @@ // Implemented features: // [X] User texture binding. Use 'ID3D11ShaderResourceView*' as ImTextureID. Read the FAQ about ImTextureID in imgui.cpp. -// [X] Keyboard navigation mapping. Enable with 'io.NavFlags |= ImGuiNavFlags_EnableKeyboard'. // You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this. // If you use this binding you'll need to call 4 functions: ImGui_ImplXXXX_Init(), ImGui_ImplXXXX_NewFrame(), ImGui::Render() and ImGui_ImplXXXX_Shutdown(). diff --git a/examples/opengl3_example/imgui_impl_glfw_gl3.cpp b/examples/opengl3_example/imgui_impl_glfw_gl3.cpp index f0d2731e57d5..86d94b2682c0 100644 --- a/examples/opengl3_example/imgui_impl_glfw_gl3.cpp +++ b/examples/opengl3_example/imgui_impl_glfw_gl3.cpp @@ -4,7 +4,6 @@ // Implemented features: // [X] User texture binding. Cast 'GLuint' OpenGL texture identifier as void*/ImTextureID. Read the FAQ about ImTextureID in imgui.cpp. -// [X] Keyboard navigation mapping. Enable with 'io.NavFlags |= ImGuiNavFlags_EnableKeyboard'. // [X] Gamepad navigation mapping. Enable with 'io.NavFlags |= ImGuiNavFlags_EnableGamepad'. // You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this. @@ -416,27 +415,8 @@ void ImGui_ImplGlfwGL3_NewFrame() // Hide OS mouse cursor if ImGui is drawing it glfwSetInputMode(g_Window, GLFW_CURSOR, io.MouseDrawCursor ? GLFW_CURSOR_HIDDEN : GLFW_CURSOR_NORMAL); - // Gamepad/keyboard navigation mapping [BETA] + // Gamepad navigation mapping [BETA] memset(io.NavInputs, 0, sizeof(io.NavInputs)); - if (io.NavFlags & ImGuiNavFlags_EnableKeyboard) - { - // Update keyboard - // FIXME-NAV: We are still using some of the ImGuiNavInput_PadXXX enums as keyboard support is incomplete. - #define MAP_KEY(NAV_NO, KEY_NO) { if (io.KeysDown[KEY_NO]) io.NavInputs[NAV_NO] = 1.0f; } - MAP_KEY(ImGuiNavInput_KeyLeft, GLFW_KEY_LEFT); - MAP_KEY(ImGuiNavInput_KeyRight, GLFW_KEY_RIGHT); - MAP_KEY(ImGuiNavInput_KeyUp, GLFW_KEY_UP); - MAP_KEY(ImGuiNavInput_KeyDown, GLFW_KEY_DOWN); - MAP_KEY(ImGuiNavInput_KeyMenu, GLFW_KEY_LEFT_ALT); - MAP_KEY(ImGuiNavInput_PadActivate, GLFW_KEY_SPACE); - MAP_KEY(ImGuiNavInput_PadCancel, GLFW_KEY_ESCAPE); - MAP_KEY(ImGuiNavInput_PadInput, GLFW_KEY_ENTER); - MAP_KEY(ImGuiNavInput_PadTweakSlow, GLFW_KEY_LEFT_ALT); - MAP_KEY(ImGuiNavInput_PadTweakSlow, GLFW_KEY_RIGHT_ALT); - MAP_KEY(ImGuiNavInput_PadTweakFast, GLFW_KEY_LEFT_SHIFT); - MAP_KEY(ImGuiNavInput_PadTweakFast, GLFW_KEY_RIGHT_SHIFT); - #undef MAP_KEY - } if (io.NavFlags & ImGuiNavFlags_EnableGamepad) { // Update gamepad inputs @@ -453,10 +433,10 @@ void ImGui_ImplGlfwGL3_NewFrame() MAP_BUTTON(ImGuiNavInput_DpadRight, 11); // D-Pad Right MAP_BUTTON(ImGuiNavInput_DpadUp, 10); // D-Pad Up MAP_BUTTON(ImGuiNavInput_DpadDown, 12); // D-Pad Down - MAP_BUTTON(ImGuiNavInput_FocusPrev, 4); // L Trigger - MAP_BUTTON(ImGuiNavInput_FocusNext, 5); // R Trigger - MAP_BUTTON(ImGuiNavInput_TweakSlow, 4); // L Trigger - MAP_BUTTON(ImGuiNavInput_TweakFast, 5); // R Trigger + MAP_BUTTON(ImGuiNavInput_FocusPrev, 4); // L1 / LB + MAP_BUTTON(ImGuiNavInput_FocusNext, 5); // R1 / RB + MAP_BUTTON(ImGuiNavInput_TweakSlow, 4); // L1 / LB + MAP_BUTTON(ImGuiNavInput_TweakFast, 5); // R1 / RB MAP_ANALOG(ImGuiNavInput_LStickLeft, 0, -0.3f, -0.9f); MAP_ANALOG(ImGuiNavInput_LStickRight,0, +0.3f, +0.9f); MAP_ANALOG(ImGuiNavInput_LStickUp, 1, +0.3f, +0.9f); diff --git a/examples/opengl3_example/imgui_impl_glfw_gl3.h b/examples/opengl3_example/imgui_impl_glfw_gl3.h index e7a4c2f650db..6b4101f21585 100644 --- a/examples/opengl3_example/imgui_impl_glfw_gl3.h +++ b/examples/opengl3_example/imgui_impl_glfw_gl3.h @@ -4,7 +4,6 @@ // Implemented features: // [X] User texture binding. Cast 'GLuint' OpenGL texture identifier as void*/ImTextureID. Read the FAQ about ImTextureID in imgui.cpp. -// [X] Keyboard navigation mapping. Enable with 'io.NavFlags |= ImGuiNavFlags_EnableKeyboard'. // [X] Gamepad navigation mapping. Enable with 'io.NavFlags |= ImGuiNavFlags_EnableGamepad'. // You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this. diff --git a/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.cpp b/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.cpp index 5d42852b5f75..b1c39ae6c5cd 100644 --- a/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.cpp +++ b/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.cpp @@ -4,7 +4,6 @@ // Implemented features: // [X] User texture binding. Cast 'GLuint' OpenGL texture identifier as void*/ImTextureID. Read the FAQ about ImTextureID in imgui.cpp. -// [X] Keyboard navigation mapping. Enable with 'io.NavFlags |= ImGuiNavFlags_EnableKeyboard'. // You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this. // If you use this binding you'll need to call 4 functions: ImGui_ImplXXXX_Init(), ImGui_ImplXXXX_NewFrame(), ImGui::Render() and ImGui_ImplXXXX_Shutdown(). @@ -414,29 +413,6 @@ void ImGui_ImplSdlGL3_NewFrame(SDL_Window* window) // Hide OS mouse cursor if ImGui is drawing it SDL_ShowCursor(io.MouseDrawCursor ? 0 : 1); - // Gamepad/keyboard navigation mapping [BETA] - memset(io.NavInputs, 0, sizeof(io.NavInputs)); - if (io.NavFlags & ImGuiNavFlags_EnableKeyboard) - { - // Update keyboard - // FIXME-NAV: We are still using some of the ImGuiNavInput_PadXXX enums as keyboard support is incomplete. - #define MAP_KEY(NAV_NO, KEY_NO) { if (io.KeysDown[KEY_NO]) io.NavInputs[NAV_NO] = 1.0f; } - MAP_KEY(ImGuiNavInput_KeyLeft, SDL_SCANCODE_LEFT); - MAP_KEY(ImGuiNavInput_KeyRight, SDL_SCANCODE_RIGHT); - MAP_KEY(ImGuiNavInput_KeyUp, SDL_SCANCODE_UP); - MAP_KEY(ImGuiNavInput_KeyDown, SDL_SCANCODE_DOWN); - MAP_KEY(ImGuiNavInput_KeyMenu, SDL_SCANCODE_LALT); - MAP_KEY(ImGuiNavInput_KeyMenu, SDL_SCANCODE_RALT); - MAP_KEY(ImGuiNavInput_PadActivate, SDL_SCANCODE_SPACE); - MAP_KEY(ImGuiNavInput_PadCancel, SDL_SCANCODE_ESCAPE); - MAP_KEY(ImGuiNavInput_PadInput, SDL_SCANCODE_RETURN); - MAP_KEY(ImGuiNavInput_PadTweakSlow, SDL_SCANCODE_LALT); - MAP_KEY(ImGuiNavInput_PadTweakSlow, SDL_SCANCODE_LALT); - MAP_KEY(ImGuiNavInput_PadTweakFast, SDL_SCANCODE_LSHIFT); - MAP_KEY(ImGuiNavInput_PadTweakFast, SDL_SCANCODE_RSHIFT); - #undef MAP_KEY - } - // Start the frame. This call will update the io.WantCaptureMouse, io.WantCaptureKeyboard flag that you can use to dispatch inputs (or not) to your application. ImGui::NewFrame(); } diff --git a/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.h b/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.h index fc7e1e96ef70..3f76e294223c 100644 --- a/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.h +++ b/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.h @@ -4,7 +4,6 @@ // Implemented features: // [X] User texture binding. Cast 'GLuint' OpenGL texture identifier as void*/ImTextureID. Read the FAQ about ImTextureID in imgui.cpp. -// [X] Keyboard navigation mapping. Enable with 'io.NavFlags |= ImGuiNavFlags_EnableKeyboard'. // You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this. // If you use this binding you'll need to call 4 functions: ImGui_ImplXXXX_Init(), ImGui_ImplXXXX_NewFrame(), ImGui::Render() and ImGui_ImplXXXX_Shutdown(). diff --git a/imgui.cpp b/imgui.cpp index 14dc9d65a0fa..3895c6c93f63 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2927,6 +2927,28 @@ static void ImGui::NavUpdate() if (g.NavScoringCount > 0) printf("[%05d] NavScoringCount %d for '%s' layer %d (Init:%d, Move:%d)\n", g.FrameCount, g.NavScoringCount, g.NavWindow ? g.NavWindow->Name : "NULL", g.NavLayer, g.NavInitRequest || g.NavInitResultId != 0, g.NavMoveRequest); #endif + // Update Keyboard->Nav inputs mapping + memset(g.IO.NavInputs + ImGuiNavInput_InternalStart_, 0, (ImGuiNavInput_COUNT - ImGuiNavInput_InternalStart_) * sizeof(g.IO.NavInputs[0])); + if (g.IO.NavFlags & ImGuiNavFlags_EnableKeyboard) + { + #define NAV_MAP_KEY(_KEY, _NAV_INPUT) if (g.IO.KeyMap[_KEY] != -1 && IsKeyDown(g.IO.KeyMap[_KEY])) g.IO.NavInputs[_NAV_INPUT] = 1.0f; + NAV_MAP_KEY(ImGuiKey_Space, ImGuiNavInput_Activate ); + NAV_MAP_KEY(ImGuiKey_Enter, ImGuiNavInput_Input ); + NAV_MAP_KEY(ImGuiKey_Escape, ImGuiNavInput_Cancel ); + NAV_MAP_KEY(ImGuiKey_LeftArrow, ImGuiNavInput_KeyLeft_ ); + NAV_MAP_KEY(ImGuiKey_RightArrow,ImGuiNavInput_KeyRight_); + NAV_MAP_KEY(ImGuiKey_UpArrow, ImGuiNavInput_KeyUp_ ); + NAV_MAP_KEY(ImGuiKey_DownArrow, ImGuiNavInput_KeyDown_ ); + if (g.IO.KeyCtrl) g.IO.NavInputs[ImGuiNavInput_TweakSlow] = 1.0f; + if (g.IO.KeyShift) g.IO.NavInputs[ImGuiNavInput_TweakFast] = 1.0f; + if (g.IO.KeyAlt) g.IO.NavInputs[ImGuiNavInput_KeyMenu_] = 1.0f; +#undef NAV_MAP_KEY + } + + memcpy(g.IO.NavInputsDownDurationPrev, g.IO.NavInputsDownDuration, sizeof(g.IO.NavInputsDownDuration)); + for (int i = 0; i < IM_ARRAYSIZE(g.IO.NavInputs); i++) + g.IO.NavInputsDownDuration[i] = (g.IO.NavInputs[i] > 0.0f) ? (g.IO.NavInputsDownDuration[i] < 0.0f ? 0.0f : g.IO.NavInputsDownDuration[i] + g.IO.DeltaTime) : -1.0f; + // Process navigation init request (select first/default focus) if (g.NavInitResultId != 0 && (!g.NavDisableHighlight || g.NavInitRequestFromMove)) { @@ -3182,6 +3204,10 @@ void ImGui::NewFrame() for (int n = 0; n < ImGuiKey_COUNT; n++) IM_ASSERT(g.IO.KeyMap[n] >= -1 && g.IO.KeyMap[n] < IM_ARRAYSIZE(g.IO.KeysDown) && "io.KeyMap[] contains an out of bound value (need to be 0..512, or -1 for unmapped key)"); + // Do a simple check for required key mapping (we intentionally do NOT check all keys to not pressure user into setting up everything, but Space is required and was super recently added in 1.54 WIP) + if (g.IO.NavFlags & ImGuiNavFlags_EnableKeyboard) + IM_ASSERT(g.IO.KeyMap[ImGuiKey_Space] != -1 && "ImGuiKey_Space is not mapped, required for keyboard navigation."); + // Initialize on first frame if (!g.Initialized) Initialize(); @@ -3235,11 +3261,8 @@ void ImGui::NewFrame() memcpy(g.IO.KeysDownDurationPrev, g.IO.KeysDownDuration, sizeof(g.IO.KeysDownDuration)); for (int i = 0; i < IM_ARRAYSIZE(g.IO.KeysDown); i++) g.IO.KeysDownDuration[i] = g.IO.KeysDown[i] ? (g.IO.KeysDownDuration[i] < 0.0f ? 0.0f : g.IO.KeysDownDuration[i] + g.IO.DeltaTime) : -1.0f; - memcpy(g.IO.NavInputsDownDurationPrev, g.IO.NavInputsDownDuration, sizeof(g.IO.NavInputsDownDuration)); - for (int i = 0; i < IM_ARRAYSIZE(g.IO.NavInputs); i++) - g.IO.NavInputsDownDuration[i] = (g.IO.NavInputs[i] > 0.0f) ? (g.IO.NavInputsDownDuration[i] < 0.0f ? 0.0f : g.IO.NavInputsDownDuration[i] + g.IO.DeltaTime) : -1.0f; - // Update directional navigation which may override MousePos if ImGuiNavFlags_MoveMouse is enabled. + // Update gamepad/keyboard directional navigation NavUpdate(); // Update mouse input state @@ -3952,6 +3975,7 @@ void ImGui::EndFrame() // Clear Input data for next frame g.IO.MouseWheel = g.IO.MouseWheelH = 0.0f; memset(g.IO.InputCharacters, 0, sizeof(g.IO.InputCharacters)); + memset(g.IO.NavInputs, 0, sizeof(g.IO.NavInputs)); g.FrameCountEnded = g.FrameCount; } diff --git a/imgui.h b/imgui.h index 397756ed5bfc..c2163640265c 100644 --- a/imgui.h +++ b/imgui.h @@ -704,45 +704,49 @@ enum ImGuiKey_ }; // [BETA] Gamepad/Keyboard directional navigation -// Fill ImGuiIO.NavInputs[] float array every frame to feed gamepad/keyboard navigation inputs. -// 0.0f= not held. 1.0f= fully held. Pass intermediate 0.0f..1.0f values for analog triggers/sticks. -// ImGui uses a simple >0.0f for activation testing, and won't attempt to test for a dead-zone. -// Your code passing analog gamepad values is likely to want to transform your raw inputs, using a dead-zone and maybe a power curve. +// Keyboard: +// - io.NavInputs[] is automatically filled in by NewFrame() if you set io.NavFlags |= ImGuiNavFlags_EnableKeyboard. +// Gamepad: +// - Fill io.NavInputs[] every frame with your gamepad inputs. Note that io.NavInputs[] is _cleared_ in EndFrame(). +// 0.0f= not held. 1.0f= fully held. Pass intermediate 0.0f..1.0f values for analog triggers/sticks. +// - We uses a simple >0.0f test for activation testing, and won't attempt to test for a dead-zone. +// Your code will probably need to transform your raw inputs (such as e.g. remapping your 0.2..0.9 raw input range to 0.0..1.0 imgui range, maybe a power curve, etc.). enum ImGuiNavInput_ { // Gamepad Mapping - ImGuiNavInput_Activate, // activate / open / toggle / tweak value // e.g. Circle (PS4), A (Xbox), B (Switch) - ImGuiNavInput_Cancel, // cancel / close / exit // e.g. Cross (PS4), B (Xbox), A (Switch) - ImGuiNavInput_Input, // text input / on-screen keyboard // e.g. Triang.(PS4), Y (Xbox), X (Switch) - ImGuiNavInput_Menu, // tap: toggle menu / hold: focus, move, resize // e.g. Square (PS4), X (Xbox), Y (Switch) - ImGuiNavInput_DpadLeft, // move / tweak / resize window (w/ PadMenu) // e.g. D-pad Left/Right/Up/Down + ImGuiNavInput_Activate, // activate / open / toggle / tweak value // e.g. Circle (PS4), A (Xbox), B (Switch), Space (Keyboard) + ImGuiNavInput_Cancel, // cancel / close / exit // e.g. Cross (PS4), B (Xbox), A (Switch), Escape (Keyboard) + ImGuiNavInput_Input, // text input / on-screen keyboard // e.g. Triang.(PS4), Y (Xbox), X (Switch), Return (Keyboard) + ImGuiNavInput_Menu, // tap: toggle menu / hold: focus, move, resize // e.g. Square (PS4), X (Xbox), Y (Switch), Alt (Keyboard) + ImGuiNavInput_DpadLeft, // move / tweak / resize window (w/ PadMenu) // e.g. D-pad Left/Right/Up/Down (Gamepads), Arrow keys (Keyboard) ImGuiNavInput_DpadRight, // ImGuiNavInput_DpadUp, // ImGuiNavInput_DpadDown, // - ImGuiNavInput_LStickLeft, // scroll / move window (w/ PadMenu) // e.g. Left Analog Stick Left/Right/Up/Down + ImGuiNavInput_LStickLeft, // scroll / move window (w/ PadMenu) // e.g. Left Analog Stick Left/Right/Up/Down ImGuiNavInput_LStickRight, // ImGuiNavInput_LStickUp, // ImGuiNavInput_LStickDown, // - ImGuiNavInput_FocusPrev, // next window (w/ PadMenu) // e.g. L1 (PS4), LB (Xbox), L (Switch) - ImGuiNavInput_FocusNext, // prev window (w/ PadMenu) // e.g. R1 (PS4), RB (Xbox), R (Switch) - ImGuiNavInput_TweakSlow, // slower tweaks // e.g. L2 (PS4), LT (Xbox), ZL (Switch), Analog - ImGuiNavInput_TweakFast, // faster tweaks // e.g. R2 (PS4), RT (Xbox), ZR (Switch), Analog - // Keyboard Mapping - // [BETA] To use keyboard control you currently need to map keys to those gamepad inputs: PadActivate (Enter), PadCancel (Escape), PadInput (Enter). - // Will add specialized keyboard mappings as we add features and clarify the input interface. - ImGuiNavInput_KeyMenu_, // toggle menu // e.g. Alt - ImGuiNavInput_KeyLeft_, // move left // e.g. Arrow keys + ImGuiNavInput_FocusPrev, // next window (w/ PadMenu) // e.g. L1 or L2 (PS4), LB or LT (Xbox), L or ZL (Switch) + ImGuiNavInput_FocusNext, // prev window (w/ PadMenu) // e.g. R1 or R2 (PS4), RB or RT (Xbox), R or ZL (Switch) + ImGuiNavInput_TweakSlow, // slower tweaks // e.g. L1 or L2 (PS4), LB or LT (Xbox), L or ZL (Switch) + ImGuiNavInput_TweakFast, // faster tweaks // e.g. R1 or R2 (PS4), RB or RT (Xbox), R or ZL (Switch) + + // [Internal] Don't use directly! This is used internally to differentiate keyboard from gamepad inputs for behaviors that require to differentiate them. + // Keyboard behavior that have no corresponding gamepad mapping (e.g. CTRL+TAB) may be directly reading from io.KeyDown[] instead of io.NavInputs[]. + ImGuiNavInput_KeyMenu_, // toggle menu // = io.KeyAlt + ImGuiNavInput_KeyLeft_, // move left // = Arrow keys ImGuiNavInput_KeyRight_, // move right ImGuiNavInput_KeyUp_, // move up ImGuiNavInput_KeyDown_, // move down ImGuiNavInput_COUNT, + ImGuiNavInput_InternalStart_ = ImGuiNavInput_KeyMenu_ }; // [BETA] Gamepad/Keyboard directional navigation options enum ImGuiNavFlags_ { - ImGuiNavFlags_EnableGamepad = 1 << 0, // Master gamepad navigation enable flag. This is mostly to instruct your imgui binding whether to fill in gamepad navigation inputs. - ImGuiNavFlags_EnableKeyboard = 1 << 1, // Master keyboard navigation enable flag. This is mostly to instruct your imgui binding whether to fill in keyboard navigation inputs. + ImGuiNavFlags_EnableKeyboard = 1 << 0, // Master keyboard navigation enable flag. NewFrame() will automatically fill io.NavInputs[] based on io.KeyDown[]. + ImGuiNavFlags_EnableGamepad = 1 << 1, // Master gamepad navigation enable flag. This is mostly to instruct your imgui back-end to fill io.NavInputs[]. ImGuiNavFlags_MoveMouse = 1 << 2, // Request navigation to allow moving the mouse cursor. May be useful on TV/console systems where moving a virtual mouse is awkward. Will update io.MousePos and set io.WantMoveMouse=true. If enabled you MUST honor io.WantMoveMouse requests in your binding, otherwise ImGui will react as if the mouse is jumping around back and forth. ImGuiNavFlags_NoCaptureKeyboard = 1 << 3 // Do not set the io.WantCaptureKeyboard flag with io.NavActive is set. }; @@ -1011,7 +1015,7 @@ struct ImGuiIO bool KeySuper; // Keyboard modifier pressed: Cmd/Super/Windows bool KeysDown[512]; // Keyboard keys that are pressed (ideally left in the "native" order your engine has access to keyboard keys, so you can use your own defines/enums for keys). ImWchar InputCharacters[16+1]; // List of characters input (translated by user from keypress+keyboard state). Fill using AddInputCharacter() helper. - float NavInputs[ImGuiNavInput_COUNT]; + float NavInputs[ImGuiNavInput_COUNT]; // Gamepad inputs (keyboard keys will be auto-mapped and be written here by ImGui::NewFrame) // Functions IMGUI_API void AddInputCharacter(ImWchar c); // Add new character into InputCharacters[] From ae30efc0fd55bf7015818e512db7aad6bf91cc9a Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 6 Feb 2018 19:58:23 +0100 Subject: [PATCH 628/823] Nav: Examples: Added commented out io.NavFlags |= ImGuiNavFlags_EnableKeyboard to all examples. (#787) --- examples/allegro5_example/main.cpp | 3 ++- examples/directx10_example/main.cpp | 3 ++- examples/directx11_example/main.cpp | 2 +- examples/directx9_example/main.cpp | 3 ++- examples/marmalade_example/main.cpp | 3 ++- examples/opengl2_example/main.cpp | 3 ++- examples/opengl3_example/main.cpp | 4 ++-- examples/sdl_opengl2_example/main.cpp | 3 ++- examples/vulkan_example/main.cpp | 3 ++- 9 files changed, 17 insertions(+), 10 deletions(-) diff --git a/examples/allegro5_example/main.cpp b/examples/allegro5_example/main.cpp index b740dace1e09..99da74928a51 100644 --- a/examples/allegro5_example/main.cpp +++ b/examples/allegro5_example/main.cpp @@ -23,7 +23,9 @@ int main(int, char**) al_register_event_source(queue, al_get_mouse_event_source()); // Setup ImGui binding + ImGuiIO& io = ImGui::GetIO(); (void)io; ImGui_ImplA5_Init(display); + //io.NavFlags |= ImGuiNavFlags_EnableKeyboard; // Enable Keyboard Controls // Setup style ImGui::StyleColorsDark(); @@ -36,7 +38,6 @@ int main(int, char**) // - The fonts will be rasterized at a given size (w/ oversampling) and stored into a texture when calling ImFontAtlas::Build()/GetTexDataAsXXXX(), which ImGui_ImplXXXX_NewFrame below will call. // - Read 'misc/fonts/README.txt' for more instructions and details. // - Remember that in C/C++ if you want to include a backslash \ in a string literal you need to write a double backslash \\ ! - //ImGuiIO& io = ImGui::GetIO(); //io.Fonts->AddFontDefault(); //io.Fonts->AddFontFromFileTTF("../../misc/fonts/Roboto-Medium.ttf", 16.0f); //io.Fonts->AddFontFromFileTTF("../../misc/fonts/Cousine-Regular.ttf", 15.0f); diff --git a/examples/directx10_example/main.cpp b/examples/directx10_example/main.cpp index aebf81f875e0..8a3d3f290d11 100644 --- a/examples/directx10_example/main.cpp +++ b/examples/directx10_example/main.cpp @@ -120,7 +120,9 @@ int main(int, char**) UpdateWindow(hwnd); // Setup ImGui binding + ImGuiIO& io = ImGui::GetIO(); (void)io; ImGui_ImplDX10_Init(hwnd, g_pd3dDevice); + //io.NavFlags |= ImGuiNavFlags_EnableKeyboard; // Enable Keyboard Controls // Setup style ImGui::StyleColorsDark(); @@ -133,7 +135,6 @@ int main(int, char**) // - The fonts will be rasterized at a given size (w/ oversampling) and stored into a texture when calling ImFontAtlas::Build()/GetTexDataAsXXXX(), which ImGui_ImplXXXX_NewFrame below will call. // - Read 'misc/fonts/README.txt' for more instructions and details. // - Remember that in C/C++ if you want to include a backslash \ in a string literal you need to write a double backslash \\ ! - //ImGuiIO& io = ImGui::GetIO(); //io.Fonts->AddFontDefault(); //io.Fonts->AddFontFromFileTTF("../../misc/fonts/Roboto-Medium.ttf", 16.0f); //io.Fonts->AddFontFromFileTTF("../../misc/fonts/Cousine-Regular.ttf", 15.0f); diff --git a/examples/directx11_example/main.cpp b/examples/directx11_example/main.cpp index 758ecc2e0a2d..48dc53ba1b0a 100644 --- a/examples/directx11_example/main.cpp +++ b/examples/directx11_example/main.cpp @@ -125,7 +125,7 @@ int main(int, char**) // Setup ImGui binding ImGuiIO& io = ImGui::GetIO(); (void)io; ImGui_ImplDX11_Init(hwnd, g_pd3dDevice, g_pd3dDeviceContext); - //io.NavFlags |= ImGuiNavFlags_EnableKeyboard; + //io.NavFlags |= ImGuiNavFlags_EnableKeyboard; // Enable Keyboard Controls // Setup style ImGui::StyleColorsDark(); diff --git a/examples/directx9_example/main.cpp b/examples/directx9_example/main.cpp index f40e5ef42b48..5b41ef62f0d4 100644 --- a/examples/directx9_example/main.cpp +++ b/examples/directx9_example/main.cpp @@ -75,7 +75,9 @@ int main(int, char**) } // Setup ImGui binding + ImGuiIO& io = ImGui::GetIO(); (void)io; ImGui_ImplDX9_Init(hwnd, g_pd3dDevice); + //io.NavFlags |= ImGuiNavFlags_EnableKeyboard; // Enable Keyboard Controls // Setup style ImGui::StyleColorsDark(); @@ -88,7 +90,6 @@ int main(int, char**) // - The fonts will be rasterized at a given size (w/ oversampling) and stored into a texture when calling ImFontAtlas::Build()/GetTexDataAsXXXX(), which ImGui_ImplXXXX_NewFrame below will call. // - Read 'misc/fonts/README.txt' for more instructions and details. // - Remember that in C/C++ if you want to include a backslash \ in a string literal you need to write a double backslash \\ ! - //ImGuiIO& io = ImGui::GetIO(); //io.Fonts->AddFontDefault(); //io.Fonts->AddFontFromFileTTF("../../misc/fonts/Roboto-Medium.ttf", 16.0f); //io.Fonts->AddFontFromFileTTF("../../misc/fonts/Cousine-Regular.ttf", 15.0f); diff --git a/examples/marmalade_example/main.cpp b/examples/marmalade_example/main.cpp index 58c2182bfb64..dc1db1b2ed19 100644 --- a/examples/marmalade_example/main.cpp +++ b/examples/marmalade_example/main.cpp @@ -15,7 +15,9 @@ int main(int, char**) { // Setup ImGui binding + ImGuiIO& io = ImGui::GetIO(); (void)io; ImGui_Marmalade_Init(true); + //io.NavFlags |= ImGuiNavFlags_EnableKeyboard; // Enable Keyboard Controls // Setup style ImGui::StyleColorsDark(); @@ -28,7 +30,6 @@ int main(int, char**) // - The fonts will be rasterized at a given size (w/ oversampling) and stored into a texture when calling ImFontAtlas::Build()/GetTexDataAsXXXX(), which ImGui_ImplXXXX_NewFrame below will call. // - Read 'misc/fonts/README.txt' for more instructions and details. // - Remember that in C/C++ if you want to include a backslash \ in a string literal you need to write a double backslash \\ ! - //ImGuiIO& io = ImGui::GetIO(); //io.Fonts->AddFontDefault(); //io.Fonts->AddFontFromFileTTF("../../misc/fonts/Roboto-Medium.ttf", 16.0f); //io.Fonts->AddFontFromFileTTF("../../misc/fonts/Cousine-Regular.ttf", 15.0f); diff --git a/examples/opengl2_example/main.cpp b/examples/opengl2_example/main.cpp index 89d41c378e67..182cc70c678b 100644 --- a/examples/opengl2_example/main.cpp +++ b/examples/opengl2_example/main.cpp @@ -27,7 +27,9 @@ int main(int, char**) glfwSwapInterval(1); // Enable vsync // Setup ImGui binding + ImGuiIO& io = ImGui::GetIO(); (void)io; ImGui_ImplGlfwGL2_Init(window, true); + //io.NavFlags |= ImGuiNavFlags_EnableKeyboard; // Enable Keyboard Controls // Setup style ImGui::StyleColorsDark(); @@ -40,7 +42,6 @@ int main(int, char**) // - The fonts will be rasterized at a given size (w/ oversampling) and stored into a texture when calling ImFontAtlas::Build()/GetTexDataAsXXXX(), which ImGui_ImplXXXX_NewFrame below will call. // - Read 'misc/fonts/README.txt' for more instructions and details. // - Remember that in C/C++ if you want to include a backslash \ in a string literal you need to write a double backslash \\ ! - //ImGuiIO& io = ImGui::GetIO(); //io.Fonts->AddFontDefault(); //io.Fonts->AddFontFromFileTTF("../../misc/fonts/Roboto-Medium.ttf", 16.0f); //io.Fonts->AddFontFromFileTTF("../../misc/fonts/Cousine-Regular.ttf", 15.0f); diff --git a/examples/opengl3_example/main.cpp b/examples/opengl3_example/main.cpp index 59c60fb69210..b5a60f7c7067 100644 --- a/examples/opengl3_example/main.cpp +++ b/examples/opengl3_example/main.cpp @@ -34,8 +34,8 @@ int main(int, char**) // Setup ImGui binding ImGuiIO& io = ImGui::GetIO(); (void)io; ImGui_ImplGlfwGL3_Init(window, true); - //io.NavFlags |= ImGuiNavFlags_EnableKeyboard; - //io.NavFlags |= ImGuiNavFlags_EnableGamepad; + //io.NavFlags |= ImGuiNavFlags_EnableKeyboard; // Enable Keyboard Controls + //io.NavFlags |= ImGuiNavFlags_EnableGamepad; // Enable Gamepad Controls // Setup style ImGui::StyleColorsDark(); diff --git a/examples/sdl_opengl2_example/main.cpp b/examples/sdl_opengl2_example/main.cpp index becf841a278d..35d28d9c23a2 100644 --- a/examples/sdl_opengl2_example/main.cpp +++ b/examples/sdl_opengl2_example/main.cpp @@ -34,7 +34,9 @@ int main(int, char**) SDL_GL_SetSwapInterval(1); // Enable vsync // Setup ImGui binding + ImGuiIO& io = ImGui::GetIO(); (void)io; ImGui_ImplSdlGL2_Init(window); + //io.NavFlags |= ImGuiNavFlags_EnableKeyboard; // Enable Keyboard Controls // Setup style ImGui::StyleColorsDark(); @@ -47,7 +49,6 @@ int main(int, char**) // - The fonts will be rasterized at a given size (w/ oversampling) and stored into a texture when calling ImFontAtlas::Build()/GetTexDataAsXXXX(), which ImGui_ImplXXXX_NewFrame below will call. // - Read 'misc/fonts/README.txt' for more instructions and details. // - Remember that in C/C++ if you want to include a backslash \ in a string literal you need to write a double backslash \\ ! - //ImGuiIO& io = ImGui::GetIO(); //io.Fonts->AddFontDefault(); //io.Fonts->AddFontFromFileTTF("../../misc/fonts/Roboto-Medium.ttf", 16.0f); //io.Fonts->AddFontFromFileTTF("../../misc/fonts/Cousine-Regular.ttf", 15.0f); diff --git a/examples/vulkan_example/main.cpp b/examples/vulkan_example/main.cpp index 41939aab0dc5..6a2c342cf35d 100644 --- a/examples/vulkan_example/main.cpp +++ b/examples/vulkan_example/main.cpp @@ -614,6 +614,7 @@ int main(int, char**) setup_vulkan(window); // Setup ImGui binding + ImGuiIO& io = ImGui::GetIO(); (void)io; ImGui_ImplGlfwVulkan_Init_Data init_data = {}; init_data.allocator = g_Allocator; init_data.gpu = g_Gpu; @@ -623,6 +624,7 @@ int main(int, char**) init_data.descriptor_pool = g_DescriptorPool; init_data.check_vk_result = check_vk_result; ImGui_ImplGlfwVulkan_Init(window, true, &init_data); + //io.NavFlags |= ImGuiNavFlags_EnableKeyboard; // Enable Keyboard Controls // Setup style ImGui::StyleColorsDark(); @@ -635,7 +637,6 @@ int main(int, char**) // - The fonts will be rasterized at a given size (w/ oversampling) and stored into a texture when calling ImFontAtlas::Build()/GetTexDataAsXXXX(), which ImGui_ImplXXXX_NewFrame below will call. // - Read 'misc/fonts/README.txt' for more instructions and details. // - Remember that in C/C++ if you want to include a backslash \ in a string literal you need to write a double backslash \\ ! - //ImGuiIO& io = ImGui::GetIO(); //io.Fonts->AddFontDefault(); //io.Fonts->AddFontFromFileTTF("../../misc/fonts/Roboto-Medium.ttf", 16.0f); //io.Fonts->AddFontFromFileTTF("../../misc/fonts/Cousine-Regular.ttf", 15.0f); From 4e5b7612aea7a63aac759f0bf6b26b591bd705ae Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 6 Feb 2018 20:05:21 +0100 Subject: [PATCH 629/823] Nav: Documentation tweaks. (#787) --- imgui.cpp | 49 +++++++++++++++++++++++++++---------------------- imgui.h | 10 +++------- 2 files changed, 30 insertions(+), 29 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 3895c6c93f63..ec2ae3d5bf9e 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -81,7 +81,6 @@ - You can apply arithmetic operators +,*,/ on numerical values. Use +- to subtract (because - would set a negative value!) - Controls are automatically adjusted for OSX to match standard OSX text editing operations. - Gamepad navigation: see suggested mappings in imgui.h ImGuiNavInput_ - - Keyboard navigation: see suggested mappings in imgui.h ImGuiNavInput_ PROGRAMMER GUIDE @@ -212,28 +211,34 @@ USING GAMEPAD/KEYBOARD NAVIGATION [BETA] - - Ask questions and report issues at https://github.com/ocornut/imgui/issues/787. + - Ask questions and report issues at https://github.com/ocornut/imgui/issues/787 - The initial focus was to support game controllers, but keyboard is becoming increasingly and decently usable. - - Your inputs are passed to imgui by filling the io.NavInputs[] array. See 'enum ImGuiNavInput_' in imgui.h for a description of available inputs. - - Please refer to the examples/ application for suggested keyboard and gamepad mapping. - - PS4 users: Consider emulating a mouse cursor with DualShock4 touch pad or a spare analog stick as a mouse-emulation fallback. - - Consoles/Tablet/Phone users: Consider using Synergy host (on your computer) + uSynergy.c (in your console/tablet/phone app) to use your PC mouse/keyboard. - - The ImGuiNavFlags_EnableGamepad and ImGuiNavFlags_EnableKeyboard flags of io.NavFlags are only here to instruct your binding whether to find inputs. - - For gamepad use, the easiest approach is to go all-or-nothing, with a buttons combo that toggle your inputs between imgui and your game/application. - Sharing inputs in a more advanced or granular way between imgui and your game/application may be tricky and requires further work on imgui. - When keyboard navigation is active (io.NavActive + NavFlags_EnableKeyboard), the io.WantCaptureKeyboard is set. - For more advanced uses, you may want to use: - - io.NavActive: true when a window is focused and it doesn't have the ImGuiWindowFlags_NoNavInputs flag set. - - io.NavVisible: true when the navigation cursor is visible (and usually goes false when mouse is used). - - query focus information with e.g. IsWindowFocused(), IsItemFocused() etc. functions. - Please reach out if you think the game vs navigation input sharing could be improved. - - On a TV/console system where readability may be lower or mouse inputs may be awkward, you may want to set the ImGuiNavFlags_MoveMouse flag in io.NavFlags. - Enabling ImGuiNavFlags_MoveMouse instructs dear imgui to move your mouse cursor along with navigation movement. - When enabled, the NewFrame() functions may alter 'io.MousePos' and set 'io.WantMoveMouse' to notify you that it did so. - When that happens your back-end NEEDS to move the OS or underlying mouse cursor on the next frame. Some of the binding in examples/ do that. - (If you set the ImGuiNavFlags_MoveMouse flag but don't honor 'io.WantMoveMouse' properly, imgui will misbehave as it will see your mouse as moving back and forth.) - (In a setup when you may not have easy control over the mouse cursor, e.g. uSynergy.c doesn't expose moving remote mouse cursor, you may want - to set a boolean to ignore your other external mouse positions until the external source is moved again.) + - Keyboard: + - Set io.NavFlags |= ImGuiNavFlags_EnableKeyboard to enable. NewFrame() will automatically fill io.NavInputs[] based on your io.KeyDown[] + io.KeyMap[] arrays. + - When keyboard navigation is active (io.NavActive + NavFlags_EnableKeyboard), the io.WantCaptureKeyboard flag will be set. + For more advanced uses, you may want to read from: + - io.NavActive: true when a window is focused and it doesn't have the ImGuiWindowFlags_NoNavInputs flag set. + - io.NavVisible: true when the navigation cursor is visible (and usually goes false when mouse is used). + - or query focus information with e.g. IsWindowFocused(), IsItemFocused() etc. functions. + Please reach out if you think the game vs navigation input sharing could be improved. + - Gamepad: + - Set io.NavFlags |= ImGuiNavFlags_EnableGamepad to enable. Fill the io.NavInputs[] fields before calling NewFrame(). Note that io.NavInputs[] is cleared by EndFrame(). + - See 'enum ImGuiNavInput_' in imgui.h for a description of inputs. For each entry of io.NavInputs[], set the following values: + 0.0f= not held. 1.0f= fully held. Pass intermediate 0.0f..1.0f values for analog triggers/sticks. + - We uses a simple >0.0f test for activation testing, and won't attempt to test for a dead-zone. + Your code will probably need to transform your raw inputs (such as e.g. remapping your 0.2..0.9 raw input range to 0.0..1.0 imgui range, maybe a power curve, etc.). + - If you need to share inputs between your game and the imgui parts, the easiest approach is to go all-or-nothing, with a buttons combo to toggle the target. + Please reach out if you think the game vs navigation input sharing could be improved. + - Mouse: + - PS4 users: Consider emulating a mouse cursor with DualShock4 touch pad or a spare analog stick as a mouse-emulation fallback. + - Consoles/Tablet/Phone users: Consider using Synergy host (on your computer) + uSynergy.c (in your console/tablet/phone app) to use your PC mouse/keyboard. + - On a TV/console system where readability may be lower or mouse inputs may be awkward, you may want to set the ImGuiNavFlags_MoveMouse flag in io.NavFlags. + Enabling ImGuiNavFlags_MoveMouse instructs dear imgui to move your mouse cursor along with navigation movements. + When enabled, the NewFrame() function may alter 'io.MousePos' and set 'io.WantMoveMouse' to notify you that it wants the mouse cursor to be moved. + When that happens your back-end NEEDS to move the OS or underlying mouse cursor on the next frame. Some of the binding in examples/ do that. + (If you set the ImGuiNavFlags_MoveMouse flag but don't honor 'io.WantMoveMouse' properly, imgui will misbehave as it will see your mouse as moving back and forth.) + (In a setup when you may not have easy control over the mouse cursor, e.g. uSynergy.c doesn't expose moving remote mouse cursor, you may want + to set a boolean to ignore your other external mouse positions until the external source is moved again.) API BREAKING CHANGES diff --git a/imgui.h b/imgui.h index c2163640265c..f4bdb6de1df2 100644 --- a/imgui.h +++ b/imgui.h @@ -704,13 +704,9 @@ enum ImGuiKey_ }; // [BETA] Gamepad/Keyboard directional navigation -// Keyboard: -// - io.NavInputs[] is automatically filled in by NewFrame() if you set io.NavFlags |= ImGuiNavFlags_EnableKeyboard. -// Gamepad: -// - Fill io.NavInputs[] every frame with your gamepad inputs. Note that io.NavInputs[] is _cleared_ in EndFrame(). -// 0.0f= not held. 1.0f= fully held. Pass intermediate 0.0f..1.0f values for analog triggers/sticks. -// - We uses a simple >0.0f test for activation testing, and won't attempt to test for a dead-zone. -// Your code will probably need to transform your raw inputs (such as e.g. remapping your 0.2..0.9 raw input range to 0.0..1.0 imgui range, maybe a power curve, etc.). +// Keyboard: Set io.NavFlags |= ImGuiNavFlags_EnableKeyboard to enable. NewFrame() will automatically fill io.NavInputs[] based on your io.KeyDown[] + io.KeyMap[] arrays. +// Gamepad: Set io.NavFlags |= ImGuiNavFlags_EnableGamepad to enable. Fill the io.NavInputs[] fields before calling NewFrame(). Note that io.NavInputs[] is cleared by EndFrame(). +// Read instructions in imgui.cpp for more details. enum ImGuiNavInput_ { // Gamepad Mapping From 7c16d52f72ec2035d47d71d165a20c0ea70c2244 Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 6 Feb 2018 20:20:34 +0100 Subject: [PATCH 630/823] Updated version to 1.60 WIP to emphasis on the addition of required calls CreateContext/DestroyContext + merged the massive Navigation branch (#1565, #787) --- imgui.cpp | 17 +++++++---------- imgui.h | 7 +++---- imgui_demo.cpp | 2 +- imgui_draw.cpp | 2 +- imgui_internal.h | 4 ++-- 5 files changed, 14 insertions(+), 18 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 4bd37157d2dc..110329d1c8b8 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1,9 +1,6 @@ -// dear imgui, v1.54 WIP +// dear imgui, v1.60 WIP // (main code and documentation) -// ** EXPERIMENTAL GAMEPAD/KEYBOARD NAVIGATION BRANCH -// ** Grep for FIXME-NAV - // Call and read ImGui::ShowDemoWindow() in imgui_demo.cpp for demo code. // Newcomers, read 'Programmer guide' below for notes on how to setup Dear ImGui in your codebase. // Get latest version at https://github.com/ocornut/imgui @@ -253,16 +250,16 @@ Here is a change-log of API breaking changes, if you are using one of the functions listed, expect to have to fix some code. Also read releases logs https://github.com/ocornut/imgui/releases for more details. - - 2018/01/21 (1.XX) - reorganized context handling to be more explicit, + - 2018/02/07 (1.60) - reorganized context handling to be more explicit, - YOU NOW NEED TO CALL ImGui::CreateContext() AT THE BEGINNING OF YOUR APP, AND CALL ImGui::DestroyContext() AT THE END. - removed Shutdown() function, as DestroyContext() serve this purpose. - you may pass a ImFontAtlas* pointer to CreateContext() to share a font atlas between contexts. Otherwhise CreateContext() will create its own font atlas instance. - removed allocator parameters from CreateContext(), they are now setup with SetAllocatorFunctions(), and shared by all contexts. - removed the default global context and font atlas instance, which were confusing for users of DLL reloading and users of multiple contexts. - - 2018/01/11 (1.54) - obsoleted IsAnyWindowHovered() in favor of IsWindowHovered(ImGuiHoveredFlags_AnyWindow). Kept redirection function (will obsolete). - - 2018/01/11 (1.54) - obsoleted IsAnyWindowFocused() in favor of IsWindowFocused(ImGuiFocusedFlags_AnyWindow). Kept redirection function (will obsolete). - - 2018/01/03 (1.54) - renamed ImGuiSizeConstraintCallback to ImGuiSizeCallback, ImGuiSizeConstraintCallbackData to ImGuiSizeCallbackData. - - 2017/12/29 (1.54) - removed CalcItemRectClosestPoint() which was weird and not really used by anyone except demo code. If you need it it's easy to replicate on your side. + - 2018/01/11 (1.60) - obsoleted IsAnyWindowHovered() in favor of IsWindowHovered(ImGuiHoveredFlags_AnyWindow). Kept redirection function (will obsolete). + - 2018/01/11 (1.60) - obsoleted IsAnyWindowFocused() in favor of IsWindowFocused(ImGuiFocusedFlags_AnyWindow). Kept redirection function (will obsolete). + - 2018/01/03 (1.60) - renamed ImGuiSizeConstraintCallback to ImGuiSizeCallback, ImGuiSizeConstraintCallbackData to ImGuiSizeCallbackData. + - 2017/12/29 (1.60) - removed CalcItemRectClosestPoint() which was weird and not really used by anyone except demo code. If you need it it's easy to replicate on your side. - 2017/12/24 (1.53) - renamed the emblematic ShowTestWindow() function to ShowDemoWindow(). Kept redirection function (will obsolete). - 2017/12/21 (1.53) - ImDrawList: renamed style.AntiAliasedShapes to style.AntiAliasedFill for consistency and as a way to explicitly break code that manipulate those flag at runtime. You can now manipulate ImDrawList::Flags - 2017/12/21 (1.53) - ImDrawList: removed 'bool anti_aliased = true' final parameter of ImDrawList::AddPolyline() and ImDrawList::AddConvexPolyFilled(). Prefer manipulating ImDrawList::Flags if you need to toggle them during the frame. @@ -3238,7 +3235,7 @@ void ImGui::NewFrame() for (int n = 0; n < ImGuiKey_COUNT; n++) IM_ASSERT(g.IO.KeyMap[n] >= -1 && g.IO.KeyMap[n] < IM_ARRAYSIZE(g.IO.KeysDown) && "io.KeyMap[] contains an out of bound value (need to be 0..512, or -1 for unmapped key)"); - // Do a simple check for required key mapping (we intentionally do NOT check all keys to not pressure user into setting up everything, but Space is required and was super recently added in 1.54 WIP) + // Do a simple check for required key mapping (we intentionally do NOT check all keys to not pressure user into setting up everything, but Space is required and was super recently added in 1.60 WIP) if (g.IO.NavFlags & ImGuiNavFlags_EnableKeyboard) IM_ASSERT(g.IO.KeyMap[ImGuiKey_Space] != -1 && "ImGuiKey_Space is not mapped, required for keyboard navigation."); diff --git a/imgui.h b/imgui.h index f24876404ec1..a516b8d87d52 100644 --- a/imgui.h +++ b/imgui.h @@ -1,4 +1,4 @@ -// dear imgui, v1.54 WIP +// dear imgui, v1.60 WIP // (headers) // See imgui.cpp file for documentation. @@ -21,8 +21,7 @@ #include // ptrdiff_t, NULL #include // memset, memmove, memcpy, strlen, strchr, strcpy, strcmp -#define IMGUI_VERSION "1.54 WIP" -#define IMGUI_HAS_NAV // navigation branch +#define IMGUI_VERSION "1.60 WIP" // Define attributes of all API symbols declarations, e.g. for DLL under Windows. #ifndef IMGUI_API @@ -1060,7 +1059,7 @@ struct ImGuiIO #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS namespace ImGui { - // OBSOLETED in 1.54 (from Dec 2017) + // OBSOLETED in 1.60 (from Dec 2017) static inline bool IsAnyWindowFocused() { return IsWindowFocused(ImGuiFocusedFlags_AnyWindow); } static inline bool IsAnyWindowHovered() { return IsWindowHovered(ImGuiHoveredFlags_AnyWindow); } static inline ImVec2 CalcItemRectClosestPoint(const ImVec2& pos, bool on_edge = false, float outward = 0.f) { (void)on_edge; (void)outward; IM_ASSERT(0); return pos; } diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 014709182831..ec9fc08e9b90 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.54 WIP +// dear imgui, v1.60 WIP // (demo code) // Message to the person tempted to delete this file when integrating ImGui into their code base: diff --git a/imgui_draw.cpp b/imgui_draw.cpp index cddb1b80d21f..f24a8e6c9fc0 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.54 WIP +// dear imgui, v1.60 WIP // (drawing and font code) // Contains implementation for diff --git a/imgui_internal.h b/imgui_internal.h index 530b7f465826..7ca3a9a7f193 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -1,4 +1,4 @@ -// dear imgui, v1.54 WIP +// dear imgui, v1.60 WIP // (internals) // You may use this file to debug, understand or extend ImGui features but we don't provide any guarantee of forward compatibility! @@ -1026,7 +1026,7 @@ namespace ImGui IMGUI_API bool IsWindowNavFocusable(ImGuiWindow* window); IMGUI_API void Initialize(ImGuiContext* context); - IMGUI_API void Shutdown(ImGuiContext* context); // Since 1.54 this is a _private_ function. You can call DestroyContext() to destroy the context created by CreateContext(). + IMGUI_API void Shutdown(ImGuiContext* context); // Since 1.60 this is a _private_ function. You can call DestroyContext() to destroy the context created by CreateContext(). IMGUI_API void MarkIniSettingsDirty(); IMGUI_API ImGuiSettingsHandler* FindSettingsHandler(const char* type_name); From d17d21da1b6c0e37e437d8f6ad400ffc05e3f159 Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 6 Feb 2018 20:21:29 +0100 Subject: [PATCH 631/823] Warning fix. (#1565) --- imgui.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/imgui.cpp b/imgui.cpp index 110329d1c8b8..af6184571462 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -13069,7 +13069,7 @@ void ImGui::ShowMetricsWindow(bool* p_open) ImGui::Text("Dear ImGui %s", ImGui::GetVersion()); ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate); ImGui::Text("%d vertices, %d indices (%d triangles)", ImGui::GetIO().MetricsRenderVertices, ImGui::GetIO().MetricsRenderIndices, ImGui::GetIO().MetricsRenderIndices / 3); - ImGui::Text("%d allocations", GImAllocatorActiveAllocationsCount); + ImGui::Text("%d allocations", (int)GImAllocatorActiveAllocationsCount); static bool show_clip_rects = true; ImGui::Checkbox("Show clipping rectangles when hovering draw commands", &show_clip_rects); ImGui::Separator(); From 2493f609ef1be38273e3140e028f62065051c7fe Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 6 Feb 2018 20:57:33 +0100 Subject: [PATCH 632/823] Examples: Vulkan: Fix (something changed in GLFW not including vulkan.h, was unwillingly relying on that) --- examples/vulkan_example/imgui_impl_glfw_vulkan.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/examples/vulkan_example/imgui_impl_glfw_vulkan.h b/examples/vulkan_example/imgui_impl_glfw_vulkan.h index 766a9595444a..54918d34a69b 100644 --- a/examples/vulkan_example/imgui_impl_glfw_vulkan.h +++ b/examples/vulkan_example/imgui_impl_glfw_vulkan.h @@ -10,6 +10,8 @@ struct GLFWwindow; +#include + #define IMGUI_VK_QUEUED_FRAMES 2 struct ImGui_ImplGlfwVulkan_Init_Data From 1d5a5ca12e20be85a6ee3cce115aff68c3d1085f Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 6 Feb 2018 21:04:12 +0100 Subject: [PATCH 633/823] README update, updated binaries, sponsors --- README.md | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index c76e6a8f82b8..a18c780821f1 100644 --- a/README.md +++ b/README.md @@ -45,7 +45,8 @@ Binaries/Demo ------------- You should be able to build the examples from sources (tested on Windows/Mac/Linux). If you don't, let me know! If you want to have a quick look at some Dear ImGui features, you can download Windows binaries of the demo app here: -- [imgui-demo-binaries-20171226.zip](http://www.miracleworld.net/imgui/binaries/imgui-demo-binaries-20171226.zip) (Windows binaries, Dear ImGui 1.53 built 2017/12/26, 5 executables) +- [imgui-demo-binaries-20180207.zip](http://www.miracleworld.net/imgui/binaries/imgui-demo-binaries-20180207.zip) (Windows binaries, Dear ImGui 1.60 WIP built 2018/01/07, 5 executables) +The demo applications are unfortunately not yet DPI aware so expect some blurryness on a 4K screen. Bindings -------- @@ -233,18 +234,20 @@ Inspiration, feedback, and testing for early versions: Casey Muratori, Atman Bin Ongoing dear imgui development is financially supported on [**Patreon**](http://www.patreon.com/imgui). Double-chocolate sponsors: +- Blizzard - Media Molecule - Mobigame -- Insomniac Games (sponsored the gamepad/keyboard navigation branch) +- Insomniac Games - Aras Pranckevičius - Lizardcube - Greggman +- DotEmu Salty caramel supporters: -- Jetha Chan, Wild Sheep Studio, Pastagames, Mārtiņš Možeiko, Daniel Collin, Recognition Robotics, Chris Genova, ikrima, Glenn Fiedler, Geoffrey Evans, Dakko Dakko, Mercury Labs, Singularity Demo Group, Mischa Alff, Sebastien Ronsse. +- Jetha Chan, Wild Sheep Studio, Pastagames, Mārtiņš Možeiko, Daniel Collin, Recognition Robotics, Chris Genova, ikrima, Glenn Fiedler, Geoffrey Evans, Dakko Dakko, Mercury Labs, Singularity Demo Group, Mischa Alff, Sebastien Ronsse, Lionel Landwerlin. Caramel supporters: -- Michel Courtine, César Leblic, Dale Kim, Alex Evans, Rui Figueira, Paul Patrashcu, Jerome Lanquetot, Ctrl Alt Ninja, Paul Fleming, Neil Henning, Stephan Dilly, Neil Blakey-Milner, Aleksei, NeiloGD, Justin Paver, FiniteSol, Vincent Pancaldi, James Billot, Robin Hübner, furrtek, Eric, Simon Barratt, Game Atelier, Julian Bosch, Simon Lundmark, Vincent Hamm, Farhan Wali, Jeff Roberts, Matt Reyer, Colin Riley, Victor Martins, Josh Simmons, Garrett Hoofman, Sergio Gonzales, Andrew Berridge, Roy Eltham, Game Preservation Society, Kit framework, Josh Faust, Martin Donlon, Quinton, Felix, Andrew Belt, Codecat, Cort Stratton, Claudio Canepa, Doug McNabb, Emmanuel Julien, Guillaume Chereau, Jeffrey Slutter, Jeremiah Deckard, r-lyeh, Roger Clark, Nekith, Joshua Fisher, Malte Hoffmann, Mustafa Karaalioglu, Merlyn Morgan-Graham, Per Vognsen, Fabian Giesen, Jan Staubach, Matt Hargett, John Shearer, Jesse Chounard, kingcoopa, Miloš Tošić. +- Michel Courtine, César Leblic, Dale Kim, Alex Evans, Rui Figueira, Paul Patrashcu, Jerome Lanquetot, Ctrl Alt Ninja, Paul Fleming, Neil Henning, Stephan Dilly, Neil Blakey-Milner, Aleksei, NeiloGD, Justin Paver, FiniteSol, Vincent Pancaldi, James Billot, Robin Hübner, furrtek, Eric, Simon Barratt, Game Atelier, Julian Bosch, Simon Lundmark, Vincent Hamm, Farhan Wali, Jeff Roberts, Matt Reyer, Colin Riley, Victor Martins, Josh Simmons, Garrett Hoofman, Sergio Gonzales, Andrew Berridge, Roy Eltham, Game Preservation Society, Kit framework, Josh Faust, Martin Donlon, Quinton, Felix, Andrew Belt, Codecat, Cort Stratton, Claudio Canepa, Doug McNabb, Emmanuel Julien, Guillaume Chereau, Jeffrey Slutter, Jeremiah Deckard, r-lyeh, Roger Clark, Nekith, Joshua Fisher, Malte Hoffmann, Mustafa Karaalioglu, Merlyn Morgan-Graham, Per Vognsen, Fabian Giesen, Jan Staubach, Matt Hargett, John Shearer, Jesse Chounard, kingcoopa, Miloš Tošić, Jonas Bernemann, Johan Andersson, Nathan Hartman, Michael Labbe, Tomasz Golebiowski, Louis Schnellbach, Felipe Alfonso, Jimmy Andrews, Bojan Endrovski, Robin Berg Pettersen, Rachel Crawford, Edsel Malasig, Andrew Johnson. And other supporters; thanks! (Please contact me or PR if you would like to be added or removed from this list) From 35804b4438b870c87934dc130d88abab367d31a7 Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 6 Feb 2018 21:05:49 +0100 Subject: [PATCH 634/823] Update README.md --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index a18c780821f1..288625c1b1c2 100644 --- a/README.md +++ b/README.md @@ -41,11 +41,12 @@ _A common misunderstanding is to think that immediate mode gui == immediate mode Dear ImGui allows you create elaborate tools as well as very short-lived ones. On the extreme side of short-liveness: using the Edit&Continue feature of modern compilers you can add a few widgets to tweaks variables while your application is running, and remove the code a minute later! Dear ImGui is not just for tweaking values. You can use it to trace a running algorithm by just emitting text commands. You can use it along with your own reflection data to browse your dataset live. You can use it to expose the internals of a subsystem in your engine, to create a logger, an inspection tool, a profiler, a debugger, an entire game making editor/framework, etc. -Binaries/Demo +Demo Binaries ------------- You should be able to build the examples from sources (tested on Windows/Mac/Linux). If you don't, let me know! If you want to have a quick look at some Dear ImGui features, you can download Windows binaries of the demo app here: - [imgui-demo-binaries-20180207.zip](http://www.miracleworld.net/imgui/binaries/imgui-demo-binaries-20180207.zip) (Windows binaries, Dear ImGui 1.60 WIP built 2018/01/07, 5 executables) + The demo applications are unfortunately not yet DPI aware so expect some blurryness on a 4K screen. Bindings From 8099f8c27041aefedf8b70f989136f3c3750e68a Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 6 Feb 2018 23:19:53 +0100 Subject: [PATCH 635/823] Comments --- imgui.h | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/imgui.h b/imgui.h index a516b8d87d52..29fef705b2f6 100644 --- a/imgui.h +++ b/imgui.h @@ -522,12 +522,16 @@ namespace ImGui IMGUI_API void CaptureKeyboardFromApp(bool capture = true); // manually override io.WantCaptureKeyboard flag next frame (said flag is entirely left for your application handle). e.g. force capture keyboard when your widget is being hovered. IMGUI_API void CaptureMouseFromApp(bool capture = true); // manually override io.WantCaptureMouse flag next frame (said flag is entirely left for your application handle). - // Helpers functions to access memory allocators and clipboard functions. + // Clipboard Utilities (also see the LogToClipboard() function to capture or output text data to the clipboard) + IMGUI_API const char* GetClipboardText(); + IMGUI_API void SetClipboardText(const char* text); + + // Memory Utilities + // All those functions are not reliant on the current context. + // If you reload the contents of imgui.cpp at runtime, you may need to call SetCurrentContext() + SetAllocatorFunctions() again. IMGUI_API void SetAllocatorFunctions(void* (*alloc_func)(size_t sz, void* user_data), void(*free_func)(void* ptr, void* user_data), void* user_data = NULL); IMGUI_API void* MemAlloc(size_t size); IMGUI_API void MemFree(void* ptr); - IMGUI_API const char* GetClipboardText(); - IMGUI_API void SetClipboardText(const char* text); } // namespace ImGui From 88dcbeb7ff0ca3dad5790963dd230353756f0443 Mon Sep 17 00:00:00 2001 From: omar Date: Thu, 8 Feb 2018 21:14:57 +0100 Subject: [PATCH 636/823] Styles: Comments and re-ordered. --- imgui.h | 10 ++--- imgui_draw.cpp | 104 ++++++++++++++++++++++++------------------------- 2 files changed, 57 insertions(+), 57 deletions(-) diff --git a/imgui.h b/imgui.h index 29fef705b2f6..eaf5d29c0bce 100644 --- a/imgui.h +++ b/imgui.h @@ -160,6 +160,11 @@ namespace ImGui IMGUI_API void ShowUserGuide(); // add basic help/info block (not a window): how to manipulate ImGui as a end-user (mouse/keyboard controls). IMGUI_API const char* GetVersion(); + // Styles + IMGUI_API void StyleColorsDark(ImGuiStyle* dst = NULL); // New, recommended style + IMGUI_API void StyleColorsClassic(ImGuiStyle* dst = NULL); // Classic imgui style (default) + IMGUI_API void StyleColorsLight(ImGuiStyle* dst = NULL); // Best used with borders and a custom, thicker font + // Window IMGUI_API bool Begin(const char* name, bool* p_open = NULL, ImGuiWindowFlags flags = 0); // push window to the stack and start appending to it. see .cpp for details. return false when window is collapsed (so you can early out in your code) but you always need to call End() regardless. 'bool* p_open' creates a widget on the upper-right to close the window (which sets your bool to false). IMGUI_API void End(); // always call even if Begin() return false (which indicates a collapsed window)! finish appending to current window, pop it off the window stack. @@ -457,11 +462,6 @@ namespace ImGui IMGUI_API void PushClipRect(const ImVec2& clip_rect_min, const ImVec2& clip_rect_max, bool intersect_with_current_clip_rect); IMGUI_API void PopClipRect(); - // Styles - IMGUI_API void StyleColorsClassic(ImGuiStyle* dst = NULL); - IMGUI_API void StyleColorsDark(ImGuiStyle* dst = NULL); - IMGUI_API void StyleColorsLight(ImGuiStyle* dst = NULL); - // Focus, Activation // (Prefer using "SetItemDefaultFocus()" over "if (IsWindowAppearing()) SetScrollHere()" when applicable, to make your code more forward compatible when navigation branch is merged) IMGUI_API void SetItemDefaultFocus(); // make last item the default focused item of a window. Please use instead of "if (IsWindowAppearing()) SetScrollHere()" to signify "default item". diff --git a/imgui_draw.cpp b/imgui_draw.cpp index f24a8e6c9fc0..10051c4fbd2e 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -127,6 +127,58 @@ using namespace IMGUI_STB_NAMESPACE; // Style functions //----------------------------------------------------------------------------- +void ImGui::StyleColorsDark(ImGuiStyle* dst) +{ + ImGuiStyle* style = dst ? dst : &ImGui::GetStyle(); + ImVec4* colors = style->Colors; + + colors[ImGuiCol_Text] = ImVec4(1.00f, 1.00f, 1.00f, 1.00f); + colors[ImGuiCol_TextDisabled] = ImVec4(0.50f, 0.50f, 0.50f, 1.00f); + colors[ImGuiCol_WindowBg] = ImVec4(0.06f, 0.06f, 0.06f, 0.94f); + colors[ImGuiCol_ChildBg] = ImVec4(1.00f, 1.00f, 1.00f, 0.00f); + colors[ImGuiCol_PopupBg] = ImVec4(0.08f, 0.08f, 0.08f, 0.94f); + colors[ImGuiCol_Border] = ImVec4(0.43f, 0.43f, 0.50f, 0.50f); + colors[ImGuiCol_BorderShadow] = ImVec4(0.00f, 0.00f, 0.00f, 0.00f); + colors[ImGuiCol_FrameBg] = ImVec4(0.16f, 0.29f, 0.48f, 0.54f); + colors[ImGuiCol_FrameBgHovered] = ImVec4(0.26f, 0.59f, 0.98f, 0.40f); + colors[ImGuiCol_FrameBgActive] = ImVec4(0.26f, 0.59f, 0.98f, 0.67f); + colors[ImGuiCol_TitleBg] = ImVec4(0.04f, 0.04f, 0.04f, 1.00f); + colors[ImGuiCol_TitleBgActive] = ImVec4(0.16f, 0.29f, 0.48f, 1.00f); + colors[ImGuiCol_TitleBgCollapsed] = ImVec4(0.00f, 0.00f, 0.00f, 0.51f); + colors[ImGuiCol_MenuBarBg] = ImVec4(0.14f, 0.14f, 0.14f, 1.00f); + colors[ImGuiCol_ScrollbarBg] = ImVec4(0.02f, 0.02f, 0.02f, 0.53f); + colors[ImGuiCol_ScrollbarGrab] = ImVec4(0.31f, 0.31f, 0.31f, 1.00f); + colors[ImGuiCol_ScrollbarGrabHovered] = ImVec4(0.41f, 0.41f, 0.41f, 1.00f); + colors[ImGuiCol_ScrollbarGrabActive] = ImVec4(0.51f, 0.51f, 0.51f, 1.00f); + colors[ImGuiCol_CheckMark] = ImVec4(0.26f, 0.59f, 0.98f, 1.00f); + colors[ImGuiCol_SliderGrab] = ImVec4(0.24f, 0.52f, 0.88f, 1.00f); + colors[ImGuiCol_SliderGrabActive] = ImVec4(0.26f, 0.59f, 0.98f, 1.00f); + colors[ImGuiCol_Button] = ImVec4(0.26f, 0.59f, 0.98f, 0.40f); + colors[ImGuiCol_ButtonHovered] = ImVec4(0.26f, 0.59f, 0.98f, 1.00f); + colors[ImGuiCol_ButtonActive] = ImVec4(0.06f, 0.53f, 0.98f, 1.00f); + colors[ImGuiCol_Header] = ImVec4(0.26f, 0.59f, 0.98f, 0.31f); + colors[ImGuiCol_HeaderHovered] = ImVec4(0.26f, 0.59f, 0.98f, 0.80f); + colors[ImGuiCol_HeaderActive] = ImVec4(0.26f, 0.59f, 0.98f, 1.00f); + colors[ImGuiCol_Separator] = colors[ImGuiCol_Border]; + colors[ImGuiCol_SeparatorHovered] = ImVec4(0.10f, 0.40f, 0.75f, 0.78f); + colors[ImGuiCol_SeparatorActive] = ImVec4(0.10f, 0.40f, 0.75f, 1.00f); + colors[ImGuiCol_ResizeGrip] = ImVec4(0.26f, 0.59f, 0.98f, 0.25f); + colors[ImGuiCol_ResizeGripHovered] = ImVec4(0.26f, 0.59f, 0.98f, 0.67f); + colors[ImGuiCol_ResizeGripActive] = ImVec4(0.26f, 0.59f, 0.98f, 0.95f); + colors[ImGuiCol_CloseButton] = ImVec4(0.41f, 0.41f, 0.41f, 0.50f); + colors[ImGuiCol_CloseButtonHovered] = ImVec4(0.98f, 0.39f, 0.36f, 1.00f); + colors[ImGuiCol_CloseButtonActive] = ImVec4(0.98f, 0.39f, 0.36f, 1.00f); + colors[ImGuiCol_PlotLines] = ImVec4(0.61f, 0.61f, 0.61f, 1.00f); + colors[ImGuiCol_PlotLinesHovered] = ImVec4(1.00f, 0.43f, 0.35f, 1.00f); + colors[ImGuiCol_PlotHistogram] = ImVec4(0.90f, 0.70f, 0.00f, 1.00f); + colors[ImGuiCol_PlotHistogramHovered] = ImVec4(1.00f, 0.60f, 0.00f, 1.00f); + colors[ImGuiCol_TextSelectedBg] = ImVec4(0.26f, 0.59f, 0.98f, 0.35f); + colors[ImGuiCol_ModalWindowDarkening] = ImVec4(0.80f, 0.80f, 0.80f, 0.35f); + colors[ImGuiCol_DragDropTarget] = ImVec4(1.00f, 1.00f, 0.00f, 0.90f); + colors[ImGuiCol_NavHighlight] = ImVec4(0.26f, 0.59f, 0.98f, 1.00f); + colors[ImGuiCol_NavWindowingHighlight] = ImVec4(1.00f, 1.00f, 1.00f, 0.70f); +} + void ImGui::StyleColorsClassic(ImGuiStyle* dst) { ImGuiStyle* style = dst ? dst : &ImGui::GetStyle(); @@ -179,58 +231,6 @@ void ImGui::StyleColorsClassic(ImGuiStyle* dst) colors[ImGuiCol_NavWindowingHighlight] = ImVec4(1.00f, 1.00f, 1.00f, 0.70f); } -void ImGui::StyleColorsDark(ImGuiStyle* dst) -{ - ImGuiStyle* style = dst ? dst : &ImGui::GetStyle(); - ImVec4* colors = style->Colors; - - colors[ImGuiCol_Text] = ImVec4(1.00f, 1.00f, 1.00f, 1.00f); - colors[ImGuiCol_TextDisabled] = ImVec4(0.50f, 0.50f, 0.50f, 1.00f); - colors[ImGuiCol_WindowBg] = ImVec4(0.06f, 0.06f, 0.06f, 0.94f); - colors[ImGuiCol_ChildBg] = ImVec4(1.00f, 1.00f, 1.00f, 0.00f); - colors[ImGuiCol_PopupBg] = ImVec4(0.08f, 0.08f, 0.08f, 0.94f); - colors[ImGuiCol_Border] = ImVec4(0.43f, 0.43f, 0.50f, 0.50f); - colors[ImGuiCol_BorderShadow] = ImVec4(0.00f, 0.00f, 0.00f, 0.00f); - colors[ImGuiCol_FrameBg] = ImVec4(0.16f, 0.29f, 0.48f, 0.54f); - colors[ImGuiCol_FrameBgHovered] = ImVec4(0.26f, 0.59f, 0.98f, 0.40f); - colors[ImGuiCol_FrameBgActive] = ImVec4(0.26f, 0.59f, 0.98f, 0.67f); - colors[ImGuiCol_TitleBg] = ImVec4(0.04f, 0.04f, 0.04f, 1.00f); - colors[ImGuiCol_TitleBgActive] = ImVec4(0.16f, 0.29f, 0.48f, 1.00f); - colors[ImGuiCol_TitleBgCollapsed] = ImVec4(0.00f, 0.00f, 0.00f, 0.51f); - colors[ImGuiCol_MenuBarBg] = ImVec4(0.14f, 0.14f, 0.14f, 1.00f); - colors[ImGuiCol_ScrollbarBg] = ImVec4(0.02f, 0.02f, 0.02f, 0.53f); - colors[ImGuiCol_ScrollbarGrab] = ImVec4(0.31f, 0.31f, 0.31f, 1.00f); - colors[ImGuiCol_ScrollbarGrabHovered] = ImVec4(0.41f, 0.41f, 0.41f, 1.00f); - colors[ImGuiCol_ScrollbarGrabActive] = ImVec4(0.51f, 0.51f, 0.51f, 1.00f); - colors[ImGuiCol_CheckMark] = ImVec4(0.26f, 0.59f, 0.98f, 1.00f); - colors[ImGuiCol_SliderGrab] = ImVec4(0.24f, 0.52f, 0.88f, 1.00f); - colors[ImGuiCol_SliderGrabActive] = ImVec4(0.26f, 0.59f, 0.98f, 1.00f); - colors[ImGuiCol_Button] = ImVec4(0.26f, 0.59f, 0.98f, 0.40f); - colors[ImGuiCol_ButtonHovered] = ImVec4(0.26f, 0.59f, 0.98f, 1.00f); - colors[ImGuiCol_ButtonActive] = ImVec4(0.06f, 0.53f, 0.98f, 1.00f); - colors[ImGuiCol_Header] = ImVec4(0.26f, 0.59f, 0.98f, 0.31f); - colors[ImGuiCol_HeaderHovered] = ImVec4(0.26f, 0.59f, 0.98f, 0.80f); - colors[ImGuiCol_HeaderActive] = ImVec4(0.26f, 0.59f, 0.98f, 1.00f); - colors[ImGuiCol_Separator] = colors[ImGuiCol_Border];//ImVec4(0.61f, 0.61f, 0.61f, 1.00f); - colors[ImGuiCol_SeparatorHovered] = ImVec4(0.10f, 0.40f, 0.75f, 0.78f); - colors[ImGuiCol_SeparatorActive] = ImVec4(0.10f, 0.40f, 0.75f, 1.00f); - colors[ImGuiCol_ResizeGrip] = ImVec4(0.26f, 0.59f, 0.98f, 0.25f); - colors[ImGuiCol_ResizeGripHovered] = ImVec4(0.26f, 0.59f, 0.98f, 0.67f); - colors[ImGuiCol_ResizeGripActive] = ImVec4(0.26f, 0.59f, 0.98f, 0.95f); - colors[ImGuiCol_CloseButton] = ImVec4(0.41f, 0.41f, 0.41f, 0.50f); - colors[ImGuiCol_CloseButtonHovered] = ImVec4(0.98f, 0.39f, 0.36f, 1.00f); - colors[ImGuiCol_CloseButtonActive] = ImVec4(0.98f, 0.39f, 0.36f, 1.00f); - colors[ImGuiCol_PlotLines] = ImVec4(0.61f, 0.61f, 0.61f, 1.00f); - colors[ImGuiCol_PlotLinesHovered] = ImVec4(1.00f, 0.43f, 0.35f, 1.00f); - colors[ImGuiCol_PlotHistogram] = ImVec4(0.90f, 0.70f, 0.00f, 1.00f); - colors[ImGuiCol_PlotHistogramHovered] = ImVec4(1.00f, 0.60f, 0.00f, 1.00f); - colors[ImGuiCol_TextSelectedBg] = ImVec4(0.26f, 0.59f, 0.98f, 0.35f); - colors[ImGuiCol_ModalWindowDarkening] = ImVec4(0.80f, 0.80f, 0.80f, 0.35f); - colors[ImGuiCol_DragDropTarget] = ImVec4(1.00f, 1.00f, 0.00f, 0.90f); - colors[ImGuiCol_NavHighlight] = ImVec4(0.26f, 0.59f, 0.98f, 1.00f); - colors[ImGuiCol_NavWindowingHighlight] = ImVec4(1.00f, 1.00f, 1.00f, 0.70f); -} - // Those light colors are better suited with a thicker font than the default one + FrameBorder void ImGui::StyleColorsLight(ImGuiStyle* dst) { From 3b163ac35baa3475364f2b22f59572da1fcafddd Mon Sep 17 00:00:00 2001 From: omar Date: Thu, 8 Feb 2018 23:11:51 +0100 Subject: [PATCH 637/823] Internals: Clarified internal storage for RootWindow with specific semantic (the Docking branch will need to introduce finer differenciation there.) --- imgui.cpp | 32 ++++++++++++++++---------------- imgui_internal.h | 7 ++++--- 2 files changed, 20 insertions(+), 19 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index af6184571462..9dac3c839579 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1938,9 +1938,10 @@ ImGuiWindow::ImGuiWindow(ImGuiContext* context, const char* name) DrawList->_OwnerName = Name; ParentWindow = NULL; RootWindow = NULL; - RootNonPopupWindow = NULL; + RootWindowForTitleBarHighlight = NULL; + RootWindowForTabbing = NULL; + RootWindowForNav = NULL; - NavRootWindow = NULL; NavLastIds[0] = NavLastIds[1] = 0; NavRectRel[0] = NavRectRel[1] = ImRect(); NavLastChildNavWindow = NULL; @@ -2408,7 +2409,7 @@ bool ImGui::ItemAdd(const ImRect& bb, ImGuiID id, const ImRect* nav_bb_arg) // We could early out with "if (is_clipped && !g.NavInitRequest) return false;" but when we wouldn't be able to reach unclipped widgets. This would work if user had explicit scrolling control (e.g. mapped on a stick) window->DC.NavLayerActiveMaskNext |= window->DC.NavLayerCurrentMask; if (g.NavId == id || g.NavAnyRequest) - if (g.NavWindow->NavRootWindow == window->NavRootWindow) + if (g.NavWindow->RootWindowForNav == window->RootWindowForNav) if (window == g.NavWindow || ((window->Flags | g.NavWindow->Flags) & ImGuiWindowFlags_NavFlattened)) NavProcessItem(window, nav_bb_arg ? *nav_bb_arg : bb, id); } @@ -2808,7 +2809,7 @@ static void ImGui::NavUpdateWindowing() if (start_windowing_with_gamepad || start_windowing_with_keyboard) if (ImGuiWindow* window = g.NavWindow ? g.NavWindow : FindWindowNavigable(g.Windows.Size - 1, -INT_MAX, -1)) { - g.NavWindowingTarget = window->RootNonPopupWindow; + g.NavWindowingTarget = window->RootWindowForTabbing; g.NavWindowingHighlightTimer = g.NavWindowingHighlightAlpha = 0.0f; g.NavWindowingToggleLayer = start_windowing_with_keyboard ? false : true; g.NavWindowingInputSource = start_windowing_with_keyboard ? ImGuiInputSource_NavKeyboard : ImGuiInputSource_NavGamepad; @@ -2877,7 +2878,7 @@ static void ImGui::NavUpdateWindowing() } // Apply final focus - if (apply_focus_window && (g.NavWindow == NULL || apply_focus_window != g.NavWindow->RootNonPopupWindow)) + if (apply_focus_window && (g.NavWindow == NULL || apply_focus_window != g.NavWindow->RootWindowForTabbing)) { g.NavDisableHighlight = false; g.NavDisableMouseHover = true; @@ -5659,14 +5660,13 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) // Initialize window->ParentWindow = parent_window; - window->RootWindow = window->RootNonPopupWindow = window; + window->RootWindow = window->RootWindowForTitleBarHighlight = window->RootWindowForTabbing = window->RootWindowForNav = window; if (parent_window && (flags & ImGuiWindowFlags_ChildWindow) && !window_is_child_tooltip) window->RootWindow = parent_window->RootWindow; if (parent_window && !(flags & ImGuiWindowFlags_Modal) && (flags & (ImGuiWindowFlags_ChildWindow | ImGuiWindowFlags_Popup))) - window->RootNonPopupWindow = parent_window->RootNonPopupWindow; - window->NavRootWindow = window; - while (window->NavRootWindow->Flags & ImGuiWindowFlags_NavFlattened) - window->NavRootWindow = window->NavRootWindow->ParentWindow; + window->RootWindowForTitleBarHighlight = window->RootWindowForTabbing = parent_window->RootWindowForTitleBarHighlight; // Same value in master branch, will differ for docking + while (window->RootWindowForNav->Flags & ImGuiWindowFlags_NavFlattened) + window->RootWindowForNav = window->RootWindowForNav->ParentWindow; window->Active = true; window->BeginOrderWithinParent = 0; @@ -5894,14 +5894,14 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) // Draw window + handle manual resize const float window_rounding = window->WindowRounding; const float window_border_size = window->WindowBorderSize; - ImRect title_bar_rect = window->TitleBarRect(); - const bool window_is_focused = want_focus || (g.NavWindow && window->RootNonPopupWindow == g.NavWindow->RootNonPopupWindow); + const bool title_bar_is_highlight = want_focus || (g.NavWindow && window->RootWindowForTitleBarHighlight == g.NavWindow->RootWindowForTitleBarHighlight); + const ImRect title_bar_rect = window->TitleBarRect(); if (window->Collapsed) { // Title bar only float backup_border_size = style.FrameBorderSize; g.Style.FrameBorderSize = window->WindowBorderSize; - ImU32 title_bar_col = GetColorU32((window_is_focused && !g.NavDisableHighlight) ? ImGuiCol_TitleBgActive : ImGuiCol_TitleBgCollapsed); + ImU32 title_bar_col = GetColorU32((title_bar_is_highlight && !g.NavDisableHighlight) ? ImGuiCol_TitleBgActive : ImGuiCol_TitleBgCollapsed); RenderFrame(title_bar_rect.Min, title_bar_rect.Max, title_bar_col, true, window_rounding); g.Style.FrameBorderSize = backup_border_size; } @@ -5917,7 +5917,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) window->DrawList->AddRectFilled(window->Pos+ImVec2(0,window->TitleBarHeight()), window->Pos+window->Size, bg_col, window_rounding, (flags & ImGuiWindowFlags_NoTitleBar) ? ImDrawCornerFlags_All : ImDrawCornerFlags_Bot); // Title bar - ImU32 title_bar_col = GetColorU32(window->Collapsed ? ImGuiCol_TitleBgCollapsed : window_is_focused ? ImGuiCol_TitleBgActive : ImGuiCol_TitleBg); + ImU32 title_bar_col = GetColorU32(window->Collapsed ? ImGuiCol_TitleBgCollapsed : title_bar_is_highlight ? ImGuiCol_TitleBgActive : ImGuiCol_TitleBg); if (!(flags & ImGuiWindowFlags_NoTitleBar)) window->DrawList->AddRectFilled(title_bar_rect.Min, title_bar_rect.Max, title_bar_col, window_rounding, ImDrawCornerFlags_Top); @@ -6753,7 +6753,7 @@ bool ImGui::IsWindowFocused(ImGuiFocusedFlags flags) bool ImGui::IsWindowNavFocusable(ImGuiWindow* window) { ImGuiContext& g = *GImGui; - return window->Active && window == window->RootNonPopupWindow && (!(window->Flags & ImGuiWindowFlags_NoNavFocus) || window == g.NavWindow); + return window->Active && window == window->RootWindowForTabbing && (!(window->Flags & ImGuiWindowFlags_NoNavFocus) || window == g.NavWindow); } float ImGui::GetWindowWidth() @@ -7198,7 +7198,7 @@ void ImGui::SetItemDefaultFocus() ImGuiWindow* window = g.CurrentWindow; if (!window->Appearing) return; - if (g.NavWindow == window->NavRootWindow && (g.NavInitRequest || g.NavInitResultId != 0) && g.NavLayer == g.NavWindow->DC.NavLayerCurrent) + if (g.NavWindow == window->RootWindowForNav && (g.NavInitRequest || g.NavInitResultId != 0) && g.NavLayer == g.NavWindow->DC.NavLayerCurrent) { g.NavInitRequest = false; g.NavInitResultId = g.NavWindow->DC.LastItemId; diff --git a/imgui_internal.h b/imgui_internal.h index 7ca3a9a7f193..168d337b96f1 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -957,10 +957,11 @@ struct IMGUI_API ImGuiWindow float FontWindowScale; // Scale multiplier per-window ImDrawList* DrawList; ImGuiWindow* ParentWindow; // If we are a child _or_ popup window, this is pointing to our parent. Otherwise NULL. - ImGuiWindow* RootWindow; // Generally point to ourself. If we are a child window, this is pointing to the first non-child parent window. - ImGuiWindow* RootNonPopupWindow; // Generally point to ourself. Used to display TitleBgActive color and for selecting which window to use for NavWindowing + ImGuiWindow* RootWindow; // Point to ourself or first ancestor that is not a child window. + ImGuiWindow* RootWindowForTitleBarHighlight; // Point to ourself or first ancestor which will display TitleBgActive color when this window is active. + ImGuiWindow* RootWindowForTabbing; // Point to ourself or first ancestor which can be CTRL-Tabbed into. + ImGuiWindow* RootWindowForNav; // Point to ourself or first ancestor which doesn't have the NavFlattened flag. - ImGuiWindow* NavRootWindow; // Generally point to ourself. If we are a child window with the NavFlattened flag, point to a parent window. ImGuiWindow* NavLastChildNavWindow; // When going to the menu bar, we remember the child window we came from. (This could probably be made implicit if we kept g.Windows sorted by last focused including child window.) ImGuiID NavLastIds[2]; // Last known NavId for this window, per layer (0/1) ImRect NavRectRel[2]; // Reference rectangle, in window relative space From f38979b26658bb3d7b7b2e208e9867f511738b3a Mon Sep 17 00:00:00 2001 From: omar Date: Fri, 9 Feb 2018 11:57:23 +0100 Subject: [PATCH 638/823] Update README.md --- README.md | 52 +++++++++++++++++++++++++++++++++------------------- 1 file changed, 33 insertions(+), 19 deletions(-) diff --git a/README.md b/README.md index 288625c1b1c2..29483bfe06ff 100644 --- a/README.md +++ b/README.md @@ -72,11 +72,11 @@ Languages: Frameworks: - Main ImGui repository include examples for DirectX9, DirectX10, DirectX11, OpenGL2/3, Vulkan, Allegro 5, SDL+GL2/3, iOS and Marmalade: https://github.com/ocornut/imgui/tree/master/examples -- Unmerged PR: DirectX12: https://github.com/ocornut/imgui/pull/301 -- Unmerged PR: SDL2 + OpenGLES + Emscripten: https://github.com/ocornut/imgui/pull/336 -- Unmerged PR: FreeGlut + OpenGL2: https://github.com/ocornut/imgui/pull/801 -- Unmerged PR: Native Win32 and OSX: https://github.com/ocornut/imgui/pull/281 -- Unmerged PR: Android: https://github.com/ocornut/imgui/pull/421 +- PR: DirectX12: https://github.com/ocornut/imgui/pull/301 +- PR: SDL2 + OpenGLES + Emscripten: https://github.com/ocornut/imgui/pull/336 +- PR: FreeGlut + OpenGL2: https://github.com/ocornut/imgui/pull/801 +- PR: Native Win32 and OSX: https://github.com/ocornut/imgui/pull/281 +- PR: Android: https://github.com/ocornut/imgui/pull/421 - Cinder: https://github.com/simongeilfus/Cinder-ImGui - cocos2d-x: https://github.com/c0i/imguix https://github.com/ocornut/imgui/issues/551 - Flexium/SFML (FlexGUI): https://github.com/DXsmiley/FlexGUI @@ -86,7 +86,7 @@ Frameworks: - openFrameworks (ofxImGui): https://github.com/jvcleave/ofxImGui - OpenSceneGraph/OSG: https://gist.github.com/fulezi/d2442ca7626bf270226014501357042c - LÖVE: https://github.com/slages/love-imgui -- NanoRT (software raytraced) https://github.com/syoyo/imgui/tree/nanort/examples/raytrace_example +- NanoRT (software raytraced) https://github.com/syoyo/imgui/tree/nanort - Qt3d https://github.com/alpqr/imgui-qt3d - Unreal Engine 4: https://github.com/segross/UnrealImGui or https://github.com/sronsse/UnrealEngine_ImGui - SFML: https://github.com/EliasD/imgui-sfml or https://github.com/Mischa-Alff/imgui-backends @@ -97,23 +97,33 @@ Please contact me with the Issues tracker or Twitter to fix/update this list. Gallery ------- -See the [Screenshots Thread](https://github.com/ocornut/imgui/issues/123) for some user creations. -Also see the [Mega screenshots](https://github.com/ocornut/imgui/issues/1273) for an idea of the available features. +User screenshots: +
[Gallery Part 1](https://github.com/ocornut/imgui/issues/123) (Feb 2015 to Feb 2016) +
[Gallery Part 2](https://github.com/ocornut/imgui/issues/539) (Feb 2016 to Aug 2016) +
[Gallery Part 3](https://github.com/ocornut/imgui/issues/772) (Aug 2016 to Jan 2017) +
[Gallery Part 4](https://github.com/ocornut/imgui/issues/973) (Jan 2017 to Aug 2017) +
[Gallery Part 5](https://github.com/ocornut/imgui/issues/1269) (Aug 2017 onward) +
Also see the [Mega screenshots](https://github.com/ocornut/imgui/issues/1273) for an idea of the available features. ![screenshot 1](https://raw.githubusercontent.com/wiki/ocornut/imgui/web/v148/examples_01.png) -[![screenshot game](https://raw.githubusercontent.com/wiki/ocornut/imgui/web/v149/gallery_TheDragonsTrap-01-thumb.jpg)](https://cloud.githubusercontent.com/assets/8225057/20628927/33e14cac-b329-11e6-80f6-9524e93b048a.png) -![screenshot 2](https://raw.githubusercontent.com/wiki/ocornut/imgui/web/v148/examples_02.png) -[![screenshot profiler](https://raw.githubusercontent.com/wiki/ocornut/imgui/web/v148/profiler-880.jpg)](https://raw.githubusercontent.com/wiki/ocornut/imgui/web/v148/profiler.png) +Various tools +
[![screenshot game](https://raw.githubusercontent.com/wiki/ocornut/imgui/web/v149/gallery_TheDragonsTrap-01-thumb.jpg)](https://cloud.githubusercontent.com/assets/8225057/20628927/33e14cac-b329-11e6-80f6-9524e93b048a.png) -![screenshot picker](https://user-images.githubusercontent.com/8225057/29062188-471e95ba-7c53-11e7-9618-c4484c0b75fe.PNG) +A custom profiler +
[![screenshot profiler](https://raw.githubusercontent.com/wiki/ocornut/imgui/web/v148/profiler-880.jpg)](https://raw.githubusercontent.com/wiki/ocornut/imgui/web/v148/profiler.png) + +Color Pickers +
![screenshot picker](https://user-images.githubusercontent.com/8225057/29062188-471e95ba-7c53-11e7-9618-c4484c0b75fe.PNG) + +Menus +
![screenshot 5](https://raw.githubusercontent.com/wiki/ocornut/imgui/web/v151/menus.png) -![screenshot 5](https://raw.githubusercontent.com/wiki/ocornut/imgui/web/v151/menus.png) ![screenshot 6](https://raw.githubusercontent.com/wiki/ocornut/imgui/web/v143/skinning_sample_02.png) ![screenshot 7](https://cloud.githubusercontent.com/assets/8225057/7903336/96f0fb7c-07d0-11e5-95d6-41c6a1595e5a.png) Dear ImGui can load TTF/OTF fonts. UTF-8 is supported for text display and input. Here using Arial Unicode font to display Japanese. Initialize custom font with: -``` +```cpp ImGuiIO& io = ImGui::GetIO(); io.Fonts->AddFontFromFileTTF("ArialUni.ttf", 18.0f, NULL, io.Fonts->GetGlyphRangesJapanese()); @@ -149,15 +159,15 @@ Frequently Asked Question (FAQ) Which version should I get? -I occasionally tag [Releases](https://github.com/ocornut/imgui/releases) but it is generally safe and recommended to sync to master. The library is fairly stable and regressions tend to be fixed fast when reported. You may also want to checkout the [navigation branch](https://github.com/ocornut/imgui/tree/navigation) if you want to use Dear ImGui with a gamepad (it is also possible to map keyboard inputs to some degree). The Navigation branch is being kept up to date with Master. +I occasionally tag [Releases](https://github.com/ocornut/imgui/releases) but it is generally safe and recommended to sync to master. The library is fairly stable and regressions tend to be fixed fast when reported. Why the odd dual naming, "dear imgui" vs "ImGui"? The library started its life and is best known as "ImGui" only due to the fact that I didn't give it a proper name when I released it. However, the term IMGUI (immediate-mode graphical user interface) was coined before and is being used in variety of other situations. It seemed confusing and unfair to hog the name. To reduce the ambiguity without affecting existing codebases, I have decided on an alternate, longer name "dear imgui" that people can use to refer to this specific library in ambiguous situations. -How can I help +How can I help?
How can I display an image? What is ImTextureID, how does it works? -
How can I have multiple widgets with the same label? Can I have widget without a label? (Yes). A primer on labels and the ID stack. +
How can I have multiple widgets with the same label? Can I have widget without a label? (Yes). A primer on labels and ID stack.
How can I tell when Dear ImGui wants my mouse/keyboard inputs VS when I can pass them to my application?
How can I load a different font than the default?
How can I easily use icons in my application? @@ -172,11 +182,15 @@ See the FAQ in imgui.cpp for answers. How do you use Dear ImGui on a platform that may not have a mouse or keyboard? -I recommend using [Synergy](http://synergy-project.org) ([sources](https://github.com/symless/synergy)). In particular, the _src/micro/uSynergy.c_ file contains a small client that you can use on any platform to connect to your host PC. You can seamlessly use your PC input devices from a video game console or a tablet. Dear ImGui allows to increase the hit box of widgets (via the _style.TouchPadding_ setting) to accommodate a little for the lack of precision of touch inputs, but it is recommended you use a mouse to allow optimising for screen real-estate. You can also checkout the beta [navigation branch](https://github.com/ocornut/imgui/tree/navigation) which provides support for using Dear ImGui with a game controller. +You can control Dear ImGui with a gamepad, see the explanation in imgui.cpp about how to use the navigation feature (short version: map your gamepad inputs into the `io.NavInputs[]` array and set `io.NavFlags |= ImGuiNavFlags_EnableGamepad`). + +You can share your computer mouse seamlessy with your console/tablet/phone using [Synergy](http://synergy-project.org) ([sources](https://github.com/symless/synergy)). This is the prefered solution for developer productivity. In particular, their [micro-synergy-client](https://github.com/symless/micro-synergy-client) repo there is _uSynergy.c_ sources for a small embeddable that you can use on any platform to connect to your host PC. You may also use a third party solution such as [Remote ImGui](https://github.com/JordiRos/remoteimgui). + +For touch inputs, you can increase the hit box of widgets (via the _style.TouchPadding_ setting) to accommodate a little for the lack of precision of touch inputs, but it is recommended you use a mouse or gamepad to allow optimising for screen real-estate and precision. Can you create elaborate/serious tools with Dear ImGui? -Yes. People have written game editors, data browsers, debuggers, profilers and all sort of non-trivial tools with the library. In my experience the simplicity of the API is very empowering. Your UI runs close to your live data. Make the tools always-on and everybody in the team will be inclined to create new tools (as opposed to more "offline" UI toolkits where only a fraction of your team effectively creates tools). +Yes. People have written game editors, data browsers, debuggers, profilers and all sort of non-trivial tools with the library. In my experience the simplicity of the API is very empowering. Your UI runs close to your live data. Make the tools always-on and everybody in the team will be inclined to create new tools (as opposed to more "offline" UI toolkits where only a fraction of your team effectively creates tools). The list of sponsors below is also an indicator that serious game teams have been using the library. Dear ImGui is very programmer centric and the immediate-mode GUI paradigm might requires you to readjust some habits before you can realize its full potential. Dear ImGui is about making things that are simple, efficient and powerful. From 56411155687aef720427f2ad8ea45eeaee59bab9 Mon Sep 17 00:00:00 2001 From: omar Date: Fri, 9 Feb 2018 12:08:53 +0100 Subject: [PATCH 639/823] Update README.md --- README.md | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 29483bfe06ff..c1db4104537b 100644 --- a/README.md +++ b/README.md @@ -110,7 +110,7 @@ User screenshots: Various tools
[![screenshot game](https://raw.githubusercontent.com/wiki/ocornut/imgui/web/v149/gallery_TheDragonsTrap-01-thumb.jpg)](https://cloud.githubusercontent.com/assets/8225057/20628927/33e14cac-b329-11e6-80f6-9524e93b048a.png) -A custom profiler +Custom profiler
[![screenshot profiler](https://raw.githubusercontent.com/wiki/ocornut/imgui/web/v148/profiler-880.jpg)](https://raw.githubusercontent.com/wiki/ocornut/imgui/web/v148/profiler.png) Color Pickers @@ -119,8 +119,11 @@ Color Pickers Menus
![screenshot 5](https://raw.githubusercontent.com/wiki/ocornut/imgui/web/v151/menus.png) -![screenshot 6](https://raw.githubusercontent.com/wiki/ocornut/imgui/web/v143/skinning_sample_02.png) -![screenshot 7](https://cloud.githubusercontent.com/assets/8225057/7903336/96f0fb7c-07d0-11e5-95d6-41c6a1595e5a.png) +Colors +
![screenshot 6](https://raw.githubusercontent.com/wiki/ocornut/imgui/web/v143/skinning_sample_02.png) + +Custom rendering +
![screenshot 7](https://raw.githubusercontent.com/wiki/ocornut/imgui/web/v160/v160-drawdatabase.jpg) Dear ImGui can load TTF/OTF fonts. UTF-8 is supported for text display and input. Here using Arial Unicode font to display Japanese. Initialize custom font with: ```cpp @@ -167,7 +170,7 @@ The library started its life and is best known as "ImGui" only due to the fact t How can I help?
How can I display an image? What is ImTextureID, how does it works? -
How can I have multiple widgets with the same label? Can I have widget without a label? (Yes). A primer on labels and ID stack. +
How can I have multiple widgets with the same label, or without any label? (Yes). A primer on labels and ID stack.
How can I tell when Dear ImGui wants my mouse/keyboard inputs VS when I can pass them to my application?
How can I load a different font than the default?
How can I easily use icons in my application? @@ -246,7 +249,7 @@ Embeds [stb_textedit.h, stb_truetype.h, stb_rectpack.h](https://github.com/nothi Inspiration, feedback, and testing for early versions: Casey Muratori, Atman Binstock, Mikko Mononen, Emmanuel Briney, Stefan Kamoda, Anton Mikhailov, Matt Willis. And everybody posting feedback, questions and patches on the GitHub. -Ongoing dear imgui development is financially supported on [**Patreon**](http://www.patreon.com/imgui). +Ongoing dear imgui development is financially supported on [**Patreon**](http://www.patreon.com/imgui) and by private sponsors. Double-chocolate sponsors: - Blizzard From febde0eb21bc1df4a682d16a13fa260bd91eb2db Mon Sep 17 00:00:00 2001 From: omar Date: Sat, 10 Feb 2018 15:44:46 +0100 Subject: [PATCH 640/823] Update README.md --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index c1db4104537b..61895552748b 100644 --- a/README.md +++ b/README.md @@ -62,7 +62,8 @@ Languages: - ChaiScript: https://github.com/JuJuBoSc/imgui-chaiscript - D (DerelictImgui): https://github.com/Extrawurst/DerelictImgui - Go (go-imgui): https://github.com/Armored-Dragon/go-imgui -- Haxe/hxcpp (linc_imgui): https://github.com/Aidan63/linc_imgui +- Haxe/hxcpp (linc_imgui): https://github.com/Aidan63/linc_imgui +- JavaScript (imgui-js): https://github.com/flyover/imgui-js - Lua: https://github.com/patrickriordan/imgui_lua_bindings - Odin: https://github.com/ThisDrunkDane/odin-dear_imgui - Pascal (imgui-pas): https://github.com/dpethes/imgui-pas From 7cc1bc7635989e2372102462922378df585e7f03 Mon Sep 17 00:00:00 2001 From: omar Date: Sat, 10 Feb 2018 16:47:13 +0100 Subject: [PATCH 641/823] Added IsAnyMouseDown() helper. Examples: DirectX9/10/11: Using IsAnyMouseDown() instead of local function. --- examples/directx10_example/imgui_impl_dx10.cpp | 17 ++++------------- examples/directx11_example/imgui_impl_dx11.cpp | 17 ++++------------- examples/directx9_example/imgui_impl_dx9.cpp | 17 ++++------------- imgui.cpp | 9 +++++++++ imgui.h | 1 + 5 files changed, 22 insertions(+), 39 deletions(-) diff --git a/examples/directx10_example/imgui_impl_dx10.cpp b/examples/directx10_example/imgui_impl_dx10.cpp index b6c0cf68c3a3..a0bd98bfc522 100644 --- a/examples/directx10_example/imgui_impl_dx10.cpp +++ b/examples/directx10_example/imgui_impl_dx10.cpp @@ -227,15 +227,6 @@ void ImGui_ImplDX10_RenderDrawLists(ImDrawData* draw_data) ctx->IASetInputLayout(old.InputLayout); if (old.InputLayout) old.InputLayout->Release(); } -static bool IsAnyMouseButtonDown() -{ - ImGuiIO& io = ImGui::GetIO(); - for (int n = 0; n < IM_ARRAYSIZE(io.MouseDown); n++) - if (io.MouseDown[n]) - return true; - return false; -} - // Process Win32 mouse/keyboard inputs. // You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs. // - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application. @@ -259,8 +250,8 @@ IMGUI_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hwnd, UINT msg, WPARAM wPa if (msg == WM_LBUTTONDOWN || msg == WM_LBUTTONDBLCLK) button = 0; if (msg == WM_RBUTTONDOWN || msg == WM_RBUTTONDBLCLK) button = 1; if (msg == WM_MBUTTONDOWN || msg == WM_MBUTTONDBLCLK) button = 2; - if (!IsAnyMouseButtonDown() && GetCapture() == NULL) - SetCapture(hwnd); + if (!ImGui::IsAnyMouseDown() && ::GetCapture() == NULL) + ::SetCapture(hwnd); io.MouseDown[button] = true; return 0; } @@ -273,8 +264,8 @@ IMGUI_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hwnd, UINT msg, WPARAM wPa if (msg == WM_RBUTTONUP) button = 1; if (msg == WM_MBUTTONUP) button = 2; io.MouseDown[button] = false; - if (!IsAnyMouseButtonDown() && GetCapture() == hwnd) - ReleaseCapture(); + if (!ImGui::IsAnyMouseDown() && ::GetCapture() == hwnd) + ::ReleaseCapture(); return 0; } case WM_MOUSEWHEEL: diff --git a/examples/directx11_example/imgui_impl_dx11.cpp b/examples/directx11_example/imgui_impl_dx11.cpp index e5cda76da40d..fa77735cada8 100644 --- a/examples/directx11_example/imgui_impl_dx11.cpp +++ b/examples/directx11_example/imgui_impl_dx11.cpp @@ -234,15 +234,6 @@ void ImGui_ImplDX11_RenderDrawLists(ImDrawData* draw_data) ctx->IASetInputLayout(old.InputLayout); if (old.InputLayout) old.InputLayout->Release(); } -static bool IsAnyMouseButtonDown() -{ - ImGuiIO& io = ImGui::GetIO(); - for (int n = 0; n < IM_ARRAYSIZE(io.MouseDown); n++) - if (io.MouseDown[n]) - return true; - return false; -} - // Process Win32 mouse/keyboard inputs. // You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs. // - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application. @@ -266,8 +257,8 @@ IMGUI_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hwnd, UINT msg, WPARAM wPa if (msg == WM_LBUTTONDOWN || msg == WM_LBUTTONDBLCLK) button = 0; if (msg == WM_RBUTTONDOWN || msg == WM_RBUTTONDBLCLK) button = 1; if (msg == WM_MBUTTONDOWN || msg == WM_MBUTTONDBLCLK) button = 2; - if (!IsAnyMouseButtonDown() && GetCapture() == NULL) - SetCapture(hwnd); + if (!ImGui::IsAnyMouseDown() && ::GetCapture() == NULL) + ::SetCapture(hwnd); io.MouseDown[button] = true; return 0; } @@ -280,8 +271,8 @@ IMGUI_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hwnd, UINT msg, WPARAM wPa if (msg == WM_RBUTTONUP) button = 1; if (msg == WM_MBUTTONUP) button = 2; io.MouseDown[button] = false; - if (!IsAnyMouseButtonDown() && GetCapture() == hwnd) - ReleaseCapture(); + if (!ImGui::IsAnyMouseDown() && ::GetCapture() == hwnd) + ::ReleaseCapture(); return 0; } case WM_MOUSEWHEEL: diff --git a/examples/directx9_example/imgui_impl_dx9.cpp b/examples/directx9_example/imgui_impl_dx9.cpp index 613cd10d1425..c89b2478a23a 100644 --- a/examples/directx9_example/imgui_impl_dx9.cpp +++ b/examples/directx9_example/imgui_impl_dx9.cpp @@ -173,15 +173,6 @@ void ImGui_ImplDX9_RenderDrawLists(ImDrawData* draw_data) d3d9_state_block->Release(); } -static bool IsAnyMouseButtonDown() -{ - ImGuiIO& io = ImGui::GetIO(); - for (int n = 0; n < IM_ARRAYSIZE(io.MouseDown); n++) - if (io.MouseDown[n]) - return true; - return false; -} - // Process Win32 mouse/keyboard inputs. // You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs. // - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application. @@ -205,8 +196,8 @@ IMGUI_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hwnd, UINT msg, WPARAM wPa if (msg == WM_LBUTTONDOWN || msg == WM_LBUTTONDBLCLK) button = 0; if (msg == WM_RBUTTONDOWN || msg == WM_RBUTTONDBLCLK) button = 1; if (msg == WM_MBUTTONDOWN || msg == WM_MBUTTONDBLCLK) button = 2; - if (!IsAnyMouseButtonDown() && GetCapture() == NULL) - SetCapture(hwnd); + if (!ImGui::IsAnyMouseDown() && ::GetCapture() == NULL) + ::SetCapture(hwnd); io.MouseDown[button] = true; return 0; } @@ -219,8 +210,8 @@ IMGUI_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hwnd, UINT msg, WPARAM wPa if (msg == WM_RBUTTONUP) button = 1; if (msg == WM_MBUTTONUP) button = 2; io.MouseDown[button] = false; - if (!IsAnyMouseButtonDown() && GetCapture() == hwnd) - ReleaseCapture(); + if (!ImGui::IsAnyMouseDown() && ::GetCapture() == hwnd) + ::ReleaseCapture(); return 0; } case WM_MOUSEWHEEL: diff --git a/imgui.cpp b/imgui.cpp index 9dac3c839579..a0eb2d70d6c7 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -4526,6 +4526,15 @@ bool ImGui::IsMouseDown(int button) return g.IO.MouseDown[button]; } +bool ImGui::IsAnyMouseDown() +{ + ImGuiContext& g = *GImGui; + for (int n = 0; n < IM_ARRAYSIZE(g.IO.MouseDown); n++) + if (g.IO.MouseDown[n]) + return true; + return false; +} + bool ImGui::IsMouseClicked(int button, bool repeat) { ImGuiContext& g = *GImGui; diff --git a/imgui.h b/imgui.h index eaf5d29c0bce..1cfd7e697fa8 100644 --- a/imgui.h +++ b/imgui.h @@ -507,6 +507,7 @@ namespace ImGui IMGUI_API bool IsKeyReleased(int user_key_index); // was key released (went from Down to !Down).. IMGUI_API int GetKeyPressedAmount(int key_index, float repeat_delay, float rate); // uses provided repeat rate/delay. return a count, most often 0 or 1 but might be >1 if RepeatRate is small enough that DeltaTime > RepeatRate IMGUI_API bool IsMouseDown(int button); // is mouse button held + IMGUI_API bool IsAnyMouseDown(); // is any mouse button held IMGUI_API bool IsMouseClicked(int button, bool repeat = false); // did mouse button clicked (went from !Down to Down) IMGUI_API bool IsMouseDoubleClicked(int button); // did mouse button double-clicked. a double-click returns false in IsMouseClicked(). uses io.MouseDoubleClickTime. IMGUI_API bool IsMouseReleased(int button); // did mouse button released (went from Down to !Down) From 64e066680367895e959e7bd79dba4aa4d0676764 Mon Sep 17 00:00:00 2001 From: omar Date: Sun, 11 Feb 2018 22:48:30 +0100 Subject: [PATCH 642/823] Internals: Moved some of NewFrame() into UpdateMovingWindow(). --- imgui.cpp | 76 ++++++++++++++++++++++++++++++------------------------- 1 file changed, 42 insertions(+), 34 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index a0eb2d70d6c7..8204910432a0 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -732,6 +732,7 @@ static void NavUpdate(); static void NavUpdateWindowing(); static void NavProcessItem(ImGuiWindow* window, const ImRect& nav_bb, const ImGuiID id); +static void UpdateMovingWindow(); static void UpdateManualResize(ImGuiWindow* window, const ImVec2& size_auto_fit, int* border_held, int resize_grip_count, ImU32 resize_grip_col[4]); static void FocusFrontMostActiveWindow(ImGuiWindow* ignore_window); } @@ -3219,6 +3220,45 @@ static void ImGui::NavUpdate() #endif } +static void ImGui::UpdateMovingWindow() +{ + ImGuiContext& g = *GImGui; + if (g.MovingWindow && g.MovingWindow->MoveId == g.ActiveId && g.ActiveIdSource == ImGuiInputSource_Mouse) + { + // We actually want to move the root window. g.MovingWindow == window we clicked on (could be a child window). + // We track it to preserve Focus and so that ActiveIdWindow == MovingWindow and ActiveId == MovingWindow->MoveId for consistency. + KeepAliveID(g.ActiveId); + IM_ASSERT(g.MovingWindow && g.MovingWindow->RootWindow); + ImGuiWindow* moving_window = g.MovingWindow->RootWindow; + if (g.IO.MouseDown[0]) + { + ImVec2 pos = g.IO.MousePos - g.ActiveIdClickOffset; + if (moving_window->PosFloat.x != pos.x || moving_window->PosFloat.y != pos.y) + { + MarkIniSettingsDirty(moving_window); + moving_window->PosFloat = pos; + } + FocusWindow(g.MovingWindow); + } + else + { + ClearActiveID(); + g.MovingWindow = NULL; + } + } + else + { + // When clicking/dragging from a window that has the _NoMove flag, we still set the ActiveId in order to prevent hovering others. + if (g.ActiveIdWindow && g.ActiveIdWindow->MoveId == g.ActiveId) + { + KeepAliveID(g.ActiveId); + if (!g.IO.MouseDown[0]) + ClearActiveID(); + } + g.MovingWindow = NULL; + } +} + void ImGui::NewFrame() { IM_ASSERT(GImGui != NULL && "No current context. Did you call ImGui::CreateContext() or ImGui::SetCurrentContext()?"); @@ -3347,40 +3387,8 @@ void ImGui::NewFrame() g.FramerateSecPerFrameIdx = (g.FramerateSecPerFrameIdx + 1) % IM_ARRAYSIZE(g.FramerateSecPerFrame); g.IO.Framerate = 1.0f / (g.FramerateSecPerFrameAccum / (float)IM_ARRAYSIZE(g.FramerateSecPerFrame)); - // Handle user moving window with mouse (at the beginning of the frame to avoid input lag or sheering). - if (g.MovingWindow && g.MovingWindow->MoveId == g.ActiveId && g.ActiveIdSource == ImGuiInputSource_Mouse) - { - KeepAliveID(g.ActiveId); - IM_ASSERT(g.MovingWindow && g.MovingWindow->RootWindow); - if (g.IO.MouseDown[0]) - { - // MovingWindow = window we clicked on, could be a child window. We track it to preserve Focus and so that ActiveIdWindow == MovingWindow and ActiveId == MovingWindow->MoveId for consistency. - ImGuiWindow* actually_moving_window = g.MovingWindow->RootWindow; - ImVec2 pos = g.IO.MousePos - g.ActiveIdClickOffset; - if (actually_moving_window->PosFloat.x != pos.x || actually_moving_window->PosFloat.y != pos.y) - { - MarkIniSettingsDirty(actually_moving_window); - actually_moving_window->PosFloat = pos; - } - FocusWindow(g.MovingWindow); - } - else - { - ClearActiveID(); - g.MovingWindow = NULL; - } - } - else - { - // When clicking/dragging from a window that has the _NoMove flag, we still set the ActiveId in order to prevent hovering others. - if (g.ActiveIdWindow && g.ActiveIdWindow->MoveId == g.ActiveId) - { - KeepAliveID(g.ActiveId); - if (!g.IO.MouseDown[0]) - ClearActiveID(); - } - g.MovingWindow = NULL; - } + // Handle user moving window with mouse (at the beginning of the frame to avoid input lag or sheering) + UpdateMovingWindow(); // Delay saving settings so we don't spam disk too much if (g.SettingsDirtyTimer > 0.0f) From 2c4a761982df036b6b361ae57ea03c680c722769 Mon Sep 17 00:00:00 2001 From: Randy Gaul Date: Mon, 12 Feb 2018 00:50:40 -0800 Subject: [PATCH 643/823] __cdecl markup for non-standard calling conventions via MSVC --- imgui.cpp | 10 ++++++++-- stb_rect_pack.h | 6 ++++-- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index a0eb2d70d6c7..ad4fdfb22f89 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -661,6 +661,12 @@ #pragma warning (disable: 4996) // 'This function or variable may be unsafe': strcpy, strdup, sprintf, vsnprintf, sscanf, fopen #endif +#ifdef _MSC_VER + #define IMGUI_CDECL __cdecl +#else + #define IMGUI_CDECL +#endif + // Clang warnings with -Weverything #ifdef __clang__ #pragma clang diagnostic ignored "-Wunknown-pragmas" // warning : unknown warning group '-Wformat-pedantic *' // not all warnings are known by all clang versions.. so ignoring warnings triggers new warnings on some configuration. great! @@ -1504,7 +1510,7 @@ void ImGuiStorage::BuildSortByKey() { struct StaticFunc { - static int PairCompareByID(const void* lhs, const void* rhs) + static int IMGUI_CDECL PairCompareByID(const void* lhs, const void* rhs) { // We can't just do a subtraction because qsort uses signed integers and subtracting our ID doesn't play well with that. if (((const Pair*)lhs)->key > ((const Pair*)rhs)->key) return +1; @@ -3793,7 +3799,7 @@ static void MarkIniSettingsDirty(ImGuiWindow* window) } // FIXME: Add a more explicit sort order in the window structure. -static int ChildWindowComparer(const void* lhs, const void* rhs) +static int IMGUI_CDECL ChildWindowComparer(const void* lhs, const void* rhs) { const ImGuiWindow* a = *(const ImGuiWindow**)lhs; const ImGuiWindow* b = *(const ImGuiWindow**)rhs; diff --git a/stb_rect_pack.h b/stb_rect_pack.h index c75527da1e08..c581cd01aa88 100644 --- a/stb_rect_pack.h +++ b/stb_rect_pack.h @@ -202,8 +202,10 @@ struct stbrp_context #ifdef _MSC_VER #define STBRP__NOTUSED(v) (void)(v) +#define STBRP__CDECL __cdecl #else #define STBRP__NOTUSED(v) (void)sizeof(v) +#define STBRP__CDECL #endif enum @@ -509,7 +511,7 @@ static stbrp__findresult stbrp__skyline_pack_rectangle(stbrp_context *context, i return res; } -static int rect_height_compare(const void *a, const void *b) +static int STBRP__CDECL rect_height_compare(const void *a, const void *b) { const stbrp_rect *p = (const stbrp_rect *) a; const stbrp_rect *q = (const stbrp_rect *) b; @@ -531,7 +533,7 @@ static int rect_width_compare(const void *a, const void *b) return (p->h > q->h) ? -1 : (p->h < q->h); } -static int rect_original_order(const void *a, const void *b) +static int STBRP__CDECL rect_original_order(const void *a, const void *b) { const stbrp_rect *p = (const stbrp_rect *) a; const stbrp_rect *q = (const stbrp_rect *) b; From ed9d4a2d8521fbcb783e205c4f1df5288fefa502 Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 12 Feb 2018 15:30:37 +0100 Subject: [PATCH 644/823] stb_rect_pack: update to 0.11 (minor changes) --- stb_rect_pack.h | 81 +++++++++++++++++++++++++++++++++++++------------ 1 file changed, 61 insertions(+), 20 deletions(-) diff --git a/stb_rect_pack.h b/stb_rect_pack.h index c75527da1e08..9faf5783d551 100644 --- a/stb_rect_pack.h +++ b/stb_rect_pack.h @@ -1,4 +1,4 @@ -// stb_rect_pack.h - v0.10 - public domain - rectangle packing +// stb_rect_pack.h - v0.11 - public domain - rectangle packing // Sean Barrett 2014 // // Useful for e.g. packing rectangular textures into an atlas. @@ -27,11 +27,14 @@ // Sean Barrett // Minor features // Martins Mozeiko +// github:IntellectualKitty +// // Bugfixes / warning fixes // Jeremy Jaussaud // // Version history: // +// 0.11 (2017-03-03) return packing success/fail result // 0.10 (2016-10-25) remove cast-away-const to avoid warnings // 0.09 (2016-08-27) fix compiler warnings // 0.08 (2015-09-13) really fix bug with empty rects (w=0 or h=0) @@ -43,9 +46,7 @@ // // LICENSE // -// This software is dual-licensed to the public domain and under the following -// license: you are granted a perpetual, irrevocable license to copy, modify, -// publish, and distribute this file as you see fit. +// See end of file for license information. ////////////////////////////////////////////////////////////////////////////// // @@ -77,7 +78,7 @@ typedef int stbrp_coord; typedef unsigned short stbrp_coord; #endif -STBRP_DEF void stbrp_pack_rects (stbrp_context *context, stbrp_rect *rects, int num_rects); +STBRP_DEF int stbrp_pack_rects (stbrp_context *context, stbrp_rect *rects, int num_rects); // Assign packed locations to rectangles. The rectangles are of type // 'stbrp_rect' defined below, stored in the array 'rects', and there // are 'num_rects' many of them. @@ -98,6 +99,9 @@ STBRP_DEF void stbrp_pack_rects (stbrp_context *context, stbrp_rect *rects, int // arrays will probably produce worse packing results than calling it // a single time with the full rectangle array, but the option is // available. +// +// The function returns 1 if all of the rectangles were successfully +// packed and 0 otherwise. struct stbrp_rect { @@ -520,17 +524,6 @@ static int rect_height_compare(const void *a, const void *b) return (p->w > q->w) ? -1 : (p->w < q->w); } -static int rect_width_compare(const void *a, const void *b) -{ - const stbrp_rect *p = (const stbrp_rect *) a; - const stbrp_rect *q = (const stbrp_rect *) b; - if (p->w > q->w) - return -1; - if (p->w < q->w) - return 1; - return (p->h > q->h) ? -1 : (p->h < q->h); -} - static int rect_original_order(const void *a, const void *b) { const stbrp_rect *p = (const stbrp_rect *) a; @@ -544,9 +537,9 @@ static int rect_original_order(const void *a, const void *b) #define STBRP__MAXVAL 0xffff #endif -STBRP_DEF void stbrp_pack_rects(stbrp_context *context, stbrp_rect *rects, int num_rects) +STBRP_DEF int stbrp_pack_rects(stbrp_context *context, stbrp_rect *rects, int num_rects) { - int i; + int i, all_rects_packed = 1; // we use the 'was_packed' field internally to allow sorting/unsorting for (i=0; i < num_rects; ++i) { @@ -576,8 +569,56 @@ STBRP_DEF void stbrp_pack_rects(stbrp_context *context, stbrp_rect *rects, int n // unsort STBRP_SORT(rects, num_rects, sizeof(rects[0]), rect_original_order); - // set was_packed flags - for (i=0; i < num_rects; ++i) + // set was_packed flags and all_rects_packed status + for (i=0; i < num_rects; ++i) { rects[i].was_packed = !(rects[i].x == STBRP__MAXVAL && rects[i].y == STBRP__MAXVAL); + if (!rects[i].was_packed) + all_rects_packed = 0; + } + + // return the all_rects_packed status + return all_rects_packed; } #endif + +/* +------------------------------------------------------------------------------ +This software is available under 2 licenses -- choose whichever you prefer. +------------------------------------------------------------------------------ +ALTERNATIVE A - MIT License +Copyright (c) 2017 Sean Barrett +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +------------------------------------------------------------------------------ +ALTERNATIVE B - Public Domain (www.unlicense.org) +This is free and unencumbered software released into the public domain. +Anyone is free to copy, modify, publish, use, compile, sell, or distribute this +software, either in source code form or as a compiled binary, for any purpose, +commercial or non-commercial, and by any means. +In jurisdictions that recognize copyright laws, the author or authors of this +software dedicate any and all copyright interest in the software to the public +domain. We make this dedication for the benefit of the public at large and to +the detriment of our heirs and successors. We intend this dedication to be an +overt act of relinquishment in perpetuity of all present and future rights to +this software under copyright law. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +------------------------------------------------------------------------------ +*/ From eb1d481915904862a06ff5172be69692c26d46c9 Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 12 Feb 2018 15:38:04 +0100 Subject: [PATCH 645/823] Comments (#1230, #1611) --- imgui.cpp | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 27ff8f3a5f0d..b72cc38d12b1 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -655,18 +655,13 @@ #define IMGUI_DEBUG_NAV_SCORING 0 #define IMGUI_DEBUG_NAV_RECTS 0 +// Visual Studio warnings #ifdef _MSC_VER #pragma warning (disable: 4127) // condition expression is constant #pragma warning (disable: 4505) // unreferenced local function has been removed (stb stuff) #pragma warning (disable: 4996) // 'This function or variable may be unsafe': strcpy, strdup, sprintf, vsnprintf, sscanf, fopen #endif -#ifdef _MSC_VER -#define IMGUI_CDECL __cdecl -#else -#define IMGUI_CDECL -#endif - // Clang warnings with -Weverything #ifdef __clang__ #pragma clang diagnostic ignored "-Wunknown-pragmas" // warning : unknown warning group '-Wformat-pedantic *' // not all warnings are known by all clang versions.. so ignoring warnings triggers new warnings on some configuration. great! @@ -688,6 +683,13 @@ #pragma GCC diagnostic ignored "-Wformat-nonliteral" // warning: format not a string literal, format string not checked #endif +// Enforce cdecl calling convention for functions called by the standard library, in case compilation settings changed the default to e.g. __vectorcall +#ifdef _MSC_VER +#define IMGUI_CDECL __cdecl +#else +#define IMGUI_CDECL +#endif + //------------------------------------------------------------------------- // Forward Declarations //------------------------------------------------------------------------- From 242bf9d9e2f51a12d190102f5169659c54476a06 Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 12 Feb 2018 17:06:04 +0100 Subject: [PATCH 646/823] Create issue_template.md --- .github/issue_template.md | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 .github/issue_template.md diff --git a/.github/issue_template.md b/.github/issue_template.md new file mode 100644 index 000000000000..28e490a60415 --- /dev/null +++ b/.github/issue_template.md @@ -0,0 +1,24 @@ +Hello! You may submit bug reports, feature requests or suggestions. You may ask for help or advices as well, however please read this wall of text before doing so. Thank you! + +**Prerequisites for new users of dear imgui:** +- Please read the FAQ in imgui.cpp. +- Please read misc/fonts/README.txt if your question relates to fonts or text. +- Please run ImGui::ShowDemoWindow() to explore the demo and its sources. +- Please use the Search function to look for similar issues. You may also browse issues by tags. +- If you get a assert, use a debugger to locate the line triggering it and read the comments around the assert. + +**Guidelines to report an issue or ask a question:** +- Try to provide a Minimal, Complete and Verifiable Example ([MCVE](https://stackoverflow.com/help/mcve)) to demonstrate your problem. An ideal submission includes a small piece of code that anyone can paste in one of the examples/ application to understand and reproduce it. Narrowing your problem to its shortest and purest form is often the easiest way to understand it. Sometimes while creating the MCVE you will end up solving the problem! +- Try to attach screenshots to clarify the context. They often convey useful information that are omitted by the description. You can drag pictures/files here (prefer github attachments over 3rd party hosting). +- If you are discussing an assert or a crash, please provide a debugger callstack. +- Please provide your imgui version number. +- Please state if you have made substancial modifications to your copy of imgui. +- When discussing issues related to rendering or inputs, please state which OS you are using, and if you are using a vanilla copy of one of the back end (imgui_impl_xxx files), or modified one, or if you built your own. +- When requesting a new feature or pushing code, please describe the usage context (how you intend to use it, why you need it, etc.). + +If you have been using dear imgui for a while and/or have been using C/C++ for several years and/or have demonstrated good behavior here, it is ok to not fullfill every item to the letter. Those are guidelines and experienced users of dear imgui will know what information are useful in a given context. + +*Please delete this wall of text before submitting your issue.* + +---- + From ace22168e056d792613b304018a85bfa1d573dc9 Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 12 Feb 2018 17:11:14 +0100 Subject: [PATCH 647/823] Contributing guidelines for issues --- .github/{issue_template.md => CONTRIBUTING.md} | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) rename .github/{issue_template.md => CONTRIBUTING.md} (89%) diff --git a/.github/issue_template.md b/.github/CONTRIBUTING.md similarity index 89% rename from .github/issue_template.md rename to .github/CONTRIBUTING.md index 28e490a60415..984ea521dc4b 100644 --- a/.github/issue_template.md +++ b/.github/CONTRIBUTING.md @@ -1,4 +1,8 @@ -Hello! You may submit bug reports, feature requests or suggestions. You may ask for help or advices as well, however please read this wall of text before doing so. Thank you! +## How to create an Issue + +Hello! + +You may use the Issue tracker to submit bug reports, feature requests or suggestions. You may ask for help or advices as well, however please read this wall of text before doing so. Thank you! **Prerequisites for new users of dear imgui:** - Please read the FAQ in imgui.cpp. @@ -18,7 +22,3 @@ Hello! You may submit bug reports, feature requests or suggestions. You may ask If you have been using dear imgui for a while and/or have been using C/C++ for several years and/or have demonstrated good behavior here, it is ok to not fullfill every item to the letter. Those are guidelines and experienced users of dear imgui will know what information are useful in a given context. -*Please delete this wall of text before submitting your issue.* - ----- - From 4a8871f4f961043945b55b75a4218c5a056a7fdd Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 12 Feb 2018 17:17:29 +0100 Subject: [PATCH 648/823] Create issue_template.md --- .github/issue_template.md | 1 + 1 file changed, 1 insertion(+) create mode 100644 .github/issue_template.md diff --git a/.github/issue_template.md b/.github/issue_template.md new file mode 100644 index 000000000000..97aacddb6a88 --- /dev/null +++ b/.github/issue_template.md @@ -0,0 +1 @@ +(Please read guidelines [here](https://github.com/ocornut/imgui/blob/master/.github/CONTRIBUTING.md)) From 9b4e674688fa15f36c5cbb40f46d13d2157ddb95 Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 12 Feb 2018 17:19:24 +0100 Subject: [PATCH 649/823] Update issue_template.md --- .github/issue_template.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/issue_template.md b/.github/issue_template.md index 97aacddb6a88..f830107e5526 100644 --- a/.github/issue_template.md +++ b/.github/issue_template.md @@ -1 +1 @@ -(Please read guidelines [here](https://github.com/ocornut/imgui/blob/master/.github/CONTRIBUTING.md)) +(Please read guidelines in https://github.com/ocornut/imgui/blob/master/.github/CONTRIBUTING.md then delete this line) From a2658378767cf572421e75500fe55aab93ab4c95 Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 12 Feb 2018 21:38:29 +0100 Subject: [PATCH 650/823] Update issue_template.md --- .github/issue_template.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/issue_template.md b/.github/issue_template.md index f830107e5526..b0dca2c2d9c3 100644 --- a/.github/issue_template.md +++ b/.github/issue_template.md @@ -1 +1 @@ -(Please read guidelines in https://github.com/ocornut/imgui/blob/master/.github/CONTRIBUTING.md then delete this line) +[//]: # (Please read guidelines in https://github.com/ocornut/imgui/blob/master/.github/CONTRIBUTING.md then delete this line) \ No newline at end of file From 24b1c30644ea281fcc203eee7499d3d19419fd03 Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 12 Feb 2018 22:07:05 +0100 Subject: [PATCH 651/823] Update issue_template.md --- .github/issue_template.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/issue_template.md b/.github/issue_template.md index b0dca2c2d9c3..a8745fad2731 100644 --- a/.github/issue_template.md +++ b/.github/issue_template.md @@ -1 +1,2 @@ -[//]: # (Please read guidelines in https://github.com/ocornut/imgui/blob/master/.github/CONTRIBUTING.md then delete this line) \ No newline at end of file +(Please read guidelines in https://github.com/ocornut/imgui/blob/master/.github/CONTRIBUTING.md then delete this line) + From fee6022f0c27f19e499fd392b0d20427e6d32b93 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Branimir=20Karad=C5=BEi=C4=87?= Date: Mon, 12 Feb 2018 20:00:43 -0800 Subject: [PATCH 652/823] =?UTF-8?q?Fixed=20warning:=20variable=20=E2=80=98?= =?UTF-8?q?L1=E2=80=99=20set=20but=20not=20used=20[-Wunused-but-set-variab?= =?UTF-8?q?le]?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- stb_rect_pack.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/stb_rect_pack.h b/stb_rect_pack.h index b1cfdcc41a5d..2b07dcc82c8c 100644 --- a/stb_rect_pack.h +++ b/stb_rect_pack.h @@ -494,17 +494,14 @@ static stbrp__findresult stbrp__skyline_pack_rectangle(stbrp_context *context, i STBRP_ASSERT(cur->next == NULL); { - stbrp_node *L1 = NULL, *L2 = NULL; int count=0; cur = context->active_head; while (cur) { - L1 = cur; cur = cur->next; ++count; } cur = context->free_head; while (cur) { - L2 = cur; cur = cur->next; ++count; } From 7e603ea469a21fb4a403fd0d67ff56778a4b67c1 Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 13 Feb 2018 18:14:17 +0100 Subject: [PATCH 653/823] Update README.md --- README.md | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 61895552748b..7138462fe28e 100644 --- a/README.md +++ b/README.md @@ -33,7 +33,19 @@ No specific build process is required. You can add the .cpp files to your projec Your code passes mouse/keyboard inputs and settings to Dear ImGui (see example applications for more details). After Dear ImGui is setup, you can use it like in this example: -![screenshot of sample code alongside its output with dear imgui](https://raw.githubusercontent.com/wiki/ocornut/imgui/web/code_sample_01.png) +```cpp +// C++ code +ImGui::Text("Hello, world %d", 123); +if (ImGui::Button("Save")) +{ + // do stuff +} +ImGui::InputText("string", buf, IM_ARRAYSIZE(buf)); +ImGui::SliderFloat("float", &f, 0.0f, 1.0f); +``` + +![sample code output](https://raw.githubusercontent.com/wiki/ocornut/imgui/web/v160/code_sample_02.png) +
_(settings: Dark style (left), Light style (right) / Font: Roboto-Medium, 16px / Rounding: 5)_ Dear ImGui outputs vertex buffers and simple command-lists that you can render in your application. The number of draw calls and state changes is typically very small. Because it doesn't know or touch graphics state directly, you can call ImGui commands anywhere in your code (e.g. in the middle of a running algorithm, or in the middle of your own rendering process). Refer to the sample applications in the examples/ folder for instructions on how to integrate dear imgui with your existing codebase. From f0a3dfa0dd8c7e58cd454dd439bd55e31249fb45 Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 13 Feb 2018 18:57:42 +0100 Subject: [PATCH 654/823] Added sample gif, removed section about performances (unnecessary) --- README.md | 51 ++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 38 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index 7138462fe28e..422b30d886e5 100644 --- a/README.md +++ b/README.md @@ -31,7 +31,9 @@ Dear ImGui is self-contained within a few files that you can easily copy and com No specific build process is required. You can add the .cpp files to your project or #include them from an existing file. -Your code passes mouse/keyboard inputs and settings to Dear ImGui (see example applications for more details). After Dear ImGui is setup, you can use it like in this example: +### Usage + +Your code passes mouse/keyboard inputs and settings to Dear ImGui (see example applications for more details). After Dear ImGui is setup, you can use it from anywhere in your code: ```cpp // C++ code @@ -47,12 +49,47 @@ ImGui::SliderFloat("float", &f, 0.0f, 1.0f); ![sample code output](https://raw.githubusercontent.com/wiki/ocornut/imgui/web/v160/code_sample_02.png)
_(settings: Dark style (left), Light style (right) / Font: Roboto-Medium, 16px / Rounding: 5)_ +```cpp +ImGui::Begin("My First Tool", &my_tool_active, ImGuiWindowFlags_MenuBar); +if (ImGui::BeginMenuBar()) +{ + if (ImGui::BeginMenu("File")) + { + if (ImGui::MenuItem("Open..", "Ctrl+O")) { /* Do stuff */ } + if (ImGui::MenuItem("Save", "Ctrl+S")) { /* Do stuff */ } + if (ImGui::MenuItem("Close", "Ctrl+W")) { my_tool_active = false; } + ImGui::EndMenu(); + } + ImGui::EndMenuBar(); +} +ImGui::ColorEdit4("Color", my_color); + +const float my_values[] = { 0.2f, 0.1f, 1.0f, 0.5f, 0.9f, 2.2f }; +ImGui::PlotLines("Frame Times", my_values, IM_ARRAYSIZE(my_values)); + +ImGui::TextColored(ImVec4(1,1,0,1), "Important Stuff"); +ImGui::BeginChild("Scrolling", ImVec2(0,0), true); +for (int n = 0; n < 50; n++) + ImGui::Text("%04d: Some text", n); +ImGui::EndChild(); +ImGui::End(); +``` + +![sample code output](https://raw.githubusercontent.com/wiki/ocornut/imgui/web/v160/code_sample_03_color.gif) +
_(Gif compression added dithering to the color wheel)_ + +### How it works + +Check out the References section if you want to understand the core principles behind the immediate-mode gui paradigm. + Dear ImGui outputs vertex buffers and simple command-lists that you can render in your application. The number of draw calls and state changes is typically very small. Because it doesn't know or touch graphics state directly, you can call ImGui commands anywhere in your code (e.g. in the middle of a running algorithm, or in the middle of your own rendering process). Refer to the sample applications in the examples/ folder for instructions on how to integrate dear imgui with your existing codebase. _A common misunderstanding is to think that immediate mode gui == immediate mode rendering, which usually implies hammering your driver/GPU with a bunch of inefficient draw calls and state changes, as the gui functions are called by the user. This is NOT what Dear ImGui does. Dear ImGui outputs vertex buffers and a small list of draw calls batches. It never touches your GPU directly. The draw call batches are decently optimal and you can render them later, in your app or even remotely._ Dear ImGui allows you create elaborate tools as well as very short-lived ones. On the extreme side of short-liveness: using the Edit&Continue feature of modern compilers you can add a few widgets to tweaks variables while your application is running, and remove the code a minute later! Dear ImGui is not just for tweaking values. You can use it to trace a running algorithm by just emitting text commands. You can use it along with your own reflection data to browse your dataset live. You can use it to expose the internals of a subsystem in your engine, to create a logger, an inspection tool, a profiler, a debugger, an entire game making editor/framework, etc. +You may read + Demo Binaries ------------- @@ -210,18 +247,6 @@ Yes. People have written game editors, data browsers, debuggers, profilers and a Dear ImGui is very programmer centric and the immediate-mode GUI paradigm might requires you to readjust some habits before you can realize its full potential. Dear ImGui is about making things that are simple, efficient and powerful. -Is Dear ImGui fast? - -Probably fast enough for most uses. Down to the foundation of its visual design, Dear ImGui is engineered to be fairly performant both in term of CPU and GPU usage. Running elaborate code and creating elaborate UI will of course have a cost but Dear ImGui aims to minimize it. - -Mileage may vary but the following screenshot can give you a rough idea of the cost of running and rendering UI code (In the case of a trivial demo application like this one, your driver/os setup are likely to be the bottleneck. Testing performance as part of a real application is recommended). - -![performance screenshot](https://raw.githubusercontent.com/wiki/ocornut/imgui/web/v138/performance_01.png) - -This is showing framerate for the full application loop on my 2011 iMac running Windows 7, OpenGL, AMD Radeon HD 6700M with an optimized executable. In contrast, librairies featuring higher-quality rendering and layouting techniques may have a higher resources footprint. - -If you intend to display large lists of items (say, 1000+) it can be beneficial for your code to perform clipping manually - one way is using helpers such as ImGuiListClipper - in order to avoid submitting them to Dear ImGui in the first place. Even though ImGui will discard your clipped items it still needs to calculate their size and that overhead will add up if you have thousands of items. If you can handle clipping and height positionning yourself then browsing a list with millions of items isn't a problem. - Can you reskin the look of Dear ImGui? You can alter the look of the interface to some degree: changing colors, sizes, padding, rounding, fonts. However, as Dear ImGui is designed and optimised to create debug tools, the amount of skinning you can apply is limited. There is only so much you can stray away from the default look and feel of the interface. Below is a screenshot from [LumixEngine](https://github.com/nem0/LumixEngine) with custom colors + a docking/tabs extension (both of which you can find in the Issues section and will eventually be merged): From 1adeaed000bbfbf928a331ea34fa870d4c84638b Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 13 Feb 2018 19:09:19 +0100 Subject: [PATCH 655/823] Update README.md --- README.md | 33 +++++++++++++++------------------ 1 file changed, 15 insertions(+), 18 deletions(-) diff --git a/README.md b/README.md index 422b30d886e5..f571c591a8a4 100644 --- a/README.md +++ b/README.md @@ -50,6 +50,8 @@ ImGui::SliderFloat("float", &f, 0.0f, 1.0f);
_(settings: Dark style (left), Light style (right) / Font: Roboto-Medium, 16px / Rounding: 5)_ ```cpp +// C++ code +// Created a window called "My First Tool" with a menu bar. ImGui::Begin("My First Tool", &my_tool_active, ImGuiWindowFlags_MenuBar); if (ImGui::BeginMenuBar()) { @@ -62,11 +64,15 @@ if (ImGui::BeginMenuBar()) } ImGui::EndMenuBar(); } + +// Edit a color (stored as ~4 floats) ImGui::ColorEdit4("Color", my_color); +// Plot some values const float my_values[] = { 0.2f, 0.1f, 1.0f, 0.5f, 0.9f, 2.2f }; ImGui::PlotLines("Frame Times", my_values, IM_ARRAYSIZE(my_values)); - + +// Display contents in a scrolling region ImGui::TextColored(ImVec4(1,1,0,1), "Important Stuff"); ImGui::BeginChild("Scrolling", ImVec2(0,0), true); for (int n = 0; n < 50; n++) @@ -82,21 +88,19 @@ ImGui::End(); Check out the References section if you want to understand the core principles behind the immediate-mode gui paradigm. -Dear ImGui outputs vertex buffers and simple command-lists that you can render in your application. The number of draw calls and state changes is typically very small. Because it doesn't know or touch graphics state directly, you can call ImGui commands anywhere in your code (e.g. in the middle of a running algorithm, or in the middle of your own rendering process). Refer to the sample applications in the examples/ folder for instructions on how to integrate dear imgui with your existing codebase. +Dear ImGui outputs vertex buffers and simple command-lists that you can trivially render in your application. The number of draw calls and state changes is typically very small. Because it doesn't know or touch graphics state directly, you can call ImGui commands anywhere in your code (e.g. in the middle of a running algorithm, or in the middle of your own rendering process). Refer to the sample applications in the examples/ folder for instructions on how to integrate dear imgui with your existing codebase. -_A common misunderstanding is to think that immediate mode gui == immediate mode rendering, which usually implies hammering your driver/GPU with a bunch of inefficient draw calls and state changes, as the gui functions are called by the user. This is NOT what Dear ImGui does. Dear ImGui outputs vertex buffers and a small list of draw calls batches. It never touches your GPU directly. The draw call batches are decently optimal and you can render them later, in your app or even remotely._ +_A common misunderstanding is to mistake immediate mode gui for immediate mode rendering, which usually implies hammering your driver/GPU with a bunch of inefficient draw calls and state changes as the gui functions are called. This is NOT what Dear ImGui does. Dear ImGui outputs vertex buffers and a small list of draw calls batches. It never touches your GPU directly. The draw call batches are decently optimal and you can render them later, in your app or even remotely._ Dear ImGui allows you create elaborate tools as well as very short-lived ones. On the extreme side of short-liveness: using the Edit&Continue feature of modern compilers you can add a few widgets to tweaks variables while your application is running, and remove the code a minute later! Dear ImGui is not just for tweaking values. You can use it to trace a running algorithm by just emitting text commands. You can use it along with your own reflection data to browse your dataset live. You can use it to expose the internals of a subsystem in your engine, to create a logger, an inspection tool, a profiler, a debugger, an entire game making editor/framework, etc. -You may read - Demo Binaries ------------- You should be able to build the examples from sources (tested on Windows/Mac/Linux). If you don't, let me know! If you want to have a quick look at some Dear ImGui features, you can download Windows binaries of the demo app here: - [imgui-demo-binaries-20180207.zip](http://www.miracleworld.net/imgui/binaries/imgui-demo-binaries-20180207.zip) (Windows binaries, Dear ImGui 1.60 WIP built 2018/01/07, 5 executables) -The demo applications are unfortunately not yet DPI aware so expect some blurryness on a 4K screen. +The demo applications are unfortunately not yet DPI aware so expect some blurryness on a 4K screen. For DPI awareness you can load/reload your font at different scale, and scale your Style with `style.ScaleAllSizes()`. Bindings -------- @@ -121,7 +125,7 @@ Languages: - Rust (imgui-rs): https://github.com/Gekkio/imgui-rs Frameworks: -- Main ImGui repository include examples for DirectX9, DirectX10, DirectX11, OpenGL2/3, Vulkan, Allegro 5, SDL+GL2/3, iOS and Marmalade: https://github.com/ocornut/imgui/tree/master/examples +- This repository include examples for DirectX9, DirectX10, DirectX11, OpenGL2/3, Vulkan, Allegro 5, SDL+GL2/3, iOS and Marmalade: https://github.com/ocornut/imgui/tree/master/examples - PR: DirectX12: https://github.com/ocornut/imgui/pull/301 - PR: SDL2 + OpenGLES + Emscripten: https://github.com/ocornut/imgui/pull/336 - PR: FreeGlut + OpenGL2: https://github.com/ocornut/imgui/pull/801 @@ -155,26 +159,19 @@ User screenshots:
[Gallery Part 5](https://github.com/ocornut/imgui/issues/1269) (Aug 2017 onward)
Also see the [Mega screenshots](https://github.com/ocornut/imgui/issues/1273) for an idea of the available features. -![screenshot 1](https://raw.githubusercontent.com/wiki/ocornut/imgui/web/v148/examples_01.png) - Various tools
[![screenshot game](https://raw.githubusercontent.com/wiki/ocornut/imgui/web/v149/gallery_TheDragonsTrap-01-thumb.jpg)](https://cloud.githubusercontent.com/assets/8225057/20628927/33e14cac-b329-11e6-80f6-9524e93b048a.png) +
[![screenshot game](https://raw.githubusercontent.com/wiki/ocornut/imgui/web/v160/editor_white_preview.jpg)](https://raw.githubusercontent.com/wiki/ocornut/imgui/web/v160/editor_white.png) + +
![screenshot 1](https://raw.githubusercontent.com/wiki/ocornut/imgui/web/v148/examples_01.png) + Custom profiler
[![screenshot profiler](https://raw.githubusercontent.com/wiki/ocornut/imgui/web/v148/profiler-880.jpg)](https://raw.githubusercontent.com/wiki/ocornut/imgui/web/v148/profiler.png) Color Pickers
![screenshot picker](https://user-images.githubusercontent.com/8225057/29062188-471e95ba-7c53-11e7-9618-c4484c0b75fe.PNG) -Menus -
![screenshot 5](https://raw.githubusercontent.com/wiki/ocornut/imgui/web/v151/menus.png) - -Colors -
![screenshot 6](https://raw.githubusercontent.com/wiki/ocornut/imgui/web/v143/skinning_sample_02.png) - -Custom rendering -
![screenshot 7](https://raw.githubusercontent.com/wiki/ocornut/imgui/web/v160/v160-drawdatabase.jpg) - Dear ImGui can load TTF/OTF fonts. UTF-8 is supported for text display and input. Here using Arial Unicode font to display Japanese. Initialize custom font with: ```cpp ImGuiIO& io = ImGui::GetIO(); From f44a7115caa18e79b693ef7012d5d58eed2d8ce0 Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 13 Feb 2018 19:22:34 +0100 Subject: [PATCH 656/823] Update README.md --- README.md | 30 ++++++++++++++++++------------ 1 file changed, 18 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index f571c591a8a4..8f0807cb2da0 100644 --- a/README.md +++ b/README.md @@ -45,7 +45,6 @@ if (ImGui::Button("Save")) ImGui::InputText("string", buf, IM_ARRAYSIZE(buf)); ImGui::SliderFloat("float", &f, 0.0f, 1.0f); ``` - ![sample code output](https://raw.githubusercontent.com/wiki/ocornut/imgui/web/v160/code_sample_02.png)
_(settings: Dark style (left), Light style (right) / Font: Roboto-Medium, 16px / Rounding: 5)_ @@ -80,7 +79,6 @@ for (int n = 0; n < 50; n++) ImGui::EndChild(); ImGui::End(); ``` - ![sample code output](https://raw.githubusercontent.com/wiki/ocornut/imgui/web/v160/code_sample_03_color.gif)
_(Gif compression added dithering to the color wheel)_ @@ -160,27 +158,35 @@ User screenshots:
Also see the [Mega screenshots](https://github.com/ocornut/imgui/issues/1273) for an idea of the available features. Various tools -
[![screenshot game](https://raw.githubusercontent.com/wiki/ocornut/imgui/web/v149/gallery_TheDragonsTrap-01-thumb.jpg)](https://cloud.githubusercontent.com/assets/8225057/20628927/33e14cac-b329-11e6-80f6-9524e93b048a.png) +[![screenshot game](https://raw.githubusercontent.com/wiki/ocornut/imgui/web/v149/gallery_TheDragonsTrap-01-thumb.jpg)](https://cloud.githubusercontent.com/assets/8225057/20628927/33e14cac-b329-11e6-80f6-9524e93b048a.png) -
[![screenshot game](https://raw.githubusercontent.com/wiki/ocornut/imgui/web/v160/editor_white_preview.jpg)](https://raw.githubusercontent.com/wiki/ocornut/imgui/web/v160/editor_white.png) +[![screenshot game](https://raw.githubusercontent.com/wiki/ocornut/imgui/web/v160/editor_white_preview.jpg)](https://raw.githubusercontent.com/wiki/ocornut/imgui/web/v160/editor_white.png) -
![screenshot 1](https://raw.githubusercontent.com/wiki/ocornut/imgui/web/v148/examples_01.png) +![screenshot 1](https://raw.githubusercontent.com/wiki/ocornut/imgui/web/v148/examples_01.png) Custom profiler -
[![screenshot profiler](https://raw.githubusercontent.com/wiki/ocornut/imgui/web/v148/profiler-880.jpg)](https://raw.githubusercontent.com/wiki/ocornut/imgui/web/v148/profiler.png) +[![screenshot profiler](https://raw.githubusercontent.com/wiki/ocornut/imgui/web/v148/profiler-880.jpg)](https://raw.githubusercontent.com/wiki/ocornut/imgui/web/v148/profiler.png) Color Pickers -
![screenshot picker](https://user-images.githubusercontent.com/8225057/29062188-471e95ba-7c53-11e7-9618-c4484c0b75fe.PNG) +![screenshot picker](https://user-images.githubusercontent.com/8225057/29062188-471e95ba-7c53-11e7-9618-c4484c0b75fe.PNG) Dear ImGui can load TTF/OTF fonts. UTF-8 is supported for text display and input. Here using Arial Unicode font to display Japanese. Initialize custom font with: ```cpp ImGuiIO& io = ImGui::GetIO(); -io.Fonts->AddFontFromFileTTF("ArialUni.ttf", 18.0f, NULL, io.Fonts->GetGlyphRangesJapanese()); - -// For Microsoft IME, pass your HWND to enable IME positioning: -io.ImeWindowHandle = my_hwnd; +io.Fonts->AddFontFromFileTTF("NotoSansCJKjp-Medium.otf", 20.0f, NULL, io.Fonts->GetGlyphRangesJapanese()); +``` +```cpp +// C++ code +ImGui::Text(u8"こんにちは!テスト %d", 123); +if (ImGui::Button(u8"ロード")) +{ + // do stuff +} +ImGui::InputText("string", buf, IM_ARRAYSIZE(buf)); +ImGui::SliderFloat("float", &f, 0.0f, 1.0f); ``` -![Japanese screenshot](https://raw.githubusercontent.com/wiki/ocornut/imgui/web/code_sample_01_jp.png) +![sample code output](https://raw.githubusercontent.com/wiki/ocornut/imgui/web/v160/code_sample_02_jp.png) +
_(settings: Dark style (left), Light style (right) / Font: NotoSansCJKjp-Medium, 20px / Rounding: 5)_ References ---------- From e2aba3cf5fb999404e429a5659ec637817d3164b Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 13 Feb 2018 20:17:34 +0100 Subject: [PATCH 657/823] Update README.md --- README.md | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 8f0807cb2da0..4ec12d858070 100644 --- a/README.md +++ b/README.md @@ -160,16 +160,12 @@ User screenshots: Various tools [![screenshot game](https://raw.githubusercontent.com/wiki/ocornut/imgui/web/v149/gallery_TheDragonsTrap-01-thumb.jpg)](https://cloud.githubusercontent.com/assets/8225057/20628927/33e14cac-b329-11e6-80f6-9524e93b048a.png) -[![screenshot game](https://raw.githubusercontent.com/wiki/ocornut/imgui/web/v160/editor_white_preview.jpg)](https://raw.githubusercontent.com/wiki/ocornut/imgui/web/v160/editor_white.png) +[![screenshot tool](https://raw.githubusercontent.com/wiki/ocornut/imgui/web/v160/editor_white_preview.jpg)](https://raw.githubusercontent.com/wiki/ocornut/imgui/web/v160/editor_white.png) -![screenshot 1](https://raw.githubusercontent.com/wiki/ocornut/imgui/web/v148/examples_01.png) +![screenshot demo](https://raw.githubusercontent.com/wiki/ocornut/imgui/web/v160/v160-misc-classic.png) -Custom profiler [![screenshot profiler](https://raw.githubusercontent.com/wiki/ocornut/imgui/web/v148/profiler-880.jpg)](https://raw.githubusercontent.com/wiki/ocornut/imgui/web/v148/profiler.png) -Color Pickers -![screenshot picker](https://user-images.githubusercontent.com/8225057/29062188-471e95ba-7c53-11e7-9618-c4484c0b75fe.PNG) - Dear ImGui can load TTF/OTF fonts. UTF-8 is supported for text display and input. Here using Arial Unicode font to display Japanese. Initialize custom font with: ```cpp ImGuiIO& io = ImGui::GetIO(); From f33440bbc2e9e633863c6a3e91379575decfebc9 Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 13 Feb 2018 20:42:01 +0100 Subject: [PATCH 658/823] Update README.md --- README.md | 59 ++++++++++++++++++++++++++++++++++--------------------- 1 file changed, 37 insertions(+), 22 deletions(-) diff --git a/README.md b/README.md index 4ec12d858070..ac0b1c38fc3b 100644 --- a/README.md +++ b/README.md @@ -123,29 +123,42 @@ Languages: - Rust (imgui-rs): https://github.com/Gekkio/imgui-rs Frameworks: -- This repository include examples for DirectX9, DirectX10, DirectX11, OpenGL2/3, Vulkan, Allegro 5, SDL+GL2/3, iOS and Marmalade: https://github.com/ocornut/imgui/tree/master/examples -- PR: DirectX12: https://github.com/ocornut/imgui/pull/301 -- PR: SDL2 + OpenGLES + Emscripten: https://github.com/ocornut/imgui/pull/336 -- PR: FreeGlut + OpenGL2: https://github.com/ocornut/imgui/pull/801 -- PR: Native Win32 and OSX: https://github.com/ocornut/imgui/pull/281 -- PR: Android: https://github.com/ocornut/imgui/pull/421 -- Cinder: https://github.com/simongeilfus/Cinder-ImGui -- cocos2d-x: https://github.com/c0i/imguix https://github.com/ocornut/imgui/issues/551 -- Flexium/SFML (FlexGUI): https://github.com/DXsmiley/FlexGUI -- GML/GameMakerStudio2 (ImGuiGML): https://marketplace.yoyogames.com/assets/6221/imguigml -- Irrlicht (IrrIMGUI): https://github.com/ZahlGraf/IrrIMGUI -- Ogre: https://bitbucket.org/LMCrashy/ogreimgui/src -- openFrameworks (ofxImGui): https://github.com/jvcleave/ofxImGui -- OpenSceneGraph/OSG: https://gist.github.com/fulezi/d2442ca7626bf270226014501357042c -- LÖVE: https://github.com/slages/love-imgui -- NanoRT (software raytraced) https://github.com/syoyo/imgui/tree/nanort -- Qt3d https://github.com/alpqr/imgui-qt3d -- Unreal Engine 4: https://github.com/segross/UnrealImGui or https://github.com/sronsse/UnrealEngine_ImGui -- SFML: https://github.com/EliasD/imgui-sfml or https://github.com/Mischa-Alff/imgui-backends +- DirectX 9, DirectX 10, DirectX 11: [github/ocornut/imgui/tree/master/examples](https://github.com/ocornut/imgui/tree/master/examples) (this repository) +- OpenGL 2/3 (with GLFW or SDL): [github/ocornut/imgui/tree/master/examples](https://github.com/ocornut/imgui/tree/master/examples) (this repository) +- Vulkan (with GLFW): [github/ocornut/imgui/tree/master/examples](https://github.com/ocornut/imgui/tree/master/examples) (this repository) +- Allegro 5, iOS, Marmalade: [github/ocornut/imgui/tree/master/examples](https://github.com/ocornut/imgui/tree/master/examples) (this repository) +- Unmerged PR: DirectX12: [github/ocornut/imgui/pull/301](https://github.com/ocornut/imgui/pull/301) +- Unmerged PR: SDL2 + OpenGLES + Emscripten: [github/ocornut/imgui/pull/336](https://github.com/ocornut/imgui/pull/336) +- Unmerged PR: FreeGlut + OpenGL2: [github/ocornut/imgui/pull/801](https://github.com/ocornut/imgui/pull/801) +- Unmerged PR: Native Win32 and OSX: [github/ocornut/imgui/pull/281](https://github.com/ocornut/imgui/pull/281) +- Unmerged PR: Android: [github/ocornut/imgui/pull/421](https://github.com/ocornut/imgui/pull/421) +- Cinder: [github/simongeilfus/Cinder-ImGui](https://github.com/simongeilfus/Cinder-ImGui) +- Cocos2d-x: [github/c0i/imguix](https://github.com/c0i/imguix), [github/ocornut/imgui/issues/551](https://github.com/ocornut/imgui/issues/551) +- Flexium/SFML (FlexGUI): [github/DXsmiley/FlexGUI](https://github.com/DXsmiley/FlexGUI) +- GML/GameMakerStudio2 (ImGuiGML): [marketplace.yoyogames.com/assets/6221/imguigml](https://marketplace.yoyogames.com/assets/6221/imguigml) +- Irrlicht (IrrIMGUI): [github/ZahlGraf/IrrIMGUI](https://github.com/ZahlGraf/IrrIMGUI) +- Ogre: [bitbucket.org/LMCrashy/ogreimgui/src](https://bitbucket.org/LMCrashy/ogreimgui/src) +- OpenFrameworks (ofxImGui): [github/jvcleave/ofxImGui](https://github.com/jvcleave/ofxImGui) +- OpenSceneGraph/OSG: [gist](https://gist.github.com/fulezi/d2442ca7626bf270226014501357042c) +- LÖVE: [github/slages/love-imgui](https://github.com/slages/love-imgui) +- NanoRT: [github/syoyo/imgui](https://github.com/syoyo/imgui/tree/nanort) +- Qt3d: [github/alpqr/imgui-qt3d](https://github.com/alpqr/imgui-qt3d) +- Unreal Engine 4: [github/segross/UnrealImGui](https://github.com/segross/UnrealImGui) or [github/sronsse/UnrealEngine_ImGui](https://github.com/sronsse/UnrealEngine_ImGui) +- SFML: [github.com/EliasD/imgui-sfml](https://github.com/EliasD/imgui-sfml) or [Mischa-Alff/imgui-backends](https://github.com/Mischa-Alff/imgui-backends) For other bindings: see [this page](https://github.com/ocornut/imgui/wiki/Links/). Please contact me with the Issues tracker or Twitter to fix/update this list. +Roadmap +------- +Some of the goals for 2018 are: +- Finish work on gamepad/keyboard controls. (see [#787](https://github.com/ocornut/imgui/issues/787)) +- Finish work on viewports and multiple OS windows management. (see [#1542](https://github.com/ocornut/imgui/issues/1542)) +- Finish work on docking, tabs. (see [#351](https://github.com/ocornut/imgui/issues/351#issuecomment-346865709)) +- Make Columns better (they are currently pretty terrible!). +- Make the examples look better, improve styles, improve font support, make the examples hi-DPI aware. + + Gallery ------- @@ -195,8 +208,6 @@ The Immediate Mode GUI paradigm may at first appear unusual to some users. This - [Nicolas Guillemot's CppCon'16 flashtalk about Dear ImGui](https://www.youtube.com/watch?v=LSRJ1jZq90k). - [Thierry Excoffier's Zero Memory Widget](http://perso.univ-lyon1.fr/thierry.excoffier/ZMW/). -See the [Software using dear imgui page](https://github.com/ocornut/imgui/wiki/Software-using-dear-imgui) for an incomplete list of software which are publicly known to use dear migui. - See the [Links page](https://github.com/ocornut/imgui/wiki/Links) for third-party bindings to different languages and frameworks. Frequently Asked Question (FAQ) @@ -211,7 +222,11 @@ Frequently Asked Question (FAQ) Which version should I get? -I occasionally tag [Releases](https://github.com/ocornut/imgui/releases) but it is generally safe and recommended to sync to master. The library is fairly stable and regressions tend to be fixed fast when reported. +I occasionally tag [Releases](https://github.com/ocornut/imgui/releases) but it is generally safe and recommended to sync to master/latest. The library is fairly stable and regressions tend to be fixed fast when reported. + +Who uses Dear ImGui? + +See the [Software using dear imgui page](https://github.com/ocornut/imgui/wiki/Software-using-dear-imgui) for an (incomplete) list of games/software which are publicly known to use dear imgui. Please add yours if you can! Why the odd dual naming, "dear imgui" vs "ImGui"? From faa3c6615423813dfacb8a3410bd6dabf7719b22 Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 13 Feb 2018 20:49:36 +0100 Subject: [PATCH 659/823] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index ac0b1c38fc3b..1370865ccfc4 100644 --- a/README.md +++ b/README.md @@ -50,7 +50,7 @@ ImGui::SliderFloat("float", &f, 0.0f, 1.0f); ```cpp // C++ code -// Created a window called "My First Tool" with a menu bar. +// Create a window called "My First Tool", with a menu bar. ImGui::Begin("My First Tool", &my_tool_active, ImGuiWindowFlags_MenuBar); if (ImGui::BeginMenuBar()) { @@ -73,7 +73,7 @@ ImGui::PlotLines("Frame Times", my_values, IM_ARRAYSIZE(my_values)); // Display contents in a scrolling region ImGui::TextColored(ImVec4(1,1,0,1), "Important Stuff"); -ImGui::BeginChild("Scrolling", ImVec2(0,0), true); +ImGui::BeginChild("Scrolling"); for (int n = 0; n < 50; n++) ImGui::Text("%04d: Some text", n); ImGui::EndChild(); From 9263bd68dbfb930621f6e9643f2260496e3cda58 Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 13 Feb 2018 21:01:21 +0100 Subject: [PATCH 660/823] Fixed legacy forward function IsRootWindowOrAnyChildHovered() broken by a63fbbca8b4340de08afa3360fb768edb0e4ef2d --- imgui.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/imgui.h b/imgui.h index 1cfd7e697fa8..03f593e09b2f 100644 --- a/imgui.h +++ b/imgui.h @@ -1076,7 +1076,7 @@ namespace ImGui static inline float GetItemsLineHeightWithSpacing() { return GetFrameHeightWithSpacing(); } // OBSOLETED in 1.52 (between Aug 2017 and Oct 2017) bool Begin(const char* name, bool* p_open, const ImVec2& size_on_first_use, float bg_alpha_override = -1.0f, ImGuiWindowFlags flags = 0); // Use SetNextWindowSize(size, ImGuiCond_FirstUseEver) + SetNextWindowBgAlpha() instead. - static inline bool IsRootWindowOrAnyChildHovered() { return IsItemHovered(ImGuiHoveredFlags_RootAndChildWindows); } + static inline bool IsRootWindowOrAnyChildHovered() { return IsWindowHovered(ImGuiHoveredFlags_RootAndChildWindows); } static inline void AlignFirstTextHeightToWidgets() { AlignTextToFramePadding(); } static inline void SetNextWindowPosCenter(ImGuiCond c=0) { ImGuiIO& io = GetIO(); SetNextWindowPos(ImVec2(io.DisplaySize.x * 0.5f, io.DisplaySize.y * 0.5f), c, ImVec2(0.5f, 0.5f)); } // OBSOLETED in 1.51 (between Jun 2017 and Aug 2017) From 4ec931853e1078c2ab9868098134a6445f4cd3e9 Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 13 Feb 2018 21:01:56 +0100 Subject: [PATCH 661/823] Demo: Fonts; Added Font Offset. --- imgui_demo.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/imgui_demo.cpp b/imgui_demo.cpp index ec9fc08e9b90..2a1972781397 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -2205,6 +2205,7 @@ void ImGui::ShowStyleEditor(ImGuiStyle* ref) ImGui::Text("The quick brown fox jumps over the lazy dog"); ImGui::PopFont(); ImGui::DragFloat("Font scale", &font->Scale, 0.005f, 0.3f, 2.0f, "%.1f"); // Scale only this font + ImGui::InputFloat("Font offset", &font->DisplayOffset.y, 1, 1, 0); ImGui::SameLine(); ShowHelpMarker("Note than the default embedded font is NOT meant to be scaled.\n\nFont are currently rendered into bitmaps at a given size at the time of building the atlas. You may oversample them to get some flexibility with scaling. You can also render at multiple sizes and select which one to use at runtime.\n\n(Glimmer of hope: the atlas system should hopefully be rewritten in the future to make scaling more natural and automatic.)"); ImGui::Text("Ascent: %f, Descent: %f, Height: %f", font->Ascent, font->Descent, font->Ascent - font->Descent); ImGui::Text("Fallback character: '%c' (%d)", font->FallbackChar, font->FallbackChar); From 1a381dcaf65ce81ce6ded371093018c84b4635ba Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 13 Feb 2018 21:13:23 +0100 Subject: [PATCH 662/823] Update README.md --- README.md | 74 +++++++++++++++++++++++++++---------------------------- 1 file changed, 37 insertions(+), 37 deletions(-) diff --git a/README.md b/README.md index 1370865ccfc4..4407ab1eef3c 100644 --- a/README.md +++ b/README.md @@ -105,46 +105,46 @@ Bindings Integrating Dear ImGui within your custom engine is a matter of wiring mouse/keyboard inputs and providing a render function that can bind a texture and render simple textured triangles. The examples/ folder is populated with applications doing just that. If you are an experienced programmer it should take you less than an hour to integrate Dear ImGui in your custom engine, but make sure to spend time reading the FAQ, the comments and other documentation! -_NB: those third-party bindings may be more or less maintained, more or less close to the spirit of original API and therefore I cannot give much guarantee about them. People who create language bindings sometimes haven't used the C++ API themselves (for the good reason that they aren't C++ users). Dear ImGui was designed with C++ in mind and some of the subtleties may be lost in translation with other languages. If your language supports it, I would suggest replicating the function overloading and default parameters used in the original, else the API may be harder to use. In doubt, please check the original C++ version first!_ - -Languages: -- C (cimgui): https://github.com/Extrawurst/cimgui -- C#/.Net (ImGui.NET): https://github.com/mellinoe/ImGui.NET -- ChaiScript: https://github.com/JuJuBoSc/imgui-chaiscript -- D (DerelictImgui): https://github.com/Extrawurst/DerelictImgui -- Go (go-imgui): https://github.com/Armored-Dragon/go-imgui -- Haxe/hxcpp (linc_imgui): https://github.com/Aidan63/linc_imgui -- JavaScript (imgui-js): https://github.com/flyover/imgui-js -- Lua: https://github.com/patrickriordan/imgui_lua_bindings -- Odin: https://github.com/ThisDrunkDane/odin-dear_imgui -- Pascal (imgui-pas): https://github.com/dpethes/imgui-pas -- Python (CyImGui): https://github.com/chromy/cyimgui -- Python (pyimgui): https://github.com/swistakm/pyimgui -- Rust (imgui-rs): https://github.com/Gekkio/imgui-rs +_NB: those third-party bindings may be more or less maintained, more or less close to the original API (as people who create language bindings sometimes haven't used the C++ API themselves.. for the good reason that they aren't C++ users). Dear ImGui was designed with C++ in mind and some of the subtleties may be lost in translation with other languages. If your language supports it, I would suggest replicating the function overloading and default parameters used in the original, else the API may be harder to use. In doubt, please check the original C++ version first!_ + +Languages: (third-party bindinds) +- C: [cimgui](https://github.com/Extrawurst/cimgui) +- C#/.Net: [ImGui.NET](https://github.com/mellinoe/ImGui.NET) +- ChaiScript: [imgui-chaiscript](https://github.com/JuJuBoSc/imgui-chaiscript) +- D: [DerelictImgui](https://github.com/Extrawurst/DerelictImgui) +- Go: [go-imgui](https://github.com/Armored-Dragon/go-imgui) +- Haxe/hxcpp: [linc_imgui](https://github.com/Aidan63/linc_imgui) +- JavaScript: [imgui-js](https://github.com/flyover/imgui-js) +- Lua: [imgui_lua_bindings](https://github.com/patrickriordan/imgui_lua_bindings) +- Odin: [odin-dear_imgui](https://github.com/ThisDrunkDane/odin-dear_imgui) +- Pascal: [imgui-pas](https://github.com/dpethes/imgui-pas) +- Python [CyImGui](https://github.com/chromy/cyimgui) +- Python [pyimgui](https://github.com/swistakm/pyimgui) +- Rust: [imgui-rs](https://github.com/Gekkio/imgui-rs) Frameworks: -- DirectX 9, DirectX 10, DirectX 11: [github/ocornut/imgui/tree/master/examples](https://github.com/ocornut/imgui/tree/master/examples) (this repository) -- OpenGL 2/3 (with GLFW or SDL): [github/ocornut/imgui/tree/master/examples](https://github.com/ocornut/imgui/tree/master/examples) (this repository) -- Vulkan (with GLFW): [github/ocornut/imgui/tree/master/examples](https://github.com/ocornut/imgui/tree/master/examples) (this repository) -- Allegro 5, iOS, Marmalade: [github/ocornut/imgui/tree/master/examples](https://github.com/ocornut/imgui/tree/master/examples) (this repository) -- Unmerged PR: DirectX12: [github/ocornut/imgui/pull/301](https://github.com/ocornut/imgui/pull/301) -- Unmerged PR: SDL2 + OpenGLES + Emscripten: [github/ocornut/imgui/pull/336](https://github.com/ocornut/imgui/pull/336) -- Unmerged PR: FreeGlut + OpenGL2: [github/ocornut/imgui/pull/801](https://github.com/ocornut/imgui/pull/801) -- Unmerged PR: Native Win32 and OSX: [github/ocornut/imgui/pull/281](https://github.com/ocornut/imgui/pull/281) -- Unmerged PR: Android: [github/ocornut/imgui/pull/421](https://github.com/ocornut/imgui/pull/421) -- Cinder: [github/simongeilfus/Cinder-ImGui](https://github.com/simongeilfus/Cinder-ImGui) -- Cocos2d-x: [github/c0i/imguix](https://github.com/c0i/imguix), [github/ocornut/imgui/issues/551](https://github.com/ocornut/imgui/issues/551) -- Flexium/SFML (FlexGUI): [github/DXsmiley/FlexGUI](https://github.com/DXsmiley/FlexGUI) -- GML/GameMakerStudio2 (ImGuiGML): [marketplace.yoyogames.com/assets/6221/imguigml](https://marketplace.yoyogames.com/assets/6221/imguigml) -- Irrlicht (IrrIMGUI): [github/ZahlGraf/IrrIMGUI](https://github.com/ZahlGraf/IrrIMGUI) -- Ogre: [bitbucket.org/LMCrashy/ogreimgui/src](https://bitbucket.org/LMCrashy/ogreimgui/src) -- OpenFrameworks (ofxImGui): [github/jvcleave/ofxImGui](https://github.com/jvcleave/ofxImGui) +- DirectX 9, DirectX 10, DirectX 11: [examples/](https://github.com/ocornut/imgui/tree/master/examples) +- OpenGL 2/3 (with GLFW or SDL): [examples/](https://github.com/ocornut/imgui/tree/master/examples) +- Vulkan (with GLFW): [examples/](https://github.com/ocornut/imgui/tree/master/examples) +- Allegro 5, iOS, Marmalade: [examples/](https://github.com/ocornut/imgui/tree/master/examples) +- Unmerged PR: DirectX12: [#301](https://github.com/ocornut/imgui/pull/301) +- Unmerged PR: SDL2 + OpenGLES + Emscripten: [#336](https://github.com/ocornut/imgui/pull/336) +- Unmerged PR: FreeGlut + OpenGL2: [#801](https://github.com/ocornut/imgui/pull/801) +- Unmerged PR: Native Win32 and OSX: [#281](https://github.com/ocornut/imgui/pull/281) +- Unmerged PR: Android: [#421](https://github.com/ocornut/imgui/pull/421) +- Cinder: [Cinder-ImGui](https://github.com/simongeilfus/Cinder-ImGui) +- Cocos2d-x: [imguix](https://github.com/c0i/imguix), [issue #551](https://github.com/ocornut/imgui/issues/551) +- Flexium/SFML: [FlexGUI](https://github.com/DXsmiley/FlexGUI) +- GML/GameMakerStudio2: [ImGuiGML](https://marketplace.yoyogames.com/assets/6221/imguigml) +- Irrlicht: [IrrIMGUI](https://github.com/ZahlGraf/IrrIMGUI) +- Ogre: [ogreimgui](https://bitbucket.org/LMCrashy/ogreimgui/src) +- OpenFrameworks: [ofxImGui](https://github.com/jvcleave/ofxImGui) - OpenSceneGraph/OSG: [gist](https://gist.github.com/fulezi/d2442ca7626bf270226014501357042c) -- LÖVE: [github/slages/love-imgui](https://github.com/slages/love-imgui) -- NanoRT: [github/syoyo/imgui](https://github.com/syoyo/imgui/tree/nanort) -- Qt3d: [github/alpqr/imgui-qt3d](https://github.com/alpqr/imgui-qt3d) -- Unreal Engine 4: [github/segross/UnrealImGui](https://github.com/segross/UnrealImGui) or [github/sronsse/UnrealEngine_ImGui](https://github.com/sronsse/UnrealEngine_ImGui) -- SFML: [github.com/EliasD/imgui-sfml](https://github.com/EliasD/imgui-sfml) or [Mischa-Alff/imgui-backends](https://github.com/Mischa-Alff/imgui-backends) +- LÖVE: [love-imgui](https://github.com/slages/love-imgui) +- NanoRT: [syoyo/imgui](https://github.com/syoyo/imgui/tree/nanort) +- Qt3d: [imgui-qt3d](https://github.com/alpqr/imgui-qt3d) +- Unreal Engine 4: [segross/UnrealImGui](https://github.com/segross/UnrealImGui) or [sronsse/UnrealEngine_ImGui](https://github.com/sronsse/UnrealEngine_ImGui) +- SFML: [imgui-sfml](https://github.com/EliasD/imgui-sfml) or [imgui-backends](https://github.com/Mischa-Alff/imgui-backends) For other bindings: see [this page](https://github.com/ocornut/imgui/wiki/Links/). Please contact me with the Issues tracker or Twitter to fix/update this list. From df32b60b3796faa0bb7675a693f6ea11f302f55f Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 13 Feb 2018 21:52:27 +0100 Subject: [PATCH 663/823] Update README.md --- README.md | 50 +++++++++++++++++++++++++------------------------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/README.md b/README.md index 4407ab1eef3c..4c7e358c1bf7 100644 --- a/README.md +++ b/README.md @@ -11,32 +11,31 @@ Monthly donations via Patreon: One-off donations via PayPal:
[![PayPal](https://www.paypalobjects.com/en_US/i/btn/btn_donate_LG.gif)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=5Q73FPZ9C526U) -Dear ImGui is a bloat-free graphical user interface library for C++. It outputs optimized vertex buffers that you can render anytime in your 3D-pipeline enabled application. It is fast, portable, renderer agnostic and self-contained (no external dependencies). +**Dear ImGui is a bloat-free graphical user interface library for C++. It outputs optimized vertex buffers that you can render anytime in your 3D-pipeline enabled application. It is fast, portable, renderer agnostic and self-contained (no external dependencies).** -Dear ImGui is designed to enable fast iteration and empower programmers to create content creation tools and visualization/ debug tools (as opposed to UI for the average end-user). It favors simplicity and productivity toward this goal, and thus lacks certain features normally found in more high-level libraries. +**Dear ImGui is designed to enable fast iterations and to empower programmers to create content creation tools and visualization / debug tools (as opposed to UI for the average end-user). It favors simplicity and productivity toward this goal, and lacks certain features normally found in more high-level libraries. Within the scope of what is has to offer, working with Dear ImGui is simpler and faster than working with Qt, WPF, etc. probably by a large order of magnitude.** -Dear ImGui is particularly suited to integration in realtime 3D applications, fullscreen applications, embedded applications, games, or any applications on consoles platforms where operating system features are non-standard. +Dear ImGui is particularly suited to integration in games, realtime 3D applications, fullscreen applications, embedded applications, or any applications on consoles platforms where operating system features are non-standard. Dear ImGui is self-contained within a few files that you can easily copy and compile into your application/engine: - - - imgui.cpp - - imgui.h - - imgui_demo.cpp - - imgui_draw.cpp - - imgui_internal.h - - imconfig.h (empty by default, user-editable) - - stb_rect_pack.h - - stb_textedit.h - - stb_truetype.h +- imgui.cpp +- imgui.h +- imgui_demo.cpp +- imgui_draw.cpp +- imgui_internal.h +- imconfig.h (empty by default, user-editable) +- stb_rect_pack.h +- stb_textedit.h +- stb_truetype.h No specific build process is required. You can add the .cpp files to your project or #include them from an existing file. ### Usage -Your code passes mouse/keyboard inputs and settings to Dear ImGui (see example applications for more details). After Dear ImGui is setup, you can use it from anywhere in your code: +Your code passes mouse/keyboard inputs and settings to Dear ImGui (see example applications for more details). After Dear ImGui is setup, you can use it from anywhere in your program loop: +Code: ```cpp -// C++ code ImGui::Text("Hello, world %d", 123); if (ImGui::Button("Save")) { @@ -45,11 +44,12 @@ if (ImGui::Button("Save")) ImGui::InputText("string", buf, IM_ARRAYSIZE(buf)); ImGui::SliderFloat("float", &f, 0.0f, 1.0f); ``` -![sample code output](https://raw.githubusercontent.com/wiki/ocornut/imgui/web/v160/code_sample_02.png) +Result: +
![sample code output](https://raw.githubusercontent.com/wiki/ocornut/imgui/web/v160/code_sample_02.png)
_(settings: Dark style (left), Light style (right) / Font: Roboto-Medium, 16px / Rounding: 5)_ +Code: ```cpp -// C++ code // Create a window called "My First Tool", with a menu bar. ImGui::Begin("My First Tool", &my_tool_active, ImGuiWindowFlags_MenuBar); if (ImGui::BeginMenuBar()) @@ -79,18 +79,18 @@ for (int n = 0; n < 50; n++) ImGui::EndChild(); ImGui::End(); ``` -![sample code output](https://raw.githubusercontent.com/wiki/ocornut/imgui/web/v160/code_sample_03_color.gif) -
_(Gif compression added dithering to the color wheel)_ +Result: +
![sample code output](https://raw.githubusercontent.com/wiki/ocornut/imgui/web/v160/code_sample_03_color.gif) ### How it works -Check out the References section if you want to understand the core principles behind the immediate-mode gui paradigm. +Check out the References section if you want to understand the core principles behind the IMGUI paradigm. An IMGUI tries to minimize state synchronization and storage from the user's point of view. It is less error prone (less code and less bugs) than traditional retained-mode interfaces, and lends itself to create dynamic user interfaces. -Dear ImGui outputs vertex buffers and simple command-lists that you can trivially render in your application. The number of draw calls and state changes is typically very small. Because it doesn't know or touch graphics state directly, you can call ImGui commands anywhere in your code (e.g. in the middle of a running algorithm, or in the middle of your own rendering process). Refer to the sample applications in the examples/ folder for instructions on how to integrate dear imgui with your existing codebase. +Dear ImGui outputs vertex buffers and command lists that you can easily render in your application. The number of draw calls and state changes is typically very small. Because it doesn't know or touch graphics state directly, you can call ImGui commands anywhere in your code (e.g. in the middle of a running algorithm, or in the middle of your own rendering process). Refer to the sample applications in the examples/ folder for instructions on how to integrate dear imgui with your existing codebase. _A common misunderstanding is to mistake immediate mode gui for immediate mode rendering, which usually implies hammering your driver/GPU with a bunch of inefficient draw calls and state changes as the gui functions are called. This is NOT what Dear ImGui does. Dear ImGui outputs vertex buffers and a small list of draw calls batches. It never touches your GPU directly. The draw call batches are decently optimal and you can render them later, in your app or even remotely._ -Dear ImGui allows you create elaborate tools as well as very short-lived ones. On the extreme side of short-liveness: using the Edit&Continue feature of modern compilers you can add a few widgets to tweaks variables while your application is running, and remove the code a minute later! Dear ImGui is not just for tweaking values. You can use it to trace a running algorithm by just emitting text commands. You can use it along with your own reflection data to browse your dataset live. You can use it to expose the internals of a subsystem in your engine, to create a logger, an inspection tool, a profiler, a debugger, an entire game making editor/framework, etc. +Dear ImGui allows you create elaborate tools as well as very short-lived ones. On the extreme side of short-liveness: using the Edit&Continue (hot code reload) feature of modern compilers you can add a few widgets to tweaks variables while your application is running, and remove the code a minute later! Dear ImGui is not just for tweaking values. You can use it to trace a running algorithm by just emitting text commands. You can use it along with your own reflection data to browse your dataset live. You can use it to expose the internals of a subsystem in your engine, to create a logger, an inspection tool, a profiler, a debugger, an entire game making editor/framework, etc. Demo Binaries ------------- @@ -158,7 +158,6 @@ Some of the goals for 2018 are: - Make Columns better (they are currently pretty terrible!). - Make the examples look better, improve styles, improve font support, make the examples hi-DPI aware. - Gallery ------- @@ -180,12 +179,12 @@ Various tools [![screenshot profiler](https://raw.githubusercontent.com/wiki/ocornut/imgui/web/v148/profiler-880.jpg)](https://raw.githubusercontent.com/wiki/ocornut/imgui/web/v148/profiler.png) Dear ImGui can load TTF/OTF fonts. UTF-8 is supported for text display and input. Here using Arial Unicode font to display Japanese. Initialize custom font with: +Code: ```cpp ImGuiIO& io = ImGui::GetIO(); io.Fonts->AddFontFromFileTTF("NotoSansCJKjp-Medium.otf", 20.0f, NULL, io.Fonts->GetGlyphRangesJapanese()); ``` ```cpp -// C++ code ImGui::Text(u8"こんにちは!テスト %d", 123); if (ImGui::Button(u8"ロード")) { @@ -194,7 +193,8 @@ if (ImGui::Button(u8"ロード")) ImGui::InputText("string", buf, IM_ARRAYSIZE(buf)); ImGui::SliderFloat("float", &f, 0.0f, 1.0f); ``` -![sample code output](https://raw.githubusercontent.com/wiki/ocornut/imgui/web/v160/code_sample_02_jp.png) +Result: +
![sample code output](https://raw.githubusercontent.com/wiki/ocornut/imgui/web/v160/code_sample_02_jp.png)
_(settings: Dark style (left), Light style (right) / Font: NotoSansCJKjp-Medium, 20px / Rounding: 5)_ References From 6bc3e7b043634bbc09cae0cf8ea308f98bd65c3f Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 13 Feb 2018 21:56:54 +0100 Subject: [PATCH 664/823] ImFontAtlas: if stbtt_PackBegin() because of failing allocation we return a little more nicely. (keeps Coverity static analyzer happy!) --- imgui_draw.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/imgui_draw.cpp b/imgui_draw.cpp index 10051c4fbd2e..e7abffb5ff18 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -1688,7 +1688,8 @@ bool ImFontAtlasBuildWithStbTruetype(ImFontAtlas* atlas) // Start packing const int max_tex_height = 1024*32; stbtt_pack_context spc = {}; - stbtt_PackBegin(&spc, NULL, atlas->TexWidth, max_tex_height, 0, atlas->TexGlyphPadding, NULL); + if (!stbtt_PackBegin(&spc, NULL, atlas->TexWidth, max_tex_height, 0, atlas->TexGlyphPadding, NULL)) + return false; stbtt_PackSetOversampling(&spc, 1, 1); // Pack our extra data rectangles first, so it will be on the upper-left corner of our texture (UV will have small values). From 0a0142adab05c2426b58bcf0659e2912ddaf705b Mon Sep 17 00:00:00 2001 From: omar Date: Wed, 14 Feb 2018 11:15:14 +0100 Subject: [PATCH 665/823] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 4c7e358c1bf7..fada3f863642 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,7 @@ One-off donations via PayPal: **Dear ImGui is a bloat-free graphical user interface library for C++. It outputs optimized vertex buffers that you can render anytime in your 3D-pipeline enabled application. It is fast, portable, renderer agnostic and self-contained (no external dependencies).** -**Dear ImGui is designed to enable fast iterations and to empower programmers to create content creation tools and visualization / debug tools (as opposed to UI for the average end-user). It favors simplicity and productivity toward this goal, and lacks certain features normally found in more high-level libraries. Within the scope of what is has to offer, working with Dear ImGui is simpler and faster than working with Qt, WPF, etc. probably by a large order of magnitude.** +**Dear ImGui is designed to enable fast iterations and to empower programmers to create content creation tools and visualization / debug tools (as opposed to UI for the average end-user). It favors simplicity and productivity toward this goal, and lacks certain features normally found in more high-level libraries. Within the scope of what it has to offer, working with Dear ImGui tends to be more efficient and less error prone than working with Qt, WPF, etc. by a significant order of magnitude.** Dear ImGui is particularly suited to integration in games, realtime 3D applications, fullscreen applications, embedded applications, or any applications on consoles platforms where operating system features are non-standard. From 26d4d32d673993a2b4f1d936309e4c8dab0d5611 Mon Sep 17 00:00:00 2001 From: omar Date: Wed, 14 Feb 2018 11:20:22 +0100 Subject: [PATCH 666/823] Travis: testing without adding external apt repositories (which frequently fails), may be unnecessary today --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 044b87a96159..de0eebee2729 100644 --- a/.travis.yml +++ b/.travis.yml @@ -9,7 +9,7 @@ compiler: - clang before_install: - - if [ $TRAVIS_OS_NAME == linux ]; then sudo add-apt-repository -y ppa:pyglfw/pyglfw && sudo apt-add-repository --yes ppa:zoogie/sdl2-snapshots && sudo apt-get update -qq && sudo apt-get install -y --no-install-recommends libglfw3-dev libxrandr-dev libxi-dev libxxf86vm-dev libsdl2-dev; fi + - if [ $TRAVIS_OS_NAME == linux ]; then sudo apt-get update -qq && sudo apt-get install -y --no-install-recommends libglfw3-dev libxrandr-dev libxi-dev libxxf86vm-dev libsdl2-dev; fi - if [ $TRAVIS_OS_NAME == osx ]; then brew update && brew install glfw3 && brew install sdl2; fi script: From 06e823e116a614c7736ac2a3c446f0817d78b66f Mon Sep 17 00:00:00 2001 From: omar Date: Wed, 14 Feb 2018 11:26:08 +0100 Subject: [PATCH 667/823] Update .travis.yml --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index de0eebee2729..e4118aebf9bb 100644 --- a/.travis.yml +++ b/.travis.yml @@ -9,7 +9,7 @@ compiler: - clang before_install: - - if [ $TRAVIS_OS_NAME == linux ]; then sudo apt-get update -qq && sudo apt-get install -y --no-install-recommends libglfw3-dev libxrandr-dev libxi-dev libxxf86vm-dev libsdl2-dev; fi + - if [ $TRAVIS_OS_NAME == linux ]; then sudo apt-get update -qq && sudo apt-get install -y --no-install-recommends libxrandr-dev libxi-dev libxxf86vm-dev libsdl2-dev; fi - if [ $TRAVIS_OS_NAME == osx ]; then brew update && brew install glfw3 && brew install sdl2; fi script: From c0af35098a30e53ca830ebefc173c2c9d6a7e4f4 Mon Sep 17 00:00:00 2001 From: omar Date: Wed, 14 Feb 2018 11:29:49 +0100 Subject: [PATCH 668/823] Update .travis.yml --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index e4118aebf9bb..a9e3cbbd2a80 100644 --- a/.travis.yml +++ b/.travis.yml @@ -9,7 +9,7 @@ compiler: - clang before_install: - - if [ $TRAVIS_OS_NAME == linux ]; then sudo apt-get update -qq && sudo apt-get install -y --no-install-recommends libxrandr-dev libxi-dev libxxf86vm-dev libsdl2-dev; fi + - if [ $TRAVIS_OS_NAME == linux ]; then sudo add-apt-repository -y ppa:keithw/glfw3 && sudo apt-get update -qq && sudo apt-get install -y --no-install-recommends libxrandr-dev libxi-dev libxxf86vm-dev libsdl2-dev; fi - if [ $TRAVIS_OS_NAME == osx ]; then brew update && brew install glfw3 && brew install sdl2; fi script: From 42bf6a4d030bc711b9435147730daf9aa1a96cb3 Mon Sep 17 00:00:00 2001 From: omar Date: Wed, 14 Feb 2018 11:33:46 +0100 Subject: [PATCH 669/823] Update .travis.yml --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index a9e3cbbd2a80..62e27968f6f9 100644 --- a/.travis.yml +++ b/.travis.yml @@ -9,7 +9,7 @@ compiler: - clang before_install: - - if [ $TRAVIS_OS_NAME == linux ]; then sudo add-apt-repository -y ppa:keithw/glfw3 && sudo apt-get update -qq && sudo apt-get install -y --no-install-recommends libxrandr-dev libxi-dev libxxf86vm-dev libsdl2-dev; fi + - if [ $TRAVIS_OS_NAME == linux ]; then sudo add-apt-repository -y ppa:keithw/glfw3 && sudo apt-get update -qq && sudo apt-get install -y --no-install-recommends libglfw3-dev libxrandr-dev libxi-dev libxxf86vm-dev libsdl2-dev; fi - if [ $TRAVIS_OS_NAME == osx ]; then brew update && brew install glfw3 && brew install sdl2; fi script: From fed0a884f721dcdd200a42631b2487dd1d56e113 Mon Sep 17 00:00:00 2001 From: omar Date: Wed, 14 Feb 2018 11:57:51 +0100 Subject: [PATCH 670/823] ImFontAtlas: Added ImFontAtlasFlags_NoPowerOfTwoHeight, ImFontAtlasFlags_NoMouseCursors flags. (#1613) --- imgui.h | 8 ++++++ imgui_draw.cpp | 44 ++++++++++++++++++++++---------- misc/freetype/imgui_freetype.cpp | 2 +- 3 files changed, 39 insertions(+), 15 deletions(-) diff --git a/imgui.h b/imgui.h index 03f593e09b2f..61f6033a83d3 100644 --- a/imgui.h +++ b/imgui.h @@ -87,6 +87,7 @@ typedef int ImGuiMouseCursor; // enum: a mouse cursor identifier typedef int ImGuiStyleVar; // enum: a variable identifier for styling // enum ImGuiStyleVar_ typedef int ImDrawCornerFlags; // flags: for ImDrawList::AddRect*() etc. // enum ImDrawCornerFlags_ typedef int ImDrawListFlags; // flags: for ImDrawList // enum ImDrawListFlags_ +typedef int ImFontAtlasFlags; // flags: for ImFontAtlas // enum ImFontAtlasFlags_ typedef int ImGuiColorEditFlags; // flags: for ColorEdit*(), ColorPicker*() // enum ImGuiColorEditFlags_ typedef int ImGuiColumnsFlags; // flags: for *Columns*() // enum ImGuiColumnsFlags_ typedef int ImGuiDragDropFlags; // flags: for *DragDrop*() // enum ImGuiDragDropFlags_ @@ -1612,6 +1613,12 @@ struct ImFontGlyph float U0, V0, U1, V1; // Texture coordinates }; +enum ImFontAtlasFlags_ +{ + ImFontAtlasFlags_NoPowerOfTwoHeight = 1 << 0, // Don't round the height to next power of two + ImFontAtlasFlags_NoMouseCursors = 1 << 1 // Don't build software mouse cursors into the atlas +}; + // Load and rasterize multiple TTF/OTF fonts into a same texture. // Sharing a texture for multiple fonts allows us to reduce the number of draw calls during rendering. // We also add custom graphic data into the texture that serves for ImGui. @@ -1706,6 +1713,7 @@ struct ImFontAtlas // [Internal] // NB: Access texture data via GetTexData*() calls! Which will setup a default font for you. + ImFontAtlasFlags Flags; // Build flags unsigned char* TexPixelsAlpha8; // 1 component per pixel, each component is unsigned 8-bit. Total size = TexWidth * TexHeight unsigned int* TexPixelsRGBA32; // 4 component per pixel, each component is unsigned 8-bit. Total size = TexWidth * TexHeight * 4 int TexWidth; // Texture width calculated during Build(). diff --git a/imgui_draw.cpp b/imgui_draw.cpp index e7abffb5ff18..037e5263aa62 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -1368,6 +1368,7 @@ ImFontAtlas::ImFontAtlas() TexWidth = TexHeight = 0; TexUvScale = ImVec2(0.0f, 0.0f); TexUvWhitePixel = ImVec2(0.0f, 0.0f); + Flags = 0x00; for (int n = 0; n < IM_ARRAYSIZE(CustomRectIds); n++) CustomRectIds[n] = -1; } @@ -1619,6 +1620,8 @@ bool ImFontAtlas::GetMouseCursorTexData(ImGuiMouseCursor cursor_type, ImVec2* ou { if (cursor_type <= ImGuiMouseCursor_None || cursor_type >= ImGuiMouseCursor_Count_) return false; + if (Flags & ImFontAtlasFlags_NoMouseCursors) + return false; ImFontAtlas::CustomRect& r = CustomRects[CustomRectIds[0]]; IM_ASSERT(r.ID == FONT_ATLAS_DEFAULT_TEX_DATA_ID); @@ -1774,7 +1777,7 @@ bool ImFontAtlasBuildWithStbTruetype(ImFontAtlas* atlas) IM_ASSERT(buf_ranges_n == total_ranges_count); // Create texture - atlas->TexHeight = ImUpperPowerOfTwo(atlas->TexHeight); + atlas->TexHeight = (atlas->Flags & ImFontAtlasFlags_NoPowerOfTwoHeight) ? (atlas->TexHeight + 1) : ImUpperPowerOfTwo(atlas->TexHeight); atlas->TexUvScale = ImVec2(1.0f / atlas->TexWidth, 1.0f / atlas->TexHeight); atlas->TexPixelsAlpha8 = (unsigned char*)ImGui::MemAlloc(atlas->TexWidth * atlas->TexHeight); memset(atlas->TexPixelsAlpha8, 0, atlas->TexWidth * atlas->TexHeight); @@ -1854,8 +1857,12 @@ bool ImFontAtlasBuildWithStbTruetype(ImFontAtlas* atlas) void ImFontAtlasBuildRegisterDefaultCustomRects(ImFontAtlas* atlas) { - if (atlas->CustomRectIds[0] < 0) + if (atlas->CustomRectIds[0] >= 0) + return; + if (!(atlas->Flags & ImFontAtlasFlags_NoMouseCursors)) atlas->CustomRectIds[0] = atlas->AddCustomRectRegular(FONT_ATLAS_DEFAULT_TEX_DATA_ID, FONT_ATLAS_DEFAULT_TEX_DATA_W_HALF*2+1, FONT_ATLAS_DEFAULT_TEX_DATA_H); + else + atlas->CustomRectIds[0] = atlas->AddCustomRectRegular(FONT_ATLAS_DEFAULT_TEX_DATA_ID, 2, 2); } void ImFontAtlasBuildSetupFont(ImFontAtlas* atlas, ImFont* font, ImFontConfig* font_config, float ascent, float descent) @@ -1901,22 +1908,31 @@ void ImFontAtlasBuildPackCustomRects(ImFontAtlas* atlas, void* pack_context_opaq static void ImFontAtlasBuildRenderDefaultTexData(ImFontAtlas* atlas) { IM_ASSERT(atlas->CustomRectIds[0] >= 0); + IM_ASSERT(atlas->TexPixelsAlpha8 != NULL); ImFontAtlas::CustomRect& r = atlas->CustomRects[atlas->CustomRectIds[0]]; IM_ASSERT(r.ID == FONT_ATLAS_DEFAULT_TEX_DATA_ID); - IM_ASSERT(r.Width == FONT_ATLAS_DEFAULT_TEX_DATA_W_HALF*2+1); - IM_ASSERT(r.Height == FONT_ATLAS_DEFAULT_TEX_DATA_H); IM_ASSERT(r.IsPacked()); - IM_ASSERT(atlas->TexPixelsAlpha8 != NULL); - // Render/copy pixels - for (int y = 0, n = 0; y < FONT_ATLAS_DEFAULT_TEX_DATA_H; y++) - for (int x = 0; x < FONT_ATLAS_DEFAULT_TEX_DATA_W_HALF; x++, n++) - { - const int offset0 = (int)(r.X + x) + (int)(r.Y + y) * atlas->TexWidth; - const int offset1 = offset0 + FONT_ATLAS_DEFAULT_TEX_DATA_W_HALF + 1; - atlas->TexPixelsAlpha8[offset0] = FONT_ATLAS_DEFAULT_TEX_DATA_PIXELS[n] == '.' ? 0xFF : 0x00; - atlas->TexPixelsAlpha8[offset1] = FONT_ATLAS_DEFAULT_TEX_DATA_PIXELS[n] == 'X' ? 0xFF : 0x00; - } + const int w = atlas->TexWidth; + if (!(atlas->Flags & ImFontAtlasFlags_NoMouseCursors)) + { + // Render/copy pixels + IM_ASSERT(r.Width == FONT_ATLAS_DEFAULT_TEX_DATA_W_HALF * 2 + 1 && r.Height == FONT_ATLAS_DEFAULT_TEX_DATA_H); + for (int y = 0, n = 0; y < FONT_ATLAS_DEFAULT_TEX_DATA_H; y++) + for (int x = 0; x < FONT_ATLAS_DEFAULT_TEX_DATA_W_HALF; x++, n++) + { + const int offset0 = (int)(r.X + x) + (int)(r.Y + y) * w; + const int offset1 = offset0 + FONT_ATLAS_DEFAULT_TEX_DATA_W_HALF + 1; + atlas->TexPixelsAlpha8[offset0] = FONT_ATLAS_DEFAULT_TEX_DATA_PIXELS[n] == '.' ? 0xFF : 0x00; + atlas->TexPixelsAlpha8[offset1] = FONT_ATLAS_DEFAULT_TEX_DATA_PIXELS[n] == 'X' ? 0xFF : 0x00; + } + } + else + { + IM_ASSERT(r.Width == 2 && r.Height == 2); + const int offset = (int)(r.X) + (int)(r.Y) * w; + atlas->TexPixelsAlpha8[offset] = atlas->TexPixelsAlpha8[offset + 1] = atlas->TexPixelsAlpha8[offset + w] = atlas->TexPixelsAlpha8[offset + w + 1] = 0xFF; + } atlas->TexUvWhitePixel = ImVec2((r.X + 0.5f) * atlas->TexUvScale.x, (r.Y + 0.5f) * atlas->TexUvScale.y); } diff --git a/misc/freetype/imgui_freetype.cpp b/misc/freetype/imgui_freetype.cpp index 9e373c7dd8c0..0a80bbdfb7d7 100644 --- a/misc/freetype/imgui_freetype.cpp +++ b/misc/freetype/imgui_freetype.cpp @@ -295,7 +295,7 @@ bool ImGuiFreeType::BuildFontAtlas(ImFontAtlas* atlas, unsigned int extra_flags) atlas->TexHeight = (int)(min_rects_per_column * (max_glyph_size.y + 1.0f)); // Create texture - atlas->TexHeight = ImUpperPowerOfTwo(atlas->TexHeight); + atlas->TexHeight = (atlas->Flags & ImFontAtlasFlags_NoPowerOfTwoHeight) ? (atlas->TexHeight + 1) : ImUpperPowerOfTwo(atlas->TexHeight); atlas->TexUvScale = ImVec2(1.0f / atlas->TexWidth, 1.0f / atlas->TexHeight); atlas->TexPixelsAlpha8 = (unsigned char*)ImGui::MemAlloc(atlas->TexWidth * atlas->TexHeight); memset(atlas->TexPixelsAlpha8, 0, atlas->TexWidth * atlas->TexHeight); From 024e23c4d701a943c91fb838c36c01270af8261d Mon Sep 17 00:00:00 2001 From: omar Date: Wed, 14 Feb 2018 12:04:21 +0100 Subject: [PATCH 671/823] Comments, moved ImFontAtlas::Flags to "public" area. --- imgui.h | 2 +- imgui_draw.cpp | 3 ++- misc/fonts/README.txt | 3 ++- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/imgui.h b/imgui.h index 61f6033a83d3..60d027e0c448 100644 --- a/imgui.h +++ b/imgui.h @@ -1707,13 +1707,13 @@ struct ImFontAtlas // Members //------------------------------------------- + ImFontAtlasFlags Flags; // Build flags (see ImFontAtlasFlags_) ImTextureID TexID; // User data to refer to the texture once it has been uploaded to user's graphic systems. It is passed back to you during rendering via the ImDrawCmd structure. int TexDesiredWidth; // Texture width desired by user before Build(). Must be a power-of-two. If have many glyphs your graphics API have texture size restrictions you may want to increase texture width to decrease height. int TexGlyphPadding; // Padding between glyphs within texture in pixels. Defaults to 1. // [Internal] // NB: Access texture data via GetTexData*() calls! Which will setup a default font for you. - ImFontAtlasFlags Flags; // Build flags unsigned char* TexPixelsAlpha8; // 1 component per pixel, each component is unsigned 8-bit. Total size = TexWidth * TexHeight unsigned int* TexPixelsRGBA32; // 4 component per pixel, each component is unsigned 8-bit. Total size = TexWidth * TexHeight * 4 int TexWidth; // Texture width calculated during Build(). diff --git a/imgui_draw.cpp b/imgui_draw.cpp index 037e5263aa62..cafe6e080ca1 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -1360,15 +1360,16 @@ static const ImVec2 FONT_ATLAS_DEFAULT_TEX_CURSOR_DATA[ImGuiMouseCursor_Count_][ ImFontAtlas::ImFontAtlas() { + Flags = 0x00; TexID = NULL; TexDesiredWidth = 0; TexGlyphPadding = 1; + TexPixelsAlpha8 = NULL; TexPixelsRGBA32 = NULL; TexWidth = TexHeight = 0; TexUvScale = ImVec2(0.0f, 0.0f); TexUvWhitePixel = ImVec2(0.0f, 0.0f); - Flags = 0x00; for (int n = 0; n < IM_ARRAYSIZE(CustomRectIds); n++) CustomRectIds[n] = -1; } diff --git a/misc/fonts/README.txt b/misc/fonts/README.txt index a3774ca77c1f..70773fcad5b0 100644 --- a/misc/fonts/README.txt +++ b/misc/fonts/README.txt @@ -80,6 +80,7 @@ In this document: - Mind the fact that some graphics drivers have texture size limitation. - Set io.Fonts.TexDesiredWidth to specify a texture width to minimize texture height (see comment in ImFontAtlas::Build function). + - Set io.Fonts.Flags |= ImFontAtlasFlags_NoPowerOfTwoHeight; to disable rounding the texture height to the next power of two. - You may reduce oversampling, e.g. config.OversampleH = 2 or 1. - Reduce glyphs ranges, consider calculating them based on your source data if this is possible. @@ -111,7 +112,7 @@ In this document: Offset font vertically by altering the io.Font->DisplayOffset value: ImFont* font = io.Fonts->AddFontFromFileTTF("font.ttf", size_pixels); - font->DisplayOffset.y += 1; // Render 1 pixel down + font->DisplayOffset.y = 1; // Render 1 pixel down --------------------------------------- From 6668e80bed2f9541be65b60985e43c8f5be160f8 Mon Sep 17 00:00:00 2001 From: omar Date: Thu, 15 Feb 2018 10:33:22 +0100 Subject: [PATCH 672/823] Update README.md --- README.md | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index fada3f863642..a51632c09424 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ dear imgui, [![Build Status](https://travis-ci.org/ocornut/imgui.svg?branch=master)](https://travis-ci.org/ocornut/imgui) [![Coverity Status](https://scan.coverity.com/projects/4720/badge.svg)](https://scan.coverity.com/projects/4720) -(This library is free but needs your support to sustain its development. There are lots of desirable new features and maintenance to do. If you are an individual using dear imgui, please consider donating via Patreon or PayPal. If your company is using dear imgui, please consider financial support (e.g. sponsoring a few weeks/months of development). I can invoice for private support, custom development etc. E-mail: omarcornut at gmail.) +_(This library is free but needs your support to sustain its development. There are many desirable features and maintenance ahead If you are an individual using dear imgui, please consider donating via Patreon or PayPal. If your company is using dear imgui, please consider financial support (e.g. sponsoring a few weeks/months of development). I can invoice for technical support, custom development etc. E-mail: omarcornut at gmail.)_ Monthly donations via Patreon:
[![Patreon](https://cloud.githubusercontent.com/assets/8225057/5990484/70413560-a9ab-11e4-8942-1a63607c0b00.png)](http://www.patreon.com/imgui) @@ -11,11 +11,11 @@ Monthly donations via Patreon: One-off donations via PayPal:
[![PayPal](https://www.paypalobjects.com/en_US/i/btn/btn_donate_LG.gif)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=5Q73FPZ9C526U) -**Dear ImGui is a bloat-free graphical user interface library for C++. It outputs optimized vertex buffers that you can render anytime in your 3D-pipeline enabled application. It is fast, portable, renderer agnostic and self-contained (no external dependencies).** +Dear ImGui is a bloat-free graphical user interface library for C++. It outputs optimized vertex buffers that you can render anytime in your 3D-pipeline enabled application. It is fast, portable, renderer agnostic and self-contained (no external dependencies).** -**Dear ImGui is designed to enable fast iterations and to empower programmers to create content creation tools and visualization / debug tools (as opposed to UI for the average end-user). It favors simplicity and productivity toward this goal, and lacks certain features normally found in more high-level libraries. Within the scope of what it has to offer, working with Dear ImGui tends to be more efficient and less error prone than working with Qt, WPF, etc. by a significant order of magnitude.** +Dear ImGui is designed to enable fast iterations and to empower programmers to create content creation tools and visualization / debug tools (as opposed to UI for the average end-user). It favors simplicity and productivity toward this goal, and lacks certain features normally found in more high-level libraries. -Dear ImGui is particularly suited to integration in games, realtime 3D applications, fullscreen applications, embedded applications, or any applications on consoles platforms where operating system features are non-standard. +Dear ImGui is particularly suited to integration in games engine (for tooling), realtime 3D applications, fullscreen applications, embedded applications, or any applications on consoles platforms where operating system features are non-standard. Dear ImGui is self-contained within a few files that you can easily copy and compile into your application/engine: - imgui.cpp @@ -32,7 +32,7 @@ No specific build process is required. You can add the .cpp files to your projec ### Usage -Your code passes mouse/keyboard inputs and settings to Dear ImGui (see example applications for more details). After Dear ImGui is setup, you can use it from anywhere in your program loop: +Your code passes mouse/keyboard/gamepad inputs and settings to Dear ImGui (see example applications for more details). After Dear ImGui is setup, you can use it from \_anywhere\_ in your program loop: Code: ```cpp @@ -84,7 +84,7 @@ Result: ### How it works -Check out the References section if you want to understand the core principles behind the IMGUI paradigm. An IMGUI tries to minimize state synchronization and storage from the user's point of view. It is less error prone (less code and less bugs) than traditional retained-mode interfaces, and lends itself to create dynamic user interfaces. +Check out the References section if you want to understand the core principles behind the IMGUI paradigm. An IMGUI tries to minimize state duplication, state synchronization and state storage from the user's point of view. It is less error prone (less code and less bugs) than traditional retained-mode interfaces, and lends itself to create dynamic user interfaces. Dear ImGui outputs vertex buffers and command lists that you can easily render in your application. The number of draw calls and state changes is typically very small. Because it doesn't know or touch graphics state directly, you can call ImGui commands anywhere in your code (e.g. in the middle of a running algorithm, or in the middle of your own rendering process). Refer to the sample applications in the examples/ folder for instructions on how to integrate dear imgui with your existing codebase. @@ -103,7 +103,7 @@ The demo applications are unfortunately not yet DPI aware so expect some blurryn Bindings -------- -Integrating Dear ImGui within your custom engine is a matter of wiring mouse/keyboard inputs and providing a render function that can bind a texture and render simple textured triangles. The examples/ folder is populated with applications doing just that. If you are an experienced programmer it should take you less than an hour to integrate Dear ImGui in your custom engine, but make sure to spend time reading the FAQ, the comments and other documentation! +Integrating Dear ImGui within your custom engine is a matter of 1) wiring mouse/keyboard/gamepad inputs 2) uploading one texture to your GPU/render engine 3) providing a render function that can bind textures and render textured triangles. The [examples/](https://github.com/ocornut/imgui/tree/master/examples) folder is populated with applications doing just that. If you are an experienced programmer and at ease with those concepts, it should take you less than an hour to integrate Dear ImGui in your custom engine, but make sure to spend time reading the FAQ, the comments and other documentation! _NB: those third-party bindings may be more or less maintained, more or less close to the original API (as people who create language bindings sometimes haven't used the C++ API themselves.. for the good reason that they aren't C++ users). Dear ImGui was designed with C++ in mind and some of the subtleties may be lost in translation with other languages. If your language supports it, I would suggest replicating the function overloading and default parameters used in the original, else the API may be harder to use. In doubt, please check the original C++ version first!_ @@ -155,7 +155,7 @@ Some of the goals for 2018 are: - Finish work on gamepad/keyboard controls. (see [#787](https://github.com/ocornut/imgui/issues/787)) - Finish work on viewports and multiple OS windows management. (see [#1542](https://github.com/ocornut/imgui/issues/1542)) - Finish work on docking, tabs. (see [#351](https://github.com/ocornut/imgui/issues/351#issuecomment-346865709)) -- Make Columns better (they are currently pretty terrible!). +- Make Columns better. (they are currently pretty terrible!) - Make the examples look better, improve styles, improve font support, make the examples hi-DPI aware. Gallery @@ -251,7 +251,7 @@ See the FAQ in imgui.cpp for answers. You can control Dear ImGui with a gamepad, see the explanation in imgui.cpp about how to use the navigation feature (short version: map your gamepad inputs into the `io.NavInputs[]` array and set `io.NavFlags |= ImGuiNavFlags_EnableGamepad`). -You can share your computer mouse seamlessy with your console/tablet/phone using [Synergy](http://synergy-project.org) ([sources](https://github.com/symless/synergy)). This is the prefered solution for developer productivity. In particular, their [micro-synergy-client](https://github.com/symless/micro-synergy-client) repo there is _uSynergy.c_ sources for a small embeddable that you can use on any platform to connect to your host PC. You may also use a third party solution such as [Remote ImGui](https://github.com/JordiRos/remoteimgui). +You can share your computer mouse seamlessy with your console/tablet/phone using [Synergy](http://synergy-project.org). This is the prefered solution for developer productivity. In particular, their [micro-synergy-client](https://github.com/symless/micro-synergy-client) repo there is _uSynergy.c_ sources for a small embeddable that you can use on any platform to connect to your host PC. You may also use a third party solution such as [Remote ImGui](https://github.com/JordiRos/remoteimgui). For touch inputs, you can increase the hit box of widgets (via the _style.TouchPadding_ setting) to accommodate a little for the lack of precision of touch inputs, but it is recommended you use a mouse or gamepad to allow optimising for screen real-estate and precision. From 30c469f7c53d52206fad64a061e95a875e2b614a Mon Sep 17 00:00:00 2001 From: omar Date: Thu, 15 Feb 2018 10:46:28 +0100 Subject: [PATCH 673/823] ImFont: DisplayOffset.y defaults to 0 instead of +1. --- imgui.cpp | 1 + imgui.h | 2 +- imgui_draw.cpp | 3 ++- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index b72cc38d12b1..6bd6fad09e85 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -250,6 +250,7 @@ Here is a change-log of API breaking changes, if you are using one of the functions listed, expect to have to fix some code. Also read releases logs https://github.com/ocornut/imgui/releases for more details. + - 2018/02/15 (1.XX) - ImFont::DisplayOffset.y field defaults to 0 instead of +1. - 2018/02/07 (1.60) - reorganized context handling to be more explicit, - YOU NOW NEED TO CALL ImGui::CreateContext() AT THE BEGINNING OF YOUR APP, AND CALL ImGui::DestroyContext() AT THE END. - removed Shutdown() function, as DestroyContext() serve this purpose. diff --git a/imgui.h b/imgui.h index 60d027e0c448..8932000285e1 100644 --- a/imgui.h +++ b/imgui.h @@ -1733,7 +1733,7 @@ struct ImFont // Members: Hot ~62/78 bytes float FontSize; // // Height of characters, set during loading (don't change after loading) float Scale; // = 1.f // Base font scale, multiplied by the per-window font scale which you can adjust with SetFontScale() - ImVec2 DisplayOffset; // = (0.f,1.f) // Offset font rendering by xx pixels + ImVec2 DisplayOffset; // = (0.f,0.f) // Offset font rendering by xx pixels ImVector Glyphs; // // All glyphs. ImVector IndexAdvanceX; // // Sparse. Glyphs->AdvanceX in a directly indexable way (more cache-friendly, for CalcTextSize functions which are often bottleneck in large UI). ImVector IndexLookup; // // Sparse. Index glyphs by Unicode code-point. diff --git a/imgui_draw.cpp b/imgui_draw.cpp index cafe6e080ca1..a2d207bea19e 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -1522,6 +1522,7 @@ ImFont* ImFontAtlas::AddFontDefault(const ImFontConfig* font_cfg_template) const char* ttf_compressed_base85 = GetDefaultCompressedFontDataTTFBase85(); ImFont* font = AddFontFromMemoryCompressedBase85TTF(ttf_compressed_base85, font_cfg.SizePixels, &font_cfg, GetGlyphRangesDefault()); + font->DisplayOffset.y = 1.0f; return font; } @@ -2133,7 +2134,7 @@ ImFont::ImFont() { Scale = 1.0f; FallbackChar = (ImWchar)'?'; - DisplayOffset = ImVec2(0.0f, 1.0f); + DisplayOffset = ImVec2(0.0f, 0.0f); ClearOutputData(); } From c433bbcd8e87c4132fd59ddac354c2ae2d1b9465 Mon Sep 17 00:00:00 2001 From: omar Date: Thu, 15 Feb 2018 10:47:20 +0100 Subject: [PATCH 674/823] ImFont: stb_truetype now rounding Ascent/Descent the same way as freetype does, they seem to vertically align better this way. --- imgui_draw.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/imgui_draw.cpp b/imgui_draw.cpp index a2d207bea19e..c03b08de7e3b 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -1820,8 +1820,8 @@ bool ImFontAtlasBuildWithStbTruetype(ImFontAtlas* atlas) int unscaled_ascent, unscaled_descent, unscaled_line_gap; stbtt_GetFontVMetrics(&tmp.FontInfo, &unscaled_ascent, &unscaled_descent, &unscaled_line_gap); - const float ascent = unscaled_ascent * font_scale; - const float descent = unscaled_descent * font_scale; + const float ascent = ImFloor(unscaled_ascent * font_scale + ((unscaled_ascent > 0.0f) ? +1 : -1)); + const float descent = ImFloor(unscaled_descent * font_scale + ((unscaled_descent > 0.0f) ? +1 : -1)); ImFontAtlasBuildSetupFont(atlas, dst_font, &cfg, ascent, descent); const float off_x = cfg.GlyphOffset.x; const float off_y = cfg.GlyphOffset.y + (float)(int)(dst_font->Ascent + 0.5f); From 41ecebff5a63b1fa71ad0d1ef6f1e6d3d39ef07d Mon Sep 17 00:00:00 2001 From: omar Date: Thu, 15 Feb 2018 11:11:21 +0100 Subject: [PATCH 675/823] Examples: SDL: Added Changelog at the top of the imgui_impl files. (#1618) --- .../sdl_opengl2_example/imgui_impl_sdl_gl2.cpp | 14 ++++++++++++++ .../sdl_opengl3_example/imgui_impl_sdl_gl3.cpp | 17 +++++++++++++++++ 2 files changed, 31 insertions(+) diff --git a/examples/sdl_opengl2_example/imgui_impl_sdl_gl2.cpp b/examples/sdl_opengl2_example/imgui_impl_sdl_gl2.cpp index fe73bcc38dc9..11aa6a5ac86e 100644 --- a/examples/sdl_opengl2_example/imgui_impl_sdl_gl2.cpp +++ b/examples/sdl_opengl2_example/imgui_impl_sdl_gl2.cpp @@ -17,6 +17,20 @@ // If you are new to ImGui, see examples/README.txt and documentation at the top of imgui.cpp. // https://github.com/ocornut/imgui +// CHANGELOG +// 2018-02-06: Removed call to ImGui::Shutdown() which is not available from 1.60 WIP, user needs to call CreateContext/DestroyContext themselves. +// 2018-02-06: SDL: Added mapping for ImGuiKey_Space. +// 2018-02-05: SDL: Using SDL_GetPerformanceCounter() instead of SDL_GetTicks() to be able to handle very high framerate (1000+ FPS). +// 2018-02-05: SDL: Keyboard mapping is using scancodes everywhere instead of a confusing mixture of keycodes and scancodes. +// 2018-01-20: SDL: Added Horizontal Mouse Wheel support. +// 2018-01-19: SDL: When available (SDL 2.0.4+) using SDL_CaptureMouse() to retrieve coordinates outside of client area when dragging. Otherwise (SDL 2.0.3 and before) testing for SDL_WINDOW_INPUT_FOCUS instead of SDL_WINDOW_MOUSE_FOCUS. +// 2018-01-18: SDL: Added mapping for ImGuiKey_Insert. +// 2017-09-01: OpenGL: Save and restore current polygon mode. +// 2017-08-25: SDL: MousePos set to -FLT_MAX,-FLT_MAX when mouse is unavailable/missing (instead of -1,-1). +// 2016-10-15: Added a void* user_data parameter to Clipboard function handlers. +// 2016-09-05: OpenGL: Fixed save and restore of current scissor rectangle. +// 2016-07-29: OpenGL: Explicitly setting GL_UNPACK_ROW_LENGTH to reduce issues because SDL changes it. (#752) + #include #include #include diff --git a/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.cpp b/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.cpp index ceb2e7ebf097..7e0d26884de0 100644 --- a/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.cpp +++ b/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.cpp @@ -10,6 +10,23 @@ // If you are new to ImGui, see examples/README.txt and documentation at the top of imgui.cpp. // https://github.com/ocornut/imgui +// CHANGELOG +// 2018-02-06: Removed call to ImGui::Shutdown() which is not available from 1.60 WIP, user needs to call CreateContext/DestroyContext themselves. +// 2018-02-06: SDL: Added mapping for ImGuiKey_Space. +// 2018-02-05: SDL: Using SDL_GetPerformanceCounter() instead of SDL_GetTicks() to be able to handle very high framerate (1000+ FPS). +// 2018-02-05: SDL: Keyboard mapping is using scancodes everywhere instead of a confusing mixture of keycodes and scancodes. +// 2018-01-20: SDL: Added Horizontal Mouse Wheel support. +// 2018-01-19: SDL: When available (SDL 2.0.4+) using SDL_CaptureMouse() to retrieve coordinates outside of client area when dragging. Otherwise (SDL 2.0.3 and before) testing for SDL_WINDOW_INPUT_FOCUS instead of SDL_WINDOW_MOUSE_FOCUS. +// 2018-01-18: SDL: Added mapping for ImGuiKey_Insert. +// 2018-01-07: OpenGL: Changed GLSL shader version from 330 to 150. +// 2017-09-01: OpenGL: Save and restore current bound sampler. Save and restore current polygon mode. +// 2017-08-25: SDL: MousePos set to -FLT_MAX,-FLT_MAX when mouse is unavailable/missing (instead of -1,-1). +// 2017-05-01: OpenGL: Fixed save and restore of current blend func state. +// 2017-05-01: OpenGL: Fixed save and restore of current GL_ACTIVE_TEXTURE. +// 2016-10-15: Added a void* user_data parameter to Clipboard function handlers. +// 2016-09-05: OpenGL: Fixed save and restore of current scissor rectangle. +// 2016-07-29: OpenGL: Explicitly setting GL_UNPACK_ROW_LENGTH to reduce issues because SDL changes it. (#752) + #include "imgui.h" #include "imgui_impl_sdl_gl3.h" From ff5f56dd21e2d088f2d4256c85e1ff24d4900652 Mon Sep 17 00:00:00 2001 From: omar Date: Fri, 16 Feb 2018 11:59:23 +0100 Subject: [PATCH 676/823] Updated to stb_truetype 1.19 (include minor fix for #1622) --- stb_truetype.h | 955 +++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 895 insertions(+), 60 deletions(-) diff --git a/stb_truetype.h b/stb_truetype.h index 92b9a875478f..a08e929f9f3d 100644 --- a/stb_truetype.h +++ b/stb_truetype.h @@ -1,4 +1,4 @@ -// stb_truetype.h - v1.14 - public domain +// stb_truetype.h - v1.19 - public domain // authored from 2009-2016 by Sean Barrett / RAD Game Tools // // This library processes TrueType files: @@ -6,6 +6,7 @@ // extract glyph metrics // extract glyph shapes // render glyphs to one-channel bitmaps with antialiasing (box filter) +// render glyphs to one-channel SDF bitmaps (signed-distance field/function) // // Todo: // non-MS cmaps @@ -21,39 +22,40 @@ // Mikko Mononen: compound shape support, more cmap formats // Tor Andersson: kerning, subpixel rendering // Dougall Johnson: OpenType / Type 2 font handling +// Daniel Ribeiro Maciel: basic GPOS-based kerning // // Misc other: // Ryan Gordon // Simon Glass // github:IntellectualKitty +// Imanol Celaya +// Daniel Ribeiro Maciel // // Bug/warning reports/fixes: -// "Zer" on mollyrocket (with fix) -// Cass Everitt -// stoiko (Haemimont Games) -// Brian Hook -// Walter van Niftrik -// David Gow -// David Given -// Ivan-Assen Ivanov -// Anthony Pesch -// Johan Duparc -// Hou Qiming -// Fabian "ryg" Giesen -// Martins Mozeiko -// Cap Petschulat -// Omar Cornut -// github:aloucks -// Peter LaValle -// Sergey Popov -// Giumo X. Clanjor -// Higor Euripedes -// Thomas Fields -// Derek Vinyard -// +// "Zer" on mollyrocket Fabian "ryg" Giesen +// Cass Everitt Martins Mozeiko +// stoiko (Haemimont Games) Cap Petschulat +// Brian Hook Omar Cornut +// Walter van Niftrik github:aloucks +// David Gow Peter LaValle +// David Given Sergey Popov +// Ivan-Assen Ivanov Giumo X. Clanjor +// Anthony Pesch Higor Euripedes +// Johan Duparc Thomas Fields +// Hou Qiming Derek Vinyard +// Rob Loach Cort Stratton +// Kenney Phillis Jr. github:oyvindjam +// Brian Costabile github:vassvik +// // VERSION HISTORY // -// 1.13 (2017-01-02) support OpenType fonts, certain Apple fonts, num-fonts-in-TTC function +// 1.19 (2018-02-11) GPOS kerning, STBTT_fmod +// 1.18 (2018-01-29) add missing function +// 1.17 (2017-07-23) make more arguments const; doc fix +// 1.16 (2017-07-12) SDF support +// 1.15 (2017-03-03) make more arguments const +// 1.14 (2017-01-16) num-fonts-in-TTC function +// 1.13 (2017-01-02) support OpenType fonts, certain Apple fonts // 1.12 (2016-10-25) suppress warnings about casting away const with -Wcast-qual // 1.11 (2016-04-02) fix unused-variable warning // 1.10 (2016-04-02) user-defined fabs(); rare memory leak; remove duplicate typedef @@ -69,9 +71,7 @@ // // LICENSE // -// This software is dual-licensed to the public domain and under the following -// license: you are granted a perpetual, irrevocable license to copy, modify, -// publish, and distribute this file as you see fit. +// See end of file for license information. // // USAGE // @@ -91,7 +91,7 @@ // Improved 3D API (more shippable): // #include "stb_rect_pack.h" -- optional, but you really want it // stbtt_PackBegin() -// stbtt_PackSetOversample() -- for improved quality on small fonts +// stbtt_PackSetOversampling() -- for improved quality on small fonts // stbtt_PackFontRanges() -- pack and renders // stbtt_PackEnd() // stbtt_GetPackedQuad() @@ -109,6 +109,7 @@ // Character advance/positioning // stbtt_GetCodepointHMetrics() // stbtt_GetFontVMetrics() +// stbtt_GetFontVMetricsOS2() // stbtt_GetCodepointKernAdvance() // // Starting with version 1.06, the rasterizer was replaced with a new, @@ -164,7 +165,7 @@ // measurement for describing font size, defined as 72 points per inch. // stb_truetype provides a point API for compatibility. However, true // "per inch" conventions don't make much sense on computer displays -// since they different monitors have different number of pixels per +// since different monitors have different number of pixels per // inch. For example, Windows traditionally uses a convention that // there are 96 pixels per inch, thus making 'inch' measurements have // nothing to do with inches, and thus effectively defining a point to @@ -174,6 +175,39 @@ // for non-commercial fonts, thus making fonts scaled in points // according to the TrueType spec incoherently sized in practice. // +// DETAILED USAGE: +// +// Scale: +// Select how high you want the font to be, in points or pixels. +// Call ScaleForPixelHeight or ScaleForMappingEmToPixels to compute +// a scale factor SF that will be used by all other functions. +// +// Baseline: +// You need to select a y-coordinate that is the baseline of where +// your text will appear. Call GetFontBoundingBox to get the baseline-relative +// bounding box for all characters. SF*-y0 will be the distance in pixels +// that the worst-case character could extend above the baseline, so if +// you want the top edge of characters to appear at the top of the +// screen where y=0, then you would set the baseline to SF*-y0. +// +// Current point: +// Set the current point where the first character will appear. The +// first character could extend left of the current point; this is font +// dependent. You can either choose a current point that is the leftmost +// point and hope, or add some padding, or check the bounding box or +// left-side-bearing of the first character to be displayed and set +// the current point based on that. +// +// Displaying a character: +// Compute the bounding box of the character. It will contain signed values +// relative to . I.e. if it returns x0,y0,x1,y1, +// then the character should be displayed in the rectangle from +// to #define STBTT_ifloor(x) ((int) floor(x)) @@ -406,6 +441,18 @@ int main(int arg, char **argv) #ifndef STBTT_sqrt #include #define STBTT_sqrt(x) sqrt(x) + #define STBTT_pow(x,y) pow(x,y) + #endif + + #ifndef STBTT_fmod + #include + #define STBTT_fmod(x,y) fmod(x,y) + #endif + + #ifndef STBTT_cos + #include + #define STBTT_cos(x) cos(x) + #define STBTT_acos(x) acos(x) #endif #ifndef STBTT_fabs @@ -431,7 +478,7 @@ int main(int arg, char **argv) #endif #ifndef STBTT_memcpy - #include + #include #define STBTT_memcpy memcpy #define STBTT_memset memset #endif @@ -494,7 +541,7 @@ typedef struct float x1,y1,s1,t1; // bottom-right } stbtt_aligned_quad; -STBTT_DEF void stbtt_GetBakedQuad(stbtt_bakedchar *chardata, int pw, int ph, // same data as above +STBTT_DEF void stbtt_GetBakedQuad(const stbtt_bakedchar *chardata, int pw, int ph, // same data as above int char_index, // character to display float *xpos, float *ypos, // pointers to current position in screen pixel space stbtt_aligned_quad *q, // output: quad to draw @@ -547,7 +594,7 @@ STBTT_DEF void stbtt_PackEnd (stbtt_pack_context *spc); #define STBTT_POINT_SIZE(x) (-(x)) -STBTT_DEF int stbtt_PackFontRange(stbtt_pack_context *spc, unsigned char *fontdata, int font_index, float font_size, +STBTT_DEF int stbtt_PackFontRange(stbtt_pack_context *spc, const unsigned char *fontdata, int font_index, float font_size, int first_unicode_char_in_range, int num_chars_in_range, stbtt_packedchar *chardata_for_range); // Creates character bitmaps from the font_index'th font found in fontdata (use // font_index=0 if you don't know what that is). It creates num_chars_in_range @@ -572,7 +619,7 @@ typedef struct unsigned char h_oversample, v_oversample; // don't set these, they're used internally } stbtt_pack_range; -STBTT_DEF int stbtt_PackFontRanges(stbtt_pack_context *spc, unsigned char *fontdata, int font_index, stbtt_pack_range *ranges, int num_ranges); +STBTT_DEF int stbtt_PackFontRanges(stbtt_pack_context *spc, const unsigned char *fontdata, int font_index, stbtt_pack_range *ranges, int num_ranges); // Creates character bitmaps from multiple ranges of characters stored in // ranges. This will usually create a better-packed bitmap than multiple // calls to stbtt_PackFontRange. Note that you can call this multiple @@ -594,7 +641,7 @@ STBTT_DEF void stbtt_PackSetOversampling(stbtt_pack_context *spc, unsigned int h // To use with PackFontRangesGather etc., you must set it before calls // call to PackFontRangesGatherRects. -STBTT_DEF void stbtt_GetPackedQuad(stbtt_packedchar *chardata, int pw, int ph, // same data as above +STBTT_DEF void stbtt_GetPackedQuad(const stbtt_packedchar *chardata, int pw, int ph, // same data as above int char_index, // character to display float *xpos, float *ypos, // pointers to current position in screen pixel space stbtt_aligned_quad *q, // output: quad to draw @@ -657,7 +704,7 @@ struct stbtt_fontinfo int numGlyphs; // number of glyphs, needed for range checking - int loca,head,glyf,hhea,hmtx,kern; // table locations as offset from start of .ttf + int loca,head,glyf,hhea,hmtx,kern,gpos; // table locations as offset from start of .ttf int index_map; // a cmap mapping for our chosen character encoding int indexToLocFormat; // format needed to map from glyph index to glyph @@ -714,6 +761,12 @@ STBTT_DEF void stbtt_GetFontVMetrics(const stbtt_fontinfo *info, int *ascent, in // these are expressed in unscaled coordinates, so you must multiply by // the scale factor for a given size +STBTT_DEF int stbtt_GetFontVMetricsOS2(const stbtt_fontinfo *info, int *typoAscent, int *typoDescent, int *typoLineGap); +// analogous to GetFontVMetrics, but returns the "typographic" values from the OS/2 +// table (specific to MS/Windows TTF files). +// +// Returns 1 on success (table present), 0 on failure. + STBTT_DEF void stbtt_GetFontBoundingBox(const stbtt_fontinfo *info, int *x0, int *y0, int *x1, int *y1); // the bounding box around all possible characters @@ -808,6 +861,10 @@ STBTT_DEF void stbtt_MakeCodepointBitmapSubpixel(const stbtt_fontinfo *info, uns // same as stbtt_MakeCodepointBitmap, but you can specify a subpixel // shift for the character +STBTT_DEF void stbtt_MakeCodepointBitmapSubpixelPrefilter(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int oversample_x, int oversample_y, float *sub_x, float *sub_y, int codepoint); +// same as stbtt_MakeCodepointBitmapSubpixel, but prefiltering +// is performed (see stbtt_PackSetOversampling) + STBTT_DEF void stbtt_GetCodepointBitmapBox(const stbtt_fontinfo *font, int codepoint, float scale_x, float scale_y, int *ix0, int *iy0, int *ix1, int *iy1); // get the bbox of the bitmap centered around the glyph origin; so the // bitmap width is ix1-ix0, height is iy1-iy0, and location to place @@ -825,6 +882,7 @@ STBTT_DEF unsigned char *stbtt_GetGlyphBitmap(const stbtt_fontinfo *info, float STBTT_DEF unsigned char *stbtt_GetGlyphBitmapSubpixel(const stbtt_fontinfo *info, float scale_x, float scale_y, float shift_x, float shift_y, int glyph, int *width, int *height, int *xoff, int *yoff); STBTT_DEF void stbtt_MakeGlyphBitmap(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, int glyph); STBTT_DEF void stbtt_MakeGlyphBitmapSubpixel(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int glyph); +STBTT_DEF void stbtt_MakeGlyphBitmapSubpixelPrefilter(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int oversample_x, int oversample_y, float *sub_x, float *sub_y, int glyph); STBTT_DEF void stbtt_GetGlyphBitmapBox(const stbtt_fontinfo *font, int glyph, float scale_x, float scale_y, int *ix0, int *iy0, int *ix1, int *iy1); STBTT_DEF void stbtt_GetGlyphBitmapBoxSubpixel(const stbtt_fontinfo *font, int glyph, float scale_x, float scale_y,float shift_x, float shift_y, int *ix0, int *iy0, int *ix1, int *iy1); @@ -847,6 +905,64 @@ STBTT_DEF void stbtt_Rasterize(stbtt__bitmap *result, // 1-channel bitmap int invert, // if non-zero, vertically flip shape void *userdata); // context for to STBTT_MALLOC +////////////////////////////////////////////////////////////////////////////// +// +// Signed Distance Function (or Field) rendering + +STBTT_DEF void stbtt_FreeSDF(unsigned char *bitmap, void *userdata); +// frees the SDF bitmap allocated below + +STBTT_DEF unsigned char * stbtt_GetGlyphSDF(const stbtt_fontinfo *info, float scale, int glyph, int padding, unsigned char onedge_value, float pixel_dist_scale, int *width, int *height, int *xoff, int *yoff); +STBTT_DEF unsigned char * stbtt_GetCodepointSDF(const stbtt_fontinfo *info, float scale, int codepoint, int padding, unsigned char onedge_value, float pixel_dist_scale, int *width, int *height, int *xoff, int *yoff); +// These functions compute a discretized SDF field for a single character, suitable for storing +// in a single-channel texture, sampling with bilinear filtering, and testing against +// larger than some threshhold to produce scalable fonts. +// info -- the font +// scale -- controls the size of the resulting SDF bitmap, same as it would be creating a regular bitmap +// glyph/codepoint -- the character to generate the SDF for +// padding -- extra "pixels" around the character which are filled with the distance to the character (not 0), +// which allows effects like bit outlines +// onedge_value -- value 0-255 to test the SDF against to reconstruct the character (i.e. the isocontour of the character) +// pixel_dist_scale -- what value the SDF should increase by when moving one SDF "pixel" away from the edge (on the 0..255 scale) +// if positive, > onedge_value is inside; if negative, < onedge_value is inside +// width,height -- output height & width of the SDF bitmap (including padding) +// xoff,yoff -- output origin of the character +// return value -- a 2D array of bytes 0..255, width*height in size +// +// pixel_dist_scale & onedge_value are a scale & bias that allows you to make +// optimal use of the limited 0..255 for your application, trading off precision +// and special effects. SDF values outside the range 0..255 are clamped to 0..255. +// +// Example: +// scale = stbtt_ScaleForPixelHeight(22) +// padding = 5 +// onedge_value = 180 +// pixel_dist_scale = 180/5.0 = 36.0 +// +// This will create an SDF bitmap in which the character is about 22 pixels +// high but the whole bitmap is about 22+5+5=32 pixels high. To produce a filled +// shape, sample the SDF at each pixel and fill the pixel if the SDF value +// is greater than or equal to 180/255. (You'll actually want to antialias, +// which is beyond the scope of this example.) Additionally, you can compute +// offset outlines (e.g. to stroke the character border inside & outside, +// or only outside). For example, to fill outside the character up to 3 SDF +// pixels, you would compare against (180-36.0*3)/255 = 72/255. The above +// choice of variables maps a range from 5 pixels outside the shape to +// 2 pixels inside the shape to 0..255; this is intended primarily for apply +// outside effects only (the interior range is needed to allow proper +// antialiasing of the font at *smaller* sizes) +// +// The function computes the SDF analytically at each SDF pixel, not by e.g. +// building a higher-res bitmap and approximating it. In theory the quality +// should be as high as possible for an SDF of this size & representation, but +// unclear if this is true in practice (perhaps building a higher-res bitmap +// and computing from that can allow drop-out prevention). +// +// The algorithm has not been optimized at all, so expect it to be slow +// if computing lots of characters or very large sizes. + + + ////////////////////////////////////////////////////////////////////////////// // // Finding the right font... @@ -1231,6 +1347,7 @@ static int stbtt_InitFont_internal(stbtt_fontinfo *info, unsigned char *data, in info->hhea = stbtt__find_table(data, fontstart, "hhea"); // required info->hmtx = stbtt__find_table(data, fontstart, "hmtx"); // required info->kern = stbtt__find_table(data, fontstart, "kern"); // not required + info->gpos = stbtt__find_table(data, fontstart, "GPOS"); // not required if (!cmap || !info->head || !info->hhea || !info->hmtx) return 0; @@ -2084,7 +2201,7 @@ static int stbtt__run_charstring(const stbtt_fontinfo *info, int glyph_index, st // push immediate if (b0 == 255) { - f = (float)stbtt__buf_get32(&b) / 0x10000; + f = (float)(stbtt_int32)stbtt__buf_get32(&b) / 0x10000; } else { stbtt__buf_skip(&b, -1); f = (float)(stbtt_int16)stbtt__cff_int(&b); @@ -2122,12 +2239,10 @@ static int stbtt__GetGlyphInfoT2(const stbtt_fontinfo *info, int glyph_index, in { stbtt__csctx c = STBTT__CSCTX_INIT(1); int r = stbtt__run_charstring(info, glyph_index, &c); - if (x0) { - *x0 = r ? c.min_x : 0; - *y0 = r ? c.min_y : 0; - *x1 = r ? c.max_x : 0; - *y1 = r ? c.max_y : 0; - } + if (x0) *x0 = r ? c.min_x : 0; + if (y0) *y0 = r ? c.min_y : 0; + if (x1) *x1 = r ? c.max_x : 0; + if (y1) *y1 = r ? c.max_y : 0; return r ? c.num_vertices : 0; } @@ -2151,7 +2266,7 @@ STBTT_DEF void stbtt_GetGlyphHMetrics(const stbtt_fontinfo *info, int glyph_inde } } -STBTT_DEF int stbtt_GetGlyphKernAdvance(const stbtt_fontinfo *info, int glyph1, int glyph2) +static int stbtt__GetGlyphKernInfoAdvance(const stbtt_fontinfo *info, int glyph1, int glyph2) { stbtt_uint8 *data = info->data + info->kern; stbtt_uint32 needle, straw; @@ -2181,9 +2296,260 @@ STBTT_DEF int stbtt_GetGlyphKernAdvance(const stbtt_fontinfo *info, int glyph1, return 0; } +static stbtt_int32 stbtt__GetCoverageIndex(stbtt_uint8 *coverageTable, int glyph) +{ + stbtt_uint16 coverageFormat = ttUSHORT(coverageTable); + switch(coverageFormat) { + case 1: { + stbtt_uint16 glyphCount = ttUSHORT(coverageTable + 2); + + // Binary search. + stbtt_int32 l=0, r=glyphCount-1, m; + int straw, needle=glyph; + while (l <= r) { + stbtt_uint8 *glyphArray = coverageTable + 4; + stbtt_uint16 glyphID; + m = (l + r) >> 1; + glyphID = ttUSHORT(glyphArray + 2 * m); + straw = glyphID; + if (needle < straw) + r = m - 1; + else if (needle > straw) + l = m + 1; + else { + return m; + } + } + } break; + + case 2: { + stbtt_uint16 rangeCount = ttUSHORT(coverageTable + 2); + stbtt_uint8 *rangeArray = coverageTable + 4; + + // Binary search. + stbtt_int32 l=0, r=rangeCount-1, m; + int strawStart, strawEnd, needle=glyph; + while (l <= r) { + stbtt_uint8 *rangeRecord; + m = (l + r) >> 1; + rangeRecord = rangeArray + 6 * m; + strawStart = ttUSHORT(rangeRecord); + strawEnd = ttUSHORT(rangeRecord + 2); + if (needle < strawStart) + r = m - 1; + else if (needle > strawEnd) + l = m + 1; + else { + stbtt_uint16 startCoverageIndex = ttUSHORT(rangeRecord + 4); + return startCoverageIndex + glyph - strawStart; + } + } + } break; + + default: { + // There are no other cases. + STBTT_assert(0); + } break; + } + + return -1; +} + +static stbtt_int32 stbtt__GetGlyphClass(stbtt_uint8 *classDefTable, int glyph) +{ + stbtt_uint16 classDefFormat = ttUSHORT(classDefTable); + switch(classDefFormat) + { + case 1: { + stbtt_uint16 startGlyphID = ttUSHORT(classDefTable + 2); + stbtt_uint16 glyphCount = ttUSHORT(classDefTable + 4); + stbtt_uint8 *classDef1ValueArray = classDefTable + 6; + + if (glyph >= startGlyphID && glyph < startGlyphID + glyphCount) + return (stbtt_int32)ttUSHORT(classDef1ValueArray + 2 * (glyph - startGlyphID)); + + classDefTable = classDef1ValueArray + 2 * glyphCount; + } break; + + case 2: { + stbtt_uint16 classRangeCount = ttUSHORT(classDefTable + 2); + stbtt_uint8 *classRangeRecords = classDefTable + 4; + + // Binary search. + stbtt_int32 l=0, r=classRangeCount-1, m; + int strawStart, strawEnd, needle=glyph; + while (l <= r) { + stbtt_uint8 *classRangeRecord; + m = (l + r) >> 1; + classRangeRecord = classRangeRecords + 6 * m; + strawStart = ttUSHORT(classRangeRecord); + strawEnd = ttUSHORT(classRangeRecord + 2); + if (needle < strawStart) + r = m - 1; + else if (needle > strawEnd) + l = m + 1; + else + return (stbtt_int32)ttUSHORT(classRangeRecord + 4); + } + + classDefTable = classRangeRecords + 6 * classRangeCount; + } break; + + default: { + // There are no other cases. + STBTT_assert(0); + } break; + } + + return -1; +} + +// Define to STBTT_assert(x) if you want to break on unimplemented formats. +#define STBTT_GPOS_TODO_assert(x) + +static stbtt_int32 stbtt__GetGlyphGPOSInfoAdvance(const stbtt_fontinfo *info, int glyph1, int glyph2) +{ + stbtt_uint16 lookupListOffset; + stbtt_uint8 *lookupList; + stbtt_uint16 lookupCount; + stbtt_uint8 *data; + stbtt_int32 i; + + if (!info->gpos) return 0; + + data = info->data + info->gpos; + + if (ttUSHORT(data+0) != 1) return 0; // Major version 1 + if (ttUSHORT(data+2) != 0) return 0; // Minor version 0 + + lookupListOffset = ttUSHORT(data+8); + lookupList = data + lookupListOffset; + lookupCount = ttUSHORT(lookupList); + + for (i=0; i> 1; + pairValue = pairValueArray + (2 + valueRecordPairSizeInBytes) * m; + secondGlyph = ttUSHORT(pairValue); + straw = secondGlyph; + if (needle < straw) + r = m - 1; + else if (needle > straw) + l = m + 1; + else { + stbtt_int16 xAdvance = ttSHORT(pairValue + 2); + return xAdvance; + } + } + } break; + + case 2: { + stbtt_uint16 valueFormat1 = ttUSHORT(table + 4); + stbtt_uint16 valueFormat2 = ttUSHORT(table + 6); + + stbtt_uint16 classDef1Offset = ttUSHORT(table + 8); + stbtt_uint16 classDef2Offset = ttUSHORT(table + 10); + int glyph1class = stbtt__GetGlyphClass(table + classDef1Offset, glyph1); + int glyph2class = stbtt__GetGlyphClass(table + classDef2Offset, glyph2); + + stbtt_uint16 class1Count = ttUSHORT(table + 12); + stbtt_uint16 class2Count = ttUSHORT(table + 14); + STBTT_assert(glyph1class < class1Count); + STBTT_assert(glyph2class < class2Count); + + // TODO: Support more formats. + STBTT_GPOS_TODO_assert(valueFormat1 == 4); + if (valueFormat1 != 4) return 0; + STBTT_GPOS_TODO_assert(valueFormat2 == 0); + if (valueFormat2 != 0) return 0; + + if (glyph1class >= 0 && glyph1class < class1Count && glyph2class >= 0 && glyph2class < class2Count) { + stbtt_uint8 *class1Records = table + 16; + stbtt_uint8 *class2Records = class1Records + 2 * (glyph1class * class2Count); + stbtt_int16 xAdvance = ttSHORT(class2Records + 2 * glyph2class); + return xAdvance; + } + } break; + + default: { + // There are no other cases. + STBTT_assert(0); + break; + }; + } + } + break; + }; + + default: + // TODO: Implement other stuff. + break; + } + } + + return 0; +} + +STBTT_DEF int stbtt_GetGlyphKernAdvance(const stbtt_fontinfo *info, int g1, int g2) +{ + int xAdvance = 0; + + if (info->gpos) + xAdvance += stbtt__GetGlyphGPOSInfoAdvance(info, g1, g2); + + if (info->kern) + xAdvance += stbtt__GetGlyphKernInfoAdvance(info, g1, g2); + + return xAdvance; +} + STBTT_DEF int stbtt_GetCodepointKernAdvance(const stbtt_fontinfo *info, int ch1, int ch2) { - if (!info->kern) // if no kerning table, don't waste time looking up both codepoint->glyphs + if (!info->kern && !info->gpos) // if no kerning table, don't waste time looking up both codepoint->glyphs return 0; return stbtt_GetGlyphKernAdvance(info, stbtt_FindGlyphIndex(info,ch1), stbtt_FindGlyphIndex(info,ch2)); } @@ -2200,6 +2566,17 @@ STBTT_DEF void stbtt_GetFontVMetrics(const stbtt_fontinfo *info, int *ascent, in if (lineGap) *lineGap = ttSHORT(info->data+info->hhea + 8); } +STBTT_DEF int stbtt_GetFontVMetricsOS2(const stbtt_fontinfo *info, int *typoAscent, int *typoDescent, int *typoLineGap) +{ + int tab = stbtt__find_table(info->data, info->fontstart, "OS/2"); + if (!tab) + return 0; + if (typoAscent ) *typoAscent = ttSHORT(info->data+tab + 68); + if (typoDescent) *typoDescent = ttSHORT(info->data+tab + 70); + if (typoLineGap) *typoLineGap = ttSHORT(info->data+tab + 72); + return 1; +} + STBTT_DEF void stbtt_GetFontBoundingBox(const stbtt_fontinfo *info, int *x0, int *y0, int *x1, int *y1) { *x0 = ttSHORT(info->data + info->head + 36); @@ -2296,7 +2673,7 @@ static void *stbtt__hheap_alloc(stbtt__hheap *hh, size_t size, void *userdata) hh->num_remaining_in_head_chunk = count; } --hh->num_remaining_in_head_chunk; - return (char *) (hh->head) + size * hh->num_remaining_in_head_chunk; + return (char *) (hh->head) + sizeof(stbtt__hheap_chunk) + size * hh->num_remaining_in_head_chunk; } } @@ -2692,19 +3069,18 @@ static void stbtt__fill_active_edges_new(float *scanline, float *scanline_fill, // from the other y segment, and it might ignored as an empty segment. to avoid // that, we need to explicitly produce segments based on x positions. - // rename variables to clear pairs + // rename variables to clearly-defined pairs float y0 = y_top; float x1 = (float) (x); float x2 = (float) (x+1); float x3 = xb; float y3 = y_bottom; - float y1,y2; // x = e->x + e->dx * (y-y_top) // (y-y_top) = (x - e->x) / e->dx // y = (x - e->x) / e->dx + y_top - y1 = (x - x0) / dx + y_top; - y2 = (x+1 - x0) / dx + y_top; + float y1 = (x - x0) / dx + y_top; + float y2 = (x+1 - x0) / dx + y_top; if (x0 < x1 && x3 > x2) { // three segments descending down-right stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x1,y1); @@ -3131,8 +3507,9 @@ static stbtt__point *stbtt_FlattenCurves(stbtt_vertex *vertices, int num_verts, STBTT_DEF void stbtt_Rasterize(stbtt__bitmap *result, float flatness_in_pixels, stbtt_vertex *vertices, int num_verts, float scale_x, float scale_y, float shift_x, float shift_y, int x_off, int y_off, int invert, void *userdata) { - float scale = scale_x > scale_y ? scale_y : scale_x; - int winding_count, *winding_lengths; + float scale = scale_x > scale_y ? scale_y : scale_x; + int winding_count = 0; + int *winding_lengths = NULL; stbtt__point *windings = stbtt_FlattenCurves(vertices, num_verts, flatness_in_pixels / scale, &winding_lengths, &winding_count, userdata); if (windings) { stbtt__rasterize(result, windings, winding_lengths, winding_count, scale_x, scale_y, shift_x, shift_y, x_off, y_off, invert, userdata); @@ -3220,6 +3597,11 @@ STBTT_DEF unsigned char *stbtt_GetCodepointBitmapSubpixel(const stbtt_fontinfo * return stbtt_GetGlyphBitmapSubpixel(info, scale_x, scale_y,shift_x,shift_y, stbtt_FindGlyphIndex(info,codepoint), width,height,xoff,yoff); } +STBTT_DEF void stbtt_MakeCodepointBitmapSubpixelPrefilter(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int oversample_x, int oversample_y, float *sub_x, float *sub_y, int codepoint) +{ + stbtt_MakeGlyphBitmapSubpixelPrefilter(info, output, out_w, out_h, out_stride, scale_x, scale_y, shift_x, shift_y, oversample_x, oversample_y, sub_x, sub_y, stbtt_FindGlyphIndex(info,codepoint)); +} + STBTT_DEF void stbtt_MakeCodepointBitmapSubpixel(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int codepoint) { stbtt_MakeGlyphBitmapSubpixel(info, output, out_w, out_h, out_stride, scale_x, scale_y, shift_x, shift_y, stbtt_FindGlyphIndex(info,codepoint)); @@ -3287,11 +3669,11 @@ static int stbtt_BakeFontBitmap_internal(unsigned char *data, int offset, // fo return bottom_y; } -STBTT_DEF void stbtt_GetBakedQuad(stbtt_bakedchar *chardata, int pw, int ph, int char_index, float *xpos, float *ypos, stbtt_aligned_quad *q, int opengl_fillrule) +STBTT_DEF void stbtt_GetBakedQuad(const stbtt_bakedchar *chardata, int pw, int ph, int char_index, float *xpos, float *ypos, stbtt_aligned_quad *q, int opengl_fillrule) { float d3d_bias = opengl_fillrule ? 0 : -0.5f; float ipw = 1.0f / pw, iph = 1.0f / ph; - stbtt_bakedchar *b = chardata + char_index; + const stbtt_bakedchar *b = chardata + char_index; int round_x = STBTT_ifloor((*xpos + b->xoff) + 0.5f); int round_y = STBTT_ifloor((*ypos + b->yoff) + 0.5f); @@ -3599,6 +3981,29 @@ STBTT_DEF int stbtt_PackFontRangesGatherRects(stbtt_pack_context *spc, const stb return k; } +STBTT_DEF void stbtt_MakeGlyphBitmapSubpixelPrefilter(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int prefilter_x, int prefilter_y, float *sub_x, float *sub_y, int glyph) +{ + stbtt_MakeGlyphBitmapSubpixel(info, + output, + out_w - (prefilter_x - 1), + out_h - (prefilter_y - 1), + out_stride, + scale_x, + scale_y, + shift_x, + shift_y, + glyph); + + if (prefilter_x > 1) + stbtt__h_prefilter(output, out_w, out_h, out_stride, prefilter_x); + + if (prefilter_y > 1) + stbtt__v_prefilter(output, out_w, out_h, out_stride, prefilter_y); + + *sub_x = stbtt__oversample_shift(prefilter_x); + *sub_y = stbtt__oversample_shift(prefilter_y); +} + // rects array must be big enough to accommodate all characters in the given ranges STBTT_DEF int stbtt_PackFontRangesRenderIntoRects(stbtt_pack_context *spc, const stbtt_fontinfo *info, stbtt_pack_range *ranges, int num_ranges, stbrp_rect *rects) { @@ -3687,7 +4092,7 @@ STBTT_DEF void stbtt_PackFontRangesPackRects(stbtt_pack_context *spc, stbrp_rect stbrp_pack_rects((stbrp_context *) spc->pack_info, rects, num_rects); } -STBTT_DEF int stbtt_PackFontRanges(stbtt_pack_context *spc, unsigned char *fontdata, int font_index, stbtt_pack_range *ranges, int num_ranges) +STBTT_DEF int stbtt_PackFontRanges(stbtt_pack_context *spc, const unsigned char *fontdata, int font_index, stbtt_pack_range *ranges, int num_ranges) { stbtt_fontinfo info; int i,j,n, return_value = 1; @@ -3723,7 +4128,7 @@ STBTT_DEF int stbtt_PackFontRanges(stbtt_pack_context *spc, unsigned char *fontd return return_value; } -STBTT_DEF int stbtt_PackFontRange(stbtt_pack_context *spc, unsigned char *fontdata, int font_index, float font_size, +STBTT_DEF int stbtt_PackFontRange(stbtt_pack_context *spc, const unsigned char *fontdata, int font_index, float font_size, int first_unicode_codepoint_in_range, int num_chars_in_range, stbtt_packedchar *chardata_for_range) { stbtt_pack_range range; @@ -3735,10 +4140,10 @@ STBTT_DEF int stbtt_PackFontRange(stbtt_pack_context *spc, unsigned char *fontda return stbtt_PackFontRanges(spc, fontdata, font_index, &range, 1); } -STBTT_DEF void stbtt_GetPackedQuad(stbtt_packedchar *chardata, int pw, int ph, int char_index, float *xpos, float *ypos, stbtt_aligned_quad *q, int align_to_integer) +STBTT_DEF void stbtt_GetPackedQuad(const stbtt_packedchar *chardata, int pw, int ph, int char_index, float *xpos, float *ypos, stbtt_aligned_quad *q, int align_to_integer) { float ipw = 1.0f / pw, iph = 1.0f / ph; - stbtt_packedchar *b = chardata + char_index; + const stbtt_packedchar *b = chardata + char_index; if (align_to_integer) { float x = (float) STBTT_ifloor((*xpos + b->xoff) + 0.5f); @@ -3762,6 +4167,387 @@ STBTT_DEF void stbtt_GetPackedQuad(stbtt_packedchar *chardata, int pw, int ph, i *xpos += b->xadvance; } +////////////////////////////////////////////////////////////////////////////// +// +// sdf computation +// + +#define STBTT_min(a,b) ((a) < (b) ? (a) : (b)) +#define STBTT_max(a,b) ((a) < (b) ? (b) : (a)) + +static int stbtt__ray_intersect_bezier(float orig[2], float ray[2], float q0[2], float q1[2], float q2[2], float hits[2][2]) +{ + float q0perp = q0[1]*ray[0] - q0[0]*ray[1]; + float q1perp = q1[1]*ray[0] - q1[0]*ray[1]; + float q2perp = q2[1]*ray[0] - q2[0]*ray[1]; + float roperp = orig[1]*ray[0] - orig[0]*ray[1]; + + float a = q0perp - 2*q1perp + q2perp; + float b = q1perp - q0perp; + float c = q0perp - roperp; + + float s0 = 0., s1 = 0.; + int num_s = 0; + + if (a != 0.0) { + float discr = b*b - a*c; + if (discr > 0.0) { + float rcpna = -1 / a; + float d = (float) STBTT_sqrt(discr); + s0 = (b+d) * rcpna; + s1 = (b-d) * rcpna; + if (s0 >= 0.0 && s0 <= 1.0) + num_s = 1; + if (d > 0.0 && s1 >= 0.0 && s1 <= 1.0) { + if (num_s == 0) s0 = s1; + ++num_s; + } + } + } else { + // 2*b*s + c = 0 + // s = -c / (2*b) + s0 = c / (-2 * b); + if (s0 >= 0.0 && s0 <= 1.0) + num_s = 1; + } + + if (num_s == 0) + return 0; + else { + float rcp_len2 = 1 / (ray[0]*ray[0] + ray[1]*ray[1]); + float rayn_x = ray[0] * rcp_len2, rayn_y = ray[1] * rcp_len2; + + float q0d = q0[0]*rayn_x + q0[1]*rayn_y; + float q1d = q1[0]*rayn_x + q1[1]*rayn_y; + float q2d = q2[0]*rayn_x + q2[1]*rayn_y; + float rod = orig[0]*rayn_x + orig[1]*rayn_y; + + float q10d = q1d - q0d; + float q20d = q2d - q0d; + float q0rd = q0d - rod; + + hits[0][0] = q0rd + s0*(2.0f - 2.0f*s0)*q10d + s0*s0*q20d; + hits[0][1] = a*s0+b; + + if (num_s > 1) { + hits[1][0] = q0rd + s1*(2.0f - 2.0f*s1)*q10d + s1*s1*q20d; + hits[1][1] = a*s1+b; + return 2; + } else { + return 1; + } + } +} + +static int equal(float *a, float *b) +{ + return (a[0] == b[0] && a[1] == b[1]); +} + +static int stbtt__compute_crossings_x(float x, float y, int nverts, stbtt_vertex *verts) +{ + int i; + float orig[2], ray[2] = { 1, 0 }; + float y_frac; + int winding = 0; + + orig[0] = x; + orig[1] = y; + + // make sure y never passes through a vertex of the shape + y_frac = (float) STBTT_fmod(y, 1.0f); + if (y_frac < 0.01f) + y += 0.01f; + else if (y_frac > 0.99f) + y -= 0.01f; + orig[1] = y; + + // test a ray from (-infinity,y) to (x,y) + for (i=0; i < nverts; ++i) { + if (verts[i].type == STBTT_vline) { + int x0 = (int) verts[i-1].x, y0 = (int) verts[i-1].y; + int x1 = (int) verts[i ].x, y1 = (int) verts[i ].y; + if (y > STBTT_min(y0,y1) && y < STBTT_max(y0,y1) && x > STBTT_min(x0,x1)) { + float x_inter = (y - y0) / (y1 - y0) * (x1-x0) + x0; + if (x_inter < x) + winding += (y0 < y1) ? 1 : -1; + } + } + if (verts[i].type == STBTT_vcurve) { + int x0 = (int) verts[i-1].x , y0 = (int) verts[i-1].y ; + int x1 = (int) verts[i ].cx, y1 = (int) verts[i ].cy; + int x2 = (int) verts[i ].x , y2 = (int) verts[i ].y ; + int ax = STBTT_min(x0,STBTT_min(x1,x2)), ay = STBTT_min(y0,STBTT_min(y1,y2)); + int by = STBTT_max(y0,STBTT_max(y1,y2)); + if (y > ay && y < by && x > ax) { + float q0[2],q1[2],q2[2]; + float hits[2][2]; + q0[0] = (float)x0; + q0[1] = (float)y0; + q1[0] = (float)x1; + q1[1] = (float)y1; + q2[0] = (float)x2; + q2[1] = (float)y2; + if (equal(q0,q1) || equal(q1,q2)) { + x0 = (int)verts[i-1].x; + y0 = (int)verts[i-1].y; + x1 = (int)verts[i ].x; + y1 = (int)verts[i ].y; + if (y > STBTT_min(y0,y1) && y < STBTT_max(y0,y1) && x > STBTT_min(x0,x1)) { + float x_inter = (y - y0) / (y1 - y0) * (x1-x0) + x0; + if (x_inter < x) + winding += (y0 < y1) ? 1 : -1; + } + } else { + int num_hits = stbtt__ray_intersect_bezier(orig, ray, q0, q1, q2, hits); + if (num_hits >= 1) + if (hits[0][0] < 0) + winding += (hits[0][1] < 0 ? -1 : 1); + if (num_hits >= 2) + if (hits[1][0] < 0) + winding += (hits[1][1] < 0 ? -1 : 1); + } + } + } + } + return winding; +} + +static float stbtt__cuberoot( float x ) +{ + if (x<0) + return -(float) STBTT_pow(-x,1.0f/3.0f); + else + return (float) STBTT_pow( x,1.0f/3.0f); +} + +// x^3 + c*x^2 + b*x + a = 0 +static int stbtt__solve_cubic(float a, float b, float c, float* r) +{ + float s = -a / 3; + float p = b - a*a / 3; + float q = a * (2*a*a - 9*b) / 27 + c; + float p3 = p*p*p; + float d = q*q + 4*p3 / 27; + if (d >= 0) { + float z = (float) STBTT_sqrt(d); + float u = (-q + z) / 2; + float v = (-q - z) / 2; + u = stbtt__cuberoot(u); + v = stbtt__cuberoot(v); + r[0] = s + u + v; + return 1; + } else { + float u = (float) STBTT_sqrt(-p/3); + float v = (float) STBTT_acos(-STBTT_sqrt(-27/p3) * q / 2) / 3; // p3 must be negative, since d is negative + float m = (float) STBTT_cos(v); + float n = (float) STBTT_cos(v-3.141592/2)*1.732050808f; + r[0] = s + u * 2 * m; + r[1] = s - u * (m + n); + r[2] = s - u * (m - n); + + //STBTT_assert( STBTT_fabs(((r[0]+a)*r[0]+b)*r[0]+c) < 0.05f); // these asserts may not be safe at all scales, though they're in bezier t parameter units so maybe? + //STBTT_assert( STBTT_fabs(((r[1]+a)*r[1]+b)*r[1]+c) < 0.05f); + //STBTT_assert( STBTT_fabs(((r[2]+a)*r[2]+b)*r[2]+c) < 0.05f); + return 3; + } +} + +STBTT_DEF unsigned char * stbtt_GetGlyphSDF(const stbtt_fontinfo *info, float scale, int glyph, int padding, unsigned char onedge_value, float pixel_dist_scale, int *width, int *height, int *xoff, int *yoff) +{ + float scale_x = scale, scale_y = scale; + int ix0,iy0,ix1,iy1; + int w,h; + unsigned char *data; + + // if one scale is 0, use same scale for both + if (scale_x == 0) scale_x = scale_y; + if (scale_y == 0) { + if (scale_x == 0) return NULL; // if both scales are 0, return NULL + scale_y = scale_x; + } + + stbtt_GetGlyphBitmapBoxSubpixel(info, glyph, scale, scale, 0.0f,0.0f, &ix0,&iy0,&ix1,&iy1); + + // if empty, return NULL + if (ix0 == ix1 || iy0 == iy1) + return NULL; + + ix0 -= padding; + iy0 -= padding; + ix1 += padding; + iy1 += padding; + + w = (ix1 - ix0); + h = (iy1 - iy0); + + if (width ) *width = w; + if (height) *height = h; + if (xoff ) *xoff = ix0; + if (yoff ) *yoff = iy0; + + // invert for y-downwards bitmaps + scale_y = -scale_y; + + { + int x,y,i,j; + float *precompute; + stbtt_vertex *verts; + int num_verts = stbtt_GetGlyphShape(info, glyph, &verts); + data = (unsigned char *) STBTT_malloc(w * h, info->userdata); + precompute = (float *) STBTT_malloc(num_verts * sizeof(float), info->userdata); + + for (i=0,j=num_verts-1; i < num_verts; j=i++) { + if (verts[i].type == STBTT_vline) { + float x0 = verts[i].x*scale_x, y0 = verts[i].y*scale_y; + float x1 = verts[j].x*scale_x, y1 = verts[j].y*scale_y; + float dist = (float) STBTT_sqrt((x1-x0)*(x1-x0) + (y1-y0)*(y1-y0)); + precompute[i] = (dist == 0) ? 0.0f : 1.0f / dist; + } else if (verts[i].type == STBTT_vcurve) { + float x2 = verts[j].x *scale_x, y2 = verts[j].y *scale_y; + float x1 = verts[i].cx*scale_x, y1 = verts[i].cy*scale_y; + float x0 = verts[i].x *scale_x, y0 = verts[i].y *scale_y; + float bx = x0 - 2*x1 + x2, by = y0 - 2*y1 + y2; + float len2 = bx*bx + by*by; + if (len2 != 0.0f) + precompute[i] = 1.0f / (bx*bx + by*by); + else + precompute[i] = 0.0f; + } else + precompute[i] = 0.0f; + } + + for (y=iy0; y < iy1; ++y) { + for (x=ix0; x < ix1; ++x) { + float val; + float min_dist = 999999.0f; + float sx = (float) x + 0.5f; + float sy = (float) y + 0.5f; + float x_gspace = (sx / scale_x); + float y_gspace = (sy / scale_y); + + int winding = stbtt__compute_crossings_x(x_gspace, y_gspace, num_verts, verts); // @OPTIMIZE: this could just be a rasterization, but needs to be line vs. non-tesselated curves so a new path + + for (i=0; i < num_verts; ++i) { + float x0 = verts[i].x*scale_x, y0 = verts[i].y*scale_y; + + // check against every point here rather than inside line/curve primitives -- @TODO: wrong if multiple 'moves' in a row produce a garbage point, and given culling, probably more efficient to do within line/curve + float dist2 = (x0-sx)*(x0-sx) + (y0-sy)*(y0-sy); + if (dist2 < min_dist*min_dist) + min_dist = (float) STBTT_sqrt(dist2); + + if (verts[i].type == STBTT_vline) { + float x1 = verts[i-1].x*scale_x, y1 = verts[i-1].y*scale_y; + + // coarse culling against bbox + //if (sx > STBTT_min(x0,x1)-min_dist && sx < STBTT_max(x0,x1)+min_dist && + // sy > STBTT_min(y0,y1)-min_dist && sy < STBTT_max(y0,y1)+min_dist) + float dist = (float) STBTT_fabs((x1-x0)*(y0-sy) - (y1-y0)*(x0-sx)) * precompute[i]; + STBTT_assert(i != 0); + if (dist < min_dist) { + // check position along line + // x' = x0 + t*(x1-x0), y' = y0 + t*(y1-y0) + // minimize (x'-sx)*(x'-sx)+(y'-sy)*(y'-sy) + float dx = x1-x0, dy = y1-y0; + float px = x0-sx, py = y0-sy; + // minimize (px+t*dx)^2 + (py+t*dy)^2 = px*px + 2*px*dx*t + t^2*dx*dx + py*py + 2*py*dy*t + t^2*dy*dy + // derivative: 2*px*dx + 2*py*dy + (2*dx*dx+2*dy*dy)*t, set to 0 and solve + float t = -(px*dx + py*dy) / (dx*dx + dy*dy); + if (t >= 0.0f && t <= 1.0f) + min_dist = dist; + } + } else if (verts[i].type == STBTT_vcurve) { + float x2 = verts[i-1].x *scale_x, y2 = verts[i-1].y *scale_y; + float x1 = verts[i ].cx*scale_x, y1 = verts[i ].cy*scale_y; + float box_x0 = STBTT_min(STBTT_min(x0,x1),x2); + float box_y0 = STBTT_min(STBTT_min(y0,y1),y2); + float box_x1 = STBTT_max(STBTT_max(x0,x1),x2); + float box_y1 = STBTT_max(STBTT_max(y0,y1),y2); + // coarse culling against bbox to avoid computing cubic unnecessarily + if (sx > box_x0-min_dist && sx < box_x1+min_dist && sy > box_y0-min_dist && sy < box_y1+min_dist) { + int num=0; + float ax = x1-x0, ay = y1-y0; + float bx = x0 - 2*x1 + x2, by = y0 - 2*y1 + y2; + float mx = x0 - sx, my = y0 - sy; + float res[3],px,py,t,it; + float a_inv = precompute[i]; + if (a_inv == 0.0) { // if a_inv is 0, it's 2nd degree so use quadratic formula + float a = 3*(ax*bx + ay*by); + float b = 2*(ax*ax + ay*ay) + (mx*bx+my*by); + float c = mx*ax+my*ay; + if (a == 0.0) { // if a is 0, it's linear + if (b != 0.0) { + res[num++] = -c/b; + } + } else { + float discriminant = b*b - 4*a*c; + if (discriminant < 0) + num = 0; + else { + float root = (float) STBTT_sqrt(discriminant); + res[0] = (-b - root)/(2*a); + res[1] = (-b + root)/(2*a); + num = 2; // don't bother distinguishing 1-solution case, as code below will still work + } + } + } else { + float b = 3*(ax*bx + ay*by) * a_inv; // could precompute this as it doesn't depend on sample point + float c = (2*(ax*ax + ay*ay) + (mx*bx+my*by)) * a_inv; + float d = (mx*ax+my*ay) * a_inv; + num = stbtt__solve_cubic(b, c, d, res); + } + if (num >= 1 && res[0] >= 0.0f && res[0] <= 1.0f) { + t = res[0], it = 1.0f - t; + px = it*it*x0 + 2*t*it*x1 + t*t*x2; + py = it*it*y0 + 2*t*it*y1 + t*t*y2; + dist2 = (px-sx)*(px-sx) + (py-sy)*(py-sy); + if (dist2 < min_dist * min_dist) + min_dist = (float) STBTT_sqrt(dist2); + } + if (num >= 2 && res[1] >= 0.0f && res[1] <= 1.0f) { + t = res[1], it = 1.0f - t; + px = it*it*x0 + 2*t*it*x1 + t*t*x2; + py = it*it*y0 + 2*t*it*y1 + t*t*y2; + dist2 = (px-sx)*(px-sx) + (py-sy)*(py-sy); + if (dist2 < min_dist * min_dist) + min_dist = (float) STBTT_sqrt(dist2); + } + if (num >= 3 && res[2] >= 0.0f && res[2] <= 1.0f) { + t = res[2], it = 1.0f - t; + px = it*it*x0 + 2*t*it*x1 + t*t*x2; + py = it*it*y0 + 2*t*it*y1 + t*t*y2; + dist2 = (px-sx)*(px-sx) + (py-sy)*(py-sy); + if (dist2 < min_dist * min_dist) + min_dist = (float) STBTT_sqrt(dist2); + } + } + } + } + if (winding == 0) + min_dist = -min_dist; // if outside the shape, value is negative + val = onedge_value + pixel_dist_scale * min_dist; + if (val < 0) + val = 0; + else if (val > 255) + val = 255; + data[(y-iy0)*w+(x-ix0)] = (unsigned char) val; + } + } + STBTT_free(precompute, info->userdata); + STBTT_free(verts, info->userdata); + } + return data; +} + +STBTT_DEF unsigned char * stbtt_GetCodepointSDF(const stbtt_fontinfo *info, float scale, int codepoint, int padding, unsigned char onedge_value, float pixel_dist_scale, int *width, int *height, int *xoff, int *yoff) +{ + return stbtt_GetGlyphSDF(info, scale, stbtt_FindGlyphIndex(info, codepoint), padding, onedge_value, pixel_dist_scale, width, height, xoff, yoff); +} + +STBTT_DEF void stbtt_FreeSDF(unsigned char *bitmap, void *userdata) +{ + STBTT_free(bitmap, userdata); +} ////////////////////////////////////////////////////////////////////////////// // @@ -3969,6 +4755,13 @@ STBTT_DEF int stbtt_CompareUTF8toUTF16_bigendian(const char *s1, int len1, const // FULL VERSION HISTORY // +// 1.19 (2018-02-11) OpenType GPOS kerning (horizontal only), STBTT_fmod +// 1.18 (2018-01-29) add missing function +// 1.17 (2017-07-23) make more arguments const; doc fix +// 1.16 (2017-07-12) SDF support +// 1.15 (2017-03-03) make more arguments const +// 1.14 (2017-01-16) num-fonts-in-TTC function +// 1.13 (2017-01-02) support OpenType fonts, certain Apple fonts // 1.12 (2016-10-25) suppress warnings about casting away const with -Wcast-qual // 1.11 (2016-04-02) fix unused-variable warning // 1.10 (2016-04-02) allow user-defined fabs() replacement @@ -4016,3 +4809,45 @@ STBTT_DEF int stbtt_CompareUTF8toUTF16_bigendian(const char *s1, int len1, const // 0.2 (2009-03-11) Fix unsigned/signed char warnings // 0.1 (2009-03-09) First public release // + +/* +------------------------------------------------------------------------------ +This software is available under 2 licenses -- choose whichever you prefer. +------------------------------------------------------------------------------ +ALTERNATIVE A - MIT License +Copyright (c) 2017 Sean Barrett +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +------------------------------------------------------------------------------ +ALTERNATIVE B - Public Domain (www.unlicense.org) +This is free and unencumbered software released into the public domain. +Anyone is free to copy, modify, publish, use, compile, sell, or distribute this +software, either in source code form or as a compiled binary, for any purpose, +commercial or non-commercial, and by any means. +In jurisdictions that recognize copyright laws, the author or authors of this +software dedicate any and all copyright interest in the software to the public +domain. We make this dedication for the benefit of the public at large and to +the detriment of our heirs and successors. We intend this dedication to be an +overt act of relinquishment in perpetuity of all present and future rights to +this software under copyright law. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +------------------------------------------------------------------------------ +*/ From 1cbfe0700c790285bc84a6150083666b8ecd9858 Mon Sep 17 00:00:00 2001 From: omar Date: Fri, 16 Feb 2018 14:34:49 +0100 Subject: [PATCH 677/823] Plot: plot a flat line if scale_min==scale_max (#1621) --- imgui.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index b72cc38d12b1..de69156ddfc8 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -9287,11 +9287,12 @@ void ImGui::PlotEx(ImGuiPlotType plot_type, const char* label, float (*values_ge } const float t_step = 1.0f / (float)res_w; + const float inv_scale = (scale_min == scale_max) ? 0.0f : (1.0f / (scale_max - scale_min)); float v0 = values_getter(data, (0 + values_offset) % values_count); float t0 = 0.0f; - ImVec2 tp0 = ImVec2( t0, 1.0f - ImSaturate((v0 - scale_min) / (scale_max - scale_min)) ); // Point in the normalized space of our target rectangle - float histogram_zero_line_t = (scale_min * scale_max < 0.0f) ? (-scale_min / (scale_max - scale_min)) : (scale_min < 0.0f ? 0.0f : 1.0f); // Where does the zero line stands + ImVec2 tp0 = ImVec2( t0, 1.0f - ImSaturate((v0 - scale_min) * inv_scale) ); // Point in the normalized space of our target rectangle + float histogram_zero_line_t = (scale_min * scale_max < 0.0f) ? (-scale_min * inv_scale) : (scale_min < 0.0f ? 0.0f : 1.0f); // Where does the zero line stands const ImU32 col_base = GetColorU32((plot_type == ImGuiPlotType_Lines) ? ImGuiCol_PlotLines : ImGuiCol_PlotHistogram); const ImU32 col_hovered = GetColorU32((plot_type == ImGuiPlotType_Lines) ? ImGuiCol_PlotLinesHovered : ImGuiCol_PlotHistogramHovered); @@ -9302,7 +9303,7 @@ void ImGui::PlotEx(ImGuiPlotType plot_type, const char* label, float (*values_ge const int v1_idx = (int)(t0 * item_count + 0.5f); IM_ASSERT(v1_idx >= 0 && v1_idx < values_count); const float v1 = values_getter(data, (v1_idx + values_offset + 1) % values_count); - const ImVec2 tp1 = ImVec2( t1, 1.0f - ImSaturate((v1 - scale_min) / (scale_max - scale_min)) ); + const ImVec2 tp1 = ImVec2( t1, 1.0f - ImSaturate((v1 - scale_min) * inv_scale) ); // NB: Draw calls are merged together by the DrawList system. Still, we should render our batch are lower level to save a bit of CPU. ImVec2 pos0 = ImLerp(inner_bb.Min, inner_bb.Max, tp0); From 20c14f95891b145ebffa8d349ca033d67eac1c24 Mon Sep 17 00:00:00 2001 From: omar Date: Fri, 16 Feb 2018 15:43:28 +0100 Subject: [PATCH 678/823] Fixed GCC zealous warnings (#1623) --- imgui.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/imgui.cpp b/imgui.cpp index de69156ddfc8..29bafca6b97e 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -681,6 +681,7 @@ #pragma GCC diagnostic ignored "-Wconversion" // warning: conversion to 'xxxx' from 'xxxx' may alter its value #pragma GCC diagnostic ignored "-Wcast-qual" // warning: cast from type 'xxxx' to type 'xxxx' casts away qualifiers #pragma GCC diagnostic ignored "-Wformat-nonliteral" // warning: format not a string literal, format string not checked +#pragma GCC diagnostic ignored "-Wstrict-overflow" // warning: assuming signed overflow does not occur when assuming that (X - c) > X is always false #endif // Enforce cdecl calling convention for functions called by the standard library, in case compilation settings changed the default to e.g. __vectorcall @@ -4876,6 +4877,7 @@ static ImGuiWindow* GetFrontMostModalRootWindow() static void ClosePopupToLevel(int remaining) { + IM_ASSERT(remaining >= 0); ImGuiContext& g = *GImGui; ImGuiWindow* focus_window = (remaining > 0) ? g.OpenPopupStack[remaining-1].Window : g.OpenPopupStack[0].ParentWindow; if (g.NavLayer == 0) @@ -11215,7 +11217,7 @@ bool ImGui::BeginMenu(const char* label, bool enabled) if (!enabled) // explicitly close if an open menu becomes disabled, facilitate users code a lot in pattern such as 'if (BeginMenu("options", has_object)) { ..use object.. }' want_close = true; if (want_close && IsPopupOpen(id)) - ClosePopupToLevel(GImGui->CurrentPopupStack.Size); + ClosePopupToLevel(g.CurrentPopupStack.Size); if (!menu_is_open && want_open && g.OpenPopupStack.Size > g.CurrentPopupStack.Size) { From 0cefd40888c3d6c5e84754d2dadb6135d91b6f1f Mon Sep 17 00:00:00 2001 From: omar Date: Fri, 16 Feb 2018 17:20:18 +0100 Subject: [PATCH 679/823] Examples: Added Changelog to make updates easier. --- .../directx10_example/imgui_impl_dx10.cpp | 13 +++++++++++++ .../directx11_example/imgui_impl_dx11.cpp | 13 +++++++++++++ .../opengl2_example/imgui_impl_glfw_gl2.cpp | 14 ++++++++++++++ .../opengl3_example/imgui_impl_glfw_gl3.cpp | 16 ++++++++++++++++ .../imgui_impl_sdl_gl2.cpp | 19 ++++++++++--------- .../imgui_impl_sdl_gl3.cpp | 19 ++++++++++--------- .../vulkan_example/imgui_impl_glfw_vulkan.cpp | 13 +++++++++++++ 7 files changed, 89 insertions(+), 18 deletions(-) diff --git a/examples/directx10_example/imgui_impl_dx10.cpp b/examples/directx10_example/imgui_impl_dx10.cpp index a0bd98bfc522..0d3f92339dc6 100644 --- a/examples/directx10_example/imgui_impl_dx10.cpp +++ b/examples/directx10_example/imgui_impl_dx10.cpp @@ -8,6 +8,19 @@ // If you are new to ImGui, see examples/README.txt and documentation at the top of imgui.cpp. // https://github.com/ocornut/imgui +// CHANGELOG +// (minor and older changes stripped away, please see git history for details) +// 2018-02-06: Misc: Removed call to ImGui::Shutdown() which is not available from 1.60 WIP, user needs to call CreateContext/DestroyContext themselves. +// 2018-02-06: Inputs: Added mapping for ImGuiKey_Space. +// 2018-02-06: Inputs: Honoring the io.WantMoveMouse by repositioning the mouse by using navigation and ImGuiNavFlags_MoveMouse is set. +// 2018-01-20: Inputs: Added Horizontal Mouse Wheel support. +// 2018-01-08: Inputs: Added mapping for ImGuiKey_Insert. +// 2018-01-05: Inputs: Added WM_LBUTTONDBLCLK double-click handlers for window classes with the CS_DBLCLKS flag. +// 2017-10-23: Inputs: Added WM_SYSKEYDOWN / WM_SYSKEYUP handlers so e.g. the VK_MENU key can be read. +// 2017-10-23: Inputs: Using Win32 ::SetCapture/::GetCapture() to retrieve mouse positions outside the client area when dragging. +// 2016-11-12: Inputs: Only call Win32 ::SetCursor(NULL) when io.MouseDrawCursor is set. +// 2016-05-07: DirectX10: Disabling depth-write. + #include "imgui.h" #include "imgui_impl_dx10.h" diff --git a/examples/directx11_example/imgui_impl_dx11.cpp b/examples/directx11_example/imgui_impl_dx11.cpp index fa77735cada8..29a4af4ff8d4 100644 --- a/examples/directx11_example/imgui_impl_dx11.cpp +++ b/examples/directx11_example/imgui_impl_dx11.cpp @@ -8,6 +8,19 @@ // If you are new to ImGui, see examples/README.txt and documentation at the top of imgui.cpp. // https://github.com/ocornut/imgui +// CHANGELOG +// (minor and older changes stripped away, please see git history for details) +// 2018-02-06: Misc: Removed call to ImGui::Shutdown() which is not available from 1.60 WIP, user needs to call CreateContext/DestroyContext themselves. +// 2018-02-06: Inputs: Added mapping for ImGuiKey_Space. +// 2018-02-06: Inputs: Honoring the io.WantMoveMouse by repositioning the mouse by using navigation and ImGuiNavFlags_MoveMouse is set. +// 2018-01-20: Inputs: Added Horizontal Mouse Wheel support. +// 2018-01-08: Inputs: Added mapping for ImGuiKey_Insert. +// 2018-01-05: Inputs: Added WM_LBUTTONDBLCLK double-click handlers for window classes with the CS_DBLCLKS flag. +// 2017-10-23: Inputs: Added WM_SYSKEYDOWN / WM_SYSKEYUP handlers so e.g. the VK_MENU key can be read. +// 2017-10-23: Inputs: Using Win32 ::SetCapture/::GetCapture() to retrieve mouse positions outside the client area when dragging. +// 2016-11-12: Inputs: Only call Win32 ::SetCursor(NULL) when io.MouseDrawCursor is set. +// 2016-05-07: DirectX11: Disabling depth-write. + #include "imgui.h" #include "imgui_impl_dx11.h" diff --git a/examples/opengl2_example/imgui_impl_glfw_gl2.cpp b/examples/opengl2_example/imgui_impl_glfw_gl2.cpp index 2df70f2b40c0..ce97f27231d2 100644 --- a/examples/opengl2_example/imgui_impl_glfw_gl2.cpp +++ b/examples/opengl2_example/imgui_impl_glfw_gl2.cpp @@ -17,6 +17,20 @@ // If you are new to ImGui, see examples/README.txt and documentation at the top of imgui.cpp. // https://github.com/ocornut/imgui +// CHANGELOG +// (minor and older changes stripped away, please see git history for details) +// 2018-02-06: Misc: Removed call to ImGui::Shutdown() which is not available from 1.60 WIP, user needs to call CreateContext/DestroyContext themselves. +// 2018-02-06: Inputs: Added mapping for ImGuiKey_Space. +// 2018-01-25: Inputs: Honoring the io.WantMoveMouse by repositioning the mouse by using navigation and ImGuiNavFlags_MoveMouse is set. +// 2018-01-20: Inputs: Added Horizontal Mouse Wheel support. +// 2018-01-18: Inputs: Added mapping for ImGuiKey_Insert. +// 2018-01-09: Misc: Renamed imgui_impl_glfw.* to imgui_impl_glfw_gl2.*. +// 2017-09-01: OpenGL: Save and restore current polygon mode. +// 2017-08-25: Inputs: MousePos set to -FLT_MAX,-FLT_MAX when mouse is unavailable/missing (instead of -1,-1). +// 2016-10-15: Misc: Added a void* user_data parameter to Clipboard function handlers. +// 2016-09-10: OpenGL: Uploading font texture as RGBA32 to increase compatibility with users shaders (not ideal). +// 2016-09-05: OpenGL: Fixed save and restore of current scissor rectangle. + #include "imgui.h" #include "imgui_impl_glfw_gl2.h" diff --git a/examples/opengl3_example/imgui_impl_glfw_gl3.cpp b/examples/opengl3_example/imgui_impl_glfw_gl3.cpp index cd652c0bc7af..2e0863f33ee1 100644 --- a/examples/opengl3_example/imgui_impl_glfw_gl3.cpp +++ b/examples/opengl3_example/imgui_impl_glfw_gl3.cpp @@ -11,6 +11,22 @@ // If you are new to ImGui, see examples/README.txt and documentation at the top of imgui.cpp. // https://github.com/ocornut/imgui +// CHANGELOG +// (minor and older changes stripped away, please see git history for details) +// 2018-02-06: Misc: Removed call to ImGui::Shutdown() which is not available from 1.60 WIP, user needs to call CreateContext/DestroyContext themselves. +// 2018-02-06: Inputs: Added mapping for ImGuiKey_Space. +// 2018-01-25: Inputs: Added gamepad support if ImGuiNavFlags_EnableGamepad is set. +// 2018-01-25: Inputs: Honoring the io.WantMoveMouse by repositioning the mouse by using navigation and ImGuiNavFlags_MoveMouse is set. +// 2018-01-20: Inputs: Added Horizontal Mouse Wheel support. +// 2018-01-18: Inputs: Added mapping for ImGuiKey_Insert. +// 2018-01-07: OpenGL: Changed GLSL shader version from 330 to 150. (Also changed GL context from 3.3 to 3.2 in example's main.cpp) +// 2017-09-01: OpenGL: Save and restore current bound sampler. Save and restore current polygon mode. +// 2017-08-25: Inputs: MousePos set to -FLT_MAX,-FLT_MAX when mouse is unavailable/missing (instead of -1,-1). +// 2017-05-01: OpenGL: Fixed save and restore of current blend function state. +// 2016-10-15: Misc: Added a void* user_data parameter to Clipboard function handlers. +// 2016-09-05: OpenGL: Fixed save and restore of current scissor rectangle. +// 2016-04-30: OpenGL: Fixed save and restore of current GL_ACTIVE_TEXTURE. + #include "imgui.h" #include "imgui_impl_glfw_gl3.h" diff --git a/examples/sdl_opengl2_example/imgui_impl_sdl_gl2.cpp b/examples/sdl_opengl2_example/imgui_impl_sdl_gl2.cpp index 11aa6a5ac86e..17c29edcdfdf 100644 --- a/examples/sdl_opengl2_example/imgui_impl_sdl_gl2.cpp +++ b/examples/sdl_opengl2_example/imgui_impl_sdl_gl2.cpp @@ -18,16 +18,17 @@ // https://github.com/ocornut/imgui // CHANGELOG -// 2018-02-06: Removed call to ImGui::Shutdown() which is not available from 1.60 WIP, user needs to call CreateContext/DestroyContext themselves. -// 2018-02-06: SDL: Added mapping for ImGuiKey_Space. -// 2018-02-05: SDL: Using SDL_GetPerformanceCounter() instead of SDL_GetTicks() to be able to handle very high framerate (1000+ FPS). -// 2018-02-05: SDL: Keyboard mapping is using scancodes everywhere instead of a confusing mixture of keycodes and scancodes. -// 2018-01-20: SDL: Added Horizontal Mouse Wheel support. -// 2018-01-19: SDL: When available (SDL 2.0.4+) using SDL_CaptureMouse() to retrieve coordinates outside of client area when dragging. Otherwise (SDL 2.0.3 and before) testing for SDL_WINDOW_INPUT_FOCUS instead of SDL_WINDOW_MOUSE_FOCUS. -// 2018-01-18: SDL: Added mapping for ImGuiKey_Insert. +// (minor and older changes stripped away, please see git history for details) +// 2018-02-06: Misc: Removed call to ImGui::Shutdown() which is not available from 1.60 WIP, user needs to call CreateContext/DestroyContext themselves. +// 2018-02-06: Inputs: Added mapping for ImGuiKey_Space. +// 2018-02-05: Misc: Using SDL_GetPerformanceCounter() instead of SDL_GetTicks() to be able to handle very high framerate (1000+ FPS). +// 2018-02-05: Inputs: Keyboard mapping is using scancodes everywhere instead of a confusing mixture of keycodes and scancodes. +// 2018-01-20: Inputs: Added Horizontal Mouse Wheel support. +// 2018-01-19: Inputs: When available (SDL 2.0.4+) using SDL_CaptureMouse() to retrieve coordinates outside of client area when dragging. Otherwise (SDL 2.0.3 and before) testing for SDL_WINDOW_INPUT_FOCUS instead of SDL_WINDOW_MOUSE_FOCUS. +// 2018-01-18: Inputs: Added mapping for ImGuiKey_Insert. // 2017-09-01: OpenGL: Save and restore current polygon mode. -// 2017-08-25: SDL: MousePos set to -FLT_MAX,-FLT_MAX when mouse is unavailable/missing (instead of -1,-1). -// 2016-10-15: Added a void* user_data parameter to Clipboard function handlers. +// 2017-08-25: Inputs: MousePos set to -FLT_MAX,-FLT_MAX when mouse is unavailable/missing (instead of -1,-1). +// 2016-10-15: Misc: Added a void* user_data parameter to Clipboard function handlers. // 2016-09-05: OpenGL: Fixed save and restore of current scissor rectangle. // 2016-07-29: OpenGL: Explicitly setting GL_UNPACK_ROW_LENGTH to reduce issues because SDL changes it. (#752) diff --git a/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.cpp b/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.cpp index 7e0d26884de0..a50988315ef8 100644 --- a/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.cpp +++ b/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.cpp @@ -11,19 +11,20 @@ // https://github.com/ocornut/imgui // CHANGELOG -// 2018-02-06: Removed call to ImGui::Shutdown() which is not available from 1.60 WIP, user needs to call CreateContext/DestroyContext themselves. -// 2018-02-06: SDL: Added mapping for ImGuiKey_Space. -// 2018-02-05: SDL: Using SDL_GetPerformanceCounter() instead of SDL_GetTicks() to be able to handle very high framerate (1000+ FPS). -// 2018-02-05: SDL: Keyboard mapping is using scancodes everywhere instead of a confusing mixture of keycodes and scancodes. -// 2018-01-20: SDL: Added Horizontal Mouse Wheel support. -// 2018-01-19: SDL: When available (SDL 2.0.4+) using SDL_CaptureMouse() to retrieve coordinates outside of client area when dragging. Otherwise (SDL 2.0.3 and before) testing for SDL_WINDOW_INPUT_FOCUS instead of SDL_WINDOW_MOUSE_FOCUS. -// 2018-01-18: SDL: Added mapping for ImGuiKey_Insert. +// (minor and older changes stripped away, please see git history for details) +// 2018-02-06: Misc: Removed call to ImGui::Shutdown() which is not available from 1.60 WIP, user needs to call CreateContext/DestroyContext themselves. +// 2018-02-06: Inputs: Added mapping for ImGuiKey_Space. +// 2018-02-05: Misc: Using SDL_GetPerformanceCounter() instead of SDL_GetTicks() to be able to handle very high framerate (1000+ FPS). +// 2018-02-05: Inputs: Keyboard mapping is using scancodes everywhere instead of a confusing mixture of keycodes and scancodes. +// 2018-01-20: Inputs: Added Horizontal Mouse Wheel support. +// 2018-01-19: Inputs: When available (SDL 2.0.4+) using SDL_CaptureMouse() to retrieve coordinates outside of client area when dragging. Otherwise (SDL 2.0.3 and before) testing for SDL_WINDOW_INPUT_FOCUS instead of SDL_WINDOW_MOUSE_FOCUS. +// 2018-01-18: Inputs: Added mapping for ImGuiKey_Insert. // 2018-01-07: OpenGL: Changed GLSL shader version from 330 to 150. // 2017-09-01: OpenGL: Save and restore current bound sampler. Save and restore current polygon mode. -// 2017-08-25: SDL: MousePos set to -FLT_MAX,-FLT_MAX when mouse is unavailable/missing (instead of -1,-1). +// 2017-08-25: Inputs: MousePos set to -FLT_MAX,-FLT_MAX when mouse is unavailable/missing (instead of -1,-1). // 2017-05-01: OpenGL: Fixed save and restore of current blend func state. // 2017-05-01: OpenGL: Fixed save and restore of current GL_ACTIVE_TEXTURE. -// 2016-10-15: Added a void* user_data parameter to Clipboard function handlers. +// 2016-10-15: Misc: Added a void* user_data parameter to Clipboard function handlers. // 2016-09-05: OpenGL: Fixed save and restore of current scissor rectangle. // 2016-07-29: OpenGL: Explicitly setting GL_UNPACK_ROW_LENGTH to reduce issues because SDL changes it. (#752) diff --git a/examples/vulkan_example/imgui_impl_glfw_vulkan.cpp b/examples/vulkan_example/imgui_impl_glfw_vulkan.cpp index d86ad575fb79..70fa6cc43ebd 100644 --- a/examples/vulkan_example/imgui_impl_glfw_vulkan.cpp +++ b/examples/vulkan_example/imgui_impl_glfw_vulkan.cpp @@ -8,6 +8,19 @@ // If you are new to ImGui, see examples/README.txt and documentation at the top of imgui.cpp. // https://github.com/ocornut/imgui +// CHANGELOG +// (minor and older changes stripped away, please see git history for details) +// 2018-02-06: Misc: Removed call to ImGui::Shutdown() which is not available from 1.60 WIP, user needs to call CreateContext/DestroyContext themselves. +// 2018-02-06: Inputs: Added mapping for ImGuiKey_Space. +// 2018-01-20: Inputs: Added Horizontal Mouse Wheel support. +// 2018-01-18: Inputs: Added mapping for ImGuiKey_Insert. +// 2017-08-25: Inputs: MousePos set to -FLT_MAX,-FLT_MAX when mouse is unavailable/missing (instead of -1,-1). +// 2017-05-15: Vulkan: Fix scissor offset being negative. Fix new Vulkan validation warnings. Set required depth member for buffer image copy. +// 2016-11-13: Vulkan: Fix validation layer warnings and errors and redeclare gl_PerVertex. +// 2016-10-18: Vulkan: Add location decorators & change to use structs as in/out in glsl, update embedded spv (produced with glslangValidator -x). Null the released resources. +// 2016-10-15: Misc: Added a void* user_data parameter to Clipboard function handlers. +// 2016-08-27: Vulkan: Fix Vulkan example for use when a depth buffer is active. + #include "imgui.h" #include "imgui_impl_glfw_vulkan.h" From 63332d152a7ad238d80f990df4cb9e77cf790c2a Mon Sep 17 00:00:00 2001 From: omar Date: Fri, 16 Feb 2018 19:18:16 +0100 Subject: [PATCH 680/823] Obsoleted the io.RenderDrawListsFn callback, you can call your graphics engine render function after ImGui::Render(). Use ImGui::GetDrawData() to retrieve the ImDrawData* to display..(#1599) Examples: Updated examples. --- examples/allegro5_example/imgui_impl_a5.cpp | 11 +++++++++-- examples/allegro5_example/imgui_impl_a5.h | 1 + examples/allegro5_example/main.cpp | 1 + examples/directx10_example/imgui_impl_dx10.cpp | 9 ++++----- examples/directx10_example/imgui_impl_dx10.h | 1 + examples/directx10_example/main.cpp | 1 + examples/directx11_example/imgui_impl_dx11.cpp | 9 ++++----- examples/directx11_example/imgui_impl_dx11.h | 1 + examples/directx11_example/main.cpp | 1 + examples/directx9_example/imgui_impl_dx9.cpp | 14 +++++++++----- examples/directx9_example/imgui_impl_dx9.h | 1 + examples/directx9_example/main.cpp | 1 + .../marmalade_example/imgui_impl_marmalade.cpp | 12 +++++++++--- examples/marmalade_example/imgui_impl_marmalade.h | 1 + examples/marmalade_example/main.cpp | 1 + examples/opengl2_example/imgui_impl_glfw_gl2.cpp | 8 ++++---- examples/opengl2_example/imgui_impl_glfw_gl2.h | 1 + examples/opengl2_example/main.cpp | 1 + examples/opengl3_example/imgui_impl_glfw_gl3.cpp | 8 ++++---- examples/opengl3_example/imgui_impl_glfw_gl3.h | 1 + examples/opengl3_example/main.cpp | 1 + .../sdl_opengl2_example/imgui_impl_sdl_gl2.cpp | 8 ++++---- examples/sdl_opengl2_example/imgui_impl_sdl_gl2.h | 1 + examples/sdl_opengl2_example/main.cpp | 1 + .../sdl_opengl3_example/imgui_impl_sdl_gl3.cpp | 4 ++-- examples/sdl_opengl3_example/imgui_impl_sdl_gl3.h | 1 + examples/sdl_opengl3_example/main.cpp | 1 + .../vulkan_example/imgui_impl_glfw_vulkan.cpp | 5 +++-- imgui.cpp | 14 ++++++++++---- imgui.h | 15 ++++++++------- 30 files changed, 88 insertions(+), 47 deletions(-) diff --git a/examples/allegro5_example/imgui_impl_a5.cpp b/examples/allegro5_example/imgui_impl_a5.cpp index d837edfa2655..479702b98639 100644 --- a/examples/allegro5_example/imgui_impl_a5.cpp +++ b/examples/allegro5_example/imgui_impl_a5.cpp @@ -10,6 +10,12 @@ // If you are new to ImGui, see examples/README.txt and documentation at the top of imgui.cpp. // https://github.com/ocornut/imgui, Original code by @birthggd +// CHANGELOG +// (minor and older changes stripped away, please see git history for details) +// 2018-02-16: Misc: Obsoleted the io.RenderDrawListsFn callback and exposed ImGui_ImplA5_RenderDrawData() in the .h file so you can call it yourself. +// 2018-02-06: Misc: Removed call to ImGui::Shutdown() which is not available from 1.60 WIP, user needs to call CreateContext/DestroyContext themselves. +// 2018-02-06: Inputs: Added mapping for ImGuiKey_Space. + #include // uint64_t #include // memcpy #include "imgui.h" @@ -35,7 +41,9 @@ struct ImDrawVertAllegro ALLEGRO_COLOR col; }; -void ImGui_ImplA5_RenderDrawLists(ImDrawData* draw_data) +// Render function. +// (this used to be set in io.RenderDrawListsFn and called by ImGui::Render(), but you can now call this directly from your main loop) +void ImGui_ImplA5_RenderDrawData(ImDrawData* draw_data) { int op, src, dst; al_get_blender(&op, &src, &dst); @@ -190,7 +198,6 @@ bool ImGui_ImplA5_Init(ALLEGRO_DISPLAY* display) io.KeyMap[ImGuiKey_Y] = ALLEGRO_KEY_Y; io.KeyMap[ImGuiKey_Z] = ALLEGRO_KEY_Z; - io.RenderDrawListsFn = ImGui_ImplA5_RenderDrawLists; // Alternatively you can set this to NULL and call ImGui::GetDrawData() after ImGui::Render() to get the same ImDrawData pointer. #ifdef _WIN32 io.ImeWindowHandle = al_get_win_window_handle(g_Display); #endif diff --git a/examples/allegro5_example/imgui_impl_a5.h b/examples/allegro5_example/imgui_impl_a5.h index 7f1644353e58..ccc3ac45f102 100644 --- a/examples/allegro5_example/imgui_impl_a5.h +++ b/examples/allegro5_example/imgui_impl_a5.h @@ -18,6 +18,7 @@ union ALLEGRO_EVENT; IMGUI_API bool ImGui_ImplA5_Init(ALLEGRO_DISPLAY* display); IMGUI_API void ImGui_ImplA5_Shutdown(); IMGUI_API void ImGui_ImplA5_NewFrame(); +IMGUI_API void ImGui_ImplA5_RenderDrawData(ImDrawData* draw_data); IMGUI_API bool ImGui_ImplA5_ProcessEvent(ALLEGRO_EVENT* event); // Use if you want to reset your rendering device without losing ImGui state. diff --git a/examples/allegro5_example/main.cpp b/examples/allegro5_example/main.cpp index 92368950d979..1478573cce9b 100644 --- a/examples/allegro5_example/main.cpp +++ b/examples/allegro5_example/main.cpp @@ -114,6 +114,7 @@ int main(int, char**) // Rendering al_clear_to_color(al_map_rgba_f(clear_color.x, clear_color.y, clear_color.z, clear_color.w)); ImGui::Render(); + ImGui_ImplA5_RenderDrawData(ImGui::GetDrawData()); al_flip_display(); } diff --git a/examples/directx10_example/imgui_impl_dx10.cpp b/examples/directx10_example/imgui_impl_dx10.cpp index 0d3f92339dc6..10da969e2c38 100644 --- a/examples/directx10_example/imgui_impl_dx10.cpp +++ b/examples/directx10_example/imgui_impl_dx10.cpp @@ -10,6 +10,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2018-02-16: Misc: Obsoleted the io.RenderDrawListsFn callback and exposed ImGui_ImplDX10_RenderDrawData() in the .h file so you can call it yourself. // 2018-02-06: Misc: Removed call to ImGui::Shutdown() which is not available from 1.60 WIP, user needs to call CreateContext/DestroyContext themselves. // 2018-02-06: Inputs: Added mapping for ImGuiKey_Space. // 2018-02-06: Inputs: Honoring the io.WantMoveMouse by repositioning the mouse by using navigation and ImGuiNavFlags_MoveMouse is set. @@ -57,10 +58,9 @@ struct VERTEX_CONSTANT_BUFFER float mvp[4][4]; }; -// 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) -void ImGui_ImplDX10_RenderDrawLists(ImDrawData* draw_data) +// Render function +// (this used to be set in io.RenderDrawListsFn and called by ImGui::Render(), but you can now call this directly from your main loop) +void ImGui_ImplDX10_RenderDrawData(ImDrawData* draw_data) { ID3D10Device* ctx = g_pd3dDevice; @@ -570,7 +570,6 @@ bool ImGui_ImplDX10_Init(void* hwnd, ID3D10Device* device) io.KeyMap[ImGuiKey_Y] = 'Y'; io.KeyMap[ImGuiKey_Z] = 'Z'; - io.RenderDrawListsFn = ImGui_ImplDX10_RenderDrawLists; // Alternatively you can set this to NULL and call ImGui::GetDrawData() after ImGui::Render() to get the same ImDrawData pointer. io.ImeWindowHandle = g_hWnd; return true; diff --git a/examples/directx10_example/imgui_impl_dx10.h b/examples/directx10_example/imgui_impl_dx10.h index 604b7b63016c..a47418476589 100644 --- a/examples/directx10_example/imgui_impl_dx10.h +++ b/examples/directx10_example/imgui_impl_dx10.h @@ -13,6 +13,7 @@ struct ID3D10Device; IMGUI_API bool ImGui_ImplDX10_Init(void* hwnd, ID3D10Device* device); IMGUI_API void ImGui_ImplDX10_Shutdown(); IMGUI_API void ImGui_ImplDX10_NewFrame(); +IMGUI_API void ImGui_ImplDX10_RenderDrawData(ImDrawData* draw_data); // Use if you want to reset your rendering device without losing ImGui state. IMGUI_API void ImGui_ImplDX10_InvalidateDeviceObjects(); diff --git a/examples/directx10_example/main.cpp b/examples/directx10_example/main.cpp index 0198b34ff85f..f20f6881e0bb 100644 --- a/examples/directx10_example/main.cpp +++ b/examples/directx10_example/main.cpp @@ -206,6 +206,7 @@ int main(int, char**) g_pd3dDevice->OMSetRenderTargets(1, &g_mainRenderTargetView, NULL); g_pd3dDevice->ClearRenderTargetView(g_mainRenderTargetView, (float*)&clear_color); ImGui::Render(); + ImGui_ImplDX10_RenderDrawData(ImGui::GetDrawData()); g_pSwapChain->Present(1, 0); // Present with vsync //g_pSwapChain->Present(0, 0); // Present without vsync diff --git a/examples/directx11_example/imgui_impl_dx11.cpp b/examples/directx11_example/imgui_impl_dx11.cpp index 29a4af4ff8d4..a0e9d7f3809c 100644 --- a/examples/directx11_example/imgui_impl_dx11.cpp +++ b/examples/directx11_example/imgui_impl_dx11.cpp @@ -10,6 +10,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2018-02-16: Misc: Obsoleted the io.RenderDrawListsFn callback and exposed ImGui_ImplDX11_RenderDrawData() in the .h file so you can call it yourself. // 2018-02-06: Misc: Removed call to ImGui::Shutdown() which is not available from 1.60 WIP, user needs to call CreateContext/DestroyContext themselves. // 2018-02-06: Inputs: Added mapping for ImGuiKey_Space. // 2018-02-06: Inputs: Honoring the io.WantMoveMouse by repositioning the mouse by using navigation and ImGuiNavFlags_MoveMouse is set. @@ -57,10 +58,9 @@ struct VERTEX_CONSTANT_BUFFER float mvp[4][4]; }; -// 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) -void ImGui_ImplDX11_RenderDrawLists(ImDrawData* draw_data) +// Render function +// (this used to be set in io.RenderDrawListsFn and called by ImGui::Render(), but you can now call this directly from your main loop) +void ImGui_ImplDX11_RenderDrawData(ImDrawData* draw_data) { ID3D11DeviceContext* ctx = g_pd3dDeviceContext; @@ -572,7 +572,6 @@ bool ImGui_ImplDX11_Init(void* hwnd, ID3D11Device* device, ID3D11DeviceContex io.KeyMap[ImGuiKey_Y] = 'Y'; io.KeyMap[ImGuiKey_Z] = 'Z'; - io.RenderDrawListsFn = ImGui_ImplDX11_RenderDrawLists; // Alternatively you can set this to NULL and call ImGui::GetDrawData() after ImGui::Render() to get the same ImDrawData pointer. io.ImeWindowHandle = g_hWnd; return true; diff --git a/examples/directx11_example/imgui_impl_dx11.h b/examples/directx11_example/imgui_impl_dx11.h index 90bfe4fe3b5e..9364b0cabf2f 100644 --- a/examples/directx11_example/imgui_impl_dx11.h +++ b/examples/directx11_example/imgui_impl_dx11.h @@ -14,6 +14,7 @@ struct ID3D11DeviceContext; IMGUI_API bool ImGui_ImplDX11_Init(void* hwnd, ID3D11Device* device, ID3D11DeviceContext* device_context); IMGUI_API void ImGui_ImplDX11_Shutdown(); IMGUI_API void ImGui_ImplDX11_NewFrame(); +IMGUI_API void ImGui_ImplDX11_RenderDrawData(ImDrawData* draw_data); // Use if you want to reset your rendering device without losing ImGui state. IMGUI_API void ImGui_ImplDX11_InvalidateDeviceObjects(); diff --git a/examples/directx11_example/main.cpp b/examples/directx11_example/main.cpp index b1127fc87354..f6dc6f74c828 100644 --- a/examples/directx11_example/main.cpp +++ b/examples/directx11_example/main.cpp @@ -209,6 +209,7 @@ int main(int, char**) g_pd3dDeviceContext->OMSetRenderTargets(1, &g_mainRenderTargetView, NULL); g_pd3dDeviceContext->ClearRenderTargetView(g_mainRenderTargetView, (float*)&clear_color); ImGui::Render(); + ImGui_ImplDX11_RenderDrawData(ImGui::GetDrawData()); g_pSwapChain->Present(1, 0); // Present with vsync //g_pSwapChain->Present(0, 0); // Present without vsync diff --git a/examples/directx9_example/imgui_impl_dx9.cpp b/examples/directx9_example/imgui_impl_dx9.cpp index c89b2478a23a..e960b7c51850 100644 --- a/examples/directx9_example/imgui_impl_dx9.cpp +++ b/examples/directx9_example/imgui_impl_dx9.cpp @@ -8,6 +8,12 @@ // If you are new to ImGui, see examples/README.txt and documentation at the top of imgui.cpp. // https://github.com/ocornut/imgui +// CHANGELOG +// (minor and older changes stripped away, please see git history for details) +// 2018-02-16: Misc: Obsoleted the io.RenderDrawListsFn callback and exposed ImGui_ImplDX9_RenderDrawData() in the .h file so you can call it yourself. +// 2018-02-06: Misc: Removed call to ImGui::Shutdown() which is not available from 1.60 WIP, user needs to call CreateContext/DestroyContext themselves. +// 2018-02-06: Inputs: Added mapping for ImGuiKey_Space. + #include "imgui.h" #include "imgui_impl_dx9.h" @@ -34,10 +40,9 @@ struct CUSTOMVERTEX }; #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) -void ImGui_ImplDX9_RenderDrawLists(ImDrawData* draw_data) +// Render function. +// (this used to be set in io.RenderDrawListsFn and called by ImGui::Render(), but you can now call this directly from your main loop) +void ImGui_ImplDX9_RenderDrawData(ImDrawData* draw_data) { // Avoid rendering when minimized ImGuiIO& io = ImGui::GetIO(); @@ -276,7 +281,6 @@ bool ImGui_ImplDX9_Init(void* hwnd, IDirect3DDevice9* device) io.KeyMap[ImGuiKey_Y] = 'Y'; io.KeyMap[ImGuiKey_Z] = 'Z'; - io.RenderDrawListsFn = ImGui_ImplDX9_RenderDrawLists; // Alternatively you can set this to NULL and call ImGui::GetDrawData() after ImGui::Render() to get the same ImDrawData pointer. io.ImeWindowHandle = g_hWnd; return true; diff --git a/examples/directx9_example/imgui_impl_dx9.h b/examples/directx9_example/imgui_impl_dx9.h index 41fa743dace5..e0ea2deae90c 100644 --- a/examples/directx9_example/imgui_impl_dx9.h +++ b/examples/directx9_example/imgui_impl_dx9.h @@ -13,6 +13,7 @@ struct IDirect3DDevice9; IMGUI_API bool ImGui_ImplDX9_Init(void* hwnd, IDirect3DDevice9* device); IMGUI_API void ImGui_ImplDX9_Shutdown(); IMGUI_API void ImGui_ImplDX9_NewFrame(); +IMGUI_API void ImGui_ImplDX9_RenderDrawData(ImDrawData* draw_data); // Use if you want to reset your rendering device without losing ImGui state. IMGUI_API void ImGui_ImplDX9_InvalidateDeviceObjects(); diff --git a/examples/directx9_example/main.cpp b/examples/directx9_example/main.cpp index dd4227ecb8c9..16482b3aa8fa 100644 --- a/examples/directx9_example/main.cpp +++ b/examples/directx9_example/main.cpp @@ -169,6 +169,7 @@ int main(int, char**) if (g_pd3dDevice->BeginScene() >= 0) { ImGui::Render(); + ImGui_ImplDX9_RenderDrawData(ImGui::GetDrawData()); g_pd3dDevice->EndScene(); } HRESULT result = g_pd3dDevice->Present(NULL, NULL, NULL, NULL); diff --git a/examples/marmalade_example/imgui_impl_marmalade.cpp b/examples/marmalade_example/imgui_impl_marmalade.cpp index 8342a7018ea1..947bcbd6fb5a 100644 --- a/examples/marmalade_example/imgui_impl_marmalade.cpp +++ b/examples/marmalade_example/imgui_impl_marmalade.cpp @@ -11,6 +11,12 @@ // Copyright (C) 2015 by Giovanni Zito // This file is part of ImGui +// CHANGELOG +// (minor and older changes stripped away, please see git history for details) +// 2018-02-16: Misc: Obsoleted the io.RenderDrawListsFn callback and exposed ImGui_Marmalade_RenderDrawData() in the .h file so you can call it yourself. +// 2018-02-06: Misc: Removed call to ImGui::Shutdown() which is not available from 1.60 WIP, user needs to call CreateContext/DestroyContext themselves. +// 2018-02-06: Inputs: Added mapping for ImGuiKey_Space. + #include "imgui.h" #include "imgui_impl_marmalade.h" @@ -30,8 +36,9 @@ static bool g_osdKeyboardEnabled = false; // use this setting to scale the interface - e.g. on device you could use 2 or 3 scale factor static ImVec2 g_RenderScale = ImVec2(1.0f,1.0f); -// This is the main rendering function that you have to implement and provide to ImGui (via setting up 'RenderDrawListsFn' in the ImGuiIO structure) -void ImGui_Marmalade_RenderDrawLists(ImDrawData* draw_data) +// Render function. +// (this used to be set in io.RenderDrawListsFn and called by ImGui::Render(), but you can now call this directly from your main loop) +void ImGui_Marmalade_RenderDrawData(ImDrawData* draw_data) { // Handle cases of screen coordinates != from framebuffer coordinates (e.g. retina displays) ImGuiIO& io = ImGui::GetIO(); @@ -232,7 +239,6 @@ bool ImGui_Marmalade_Init(bool install_callbacks) io.KeyMap[ImGuiKey_Y] = s3eKeyY; io.KeyMap[ImGuiKey_Z] = s3eKeyZ; - io.RenderDrawListsFn = ImGui_Marmalade_RenderDrawLists; // Alternatively you can set this to NULL and call ImGui::GetDrawData() after ImGui::Render() to get the same ImDrawData pointer. io.SetClipboardTextFn = ImGui_Marmalade_SetClipboardText; io.GetClipboardTextFn = ImGui_Marmalade_GetClipboardText; diff --git a/examples/marmalade_example/imgui_impl_marmalade.h b/examples/marmalade_example/imgui_impl_marmalade.h index 79b5e50a3918..c41a5e8f264f 100644 --- a/examples/marmalade_example/imgui_impl_marmalade.h +++ b/examples/marmalade_example/imgui_impl_marmalade.h @@ -14,6 +14,7 @@ IMGUI_API bool ImGui_Marmalade_Init(bool install_callbacks); IMGUI_API void ImGui_Marmalade_Shutdown(); IMGUI_API void ImGui_Marmalade_NewFrame(); +IMGUI_API void ImGui_Marmalade_RenderDrawData(ImDrawData* draw_data); // Use if you want to reset your rendering device without losing ImGui state. IMGUI_API void ImGui_Marmalade_InvalidateDeviceObjects(); diff --git a/examples/marmalade_example/main.cpp b/examples/marmalade_example/main.cpp index 0b862399c996..f2ddae404829 100644 --- a/examples/marmalade_example/main.cpp +++ b/examples/marmalade_example/main.cpp @@ -100,6 +100,7 @@ int main(int, char**) IwGxSetColClear(clear_color.x * 255, clear_color.y * 255, clear_color.z * 255, clear_color.w * 255); IwGxClear(); ImGui::Render(); + ImGui_Marmalade_RenderDrawData(ImGui::GetDrawData()); IwGxSwapBuffers(); s3eDeviceYield(0); diff --git a/examples/opengl2_example/imgui_impl_glfw_gl2.cpp b/examples/opengl2_example/imgui_impl_glfw_gl2.cpp index ce97f27231d2..2630f164cc15 100644 --- a/examples/opengl2_example/imgui_impl_glfw_gl2.cpp +++ b/examples/opengl2_example/imgui_impl_glfw_gl2.cpp @@ -19,6 +19,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2018-02-16: Misc: Obsoleted the io.RenderDrawListsFn callback and exposed ImGui_ImplGlfwGL2_RenderDrawData() in the .h file so you can call it yourself. // 2018-02-06: Misc: Removed call to ImGui::Shutdown() which is not available from 1.60 WIP, user needs to call CreateContext/DestroyContext themselves. // 2018-02-06: Inputs: Added mapping for ImGuiKey_Space. // 2018-01-25: Inputs: Honoring the io.WantMoveMouse by repositioning the mouse by using navigation and ImGuiNavFlags_MoveMouse is set. @@ -49,10 +50,10 @@ static double g_Time = 0.0f; static bool g_MouseJustPressed[3] = { false, false, false }; static GLuint g_FontTexture = 0; -// This is the main rendering function that you have to implement and provide to ImGui (via setting up 'RenderDrawListsFn' in the ImGuiIO structure) -void ImGui_ImplGlfwGL2_RenderDrawLists(ImDrawData* draw_data) +// OpenGL2 Render function. +// (this used to be set in io.RenderDrawListsFn and called by ImGui::Render(), but you can now call this directly from your main loop) // Note that this implementation is little overcomplicated because we are saving/setting up/restoring every OpenGL state explicitly, in order to be able to run within any OpenGL engine that doesn't do so. -// 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) +void ImGui_ImplGlfwGL2_RenderDrawData(ImDrawData* draw_data) { // Avoid rendering when minimized, scale coordinates for retina displays (screen coordinates != framebuffer coordinates) ImGuiIO& io = ImGui::GetIO(); @@ -241,7 +242,6 @@ bool ImGui_ImplGlfwGL2_Init(GLFWwindow* window, bool install_callbacks) io.KeyMap[ImGuiKey_Y] = GLFW_KEY_Y; io.KeyMap[ImGuiKey_Z] = GLFW_KEY_Z; - io.RenderDrawListsFn = ImGui_ImplGlfwGL2_RenderDrawLists; // Alternatively you can set this to NULL and call ImGui::GetDrawData() after ImGui::Render() to get the same ImDrawData pointer. io.SetClipboardTextFn = ImGui_ImplGlfwGL2_SetClipboardText; io.GetClipboardTextFn = ImGui_ImplGlfwGL2_GetClipboardText; io.ClipboardUserData = g_Window; diff --git a/examples/opengl2_example/imgui_impl_glfw_gl2.h b/examples/opengl2_example/imgui_impl_glfw_gl2.h index 91d1e0873421..268b0e498450 100644 --- a/examples/opengl2_example/imgui_impl_glfw_gl2.h +++ b/examples/opengl2_example/imgui_impl_glfw_gl2.h @@ -18,6 +18,7 @@ struct GLFWwindow; IMGUI_API bool ImGui_ImplGlfwGL2_Init(GLFWwindow* window, bool install_callbacks); IMGUI_API void ImGui_ImplGlfwGL2_Shutdown(); IMGUI_API void ImGui_ImplGlfwGL2_NewFrame(); +IMGUI_API void ImGui_ImplGlfwGL2_RenderDrawData(ImDrawData* draw_data); // Use if you want to reset your rendering device without losing ImGui state. IMGUI_API void ImGui_ImplGlfwGL2_InvalidateDeviceObjects(); diff --git a/examples/opengl2_example/main.cpp b/examples/opengl2_example/main.cpp index d0b500c86aa6..caae8c2b66c9 100644 --- a/examples/opengl2_example/main.cpp +++ b/examples/opengl2_example/main.cpp @@ -110,6 +110,7 @@ int main(int, char**) glClear(GL_COLOR_BUFFER_BIT); //glUseProgram(0); // You may want this if using this code in an OpenGL 3+ context where shaders may be bound, but prefer using the GL3+ code. ImGui::Render(); + ImGui_ImplGlfwGL2_RenderDrawData(ImGui::GetDrawData()); glfwSwapBuffers(window); } diff --git a/examples/opengl3_example/imgui_impl_glfw_gl3.cpp b/examples/opengl3_example/imgui_impl_glfw_gl3.cpp index 2e0863f33ee1..9c82abc5c3ae 100644 --- a/examples/opengl3_example/imgui_impl_glfw_gl3.cpp +++ b/examples/opengl3_example/imgui_impl_glfw_gl3.cpp @@ -13,6 +13,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2018-02-16: Misc: Obsoleted the io.RenderDrawListsFn callback and exposed ImGui_ImplGlfwGL3_RenderDrawData() in the .h file so you can call it yourself. // 2018-02-06: Misc: Removed call to ImGui::Shutdown() which is not available from 1.60 WIP, user needs to call CreateContext/DestroyContext themselves. // 2018-02-06: Inputs: Added mapping for ImGuiKey_Space. // 2018-01-25: Inputs: Added gamepad support if ImGuiNavFlags_EnableGamepad is set. @@ -50,10 +51,10 @@ static int g_AttribLocationTex = 0, g_AttribLocationProjMtx = 0; static int g_AttribLocationPosition = 0, g_AttribLocationUV = 0, g_AttribLocationColor = 0; static unsigned int g_VboHandle = 0, g_VaoHandle = 0, g_ElementsHandle = 0; -// This is the main rendering function that you have to implement and provide to ImGui (via setting up 'RenderDrawListsFn' in the ImGuiIO structure) +// OpenGL3 Render function. +// (this used to be set in io.RenderDrawListsFn and called by ImGui::Render(), but you can now call this directly from your main loop) // Note that this implementation is little overcomplicated because we are saving/setting up/restoring every OpenGL state explicitly, in order to be able to run within any OpenGL engine that doesn't do so. -// 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) -void ImGui_ImplGlfwGL3_RenderDrawLists(ImDrawData* draw_data) +void ImGui_ImplGlfwGL3_RenderDrawData(ImDrawData* draw_data) { // Avoid rendering when minimized, scale coordinates for retina displays (screen coordinates != framebuffer coordinates) ImGuiIO& io = ImGui::GetIO(); @@ -356,7 +357,6 @@ bool ImGui_ImplGlfwGL3_Init(GLFWwindow* window, bool install_callbacks) io.KeyMap[ImGuiKey_Y] = GLFW_KEY_Y; io.KeyMap[ImGuiKey_Z] = GLFW_KEY_Z; - io.RenderDrawListsFn = ImGui_ImplGlfwGL3_RenderDrawLists; // Alternatively you can set this to NULL and call ImGui::GetDrawData() after ImGui::Render() to get the same ImDrawData pointer. io.SetClipboardTextFn = ImGui_ImplGlfwGL3_SetClipboardText; io.GetClipboardTextFn = ImGui_ImplGlfwGL3_GetClipboardText; io.ClipboardUserData = g_Window; diff --git a/examples/opengl3_example/imgui_impl_glfw_gl3.h b/examples/opengl3_example/imgui_impl_glfw_gl3.h index 6b4101f21585..0e039d8d0b78 100644 --- a/examples/opengl3_example/imgui_impl_glfw_gl3.h +++ b/examples/opengl3_example/imgui_impl_glfw_gl3.h @@ -16,6 +16,7 @@ struct GLFWwindow; IMGUI_API bool ImGui_ImplGlfwGL3_Init(GLFWwindow* window, bool install_callbacks); IMGUI_API void ImGui_ImplGlfwGL3_Shutdown(); IMGUI_API void ImGui_ImplGlfwGL3_NewFrame(); +IMGUI_API void ImGui_ImplGlfwGL3_RenderDrawData(ImDrawData* draw_data); // Use if you want to reset your rendering device without losing ImGui state. IMGUI_API void ImGui_ImplGlfwGL3_InvalidateDeviceObjects(); diff --git a/examples/opengl3_example/main.cpp b/examples/opengl3_example/main.cpp index a13cbe5ce805..a5f59e8aaf22 100644 --- a/examples/opengl3_example/main.cpp +++ b/examples/opengl3_example/main.cpp @@ -115,6 +115,7 @@ int main(int, char**) glClearColor(clear_color.x, clear_color.y, clear_color.z, clear_color.w); glClear(GL_COLOR_BUFFER_BIT); ImGui::Render(); + ImGui_ImplGlfwGL3_RenderDrawData(ImGui::GetDrawData()); glfwSwapBuffers(window); } diff --git a/examples/sdl_opengl2_example/imgui_impl_sdl_gl2.cpp b/examples/sdl_opengl2_example/imgui_impl_sdl_gl2.cpp index 17c29edcdfdf..26cf8c65d811 100644 --- a/examples/sdl_opengl2_example/imgui_impl_sdl_gl2.cpp +++ b/examples/sdl_opengl2_example/imgui_impl_sdl_gl2.cpp @@ -19,6 +19,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2018-02-16: Misc: Obsoleted the io.RenderDrawListsFn callback and exposed ImGui_ImplSdlGL2_RenderDrawData() in the .h file so you can call it yourself. // 2018-02-06: Misc: Removed call to ImGui::Shutdown() which is not available from 1.60 WIP, user needs to call CreateContext/DestroyContext themselves. // 2018-02-06: Inputs: Added mapping for ImGuiKey_Space. // 2018-02-05: Misc: Using SDL_GetPerformanceCounter() instead of SDL_GetTicks() to be able to handle very high framerate (1000+ FPS). @@ -43,10 +44,10 @@ static Uint64 g_Time = 0; static bool g_MousePressed[3] = { false, false, false }; static GLuint g_FontTexture = 0; -// This is the main rendering function that you have to implement and provide to ImGui (via setting up 'RenderDrawListsFn' in the ImGuiIO structure) +// OpenGL2 Render function. +// (this used to be set in io.RenderDrawListsFn and called by ImGui::Render(), but you can now call this directly from your main loop) // Note that this implementation is little overcomplicated because we are saving/setting up/restoring every OpenGL state explicitly, in order to be able to run within any OpenGL engine that doesn't do so. -// 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) -void ImGui_ImplSdlGL2_RenderDrawLists(ImDrawData* draw_data) +void ImGui_ImplSdlGL2_RenderDrawData(ImDrawData* draw_data) { // Avoid rendering when minimized, scale coordinates for retina displays (screen coordinates != framebuffer coordinates) ImGuiIO& io = ImGui::GetIO(); @@ -245,7 +246,6 @@ bool ImGui_ImplSdlGL2_Init(SDL_Window* window) io.KeyMap[ImGuiKey_Y] = SDL_SCANCODE_Y; io.KeyMap[ImGuiKey_Z] = SDL_SCANCODE_Z; - io.RenderDrawListsFn = ImGui_ImplSdlGL2_RenderDrawLists; // Alternatively you can set this to NULL and call ImGui::GetDrawData() after ImGui::Render() to get the same ImDrawData pointer. io.SetClipboardTextFn = ImGui_ImplSdlGL2_SetClipboardText; io.GetClipboardTextFn = ImGui_ImplSdlGL2_GetClipboardText; io.ClipboardUserData = NULL; diff --git a/examples/sdl_opengl2_example/imgui_impl_sdl_gl2.h b/examples/sdl_opengl2_example/imgui_impl_sdl_gl2.h index 915ae52d7545..4df1c169c4ee 100644 --- a/examples/sdl_opengl2_example/imgui_impl_sdl_gl2.h +++ b/examples/sdl_opengl2_example/imgui_impl_sdl_gl2.h @@ -19,6 +19,7 @@ typedef union SDL_Event SDL_Event; IMGUI_API bool ImGui_ImplSdlGL2_Init(SDL_Window* window); IMGUI_API void ImGui_ImplSdlGL2_Shutdown(); IMGUI_API void ImGui_ImplSdlGL2_NewFrame(SDL_Window* window); +IMGUI_API void ImGui_ImplSdlGL2_RenderDrawData(ImDrawData* draw_data); IMGUI_API bool ImGui_ImplSdlGL2_ProcessEvent(SDL_Event* event); // Use if you want to reset your rendering device without losing ImGui state. diff --git a/examples/sdl_opengl2_example/main.cpp b/examples/sdl_opengl2_example/main.cpp index f7926d002eff..8f4ca93dcb13 100644 --- a/examples/sdl_opengl2_example/main.cpp +++ b/examples/sdl_opengl2_example/main.cpp @@ -122,6 +122,7 @@ int main(int, char**) glClear(GL_COLOR_BUFFER_BIT); //glUseProgram(0); // You may want this if using this code in an OpenGL 3+ context where shaders may be bound ImGui::Render(); + ImGui_ImplSdlGL2_RenderDrawData(ImGui::GetDrawData()); SDL_GL_SwapWindow(window); } diff --git a/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.cpp b/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.cpp index a50988315ef8..b73fdbde0389 100644 --- a/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.cpp +++ b/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.cpp @@ -12,6 +12,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2018-02-16: Misc: Obsoleted the io.RenderDrawListsFn callback and exposed ImGui_ImplSdlGL3_RenderDrawData() in the .h file so you can call it yourself. // 2018-02-06: Misc: Removed call to ImGui::Shutdown() which is not available from 1.60 WIP, user needs to call CreateContext/DestroyContext themselves. // 2018-02-06: Inputs: Added mapping for ImGuiKey_Space. // 2018-02-05: Misc: Using SDL_GetPerformanceCounter() instead of SDL_GetTicks() to be able to handle very high framerate (1000+ FPS). @@ -48,7 +49,7 @@ static unsigned int g_VboHandle = 0, g_VaoHandle = 0, g_ElementsHandle = 0; // This is the main rendering function that you have to implement and provide to ImGui (via setting up 'RenderDrawListsFn' in the ImGuiIO structure) // Note that this implementation is little overcomplicated because we are saving/setting up/restoring every OpenGL state explicitly, in order to be able to run within any OpenGL engine that doesn't do so. // 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) -void ImGui_ImplSdlGL3_RenderDrawLists(ImDrawData* draw_data) +void ImGui_ImplSdlGL3_RenderDrawData(ImDrawData* draw_data) { // Avoid rendering when minimized, scale coordinates for retina displays (screen coordinates != framebuffer coordinates) ImGuiIO& io = ImGui::GetIO(); @@ -359,7 +360,6 @@ bool ImGui_ImplSdlGL3_Init(SDL_Window* window) io.KeyMap[ImGuiKey_Y] = SDL_SCANCODE_Y; io.KeyMap[ImGuiKey_Z] = SDL_SCANCODE_Z; - io.RenderDrawListsFn = ImGui_ImplSdlGL3_RenderDrawLists; // Alternatively you can set this to NULL and call ImGui::GetDrawData() after ImGui::Render() to get the same ImDrawData pointer. io.SetClipboardTextFn = ImGui_ImplSdlGL3_SetClipboardText; io.GetClipboardTextFn = ImGui_ImplSdlGL3_GetClipboardText; io.ClipboardUserData = NULL; diff --git a/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.h b/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.h index 3f76e294223c..fa111a1793b7 100644 --- a/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.h +++ b/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.h @@ -16,6 +16,7 @@ typedef union SDL_Event SDL_Event; IMGUI_API bool ImGui_ImplSdlGL3_Init(SDL_Window* window); IMGUI_API void ImGui_ImplSdlGL3_Shutdown(); IMGUI_API void ImGui_ImplSdlGL3_NewFrame(SDL_Window* window); +IMGUI_API void ImGui_ImplSdlGL3_RenderDrawData(ImDrawData* draw_data); IMGUI_API bool ImGui_ImplSdlGL3_ProcessEvent(SDL_Event* event); // Use if you want to reset your rendering device without losing ImGui state. diff --git a/examples/sdl_opengl3_example/main.cpp b/examples/sdl_opengl3_example/main.cpp index af25fdf0a858..a3fc625c2512 100644 --- a/examples/sdl_opengl3_example/main.cpp +++ b/examples/sdl_opengl3_example/main.cpp @@ -121,6 +121,7 @@ int main(int, char**) glClearColor(clear_color.x, clear_color.y, clear_color.z, clear_color.w); glClear(GL_COLOR_BUFFER_BIT); ImGui::Render(); + ImGui_ImplSdlGL3_RenderDrawData(ImGui::GetDrawData()); SDL_GL_SwapWindow(window); } diff --git a/examples/vulkan_example/imgui_impl_glfw_vulkan.cpp b/examples/vulkan_example/imgui_impl_glfw_vulkan.cpp index 70fa6cc43ebd..8e93e7e94c6a 100644 --- a/examples/vulkan_example/imgui_impl_glfw_vulkan.cpp +++ b/examples/vulkan_example/imgui_impl_glfw_vulkan.cpp @@ -10,6 +10,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2018-02-16: Misc: Obsoleted the io.RenderDrawListsFn callback, ImGui_ImplGlfwVulkan_Render() calls ImGui_ImplGlfwVulkan_RenderDrawData() itself. // 2018-02-06: Misc: Removed call to ImGui::Shutdown() which is not available from 1.60 WIP, user needs to call CreateContext/DestroyContext themselves. // 2018-02-06: Inputs: Added mapping for ImGuiKey_Space. // 2018-01-20: Inputs: Added Horizontal Mouse Wheel support. @@ -165,7 +166,7 @@ static void ImGui_ImplGlfwVulkan_VkResult(VkResult err) } // This is the main rendering function that you have to implement and provide to ImGui (via setting up 'RenderDrawListsFn' in the ImGuiIO structure) -void ImGui_ImplGlfwVulkan_RenderDrawLists(ImDrawData* draw_data) +void ImGui_ImplGlfwVulkan_RenderDrawData(ImDrawData* draw_data) { VkResult err; ImGuiIO& io = ImGui::GetIO(); @@ -778,7 +779,6 @@ bool ImGui_ImplGlfwVulkan_Init(GLFWwindow* window, bool install_callbacks, Im io.KeyMap[ImGuiKey_Y] = GLFW_KEY_Y; io.KeyMap[ImGuiKey_Z] = GLFW_KEY_Z; - io.RenderDrawListsFn = ImGui_ImplGlfwVulkan_RenderDrawLists; // Alternatively you can set this to NULL and call ImGui::GetDrawData() after ImGui::Render() to get the same ImDrawData pointer. io.SetClipboardTextFn = ImGui_ImplGlfwVulkan_SetClipboardText; io.GetClipboardTextFn = ImGui_ImplGlfwVulkan_GetClipboardText; io.ClipboardUserData = g_Window; @@ -851,6 +851,7 @@ void ImGui_ImplGlfwVulkan_Render(VkCommandBuffer command_buffer) { g_CommandBuffer = command_buffer; ImGui::Render(); + ImGui_ImplGlfwVulkan_RenderDrawData(ImGui::GetDrawData()); g_CommandBuffer = VK_NULL_HANDLE; g_FrameIndex = (g_FrameIndex + 1) % IMGUI_VK_QUEUED_FRAMES; } diff --git a/imgui.cpp b/imgui.cpp index 29bafca6b97e..3eb519582e7f 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -131,7 +131,6 @@ ImGuiIO& io = ImGui::GetIO(); io.DisplaySize.x = 1920.0f; io.DisplaySize.y = 1280.0f; - io.RenderDrawListsFn = MyRenderFunction; // Setup a render function, or set to NULL and call GetDrawData() after Render() to access render data. // TODO: Fill others settings of the io structure later. // Load texture atlas (there is a default font so you don't need to care about choosing a font yet) @@ -162,6 +161,7 @@ // Render & swap video buffers ImGui::Render(); + MyImGuiRenderFunction(ImGui::GetDrawData()); SwapBuffers(); } @@ -250,6 +250,7 @@ Here is a change-log of API breaking changes, if you are using one of the functions listed, expect to have to fix some code. Also read releases logs https://github.com/ocornut/imgui/releases for more details. + - 2018/02/16 (1.60) - obsoleted the io.RenderDrawListsFn callback, you can call your graphics engine render function after ImGui::Render(). Use ImGui::GetDrawData() to retrieve the ImDrawData* to display. - 2018/02/07 (1.60) - reorganized context handling to be more explicit, - YOU NOW NEED TO CALL ImGui::CreateContext() AT THE BEGINNING OF YOUR APP, AND CALL ImGui::DestroyContext() AT THE END. - removed Shutdown() function, as DestroyContext() serve this purpose. @@ -882,15 +883,18 @@ ImGuiIO::ImGuiIO() OptMacOSXBehaviors = false; #endif OptCursorBlink = true; - + // Settings (User Functions) - RenderDrawListsFn = NULL; GetClipboardTextFn = GetClipboardTextFn_DefaultImpl; // Platform dependent default implementations SetClipboardTextFn = SetClipboardTextFn_DefaultImpl; ClipboardUserData = NULL; ImeSetInputScreenPosFn = ImeSetInputScreenPosFn_DefaultImpl; ImeWindowHandle = NULL; +#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS + RenderDrawListsFn = NULL; +#endif + // Input (NB: we already have memset zero the entire structure) MousePos = ImVec2(-FLT_MAX, -FLT_MAX); MousePosPrev = ImVec2(-FLT_MAX, -FLT_MAX); @@ -2657,7 +2661,7 @@ ImGuiStyle& ImGui::GetStyle() return GImGui->Style; } -// Same value as passed to your RenderDrawListsFn() function. valid after Render() and until the next call to NewFrame() +// Same value as passed to the old io.RenderDrawListsFn function. Valid after Render() and until the next call to NewFrame() ImDrawData* ImGui::GetDrawData() { return GImGui->DrawData.Valid ? &GImGui->DrawData : NULL; @@ -4079,8 +4083,10 @@ void ImGui::Render() g.IO.MetricsRenderIndices = g.DrawData.TotalIdxCount; // Render. If user hasn't set a callback then they may retrieve the draw data via GetDrawData() +#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS if (g.DrawData.CmdListsCount > 0 && g.IO.RenderDrawListsFn != NULL) g.IO.RenderDrawListsFn(&g.DrawData); +#endif } } diff --git a/imgui.h b/imgui.h index 60d027e0c448..d421e224a7f5 100644 --- a/imgui.h +++ b/imgui.h @@ -147,9 +147,9 @@ namespace ImGui // Main IMGUI_API ImGuiIO& GetIO(); IMGUI_API ImGuiStyle& GetStyle(); - IMGUI_API ImDrawData* GetDrawData(); // same value as passed to your io.RenderDrawListsFn() function. valid after Render() and until the next call to NewFrame() IMGUI_API void NewFrame(); // start a new ImGui frame, you can submit any command from this point until Render()/EndFrame(). - IMGUI_API void Render(); // ends the ImGui frame, finalize the draw data, then call your io.RenderDrawListsFn() function if set. + IMGUI_API void Render(); // ends the ImGui frame, finalize the draw data. (Obsolete: optionally call io.RenderDrawListsFn if set. Nowadays, prefer calling your render function yourself.) + IMGUI_API ImDrawData* GetDrawData(); // valid after Render() and until the next call to NewFrame(). this is what you have to render. (Obsolete: this used to be passed to your io.RenderDrawListsFn() function.) IMGUI_API void EndFrame(); // ends the ImGui frame. automatically called by Render(), so most likely don't need to ever call that yourself directly. If you don't need to render you may call EndFrame() but you'll have wasted CPU already. If you don't need to render, better to not create any imgui windows instead! // Demo, Debug, Informations @@ -981,11 +981,6 @@ struct ImGuiIO // Settings (User Functions) //------------------------------------------------------------------ - // Rendering function, will be called in Render(). - // Alternatively you can keep this to NULL and call GetDrawData() after Render() to get the same pointer. - // See example applications if you are unsure of how to implement this. - void (*RenderDrawListsFn)(ImDrawData* data); - // Optional: access OS clipboard // (default to use native Win32 clipboard on Windows, otherwise uses a private clipboard. Override to access OS clipboard on other architectures) const char* (*GetClipboardTextFn)(void* user_data); @@ -997,6 +992,12 @@ struct ImGuiIO void (*ImeSetInputScreenPosFn)(int x, int y); void* ImeWindowHandle; // (Windows) Set this to your HWND to get automatic IME cursor positioning. +#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS + // [OBSOLETE] Rendering function, will be automatically called in Render(). Please call your rendering function yourself now! You can obtain the ImDrawData* by calling ImGui::GetDrawData() after Render(). + // See example applications if you are unsure of how to implement this. + void (*RenderDrawListsFn)(ImDrawData* data); +#endif + //------------------------------------------------------------------ // Input - Fill before calling NewFrame() //------------------------------------------------------------------ From ffb6e89f30160c7b0f30acfa901531ff1aa07e06 Mon Sep 17 00:00:00 2001 From: Oliver Faircliff Date: Fri, 16 Feb 2018 17:45:31 +0000 Subject: [PATCH 681/823] Use SDL system cursors in SDL examples. (#1626) (Squashed 4 commits) --- .../imgui_impl_sdl_gl2.cpp | 21 ++++++++++++++++++- .../imgui_impl_sdl_gl3.cpp | 21 ++++++++++++++++++- 2 files changed, 40 insertions(+), 2 deletions(-) diff --git a/examples/sdl_opengl2_example/imgui_impl_sdl_gl2.cpp b/examples/sdl_opengl2_example/imgui_impl_sdl_gl2.cpp index 26cf8c65d811..fc5473ba9be2 100644 --- a/examples/sdl_opengl2_example/imgui_impl_sdl_gl2.cpp +++ b/examples/sdl_opengl2_example/imgui_impl_sdl_gl2.cpp @@ -43,6 +43,7 @@ static Uint64 g_Time = 0; static bool g_MousePressed[3] = { false, false, false }; static GLuint g_FontTexture = 0; +static SDL_Cursor *g_SdlCursorMap[ImGuiMouseCursor_Count_]; // OpenGL2 Render function. // (this used to be set in io.RenderDrawListsFn and called by ImGui::Render(), but you can now call this directly from your main loop) @@ -250,6 +251,14 @@ bool ImGui_ImplSdlGL2_Init(SDL_Window* window) io.GetClipboardTextFn = ImGui_ImplSdlGL2_GetClipboardText; io.ClipboardUserData = NULL; + g_SdlCursorMap[ImGuiMouseCursor_Arrow] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_ARROW); + g_SdlCursorMap[ImGuiMouseCursor_TextInput] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_IBEAM); + g_SdlCursorMap[ImGuiMouseCursor_Move] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_HAND); + g_SdlCursorMap[ImGuiMouseCursor_ResizeNS] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZENS); + g_SdlCursorMap[ImGuiMouseCursor_ResizeEW] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZEWE); + g_SdlCursorMap[ImGuiMouseCursor_ResizeNESW] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZENESW); + g_SdlCursorMap[ImGuiMouseCursor_ResizeNWSE] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZENWSE); + #ifdef _WIN32 SDL_SysWMinfo wmInfo; SDL_VERSION(&wmInfo.version); @@ -265,6 +274,9 @@ bool ImGui_ImplSdlGL2_Init(SDL_Window* window) void ImGui_ImplSdlGL2_Shutdown() { ImGui_ImplSdlGL2_InvalidateDeviceObjects(); + + for (ImGuiMouseCursor cursor_n = 0; cursor_n < ImGuiMouseCursor_Count_; cursor_n++) + SDL_FreeCursor(g_SdlCursorMap[cursor_n]); } void ImGui_ImplSdlGL2_NewFrame(SDL_Window *window) @@ -314,7 +326,14 @@ void ImGui_ImplSdlGL2_NewFrame(SDL_Window *window) #endif // Hide OS mouse cursor if ImGui is drawing it - SDL_ShowCursor(io.MouseDrawCursor ? 0 : 1); + if (io.MouseDrawCursor) + SDL_ShowCursor(0); + else + { + SDL_Cursor *cursor = g_SdlCursorMap[ImGui::GetMouseCursor()]; + SDL_SetCursor(cursor); + SDL_ShowCursor(1); + } // Start the frame. This call will update the io.WantCaptureMouse, io.WantCaptureKeyboard flag that you can use to dispatch inputs (or not) to your application. ImGui::NewFrame(); diff --git a/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.cpp b/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.cpp index b73fdbde0389..10726300ef2d 100644 --- a/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.cpp +++ b/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.cpp @@ -45,6 +45,7 @@ static int g_ShaderHandle = 0, g_VertHandle = 0, g_FragHandle = 0; static int g_AttribLocationTex = 0, g_AttribLocationProjMtx = 0; static int g_AttribLocationPosition = 0, g_AttribLocationUV = 0, g_AttribLocationColor = 0; static unsigned int g_VboHandle = 0, g_VaoHandle = 0, g_ElementsHandle = 0; +static SDL_Cursor *g_SdlCursorMap[ImGuiMouseCursor_Count_]; // This is the main rendering function that you have to implement and provide to ImGui (via setting up 'RenderDrawListsFn' in the ImGuiIO structure) // Note that this implementation is little overcomplicated because we are saving/setting up/restoring every OpenGL state explicitly, in order to be able to run within any OpenGL engine that doesn't do so. @@ -364,6 +365,14 @@ bool ImGui_ImplSdlGL3_Init(SDL_Window* window) io.GetClipboardTextFn = ImGui_ImplSdlGL3_GetClipboardText; io.ClipboardUserData = NULL; + g_SdlCursorMap[ImGuiMouseCursor_Arrow] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_ARROW); + g_SdlCursorMap[ImGuiMouseCursor_TextInput] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_IBEAM); + g_SdlCursorMap[ImGuiMouseCursor_Move] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_HAND); + g_SdlCursorMap[ImGuiMouseCursor_ResizeNS] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZENS); + g_SdlCursorMap[ImGuiMouseCursor_ResizeEW] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZEWE); + g_SdlCursorMap[ImGuiMouseCursor_ResizeNESW] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZENESW); + g_SdlCursorMap[ImGuiMouseCursor_ResizeNWSE] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZENWSE); + #ifdef _WIN32 SDL_SysWMinfo wmInfo; SDL_VERSION(&wmInfo.version); @@ -379,6 +388,9 @@ bool ImGui_ImplSdlGL3_Init(SDL_Window* window) void ImGui_ImplSdlGL3_Shutdown() { ImGui_ImplSdlGL3_InvalidateDeviceObjects(); + + for (ImGuiMouseCursor cursor_n = 0; cursor_n < ImGuiMouseCursor_Count_; cursor_n++) + SDL_FreeCursor(g_SdlCursorMap[cursor_n]); } void ImGui_ImplSdlGL3_NewFrame(SDL_Window* window) @@ -428,7 +440,14 @@ void ImGui_ImplSdlGL3_NewFrame(SDL_Window* window) #endif // Hide OS mouse cursor if ImGui is drawing it - SDL_ShowCursor(io.MouseDrawCursor ? 0 : 1); + if (io.MouseDrawCursor) + SDL_ShowCursor(0); + else + { + SDL_Cursor *cursor = g_SdlCursorMap[ImGui::GetMouseCursor()]; + SDL_SetCursor(cursor); + SDL_ShowCursor(1); + } // Start the frame. This call will update the io.WantCaptureMouse, io.WantCaptureKeyboard flag that you can use to dispatch inputs (or not) to your application. ImGui::NewFrame(); From 7c7583520043078b18cef0c4e7847d623b37a29f Mon Sep 17 00:00:00 2001 From: omar Date: Fri, 16 Feb 2018 19:49:33 +0100 Subject: [PATCH 682/823] Renamed misleading ImGuiMouseCursor_Move to ImGuiMouseCursor_ResizeAll. SDL: Fixed cursor. (#1626) --- examples/allegro5_example/imgui_impl_a5.cpp | 2 +- examples/sdl_opengl2_example/imgui_impl_sdl_gl2.cpp | 2 +- examples/sdl_opengl3_example/imgui_impl_sdl_gl3.cpp | 2 +- imgui.h | 2 +- imgui_draw.cpp | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/examples/allegro5_example/imgui_impl_a5.cpp b/examples/allegro5_example/imgui_impl_a5.cpp index 479702b98639..127bf196a0e1 100644 --- a/examples/allegro5_example/imgui_impl_a5.cpp +++ b/examples/allegro5_example/imgui_impl_a5.cpp @@ -291,7 +291,7 @@ void ImGui_ImplA5_NewFrame() switch (ImGui::GetMouseCursor()) { case ImGuiMouseCursor_TextInput: cursor_id = ALLEGRO_SYSTEM_MOUSE_CURSOR_EDIT; break; - case ImGuiMouseCursor_Move: cursor_id = ALLEGRO_SYSTEM_MOUSE_CURSOR_MOVE; break; + case ImGuiMouseCursor_ResizeAll: cursor_id = ALLEGRO_SYSTEM_MOUSE_CURSOR_MOVE; break; case ImGuiMouseCursor_ResizeNS: cursor_id = ALLEGRO_SYSTEM_MOUSE_CURSOR_RESIZE_N; break; case ImGuiMouseCursor_ResizeEW: cursor_id = ALLEGRO_SYSTEM_MOUSE_CURSOR_RESIZE_E; break; case ImGuiMouseCursor_ResizeNESW: cursor_id = ALLEGRO_SYSTEM_MOUSE_CURSOR_RESIZE_NE; break; diff --git a/examples/sdl_opengl2_example/imgui_impl_sdl_gl2.cpp b/examples/sdl_opengl2_example/imgui_impl_sdl_gl2.cpp index fc5473ba9be2..0a7b8d7e946a 100644 --- a/examples/sdl_opengl2_example/imgui_impl_sdl_gl2.cpp +++ b/examples/sdl_opengl2_example/imgui_impl_sdl_gl2.cpp @@ -253,7 +253,7 @@ bool ImGui_ImplSdlGL2_Init(SDL_Window* window) g_SdlCursorMap[ImGuiMouseCursor_Arrow] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_ARROW); g_SdlCursorMap[ImGuiMouseCursor_TextInput] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_IBEAM); - g_SdlCursorMap[ImGuiMouseCursor_Move] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_HAND); + g_SdlCursorMap[ImGuiMouseCursor_ResizeAll] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZEALL); g_SdlCursorMap[ImGuiMouseCursor_ResizeNS] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZENS); g_SdlCursorMap[ImGuiMouseCursor_ResizeEW] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZEWE); g_SdlCursorMap[ImGuiMouseCursor_ResizeNESW] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZENESW); diff --git a/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.cpp b/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.cpp index 10726300ef2d..186e6d2ca581 100644 --- a/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.cpp +++ b/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.cpp @@ -367,7 +367,7 @@ bool ImGui_ImplSdlGL3_Init(SDL_Window* window) g_SdlCursorMap[ImGuiMouseCursor_Arrow] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_ARROW); g_SdlCursorMap[ImGuiMouseCursor_TextInput] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_IBEAM); - g_SdlCursorMap[ImGuiMouseCursor_Move] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_HAND); + g_SdlCursorMap[ImGuiMouseCursor_ResizeAll] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZEALL); g_SdlCursorMap[ImGuiMouseCursor_ResizeNS] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZENS); g_SdlCursorMap[ImGuiMouseCursor_ResizeEW] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZEWE); g_SdlCursorMap[ImGuiMouseCursor_ResizeNESW] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZENESW); diff --git a/imgui.h b/imgui.h index d421e224a7f5..5ab6f3327eb1 100644 --- a/imgui.h +++ b/imgui.h @@ -881,7 +881,7 @@ enum ImGuiMouseCursor_ ImGuiMouseCursor_None = -1, ImGuiMouseCursor_Arrow = 0, ImGuiMouseCursor_TextInput, // When hovering over InputText, etc. - ImGuiMouseCursor_Move, // Unused + ImGuiMouseCursor_ResizeAll, // Unused ImGuiMouseCursor_ResizeNS, // When hovering over an horizontal border ImGuiMouseCursor_ResizeEW, // When hovering over a vertical border or a column ImGuiMouseCursor_ResizeNESW, // When hovering over the bottom-left corner of a window diff --git a/imgui_draw.cpp b/imgui_draw.cpp index cafe6e080ca1..118acabc5f27 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -1351,7 +1351,7 @@ static const ImVec2 FONT_ATLAS_DEFAULT_TEX_CURSOR_DATA[ImGuiMouseCursor_Count_][ // Pos ........ Size ......... Offset ...... { ImVec2(0,3), ImVec2(12,19), ImVec2( 0, 0) }, // ImGuiMouseCursor_Arrow { ImVec2(13,0), ImVec2(7,16), ImVec2( 4, 8) }, // ImGuiMouseCursor_TextInput - { ImVec2(31,0), ImVec2(23,23), ImVec2(11,11) }, // ImGuiMouseCursor_Move + { ImVec2(31,0), ImVec2(23,23), ImVec2(11,11) }, // ImGuiMouseCursor_ResizeAll { ImVec2(21,0), ImVec2( 9,23), ImVec2( 5,11) }, // ImGuiMouseCursor_ResizeNS { ImVec2(55,18),ImVec2(23, 9), ImVec2(11, 5) }, // ImGuiMouseCursor_ResizeEW { ImVec2(73,0), ImVec2(17,17), ImVec2( 9, 9) }, // ImGuiMouseCursor_ResizeNESW From 03a44acf6f53887fc62758de5a48cafc9197bf44 Mon Sep 17 00:00:00 2001 From: omar Date: Fri, 16 Feb 2018 19:55:16 +0100 Subject: [PATCH 683/823] Examples: SDL: Minor stylistic tweaks. Fixed handling of ImGuiMouseCursor_None so it doesn't underflow array. Fixed harmless uninitialized pointer. (#1626) --- .../imgui_impl_sdl_gl2.cpp | 27 ++++++++++--------- .../imgui_impl_sdl_gl3.cpp | 27 ++++++++++--------- 2 files changed, 30 insertions(+), 24 deletions(-) diff --git a/examples/sdl_opengl2_example/imgui_impl_sdl_gl2.cpp b/examples/sdl_opengl2_example/imgui_impl_sdl_gl2.cpp index 0a7b8d7e946a..769ebb9fd531 100644 --- a/examples/sdl_opengl2_example/imgui_impl_sdl_gl2.cpp +++ b/examples/sdl_opengl2_example/imgui_impl_sdl_gl2.cpp @@ -19,6 +19,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2018-02-16: Inputs: Added support for mouse cursors, honoring ImGui::GetMouseCursor() value. // 2018-02-16: Misc: Obsoleted the io.RenderDrawListsFn callback and exposed ImGui_ImplSdlGL2_RenderDrawData() in the .h file so you can call it yourself. // 2018-02-06: Misc: Removed call to ImGui::Shutdown() which is not available from 1.60 WIP, user needs to call CreateContext/DestroyContext themselves. // 2018-02-06: Inputs: Added mapping for ImGuiKey_Space. @@ -43,7 +44,7 @@ static Uint64 g_Time = 0; static bool g_MousePressed[3] = { false, false, false }; static GLuint g_FontTexture = 0; -static SDL_Cursor *g_SdlCursorMap[ImGuiMouseCursor_Count_]; +static SDL_Cursor* g_SdlCursors[ImGuiMouseCursor_Count_] = { 0 }; // OpenGL2 Render function. // (this used to be set in io.RenderDrawListsFn and called by ImGui::Render(), but you can now call this directly from your main loop) @@ -251,13 +252,13 @@ bool ImGui_ImplSdlGL2_Init(SDL_Window* window) io.GetClipboardTextFn = ImGui_ImplSdlGL2_GetClipboardText; io.ClipboardUserData = NULL; - g_SdlCursorMap[ImGuiMouseCursor_Arrow] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_ARROW); - g_SdlCursorMap[ImGuiMouseCursor_TextInput] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_IBEAM); - g_SdlCursorMap[ImGuiMouseCursor_ResizeAll] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZEALL); - g_SdlCursorMap[ImGuiMouseCursor_ResizeNS] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZENS); - g_SdlCursorMap[ImGuiMouseCursor_ResizeEW] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZEWE); - g_SdlCursorMap[ImGuiMouseCursor_ResizeNESW] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZENESW); - g_SdlCursorMap[ImGuiMouseCursor_ResizeNWSE] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZENWSE); + g_SdlCursors[ImGuiMouseCursor_Arrow] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_ARROW); + g_SdlCursors[ImGuiMouseCursor_TextInput] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_IBEAM); + g_SdlCursors[ImGuiMouseCursor_ResizeAll] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZEALL); + g_SdlCursors[ImGuiMouseCursor_ResizeNS] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZENS); + g_SdlCursors[ImGuiMouseCursor_ResizeEW] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZEWE); + g_SdlCursors[ImGuiMouseCursor_ResizeNESW] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZENESW); + g_SdlCursors[ImGuiMouseCursor_ResizeNWSE] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZENWSE); #ifdef _WIN32 SDL_SysWMinfo wmInfo; @@ -276,7 +277,7 @@ void ImGui_ImplSdlGL2_Shutdown() ImGui_ImplSdlGL2_InvalidateDeviceObjects(); for (ImGuiMouseCursor cursor_n = 0; cursor_n < ImGuiMouseCursor_Count_; cursor_n++) - SDL_FreeCursor(g_SdlCursorMap[cursor_n]); + SDL_FreeCursor(g_SdlCursors[cursor_n]); } void ImGui_ImplSdlGL2_NewFrame(SDL_Window *window) @@ -326,12 +327,14 @@ void ImGui_ImplSdlGL2_NewFrame(SDL_Window *window) #endif // Hide OS mouse cursor if ImGui is drawing it - if (io.MouseDrawCursor) + ImGuiMouseCursor cursor = ImGui::GetMouseCursor(); + if (io.MouseDrawCursor || cursor == ImGuiMouseCursor_None) + { SDL_ShowCursor(0); + } else { - SDL_Cursor *cursor = g_SdlCursorMap[ImGui::GetMouseCursor()]; - SDL_SetCursor(cursor); + SDL_SetCursor(g_SdlCursors[cursor]); SDL_ShowCursor(1); } diff --git a/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.cpp b/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.cpp index 186e6d2ca581..5a1ec15d30d6 100644 --- a/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.cpp +++ b/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.cpp @@ -12,6 +12,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2018-02-16: Inputs: Added support for mouse cursors, honoring ImGui::GetMouseCursor() value. // 2018-02-16: Misc: Obsoleted the io.RenderDrawListsFn callback and exposed ImGui_ImplSdlGL3_RenderDrawData() in the .h file so you can call it yourself. // 2018-02-06: Misc: Removed call to ImGui::Shutdown() which is not available from 1.60 WIP, user needs to call CreateContext/DestroyContext themselves. // 2018-02-06: Inputs: Added mapping for ImGuiKey_Space. @@ -45,7 +46,7 @@ static int g_ShaderHandle = 0, g_VertHandle = 0, g_FragHandle = 0; static int g_AttribLocationTex = 0, g_AttribLocationProjMtx = 0; static int g_AttribLocationPosition = 0, g_AttribLocationUV = 0, g_AttribLocationColor = 0; static unsigned int g_VboHandle = 0, g_VaoHandle = 0, g_ElementsHandle = 0; -static SDL_Cursor *g_SdlCursorMap[ImGuiMouseCursor_Count_]; +static SDL_Cursor* g_SdlCursors[ImGuiMouseCursor_Count_] = { 0 }; // This is the main rendering function that you have to implement and provide to ImGui (via setting up 'RenderDrawListsFn' in the ImGuiIO structure) // Note that this implementation is little overcomplicated because we are saving/setting up/restoring every OpenGL state explicitly, in order to be able to run within any OpenGL engine that doesn't do so. @@ -365,13 +366,13 @@ bool ImGui_ImplSdlGL3_Init(SDL_Window* window) io.GetClipboardTextFn = ImGui_ImplSdlGL3_GetClipboardText; io.ClipboardUserData = NULL; - g_SdlCursorMap[ImGuiMouseCursor_Arrow] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_ARROW); - g_SdlCursorMap[ImGuiMouseCursor_TextInput] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_IBEAM); - g_SdlCursorMap[ImGuiMouseCursor_ResizeAll] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZEALL); - g_SdlCursorMap[ImGuiMouseCursor_ResizeNS] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZENS); - g_SdlCursorMap[ImGuiMouseCursor_ResizeEW] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZEWE); - g_SdlCursorMap[ImGuiMouseCursor_ResizeNESW] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZENESW); - g_SdlCursorMap[ImGuiMouseCursor_ResizeNWSE] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZENWSE); + g_SdlCursors[ImGuiMouseCursor_Arrow] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_ARROW); + g_SdlCursors[ImGuiMouseCursor_TextInput] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_IBEAM); + g_SdlCursors[ImGuiMouseCursor_ResizeAll] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZEALL); + g_SdlCursors[ImGuiMouseCursor_ResizeNS] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZENS); + g_SdlCursors[ImGuiMouseCursor_ResizeEW] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZEWE); + g_SdlCursors[ImGuiMouseCursor_ResizeNESW] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZENESW); + g_SdlCursors[ImGuiMouseCursor_ResizeNWSE] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZENWSE); #ifdef _WIN32 SDL_SysWMinfo wmInfo; @@ -390,7 +391,7 @@ void ImGui_ImplSdlGL3_Shutdown() ImGui_ImplSdlGL3_InvalidateDeviceObjects(); for (ImGuiMouseCursor cursor_n = 0; cursor_n < ImGuiMouseCursor_Count_; cursor_n++) - SDL_FreeCursor(g_SdlCursorMap[cursor_n]); + SDL_FreeCursor(g_SdlCursors[cursor_n]); } void ImGui_ImplSdlGL3_NewFrame(SDL_Window* window) @@ -440,12 +441,14 @@ void ImGui_ImplSdlGL3_NewFrame(SDL_Window* window) #endif // Hide OS mouse cursor if ImGui is drawing it - if (io.MouseDrawCursor) + ImGuiMouseCursor cursor = ImGui::GetMouseCursor(); + if (io.MouseDrawCursor || cursor == ImGuiMouseCursor_None) + { SDL_ShowCursor(0); + } else { - SDL_Cursor *cursor = g_SdlCursorMap[ImGui::GetMouseCursor()]; - SDL_SetCursor(cursor); + SDL_SetCursor(g_SdlCursors[cursor]); SDL_ShowCursor(1); } From 00b24f27c26694b7c33ebb337e744fac8573a1cc Mon Sep 17 00:00:00 2001 From: omar Date: Fri, 16 Feb 2018 22:09:23 +0100 Subject: [PATCH 684/823] Examples: SDL: Added .vcproj files. --- .../sdl_opengl2_example.vcxproj | 172 +++++++++++++++++ .../sdl_opengl2_example.vcxproj.filters | 49 +++++ .../sdl_opengl3_example.vcxproj | 175 ++++++++++++++++++ .../sdl_opengl3_example.vcxproj.filters | 61 ++++++ 4 files changed, 457 insertions(+) create mode 100644 examples/sdl_opengl2_example/sdl_opengl2_example.vcxproj create mode 100644 examples/sdl_opengl2_example/sdl_opengl2_example.vcxproj.filters create mode 100644 examples/sdl_opengl3_example/sdl_opengl3_example.vcxproj create mode 100644 examples/sdl_opengl3_example/sdl_opengl3_example.vcxproj.filters diff --git a/examples/sdl_opengl2_example/sdl_opengl2_example.vcxproj b/examples/sdl_opengl2_example/sdl_opengl2_example.vcxproj new file mode 100644 index 000000000000..ad83c48150df --- /dev/null +++ b/examples/sdl_opengl2_example/sdl_opengl2_example.vcxproj @@ -0,0 +1,172 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + {2AE17FDE-F7F3-4CAC-ADAB-0710EDA4F741} + opengl3_example + + + + Application + true + MultiByte + + + Application + true + MultiByte + + + Application + false + true + MultiByte + + + Application + false + true + MultiByte + + + + + + + + + + + + + + + + + + + $(ProjectDir)$(Configuration)\ + $(ProjectDir)$(Configuration)\ + $(IncludePath) + + + $(ProjectDir)$(Configuration)\ + $(ProjectDir)$(Configuration)\ + $(IncludePath) + + + $(ProjectDir)$(Configuration)\ + $(ProjectDir)$(Configuration)\ + $(IncludePath) + + + $(ProjectDir)$(Configuration)\ + $(ProjectDir)$(Configuration)\ + $(IncludePath) + + + + Level4 + Disabled + %SDL_DIR%\include;$(SolutionDir)\libs\gl3w;..\..;%(AdditionalIncludeDirectories) + + + true + %SDL_DIR%\lib\x86;%(AdditionalLibraryDirectories) + opengl32.lib;SDL2.lib;SDL2main.lib;%(AdditionalDependencies) + Console + msvcrt.lib + + + + + Level4 + Disabled + %SDL_DIR%\include;$(SolutionDir)\libs\gl3w;..\..;%(AdditionalIncludeDirectories) + + + true + %SDL_DIR%\lib\x64;%(AdditionalLibraryDirectories) + opengl32.lib;SDL2.lib;SDL2main.lib;%(AdditionalDependencies) + Console + msvcrt.lib + + + + + Level4 + MaxSpeed + true + true + %SDL_DIR%\include;$(SolutionDir)\libs\gl3w;..\..;%(AdditionalIncludeDirectories) + false + + + true + true + true + %SDL_DIR%\lib\x86;%(AdditionalLibraryDirectories) + opengl32.lib;SDL2.lib;SDL2main.lib;%(AdditionalDependencies) + Console + + + + + + + Level4 + MaxSpeed + true + true + %SDL_DIR%\include;$(SolutionDir)\libs\gl3w;..\..;%(AdditionalIncludeDirectories) + false + + + true + true + true + %SDL_DIR%\lib\x64;%(AdditionalLibraryDirectories) + opengl32.lib;SDL2.lib;SDL2main.lib;%(AdditionalDependencies) + Console + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/examples/sdl_opengl2_example/sdl_opengl2_example.vcxproj.filters b/examples/sdl_opengl2_example/sdl_opengl2_example.vcxproj.filters new file mode 100644 index 000000000000..1c505f4e579f --- /dev/null +++ b/examples/sdl_opengl2_example/sdl_opengl2_example.vcxproj.filters @@ -0,0 +1,49 @@ + + + + + {20b90ce4-7fcb-4731-b9a0-075f875de82d} + + + {f18ab499-84e1-499f-8eff-9754361e0e52} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + + + imgui + + + imgui + + + imgui + + + sources + + + sources + + + + + imgui + + + imgui + + + imgui + + + sources + + + + + + sources + + + \ No newline at end of file diff --git a/examples/sdl_opengl3_example/sdl_opengl3_example.vcxproj b/examples/sdl_opengl3_example/sdl_opengl3_example.vcxproj new file mode 100644 index 000000000000..1ac4d0acc893 --- /dev/null +++ b/examples/sdl_opengl3_example/sdl_opengl3_example.vcxproj @@ -0,0 +1,175 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + {BBAEB705-1669-40F3-8567-04CF6A991F4C} + opengl3_example + + + + Application + true + MultiByte + + + Application + true + MultiByte + + + Application + false + true + MultiByte + + + Application + false + true + MultiByte + + + + + + + + + + + + + + + + + + + $(ProjectDir)$(Configuration)\ + $(ProjectDir)$(Configuration)\ + $(IncludePath) + + + $(ProjectDir)$(Configuration)\ + $(ProjectDir)$(Configuration)\ + $(IncludePath) + + + $(ProjectDir)$(Configuration)\ + $(ProjectDir)$(Configuration)\ + $(IncludePath) + + + $(ProjectDir)$(Configuration)\ + $(ProjectDir)$(Configuration)\ + $(IncludePath) + + + + Level4 + Disabled + %SDL_DIR%\include;$(SolutionDir)\libs\gl3w;..\..;%(AdditionalIncludeDirectories) + + + true + %SDL_DIR%\lib\x86;%(AdditionalLibraryDirectories) + opengl32.lib;SDL2.lib;SDL2main.lib;%(AdditionalDependencies) + Console + msvcrt.lib + + + + + Level4 + Disabled + %SDL_DIR%\include;$(SolutionDir)\libs\gl3w;..\..;%(AdditionalIncludeDirectories) + + + true + %SDL_DIR%\lib\x64;%(AdditionalLibraryDirectories) + opengl32.lib;SDL2.lib;SDL2main.lib;%(AdditionalDependencies) + Console + msvcrt.lib + + + + + Level4 + MaxSpeed + true + true + %SDL_DIR%\include;$(SolutionDir)\libs\gl3w;..\..;%(AdditionalIncludeDirectories) + false + + + true + true + true + %SDL_DIR%\lib\x86;%(AdditionalLibraryDirectories) + opengl32.lib;SDL2.lib;SDL2main.lib;%(AdditionalDependencies) + Console + + + + + + + Level4 + MaxSpeed + true + true + %SDL_DIR%\include;$(SolutionDir)\libs\gl3w;..\..;%(AdditionalIncludeDirectories) + false + + + true + true + true + %SDL_DIR%\lib\x64;%(AdditionalLibraryDirectories) + opengl32.lib;SDL2.lib;SDL2main.lib;%(AdditionalDependencies) + Console + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/examples/sdl_opengl3_example/sdl_opengl3_example.vcxproj.filters b/examples/sdl_opengl3_example/sdl_opengl3_example.vcxproj.filters new file mode 100644 index 000000000000..f8f434155c3f --- /dev/null +++ b/examples/sdl_opengl3_example/sdl_opengl3_example.vcxproj.filters @@ -0,0 +1,61 @@ + + + + + {20b90ce4-7fcb-4731-b9a0-075f875de82d} + + + {f18ab499-84e1-499f-8eff-9754361e0e52} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {f9997b32-5479-4756-9ffc-77793ad3764f} + + + + + imgui + + + imgui + + + imgui + + + sources + + + sources + + + gl3w + + + + + imgui + + + imgui + + + imgui + + + sources + + + gl3w + + + gl3w + + + + + + sources + + + \ No newline at end of file From 31158e575f637ccd5919bd611e7cca54f8dac1b5 Mon Sep 17 00:00:00 2001 From: omar Date: Fri, 16 Feb 2018 22:09:32 +0100 Subject: [PATCH 685/823] Examples: SDL: Fixed minor warning. --- examples/sdl_opengl3_example/imgui_impl_sdl_gl3.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.cpp b/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.cpp index 5a1ec15d30d6..585439abdcc4 100644 --- a/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.cpp +++ b/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.cpp @@ -39,7 +39,7 @@ #include // This example is using gl3w to access OpenGL functions (because it is small). You may use glew/glad/glLoadGen/etc. whatever already works for you. // Data -static Uint64 g_Time = 0.0f; +static Uint64 g_Time = 0; static bool g_MousePressed[3] = { false, false, false }; static GLuint g_FontTexture = 0; static int g_ShaderHandle = 0, g_VertHandle = 0, g_FragHandle = 0; From 10752423ec04443f0cd4f7675eb0a624137bba62 Mon Sep 17 00:00:00 2001 From: omar Date: Fri, 16 Feb 2018 22:34:41 +0100 Subject: [PATCH 686/823] Examples: Vulkan: Added .vcproj files. --- examples/.gitignore | 4 + .../vulkan_example/vulkan_example.vcxproj | 172 ++++++++++++++++++ .../vulkan_example.vcxproj.filters | 49 +++++ 3 files changed, 225 insertions(+) create mode 100644 examples/vulkan_example/vulkan_example.vcxproj create mode 100644 examples/vulkan_example/vulkan_example.vcxproj.filters diff --git a/examples/.gitignore b/examples/.gitignore index 127854990063..7a6e9f4f35aa 100644 --- a/examples/.gitignore +++ b/examples/.gitignore @@ -33,6 +33,10 @@ sdl_opengl3_example/Debug/* sdl_opengl3_example/Release/* sdl_opengl3_example/ipch/* sdl_opengl3_example/x64/* +vulkan_example/Debug/* +vulkan_example/Release/* +vulkan_example/ipch/* +vulkan_example/x64/* *.opensdf *.sdf *.suo diff --git a/examples/vulkan_example/vulkan_example.vcxproj b/examples/vulkan_example/vulkan_example.vcxproj new file mode 100644 index 000000000000..a315d69ea27e --- /dev/null +++ b/examples/vulkan_example/vulkan_example.vcxproj @@ -0,0 +1,172 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + {57E2DF5A-6FC8-45BB-99DD-91A18C646E80} + opengl3_example + + + + Application + true + MultiByte + + + Application + true + MultiByte + + + Application + false + true + MultiByte + + + Application + false + true + MultiByte + + + + + + + + + + + + + + + + + + + $(ProjectDir)$(Configuration)\ + $(ProjectDir)$(Configuration)\ + $(IncludePath) + + + $(ProjectDir)$(Configuration)\ + $(ProjectDir)$(Configuration)\ + $(IncludePath) + + + $(ProjectDir)$(Configuration)\ + $(ProjectDir)$(Configuration)\ + $(IncludePath) + + + $(ProjectDir)$(Configuration)\ + $(ProjectDir)$(Configuration)\ + $(IncludePath) + + + + Level4 + Disabled + %VULKAN_SDK%\include;$(SolutionDir)\libs\glfw\include;..\..;%(AdditionalIncludeDirectories) + + + true + %VULKAN_SDK%\lib32;$(SolutionDir)\libs\glfw\lib-vc2010-32;%(AdditionalLibraryDirectories) + vulkan-1.lib;glfw3.lib;%(AdditionalDependencies) + Console + msvcrt.lib + + + + + Level4 + Disabled + %VULKAN_SDK%\include;$(SolutionDir)\libs\glfw\include;..\..;%(AdditionalIncludeDirectories) + + + true + %VULKAN_SDK%\lib;$(SolutionDir)\libs\glfw\lib-vc2010-64;%(AdditionalLibraryDirectories) + vulkan-1.lib;glfw3.lib;%(AdditionalDependencies) + Console + msvcrt.lib + + + + + Level4 + MaxSpeed + true + true + %VULKAN_SDK%\include;$(SolutionDir)\libs\glfw\include;..\..;%(AdditionalIncludeDirectories) + false + + + true + true + true + %VULKAN_SDK%\lib32;$(SolutionDir)\libs\glfw\lib-vc2010-32;%(AdditionalLibraryDirectories) + vulkan-1.lib;glfw3.lib;%(AdditionalDependencies) + Console + + + + + + + Level4 + MaxSpeed + true + true + %VULKAN_SDK%\include;$(SolutionDir)\libs\glfw\include;..\..;%(AdditionalIncludeDirectories) + false + + + true + true + true + %VULKAN_SDK%\lib;$(SolutionDir)\libs\glfw\lib-vc2010-64;%(AdditionalLibraryDirectories) + vulkan-1.lib;glfw3.lib;%(AdditionalDependencies) + Console + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/examples/vulkan_example/vulkan_example.vcxproj.filters b/examples/vulkan_example/vulkan_example.vcxproj.filters new file mode 100644 index 000000000000..f3ed8ede4db6 --- /dev/null +++ b/examples/vulkan_example/vulkan_example.vcxproj.filters @@ -0,0 +1,49 @@ + + + + + {20b90ce4-7fcb-4731-b9a0-075f875de82d} + + + {f18ab499-84e1-499f-8eff-9754361e0e52} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + + + imgui + + + imgui + + + imgui + + + sources + + + sources + + + + + imgui + + + imgui + + + imgui + + + sources + + + + + + sources + + + \ No newline at end of file From 243fd67b1cd4bd10c4c0f088e17072663baae316 Mon Sep 17 00:00:00 2001 From: omar Date: Fri, 16 Feb 2018 22:28:52 +0100 Subject: [PATCH 687/823] Examples: Vulkan: Fix for empty draw data (init time) + fixed warning. --- examples/vulkan_example/imgui_impl_glfw_vulkan.cpp | 2 ++ examples/vulkan_example/main.cpp | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/examples/vulkan_example/imgui_impl_glfw_vulkan.cpp b/examples/vulkan_example/imgui_impl_glfw_vulkan.cpp index 8e93e7e94c6a..31f22e8627b8 100644 --- a/examples/vulkan_example/imgui_impl_glfw_vulkan.cpp +++ b/examples/vulkan_example/imgui_impl_glfw_vulkan.cpp @@ -170,6 +170,8 @@ void ImGui_ImplGlfwVulkan_RenderDrawData(ImDrawData* draw_data) { VkResult err; ImGuiIO& io = ImGui::GetIO(); + if (draw_data->TotalVtxCount == 0) + return; // Create the Vertex Buffer: size_t vertex_size = draw_data->TotalVtxCount * sizeof(ImDrawVert); diff --git a/examples/vulkan_example/main.cpp b/examples/vulkan_example/main.cpp index 597374b5f8c3..be5fe528498f 100644 --- a/examples/vulkan_example/main.cpp +++ b/examples/vulkan_example/main.cpp @@ -507,7 +507,7 @@ static void cleanup_vulkan() static void frame_begin() { VkResult err; - while (true) + for (;;) { err = vkWaitForFences(g_Device, 1, &g_Fence[g_FrameIndex], VK_TRUE, 100); if (err == VK_SUCCESS) break; From 9e713b115f6dcc89ba088dda9af1a736f4bf1236 Mon Sep 17 00:00:00 2001 From: omar Date: Fri, 16 Feb 2018 21:46:14 +0100 Subject: [PATCH 688/823] Examples: Renamed .sln file. --- examples/{imgui_examples_msvc2010.sln => imgui_examples.sln} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename examples/{imgui_examples_msvc2010.sln => imgui_examples.sln} (100%) diff --git a/examples/imgui_examples_msvc2010.sln b/examples/imgui_examples.sln similarity index 100% rename from examples/imgui_examples_msvc2010.sln rename to examples/imgui_examples.sln From f5f3730b16e29fa3df7ad6348681263cc2450744 Mon Sep 17 00:00:00 2001 From: omar Date: Fri, 16 Feb 2018 23:19:38 +0100 Subject: [PATCH 689/823] Examples: GLFW+GL2/GL3: Added glPixelStorei() calls borrowed from SDL examples. --- examples/opengl2_example/imgui_impl_glfw_gl2.cpp | 1 + examples/opengl3_example/imgui_impl_glfw_gl3.cpp | 1 + 2 files changed, 2 insertions(+) diff --git a/examples/opengl2_example/imgui_impl_glfw_gl2.cpp b/examples/opengl2_example/imgui_impl_glfw_gl2.cpp index 2630f164cc15..d4a4357048b0 100644 --- a/examples/opengl2_example/imgui_impl_glfw_gl2.cpp +++ b/examples/opengl2_example/imgui_impl_glfw_gl2.cpp @@ -194,6 +194,7 @@ bool ImGui_ImplGlfwGL2_CreateDeviceObjects() glBindTexture(GL_TEXTURE_2D, g_FontTexture); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels); // Store our identifier diff --git a/examples/opengl3_example/imgui_impl_glfw_gl3.cpp b/examples/opengl3_example/imgui_impl_glfw_gl3.cpp index 9c82abc5c3ae..24097686238e 100644 --- a/examples/opengl3_example/imgui_impl_glfw_gl3.cpp +++ b/examples/opengl3_example/imgui_impl_glfw_gl3.cpp @@ -218,6 +218,7 @@ bool ImGui_ImplGlfwGL3_CreateFontsTexture() glBindTexture(GL_TEXTURE_2D, g_FontTexture); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels); // Store our identifier From bdb27366e750ca83b6a72b2ccc6cd8ed1023f922 Mon Sep 17 00:00:00 2001 From: omar Date: Sat, 17 Feb 2018 00:19:04 +0100 Subject: [PATCH 690/823] Nav: Tweak windowing highlighting for full viewport windows. --- imgui.cpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 3eb519582e7f..168162d175a7 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -5999,11 +5999,15 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) // Draw navigation selection/windowing rectangle border if (g.NavWindowingTarget == window) { + float rounding = ImMax(window->WindowRounding, g.Style.WindowRounding); ImRect bb = window->Rect(); bb.Expand(g.FontSize); - if (bb.Contains(viewport_rect)) - bb.Expand(-g.FontSize - 2.0f); - window->DrawList->AddRect(bb.Min, bb.Max, GetColorU32(ImGuiCol_NavWindowingHighlight, g.NavWindowingHighlightAlpha), g.Style.WindowRounding, ~0, 3.0f); + if (bb.Contains(viewport_rect)) // If a window fits the entire viewport, adjust its highlight inward + { + bb.Expand(-g.FontSize - 1.0f); + rounding = window->WindowRounding; + } + window->DrawList->AddRect(bb.Min, bb.Max, GetColorU32(ImGuiCol_NavWindowingHighlight, g.NavWindowingHighlightAlpha), rounding, ~0, 3.0f); } // Store a backup of SizeFull which we will use next frame to decide if we need scrollbars. From 1399c9c8a9cf1866bdddb8462bb50a3d4ccbfc0d Mon Sep 17 00:00:00 2001 From: omar Date: Sat, 17 Feb 2018 00:49:57 +0100 Subject: [PATCH 691/823] Merged a bunch of small inconsequential things from my work branch, to reduce the diff noise. --- imgui.cpp | 25 +++++++++++++------------ imgui.h | 10 +++++----- 2 files changed, 18 insertions(+), 17 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 168162d175a7..a2a7826dc866 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -705,13 +705,13 @@ static void SetWindowScrollY(ImGuiWindow* window, float new_scroll_y static void SetWindowPos(ImGuiWindow* window, const ImVec2& pos, ImGuiCond cond); static void SetWindowSize(ImGuiWindow* window, const ImVec2& size, ImGuiCond cond); static void SetWindowCollapsed(ImGuiWindow* window, bool collapsed, ImGuiCond cond); -static ImGuiWindow* FindHoveredWindow(ImVec2 pos); +static ImGuiWindow* FindHoveredWindow(); static ImGuiWindow* CreateNewWindow(const char* name, ImVec2 size, ImGuiWindowFlags flags); static void CheckStacksSize(ImGuiWindow* window, bool write); static ImVec2 CalcNextScrollFromScrollTargetAndClamp(ImGuiWindow* window); -static void AddDrawListToDrawData(ImVector* out_render_list, ImDrawList* draw_list); -static void AddWindowToDrawData(ImVector* out_render_list, ImGuiWindow* window); +static void AddDrawListToDrawData(ImVector* out_list, ImDrawList* draw_list); +static void AddWindowToDrawData(ImVector* out_list, ImGuiWindow* window); static void AddWindowToSortedBuffer(ImVector* out_sorted_windows, ImGuiWindow* window); static ImGuiWindowSettings* AddWindowSettings(const char* name); @@ -857,10 +857,10 @@ ImGuiIO::ImGuiIO() // Settings DisplaySize = ImVec2(-1.0f, -1.0f); DeltaTime = 1.0f/60.0f; + NavFlags = 0x00; IniSavingRate = 5.0f; IniFilename = "imgui.ini"; LogFilename = "imgui_log.txt"; - NavFlags = 0x00; MouseDoubleClickTime = 0.30f; MouseDoubleClickMaxDist = 6.0f; for (int i = 0; i < ImGuiKey_COUNT; i++) @@ -2664,7 +2664,8 @@ ImGuiStyle& ImGui::GetStyle() // Same value as passed to the old io.RenderDrawListsFn function. Valid after Render() and until the next call to NewFrame() ImDrawData* ImGui::GetDrawData() { - return GImGui->DrawData.Valid ? &GImGui->DrawData : NULL; + ImGuiContext& g = *GImGui; + return g.DrawData.Valid ? &g.DrawData : NULL; } float ImGui::GetTime() @@ -3415,7 +3416,7 @@ void ImGui::NewFrame() // - Child windows can extend beyond the limit of their parent so we need to derive HoveredRootWindow from HoveredWindow. // - When moving a window we can skip the search, which also conveniently bypasses the fact that window->WindowRectClipped is lagging as this point. // - We also support the moved window toggling the NoInputs flag after moving has started in order to be able to detect windows below it, which is useful for e.g. docking mechanisms. - g.HoveredWindow = (g.MovingWindow && !(g.MovingWindow->Flags & ImGuiWindowFlags_NoInputs)) ? g.MovingWindow : FindHoveredWindow(g.IO.MousePos); + g.HoveredWindow = (g.MovingWindow && !(g.MovingWindow->Flags & ImGuiWindowFlags_NoInputs)) ? g.MovingWindow : FindHoveredWindow(); g.HoveredRootWindow = g.HoveredWindow ? g.HoveredWindow->RootWindow : NULL; ImGuiWindow* modal_window = GetFrontMostModalRootWindow(); @@ -3633,6 +3634,7 @@ void ImGui::Shutdown(ImGuiContext* context) SaveIniSettingsToDisk(g.IO.IniFilename); + // Clear everything else for (int i = 0; i < g.Windows.Size; i++) IM_DELETE(g.Windows[i]); g.Windows.clear(); @@ -4445,7 +4447,7 @@ void ImGui::CalcListClipping(int items_count, float items_height, int* out_items // Find window given position, search front-to-back // FIXME: Note that we have a lag here because WindowRectClipped is updated in Begin() so windows moved by user via SetWindowPos() and not SetNextWindowPos() will have that rectangle lagging by a frame at the time FindHoveredWindow() is called, aka before the next Begin(). Moving window thankfully isn't affected. -static ImGuiWindow* FindHoveredWindow(ImVec2 pos) +static ImGuiWindow* FindHoveredWindow() { ImGuiContext& g = *GImGui; for (int i = g.Windows.Size - 1; i >= 0; i--) @@ -4458,7 +4460,7 @@ static ImGuiWindow* FindHoveredWindow(ImVec2 pos) // Using the clipped AABB, a child window will typically be clipped by its parent (not always) ImRect bb(window->WindowRectClipped.Min - g.Style.TouchExtraPadding, window->WindowRectClipped.Max + g.Style.TouchExtraPadding); - if (bb.Contains(pos)) + if (bb.Contains(g.IO.MousePos)) return window; } return NULL; @@ -6209,14 +6211,13 @@ void ImGui::End() if (window->DC.ColumnsSet != NULL) EndColumns(); - PopClipRect(); // inner window clip rectangle + PopClipRect(); // Inner window clip rectangle // Stop logging if (!(window->Flags & ImGuiWindowFlags_ChildWindow)) // FIXME: add more options for scope of logging LogFinish(); - // Pop - // NB: we don't clear 'window->RootWindow'. The pointer is allowed to live until the next call to Begin(). + // Pop from window stack g.CurrentWindowStack.pop_back(); if (window->Flags & ImGuiWindowFlags_Popup) g.CurrentPopupStack.pop_back(); @@ -13125,7 +13126,7 @@ void ImGui::ShowMetricsWindow(bool* p_open) return; } - ImDrawList* overlay_draw_list = &GImGui->OverlayDrawList; // Render additional visuals into the top-most draw list + ImDrawList* overlay_draw_list = ImGui::GetOverlayDrawList(); // Render additional visuals into the top-most draw list if (window && ImGui::IsItemHovered()) overlay_draw_list->AddRect(window->Pos, window->Pos + window->Size, IM_COL32(255, 255, 0, 255)); if (!node_open) diff --git a/imgui.h b/imgui.h index 5ab6f3327eb1..7629e06c874f 100644 --- a/imgui.h +++ b/imgui.h @@ -116,7 +116,7 @@ struct ImVec2 float x, y; ImVec2() { x = y = 0.0f; } ImVec2(float _x, float _y) { x = _x; y = _y; } - float operator[] (size_t idx) const { IM_ASSERT(idx == 0 || idx == 1); return *(&x + idx); } // We very rarely use this [] operator, thus an assert is fine. + float operator[] (size_t idx) const { IM_ASSERT(idx == 0 || idx == 1); return (&x)[idx]; } // We very rarely use this [] operator, thus an assert is fine. #ifdef IM_VEC2_CLASS_EXTRA // Define constructor and implicit cast operators in imconfig.h to convert back<>forth from your math types and ImVec2. IM_VEC2_CLASS_EXTRA #endif @@ -744,7 +744,7 @@ enum ImGuiNavInput_ ImGuiNavInput_InternalStart_ = ImGuiNavInput_KeyMenu_ }; -// [BETA] Gamepad/Keyboard directional navigation options +// [BETA] Gamepad/Keyboard directional navigation flags, stored in io.NavFlags enum ImGuiNavFlags_ { ImGuiNavFlags_EnableKeyboard = 1 << 0, // Master keyboard navigation enable flag. NewFrame() will automatically fill io.NavInputs[] based on io.KeyDown[]. @@ -953,10 +953,10 @@ struct ImGuiIO ImVec2 DisplaySize; // // Display size, in pixels. For clamping windows positions. float DeltaTime; // = 1.0f/60.0f // Time elapsed since last frame, in seconds. + ImGuiNavFlags NavFlags; // = 0x00 // See ImGuiNavFlags_. Gamepad/keyboard navigation options. float IniSavingRate; // = 5.0f // Maximum time between saving positions/sizes to .ini file, in seconds. const char* IniFilename; // = "imgui.ini" // Path to .ini file. NULL to disable .ini saving. const char* LogFilename; // = "imgui_log.txt" // Path to .log file (default parameter to ImGui::LogToFile when no file is specified). - ImGuiNavFlags NavFlags; // = 0 // See ImGuiNavFlags_. Gamepad/keyboard navigation options. float MouseDoubleClickTime; // = 0.30f // Time for a double-click, in seconds. float MouseDoubleClickMaxDist; // = 6.0f // Distance threshold to stay in to validate a double-click, in pixels. float MouseDragThreshold; // = 6.0f // Distance threshold before considering we are dragging. @@ -1005,7 +1005,7 @@ struct ImGuiIO ImVec2 MousePos; // Mouse position, in pixels. Set to ImVec2(-FLT_MAX,-FLT_MAX) if mouse is unavailable (on another screen, etc.) bool MouseDown[5]; // Mouse buttons: left, right, middle + extras. ImGui itself mostly only uses left button (BeginPopupContext** are using right button). Others buttons allows us to track if the mouse is being used by your application + available to user as a convenience via IsMouse** API. float MouseWheel; // Mouse wheel: 1 unit scrolls about 5 lines text. - float MouseWheelH; // Mouse wheel (Horizontal). Most users don't have a mouse with an horizontal wheel, may not be filled by all back ends. + float MouseWheelH; // Mouse wheel (Horizontal). Most users don't have a mouse with an horizontal wheel, may not be filled by all back-ends. bool MouseDrawCursor; // Request ImGui to draw a mouse cursor for you (if you are on a platform without a mouse cursor). bool KeyCtrl; // Keyboard modifier pressed: Control bool KeyShift; // Keyboard modifier pressed: Shift @@ -1151,7 +1151,7 @@ class ImVector inline void pop_back() { IM_ASSERT(Size > 0); Size--; } inline void push_front(const value_type& v) { if (Size == 0) push_back(v); else insert(Data, v); } - inline iterator erase(const_iterator it) { IM_ASSERT(it >= Data && it < Data+Size); const ptrdiff_t off = it - Data; memmove(Data + off, Data + off + 1, ((size_t)Size - (size_t)off - 1) * sizeof(value_type)); Size--; return Data + off; } + inline iterator erase(const_iterator it) { IM_ASSERT(it >= Data && it < Data+Size); const ptrdiff_t off = it - Data; memmove(Data + off, Data + off + 1, ((size_t)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 >= Data && it <= Data+Size); const ptrdiff_t off = it - Data; if (Size == Capacity) reserve(_grow_capacity(Size + 1)); if (off < (int)Size) memmove(Data + off + 1, Data + off, ((size_t)Size - (size_t)off) * sizeof(value_type)); Data[off] = v; Size++; return Data + off; } inline bool contains(const value_type& v) const { const T* data = Data; const T* data_end = Data + Size; while (data < data_end) if (*data++ == v) return true; return false; } }; From b33f0e215f82d3d4717b0cee797500c8e6ed1365 Mon Sep 17 00:00:00 2001 From: omar Date: Sun, 18 Feb 2018 23:25:48 +0100 Subject: [PATCH 692/823] Initialization happens during CreateContext(), which makes it easier for platform layers to interact with the context during their initialization. --- imgui.cpp | 17 +++++++++++------ imgui_internal.h | 2 ++ 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index a2a7826dc866..f50f79f5e067 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2636,6 +2636,7 @@ ImGuiContext* ImGui::CreateContext(ImFontAtlas* shared_font_atlas) ImGuiContext* ctx = IM_NEW(ImGuiContext)(shared_font_atlas); if (GImGui == NULL) SetCurrentContext(ctx); + Initialize(ctx); return ctx; } @@ -3280,6 +3281,7 @@ void ImGui::NewFrame() // Check user data // (We pass an error message in the assert expression as a trick to get it visible to programmers who are not using a debugger, as most assert handlers display their argument) + IM_ASSERT(g.Initialized); IM_ASSERT(g.IO.DeltaTime >= 0.0f && "Need a positive DeltaTime (zero is tolerated but will cause some timing issues)"); IM_ASSERT(g.IO.DisplaySize.x >= 0.0f && g.IO.DisplaySize.y >= 0.0f && "Invalid DisplaySize value"); IM_ASSERT(g.IO.Fonts->Fonts.Size > 0 && "Font Atlas not built. Did you call io.Fonts->GetTexDataAsRGBA32() / GetTexDataAsAlpha8() ?"); @@ -3294,9 +3296,13 @@ void ImGui::NewFrame() if (g.IO.NavFlags & ImGuiNavFlags_EnableKeyboard) IM_ASSERT(g.IO.KeyMap[ImGuiKey_Space] != -1 && "ImGuiKey_Space is not mapped, required for keyboard navigation."); - // Initialize on first frame - if (!g.Initialized) - Initialize(&g); + // Load settings on first frame + if (!g.SettingsLoaded) + { + IM_ASSERT(g.SettingsWindows.empty()); + LoadIniSettingsFromDisk(g.IO.IniFilename); + g.SettingsLoaded = true; + } g.Time += g.IO.DeltaTime; g.FrameCount += 1; @@ -3602,6 +3608,7 @@ static void SettingsHandlerWindow_WriteAll(ImGuiContext* imgui_ctx, ImGuiSetting void ImGui::Initialize(ImGuiContext* context) { ImGuiContext& g = *context; + IM_ASSERT(!g.Initialized && !g.SettingsLoaded); g.LogClipboard = IM_NEW(ImGuiTextBuffer)(); // Add .ini handle for ImGuiWindow type @@ -3613,9 +3620,6 @@ void ImGui::Initialize(ImGuiContext* context) ini_handler.WriteAllFn = SettingsHandlerWindow_WriteAll; g.SettingsHandlers.push_front(ini_handler); - // Load .ini file - IM_ASSERT(g.SettingsWindows.empty()); - LoadIniSettingsFromDisk(g.IO.IniFilename); g.Initialized = true; } @@ -3765,6 +3769,7 @@ static void LoadIniSettingsFromMemory(const char* buf_readonly) } } ImGui::MemFree(buf); + g.SettingsLoaded = true; } static void SaveIniSettingsToDisk(const char* ini_filename) diff --git a/imgui_internal.h b/imgui_internal.h index 168d337b96f1..77d621bb8d53 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -687,6 +687,7 @@ struct ImGuiContext ImVec2 OsImePosRequest, OsImePosSet; // Cursor position request & last passed to the OS Input Method Editor // Settings + bool SettingsLoaded; float SettingsDirtyTimer; // Save .ini Settings on disk when time reaches zero ImVector SettingsWindows; // .ini settings for ImGuiWindow ImVector SettingsHandlers; // List of .ini settings handlers @@ -789,6 +790,7 @@ struct ImGuiContext TooltipOverrideCount = 0; OsImePosRequest = OsImePosSet = ImVec2(-1.0f, -1.0f); + SettingsLoaded = false; SettingsDirtyTimer = 0.0f; LogEnabled = false; From 7ee2bc8f5eae50db1016d376e2d630a60c8ea1c9 Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 20 Feb 2018 10:24:31 +0100 Subject: [PATCH 693/823] FAQ about backslashes in string literal since the one in main.cpp isn't being noticed enough. (#1397) --- imgui.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/imgui.cpp b/imgui.cpp index f50f79f5e067..4dd404a4638c 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -547,11 +547,15 @@ Q: How can I load a different font than the default? (default is an embedded version of ProggyClean.ttf, rendered at size 13) A: Use the font atlas to load the TTF/OTF file you want: - ImGuiIO& io = ImGui::GetIO(); io.Fonts->AddFontFromFileTTF("myfontfile.ttf", size_in_pixels); io.Fonts->GetTexDataAsRGBA32() or GetTexDataAsAlpha8() + New programmers: remember that in C/C++ and most programming languages if you want to use a backslash \ in a string literal you need to write a double backslash "\\": + io.Fonts->AddFontFromFileTTF("MyDataFolder\MyFontFile.ttf", size_in_pixels); // WRONG + io.Fonts->AddFontFromFileTTF("MyDataFolder\\MyFontFile.ttf", size_in_pixels); // CORRECT + io.Fonts->AddFontFromFileTTF("MyDataFolder/MyFontFile.ttf", size_in_pixels); // ALSO CORRECT + Q: How can I easily use icons in my application? A: The most convenient and practical way is to merge an icon font such as FontAwesome inside you main font. Then you can refer to icons within your strings. Read 'How can I load multiple fonts?' and the file 'misc/fonts/README.txt' for instructions and useful header files. From 7cbcccd96b18f3c5d4d4fe6e9570e40fb2dc3c3a Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 20 Feb 2018 12:08:37 +0100 Subject: [PATCH 694/823] Update Breaking Change section with moved misc/fonts/ (#1631) --- imgui.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/imgui.cpp b/imgui.cpp index 4dd404a4638c..d6d9f40f680d 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -257,6 +257,7 @@ - you may pass a ImFontAtlas* pointer to CreateContext() to share a font atlas between contexts. Otherwhise CreateContext() will create its own font atlas instance. - removed allocator parameters from CreateContext(), they are now setup with SetAllocatorFunctions(), and shared by all contexts. - removed the default global context and font atlas instance, which were confusing for users of DLL reloading and users of multiple contexts. + - 2018/01/31 (1.60) - moved sample TTF files from extra_fonts/ to misc/fonts/. If you loaded files directly from the imgui repo you may need to update your paths. - 2018/01/11 (1.60) - obsoleted IsAnyWindowHovered() in favor of IsWindowHovered(ImGuiHoveredFlags_AnyWindow). Kept redirection function (will obsolete). - 2018/01/11 (1.60) - obsoleted IsAnyWindowFocused() in favor of IsWindowFocused(ImGuiFocusedFlags_AnyWindow). Kept redirection function (will obsolete). - 2018/01/03 (1.60) - renamed ImGuiSizeConstraintCallback to ImGuiSizeCallback, ImGuiSizeConstraintCallbackData to ImGuiSizeCallbackData. From 7e2e0535dd4261f7a9102f9a776f0dd7a5357b45 Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 20 Feb 2018 13:55:09 +0100 Subject: [PATCH 695/823] Examples: DirectX 9,10,11: Inputs: Added support for mouse cursors (ImGui::GetMouseCursor() value and WM_SETCURSOR message handling). (#1495) --- .../directx10_example/imgui_impl_dx10.cpp | 51 +++++++++++++++++-- examples/directx10_example/main.cpp | 2 +- .../directx11_example/imgui_impl_dx11.cpp | 51 +++++++++++++++++-- examples/directx11_example/main.cpp | 2 +- examples/directx9_example/imgui_impl_dx9.cpp | 50 ++++++++++++++++-- examples/directx9_example/main.cpp | 2 +- 6 files changed, 141 insertions(+), 17 deletions(-) diff --git a/examples/directx10_example/imgui_impl_dx10.cpp b/examples/directx10_example/imgui_impl_dx10.cpp index 10da969e2c38..ed1efeef56d3 100644 --- a/examples/directx10_example/imgui_impl_dx10.cpp +++ b/examples/directx10_example/imgui_impl_dx10.cpp @@ -10,6 +10,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2018-02-20: Inputs: Added support for mouse cursors (ImGui::GetMouseCursor() value and WM_SETCURSOR message handling). // 2018-02-16: Misc: Obsoleted the io.RenderDrawListsFn callback and exposed ImGui_ImplDX10_RenderDrawData() in the .h file so you can call it yourself. // 2018-02-06: Misc: Removed call to ImGui::Shutdown() which is not available from 1.60 WIP, user needs to call CreateContext/DestroyContext themselves. // 2018-02-06: Inputs: Added mapping for ImGuiKey_Space. @@ -32,11 +33,13 @@ #define DIRECTINPUT_VERSION 0x0800 #include -// Data +// Win32 Data +static HWND g_hWnd = 0; static INT64 g_Time = 0; static INT64 g_TicksPerSecond = 0; +static ImGuiMouseCursor g_LastMouseCursor = ImGuiMouseCursor_Count_; -static HWND g_hWnd = 0; +// DirectX data static ID3D10Device* g_pd3dDevice = NULL; static ID3D10Buffer* g_pVB = NULL; static ID3D10Buffer* g_pIB = NULL; @@ -240,6 +243,33 @@ void ImGui_ImplDX10_RenderDrawData(ImDrawData* draw_data) ctx->IASetInputLayout(old.InputLayout); if (old.InputLayout) old.InputLayout->Release(); } +static void ImGui_ImplWin32_UpdateMouseCursor() +{ + ImGuiIO& io = ImGui::GetIO(); + ImGuiMouseCursor imgui_cursor = io.MouseDrawCursor ? ImGuiMouseCursor_None : ImGui::GetMouseCursor(); + if (imgui_cursor == ImGuiMouseCursor_None) + { + // Hide OS mouse cursor if imgui is drawing it or if it wants no cursor + ::SetCursor(NULL); + } + else + { + // Hardware cursor type + LPTSTR win32_cursor = IDC_ARROW; + switch (imgui_cursor) + { + case ImGuiMouseCursor_Arrow: win32_cursor = IDC_ARROW; break; + case ImGuiMouseCursor_TextInput: win32_cursor = IDC_IBEAM; break; + case ImGuiMouseCursor_ResizeAll: win32_cursor = IDC_SIZEALL; break; + case ImGuiMouseCursor_ResizeEW: win32_cursor = IDC_SIZEWE; break; + case ImGuiMouseCursor_ResizeNS: win32_cursor = IDC_SIZENS; break; + case ImGuiMouseCursor_ResizeNESW: win32_cursor = IDC_SIZENESW; break; + case ImGuiMouseCursor_ResizeNWSE: win32_cursor = IDC_SIZENWSE; break; + } + ::SetCursor(::LoadCursor(NULL, win32_cursor)); + } +} + // Process Win32 mouse/keyboard inputs. // You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs. // - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application. @@ -306,6 +336,13 @@ IMGUI_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hwnd, UINT msg, WPARAM wPa if (wParam > 0 && wParam < 0x10000) io.AddInputCharacter((unsigned short)wParam); return 0; + case WM_SETCURSOR: + if (LOWORD(lParam) == HTCLIENT) + { + ImGui_ImplWin32_UpdateMouseCursor(); + return 1; + } + return 0; } return 0; } @@ -618,9 +655,13 @@ void ImGui_ImplDX10_NewFrame() SetCursorPos(pos.x, pos.y); } - // Hide OS mouse cursor if ImGui is drawing it - if (io.MouseDrawCursor) - SetCursor(NULL); + // Update OS mouse cursor with the cursor requested by imgui + ImGuiMouseCursor mouse_cursor = io.MouseDrawCursor ? ImGuiMouseCursor_None : ImGui::GetMouseCursor(); + if (g_LastMouseCursor != mouse_cursor) + { + g_LastMouseCursor = mouse_cursor; + ImGui_ImplWin32_UpdateMouseCursor(); + } // Start the frame. This call will update the io.WantCaptureMouse, io.WantCaptureKeyboard flag that you can use to dispatch inputs (or not) to your application. ImGui::NewFrame(); diff --git a/examples/directx10_example/main.cpp b/examples/directx10_example/main.cpp index f20f6881e0bb..4edf8be62c9e 100644 --- a/examples/directx10_example/main.cpp +++ b/examples/directx10_example/main.cpp @@ -103,7 +103,7 @@ LRESULT WINAPI WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) int main(int, char**) { // Create application window - WNDCLASSEX wc = { sizeof(WNDCLASSEX), CS_CLASSDC, WndProc, 0L, 0L, GetModuleHandle(NULL), NULL, LoadCursor(NULL, IDC_ARROW), NULL, NULL, _T("ImGui Example"), NULL }; + WNDCLASSEX wc = { sizeof(WNDCLASSEX), CS_CLASSDC, WndProc, 0L, 0L, GetModuleHandle(NULL), NULL, NULL, NULL, NULL, _T("ImGui Example"), NULL }; RegisterClassEx(&wc); HWND hwnd = CreateWindow(_T("ImGui Example"), _T("ImGui DirectX10 Example"), WS_OVERLAPPEDWINDOW, 100, 100, 1280, 800, NULL, NULL, wc.hInstance, NULL); diff --git a/examples/directx11_example/imgui_impl_dx11.cpp b/examples/directx11_example/imgui_impl_dx11.cpp index a0e9d7f3809c..84dcdbee49c1 100644 --- a/examples/directx11_example/imgui_impl_dx11.cpp +++ b/examples/directx11_example/imgui_impl_dx11.cpp @@ -10,6 +10,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2018-02-20: Inputs: Added support for mouse cursors (ImGui::GetMouseCursor() value and WM_SETCURSOR message handling). // 2018-02-16: Misc: Obsoleted the io.RenderDrawListsFn callback and exposed ImGui_ImplDX11_RenderDrawData() in the .h file so you can call it yourself. // 2018-02-06: Misc: Removed call to ImGui::Shutdown() which is not available from 1.60 WIP, user needs to call CreateContext/DestroyContext themselves. // 2018-02-06: Inputs: Added mapping for ImGuiKey_Space. @@ -31,11 +32,13 @@ #define DIRECTINPUT_VERSION 0x0800 #include -// Data +// Win32 data +static HWND g_hWnd = 0; static INT64 g_Time = 0; static INT64 g_TicksPerSecond = 0; +static ImGuiMouseCursor g_LastMouseCursor = ImGuiMouseCursor_Count_; -static HWND g_hWnd = 0; +// DirectX data static ID3D11Device* g_pd3dDevice = NULL; static ID3D11DeviceContext* g_pd3dDeviceContext = NULL; static ID3D11Buffer* g_pVB = NULL; @@ -247,6 +250,33 @@ void ImGui_ImplDX11_RenderDrawData(ImDrawData* draw_data) ctx->IASetInputLayout(old.InputLayout); if (old.InputLayout) old.InputLayout->Release(); } +static void ImGui_ImplWin32_UpdateMouseCursor() +{ + ImGuiIO& io = ImGui::GetIO(); + ImGuiMouseCursor imgui_cursor = io.MouseDrawCursor ? ImGuiMouseCursor_None : ImGui::GetMouseCursor(); + if (imgui_cursor == ImGuiMouseCursor_None) + { + // Hide OS mouse cursor if imgui is drawing it or if it wants no cursor + ::SetCursor(NULL); + } + else + { + // Hardware cursor type + LPTSTR win32_cursor = IDC_ARROW; + switch (imgui_cursor) + { + case ImGuiMouseCursor_Arrow: win32_cursor = IDC_ARROW; break; + case ImGuiMouseCursor_TextInput: win32_cursor = IDC_IBEAM; break; + case ImGuiMouseCursor_ResizeAll: win32_cursor = IDC_SIZEALL; break; + case ImGuiMouseCursor_ResizeEW: win32_cursor = IDC_SIZEWE; break; + case ImGuiMouseCursor_ResizeNS: win32_cursor = IDC_SIZENS; break; + case ImGuiMouseCursor_ResizeNESW: win32_cursor = IDC_SIZENESW; break; + case ImGuiMouseCursor_ResizeNWSE: win32_cursor = IDC_SIZENWSE; break; + } + ::SetCursor(::LoadCursor(NULL, win32_cursor)); + } +} + // Process Win32 mouse/keyboard inputs. // You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs. // - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application. @@ -313,6 +343,13 @@ IMGUI_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hwnd, UINT msg, WPARAM wPa if (wParam > 0 && wParam < 0x10000) io.AddInputCharacter((unsigned short)wParam); return 0; + case WM_SETCURSOR: + if (LOWORD(lParam) == HTCLIENT) + { + ImGui_ImplWin32_UpdateMouseCursor(); + return 1; + } + return 0; } return 0; } @@ -621,9 +658,13 @@ void ImGui_ImplDX11_NewFrame() SetCursorPos(pos.x, pos.y); } - // Hide OS mouse cursor if ImGui is drawing it - if (io.MouseDrawCursor) - SetCursor(NULL); + // Update OS mouse cursor with the cursor requested by imgui + ImGuiMouseCursor mouse_cursor = io.MouseDrawCursor ? ImGuiMouseCursor_None : ImGui::GetMouseCursor(); + if (g_LastMouseCursor != mouse_cursor) + { + g_LastMouseCursor = mouse_cursor; + ImGui_ImplWin32_UpdateMouseCursor(); + } // Start the frame. This call will update the io.WantCaptureMouse, io.WantCaptureKeyboard flag that you can use to dispatch inputs (or not) to your application. ImGui::NewFrame(); diff --git a/examples/directx11_example/main.cpp b/examples/directx11_example/main.cpp index f6dc6f74c828..2ded0a9026a2 100644 --- a/examples/directx11_example/main.cpp +++ b/examples/directx11_example/main.cpp @@ -106,7 +106,7 @@ LRESULT WINAPI WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) int main(int, char**) { // Create application window - WNDCLASSEX wc = { sizeof(WNDCLASSEX), CS_CLASSDC, WndProc, 0L, 0L, GetModuleHandle(NULL), NULL, LoadCursor(NULL, IDC_ARROW), NULL, NULL, _T("ImGui Example"), NULL }; + WNDCLASSEX wc = { sizeof(WNDCLASSEX), CS_CLASSDC, WndProc, 0L, 0L, GetModuleHandle(NULL), NULL, NULL, NULL, NULL, _T("ImGui Example"), NULL }; RegisterClassEx(&wc); HWND hwnd = CreateWindow(_T("ImGui Example"), _T("ImGui DirectX11 Example"), WS_OVERLAPPEDWINDOW, 100, 100, 1280, 800, NULL, NULL, wc.hInstance, NULL); diff --git a/examples/directx9_example/imgui_impl_dx9.cpp b/examples/directx9_example/imgui_impl_dx9.cpp index e960b7c51850..194752fb8bc7 100644 --- a/examples/directx9_example/imgui_impl_dx9.cpp +++ b/examples/directx9_example/imgui_impl_dx9.cpp @@ -10,6 +10,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2018-02-20: Inputs: Added support for mouse cursors (ImGui::GetMouseCursor() value and WM_SETCURSOR message handling). // 2018-02-16: Misc: Obsoleted the io.RenderDrawListsFn callback and exposed ImGui_ImplDX9_RenderDrawData() in the .h file so you can call it yourself. // 2018-02-06: Misc: Removed call to ImGui::Shutdown() which is not available from 1.60 WIP, user needs to call CreateContext/DestroyContext themselves. // 2018-02-06: Inputs: Added mapping for ImGuiKey_Space. @@ -22,10 +23,13 @@ #define DIRECTINPUT_VERSION 0x0800 #include -// Data +// Win32 data static HWND g_hWnd = 0; static INT64 g_Time = 0; static INT64 g_TicksPerSecond = 0; +static ImGuiMouseCursor g_LastMouseCursor = ImGuiMouseCursor_Count_; + +// DirectX data static LPDIRECT3DDEVICE9 g_pd3dDevice = NULL; static LPDIRECT3DVERTEXBUFFER9 g_pVB = NULL; static LPDIRECT3DINDEXBUFFER9 g_pIB = NULL; @@ -178,6 +182,33 @@ void ImGui_ImplDX9_RenderDrawData(ImDrawData* draw_data) d3d9_state_block->Release(); } +static void ImGui_ImplWin32_UpdateMouseCursor() +{ + ImGuiIO& io = ImGui::GetIO(); + ImGuiMouseCursor imgui_cursor = io.MouseDrawCursor ? ImGuiMouseCursor_None : ImGui::GetMouseCursor(); + if (imgui_cursor == ImGuiMouseCursor_None) + { + // Hide OS mouse cursor if imgui is drawing it or if it wants no cursor + ::SetCursor(NULL); + } + else + { + // Hardware cursor type + LPTSTR win32_cursor = IDC_ARROW; + switch (imgui_cursor) + { + case ImGuiMouseCursor_Arrow: win32_cursor = IDC_ARROW; break; + case ImGuiMouseCursor_TextInput: win32_cursor = IDC_IBEAM; break; + case ImGuiMouseCursor_ResizeAll: win32_cursor = IDC_SIZEALL; break; + case ImGuiMouseCursor_ResizeEW: win32_cursor = IDC_SIZEWE; break; + case ImGuiMouseCursor_ResizeNS: win32_cursor = IDC_SIZENS; break; + case ImGuiMouseCursor_ResizeNESW: win32_cursor = IDC_SIZENESW; break; + case ImGuiMouseCursor_ResizeNWSE: win32_cursor = IDC_SIZENWSE; break; + } + ::SetCursor(::LoadCursor(NULL, win32_cursor)); + } +} + // Process Win32 mouse/keyboard inputs. // You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs. // - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application. @@ -244,6 +275,13 @@ IMGUI_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hwnd, UINT msg, WPARAM wPa if (wParam > 0 && wParam < 0x10000) io.AddInputCharacter((unsigned short)wParam); return 0; + case WM_SETCURSOR: + if (LOWORD(lParam) == HTCLIENT) + { + ImGui_ImplWin32_UpdateMouseCursor(); + return 1; + } + return 0; } return 0; } @@ -387,9 +425,13 @@ void ImGui_ImplDX9_NewFrame() SetCursorPos(pos.x, pos.y); } - // Hide OS mouse cursor if ImGui is drawing it - if (io.MouseDrawCursor) - SetCursor(NULL); + // Update OS mouse cursor with the cursor requested by imgui + ImGuiMouseCursor mouse_cursor = io.MouseDrawCursor ? ImGuiMouseCursor_None : ImGui::GetMouseCursor(); + if (g_LastMouseCursor != mouse_cursor) + { + g_LastMouseCursor = mouse_cursor; + ImGui_ImplWin32_UpdateMouseCursor(); + } // Start the frame. This call will update the io.WantCaptureMouse, io.WantCaptureKeyboard flag that you can use to dispatch inputs (or not) to your application. ImGui::NewFrame(); diff --git a/examples/directx9_example/main.cpp b/examples/directx9_example/main.cpp index 16482b3aa8fa..f4c7a9f0c6a2 100644 --- a/examples/directx9_example/main.cpp +++ b/examples/directx9_example/main.cpp @@ -46,7 +46,7 @@ LRESULT WINAPI WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) int main(int, char**) { // Create application window - WNDCLASSEX wc = { sizeof(WNDCLASSEX), CS_CLASSDC, WndProc, 0L, 0L, GetModuleHandle(NULL), NULL, LoadCursor(NULL, IDC_ARROW), NULL, NULL, _T("ImGui Example"), NULL }; + WNDCLASSEX wc = { sizeof(WNDCLASSEX), CS_CLASSDC, WndProc, 0L, 0L, GetModuleHandle(NULL), NULL, NULL, NULL, NULL, _T("ImGui Example"), NULL }; RegisterClassEx(&wc); HWND hwnd = CreateWindow(_T("ImGui Example"), _T("ImGui DirectX9 Example"), WS_OVERLAPPEDWINDOW, 100, 100, 1280, 800, NULL, NULL, wc.hInstance, NULL); From 11b12488e87b5a57ae4541cd6aba35bc3fe38b45 Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 20 Feb 2018 14:09:46 +0100 Subject: [PATCH 696/823] Examples: GLFW*: Renamed GLFW callbacks exposed in .h to not include GL2/GL3/Vulkan in their name. --- .../opengl2_example/imgui_impl_glfw_gl2.cpp | 24 +++++++++++-------- .../opengl2_example/imgui_impl_glfw_gl2.h | 8 +++---- .../opengl3_example/imgui_impl_glfw_gl3.cpp | 24 +++++++++++-------- .../opengl3_example/imgui_impl_glfw_gl3.h | 8 +++---- .../vulkan_example/imgui_impl_glfw_vulkan.cpp | 24 +++++++++++-------- .../vulkan_example/imgui_impl_glfw_vulkan.h | 8 +++---- 6 files changed, 54 insertions(+), 42 deletions(-) diff --git a/examples/opengl2_example/imgui_impl_glfw_gl2.cpp b/examples/opengl2_example/imgui_impl_glfw_gl2.cpp index d4a4357048b0..42075e4f163d 100644 --- a/examples/opengl2_example/imgui_impl_glfw_gl2.cpp +++ b/examples/opengl2_example/imgui_impl_glfw_gl2.cpp @@ -19,6 +19,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2018-02-20: Inputs: Renamed GLFW callbacks exposed in .h to not include GL2 in their name. // 2018-02-16: Misc: Obsoleted the io.RenderDrawListsFn callback and exposed ImGui_ImplGlfwGL2_RenderDrawData() in the .h file so you can call it yourself. // 2018-02-06: Misc: Removed call to ImGui::Shutdown() which is not available from 1.60 WIP, user needs to call CreateContext/DestroyContext themselves. // 2018-02-06: Inputs: Added mapping for ImGuiKey_Space. @@ -144,20 +145,20 @@ static void ImGui_ImplGlfwGL2_SetClipboardText(void* user_data, const char* text glfwSetClipboardString((GLFWwindow*)user_data, text); } -void ImGui_ImplGlfwGL2_MouseButtonCallback(GLFWwindow*, int button, int action, int /*mods*/) +void ImGui_ImplGlfw_MouseButtonCallback(GLFWwindow*, int button, int action, int /*mods*/) { if (action == GLFW_PRESS && button >= 0 && button < 3) g_MouseJustPressed[button] = true; } -void ImGui_ImplGlfwGL2_ScrollCallback(GLFWwindow*, double xoffset, double yoffset) +void ImGui_ImplGlfw_ScrollCallback(GLFWwindow*, double xoffset, double yoffset) { ImGuiIO& io = ImGui::GetIO(); io.MouseWheelH += (float)xoffset; io.MouseWheel += (float)yoffset; } -void ImGui_ImplGlfwGL2_KeyCallback(GLFWwindow*, int key, int, int action, int mods) +void ImGui_ImplGlfw_KeyCallback(GLFWwindow*, int key, int, int action, int mods) { ImGuiIO& io = ImGui::GetIO(); if (action == GLFW_PRESS) @@ -172,7 +173,7 @@ void ImGui_ImplGlfwGL2_KeyCallback(GLFWwindow*, int key, int, int action, int mo io.KeySuper = io.KeysDown[GLFW_KEY_LEFT_SUPER] || io.KeysDown[GLFW_KEY_RIGHT_SUPER]; } -void ImGui_ImplGlfwGL2_CharCallback(GLFWwindow*, unsigned int c) +void ImGui_ImplGlfw_CharCallback(GLFWwindow*, unsigned int c) { ImGuiIO& io = ImGui::GetIO(); if (c > 0 && c < 0x10000) @@ -216,6 +217,14 @@ void ImGui_ImplGlfwGL2_InvalidateDeviceObjects() } } +static void ImGui_ImplGlfw_InstallCallbacks(GLFWwindow* window) +{ + glfwSetMouseButtonCallback(window, ImGui_ImplGlfw_MouseButtonCallback); + glfwSetScrollCallback(window, ImGui_ImplGlfw_ScrollCallback); + glfwSetKeyCallback(window, ImGui_ImplGlfw_KeyCallback); + glfwSetCharCallback(window, ImGui_ImplGlfw_CharCallback); +} + bool ImGui_ImplGlfwGL2_Init(GLFWwindow* window, bool install_callbacks) { g_Window = window; @@ -251,12 +260,7 @@ bool ImGui_ImplGlfwGL2_Init(GLFWwindow* window, bool install_callbacks) #endif if (install_callbacks) - { - glfwSetMouseButtonCallback(window, ImGui_ImplGlfwGL2_MouseButtonCallback); - glfwSetScrollCallback(window, ImGui_ImplGlfwGL2_ScrollCallback); - glfwSetKeyCallback(window, ImGui_ImplGlfwGL2_KeyCallback); - glfwSetCharCallback(window, ImGui_ImplGlfwGL2_CharCallback); - } + ImGui_ImplGlfw_InstallCallbacks(window); return true; } diff --git a/examples/opengl2_example/imgui_impl_glfw_gl2.h b/examples/opengl2_example/imgui_impl_glfw_gl2.h index 268b0e498450..4e0f393ccc04 100644 --- a/examples/opengl2_example/imgui_impl_glfw_gl2.h +++ b/examples/opengl2_example/imgui_impl_glfw_gl2.h @@ -26,7 +26,7 @@ IMGUI_API bool ImGui_ImplGlfwGL2_CreateDeviceObjects(); // GLFW callbacks (registered by default to GLFW if you enable 'install_callbacks' during initialization) // Provided here if you want to chain callbacks yourself. You may also handle inputs yourself and use those as a reference. -IMGUI_API void ImGui_ImplGlfwGL2_MouseButtonCallback(GLFWwindow* window, int button, int action, int mods); -IMGUI_API void ImGui_ImplGlfwGL2_ScrollCallback(GLFWwindow* window, double xoffset, double yoffset); -IMGUI_API void ImGui_ImplGlfwGL2_KeyCallback(GLFWwindow* window, int key, int scancode, int action, int mods); -IMGUI_API void ImGui_ImplGlfwGL2_CharCallback(GLFWwindow* window, unsigned int c); +IMGUI_API void ImGui_ImplGlfw_MouseButtonCallback(GLFWwindow* window, int button, int action, int mods); +IMGUI_API void ImGui_ImplGlfw_ScrollCallback(GLFWwindow* window, double xoffset, double yoffset); +IMGUI_API void ImGui_ImplGlfw_KeyCallback(GLFWwindow* window, int key, int scancode, int action, int mods); +IMGUI_API void ImGui_ImplGlfw_CharCallback(GLFWwindow* window, unsigned int c); diff --git a/examples/opengl3_example/imgui_impl_glfw_gl3.cpp b/examples/opengl3_example/imgui_impl_glfw_gl3.cpp index 24097686238e..16f89643a4a9 100644 --- a/examples/opengl3_example/imgui_impl_glfw_gl3.cpp +++ b/examples/opengl3_example/imgui_impl_glfw_gl3.cpp @@ -13,6 +13,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2018-02-20: Inputs: Renamed GLFW callbacks exposed in .h to not include GL3 in their name. // 2018-02-16: Misc: Obsoleted the io.RenderDrawListsFn callback and exposed ImGui_ImplGlfwGL3_RenderDrawData() in the .h file so you can call it yourself. // 2018-02-06: Misc: Removed call to ImGui::Shutdown() which is not available from 1.60 WIP, user needs to call CreateContext/DestroyContext themselves. // 2018-02-06: Inputs: Added mapping for ImGuiKey_Space. @@ -168,20 +169,20 @@ static void ImGui_ImplGlfwGL3_SetClipboardText(void* user_data, const char* text glfwSetClipboardString((GLFWwindow*)user_data, text); } -void ImGui_ImplGlfwGL3_MouseButtonCallback(GLFWwindow*, int button, int action, int /*mods*/) +void ImGui_ImplGlfw_MouseButtonCallback(GLFWwindow*, int button, int action, int /*mods*/) { if (action == GLFW_PRESS && button >= 0 && button < 3) g_MouseJustPressed[button] = true; } -void ImGui_ImplGlfwGL3_ScrollCallback(GLFWwindow*, double xoffset, double yoffset) +void ImGui_ImplGlfw_ScrollCallback(GLFWwindow*, double xoffset, double yoffset) { ImGuiIO& io = ImGui::GetIO(); io.MouseWheelH += (float)xoffset; io.MouseWheel += (float)yoffset; } -void ImGui_ImplGlfwGL3_KeyCallback(GLFWwindow*, int key, int, int action, int mods) +void ImGui_ImplGlfw_KeyCallback(GLFWwindow*, int key, int, int action, int mods) { ImGuiIO& io = ImGui::GetIO(); if (action == GLFW_PRESS) @@ -196,7 +197,7 @@ void ImGui_ImplGlfwGL3_KeyCallback(GLFWwindow*, int key, int, int action, int mo io.KeySuper = io.KeysDown[GLFW_KEY_LEFT_SUPER] || io.KeysDown[GLFW_KEY_RIGHT_SUPER]; } -void ImGui_ImplGlfwGL3_CharCallback(GLFWwindow*, unsigned int c) +void ImGui_ImplGlfw_CharCallback(GLFWwindow*, unsigned int c) { ImGuiIO& io = ImGui::GetIO(); if (c > 0 && c < 0x10000) @@ -331,6 +332,14 @@ void ImGui_ImplGlfwGL3_InvalidateDeviceObjects() } } +static void ImGui_ImplGlfw_InstallCallbacks(GLFWwindow* window) +{ + glfwSetMouseButtonCallback(window, ImGui_ImplGlfw_MouseButtonCallback); + glfwSetScrollCallback(window, ImGui_ImplGlfw_ScrollCallback); + glfwSetKeyCallback(window, ImGui_ImplGlfw_KeyCallback); + glfwSetCharCallback(window, ImGui_ImplGlfw_CharCallback); +} + bool ImGui_ImplGlfwGL3_Init(GLFWwindow* window, bool install_callbacks) { g_Window = window; @@ -366,12 +375,7 @@ bool ImGui_ImplGlfwGL3_Init(GLFWwindow* window, bool install_callbacks) #endif if (install_callbacks) - { - glfwSetMouseButtonCallback(window, ImGui_ImplGlfwGL3_MouseButtonCallback); - glfwSetScrollCallback(window, ImGui_ImplGlfwGL3_ScrollCallback); - glfwSetKeyCallback(window, ImGui_ImplGlfwGL3_KeyCallback); - glfwSetCharCallback(window, ImGui_ImplGlfwGL3_CharCallback); - } + ImGui_ImplGlfw_InstallCallbacks(window); return true; } diff --git a/examples/opengl3_example/imgui_impl_glfw_gl3.h b/examples/opengl3_example/imgui_impl_glfw_gl3.h index 0e039d8d0b78..71ea4122c8ab 100644 --- a/examples/opengl3_example/imgui_impl_glfw_gl3.h +++ b/examples/opengl3_example/imgui_impl_glfw_gl3.h @@ -25,7 +25,7 @@ IMGUI_API bool ImGui_ImplGlfwGL3_CreateDeviceObjects(); // GLFW callbacks (installed by default if you enable 'install_callbacks' during initialization) // Provided here if you want to chain callbacks. // You can also handle inputs yourself and use those as a reference. -IMGUI_API void ImGui_ImplGlfwGL3_MouseButtonCallback(GLFWwindow* window, int button, int action, int mods); -IMGUI_API void ImGui_ImplGlfwGL3_ScrollCallback(GLFWwindow* window, double xoffset, double yoffset); -IMGUI_API void ImGui_ImplGlfwGL3_KeyCallback(GLFWwindow* window, int key, int scancode, int action, int mods); -IMGUI_API void ImGui_ImplGlfwGL3_CharCallback(GLFWwindow* window, unsigned int c); +IMGUI_API void ImGui_ImplGlfw_MouseButtonCallback(GLFWwindow* window, int button, int action, int mods); +IMGUI_API void ImGui_ImplGlfw_ScrollCallback(GLFWwindow* window, double xoffset, double yoffset); +IMGUI_API void ImGui_ImplGlfw_KeyCallback(GLFWwindow* window, int key, int scancode, int action, int mods); +IMGUI_API void ImGui_ImplGlfw_CharCallback(GLFWwindow* window, unsigned int c); diff --git a/examples/vulkan_example/imgui_impl_glfw_vulkan.cpp b/examples/vulkan_example/imgui_impl_glfw_vulkan.cpp index 31f22e8627b8..3b3a1f025243 100644 --- a/examples/vulkan_example/imgui_impl_glfw_vulkan.cpp +++ b/examples/vulkan_example/imgui_impl_glfw_vulkan.cpp @@ -10,6 +10,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2018-02-20: Inputs: Renamed GLFW callbacks exposed in .h to not include Vulkan in their name. // 2018-02-16: Misc: Obsoleted the io.RenderDrawListsFn callback, ImGui_ImplGlfwVulkan_Render() calls ImGui_ImplGlfwVulkan_RenderDrawData() itself. // 2018-02-06: Misc: Removed call to ImGui::Shutdown() which is not available from 1.60 WIP, user needs to call CreateContext/DestroyContext themselves. // 2018-02-06: Inputs: Added mapping for ImGuiKey_Space. @@ -340,20 +341,20 @@ static void ImGui_ImplGlfwVulkan_SetClipboardText(void* user_data, const char* t glfwSetClipboardString((GLFWwindow*)user_data, text); } -void ImGui_ImplGlfwVulkan_MouseButtonCallback(GLFWwindow*, int button, int action, int /*mods*/) +void ImGui_ImplGlfw_MouseButtonCallback(GLFWwindow*, int button, int action, int /*mods*/) { if (action == GLFW_PRESS && button >= 0 && button < 3) g_MouseJustPressed[button] = true; } -void ImGui_ImplGlfwVulkan_ScrollCallback(GLFWwindow*, double xoffset, double yoffset) +void ImGui_ImplGlfw_ScrollCallback(GLFWwindow*, double xoffset, double yoffset) { ImGuiIO& io = ImGui::GetIO(); io.MouseWheelH += (float)xoffset; io.MouseWheel += (float)yoffset; } -void ImGui_ImplGlfwVulkan_KeyCallback(GLFWwindow*, int key, int, int action, int mods) +void ImGui_ImplGlfw_KeyCallback(GLFWwindow*, int key, int, int action, int mods) { ImGuiIO& io = ImGui::GetIO(); if (action == GLFW_PRESS) @@ -368,7 +369,7 @@ void ImGui_ImplGlfwVulkan_KeyCallback(GLFWwindow*, int key, int, int action, int io.KeySuper = io.KeysDown[GLFW_KEY_LEFT_SUPER] || io.KeysDown[GLFW_KEY_RIGHT_SUPER]; } -void ImGui_ImplGlfwVulkan_CharCallback(GLFWwindow*, unsigned int c) +void ImGui_ImplGlfw_CharCallback(GLFWwindow*, unsigned int c) { ImGuiIO& io = ImGui::GetIO(); if (c > 0 && c < 0x10000) @@ -746,6 +747,14 @@ void ImGui_ImplGlfwVulkan_InvalidateDeviceObjects() if (g_Pipeline) { vkDestroyPipeline(g_Device, g_Pipeline, g_Allocator); g_Pipeline = VK_NULL_HANDLE; } } +static void ImGui_ImplGlfw_InstallCallbacks(GLFWwindow* window) +{ + glfwSetMouseButtonCallback(window, ImGui_ImplGlfw_MouseButtonCallback); + glfwSetScrollCallback(window, ImGui_ImplGlfw_ScrollCallback); + glfwSetKeyCallback(window, ImGui_ImplGlfw_KeyCallback); + glfwSetCharCallback(window, ImGui_ImplGlfw_CharCallback); +} + bool ImGui_ImplGlfwVulkan_Init(GLFWwindow* window, bool install_callbacks, ImGui_ImplGlfwVulkan_Init_Data *init_data) { g_Allocator = init_data->allocator; @@ -789,12 +798,7 @@ bool ImGui_ImplGlfwVulkan_Init(GLFWwindow* window, bool install_callbacks, Im #endif if (install_callbacks) - { - glfwSetMouseButtonCallback(window, ImGui_ImplGlfwVulkan_MouseButtonCallback); - glfwSetScrollCallback(window, ImGui_ImplGlfwVulkan_ScrollCallback); - glfwSetKeyCallback(window, ImGui_ImplGlfwVulkan_KeyCallback); - glfwSetCharCallback(window, ImGui_ImplGlfwVulkan_CharCallback); - } + ImGui_ImplGlfw_InstallCallbacks(window); ImGui_ImplGlfwVulkan_CreateDeviceObjects(); diff --git a/examples/vulkan_example/imgui_impl_glfw_vulkan.h b/examples/vulkan_example/imgui_impl_glfw_vulkan.h index 54918d34a69b..5d2b63cc180d 100644 --- a/examples/vulkan_example/imgui_impl_glfw_vulkan.h +++ b/examples/vulkan_example/imgui_impl_glfw_vulkan.h @@ -39,8 +39,8 @@ IMGUI_API bool ImGui_ImplGlfwVulkan_CreateDeviceObjects(); // GLFW callbacks (installed by default if you enable 'install_callbacks' during initialization) // Provided here if you want to chain callbacks. // You can also handle inputs yourself and use those as a reference. -IMGUI_API void ImGui_ImplGlfwVulkan_MouseButtonCallback(GLFWwindow* window, int button, int action, int mods); -IMGUI_API void ImGui_ImplGlfwVulkan_ScrollCallback(GLFWwindow* window, double xoffset, double yoffset); -IMGUI_API void ImGui_ImplGlfwVulkan_KeyCallback(GLFWwindow* window, int key, int scancode, int action, int mods); -IMGUI_API void ImGui_ImplGlfwVulkan_CharCallback(GLFWwindow* window, unsigned int c); +IMGUI_API void ImGui_ImplGlfw_MouseButtonCallback(GLFWwindow* window, int button, int action, int mods); +IMGUI_API void ImGui_ImplGlfw_ScrollCallback(GLFWwindow* window, double xoffset, double yoffset); +IMGUI_API void ImGui_ImplGlfw_KeyCallback(GLFWwindow* window, int key, int scancode, int action, int mods); +IMGUI_API void ImGui_ImplGlfw_CharCallback(GLFWwindow* window, unsigned int c); From d5342076220f2f4f270c1fdcb41b82d39fad25e4 Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 20 Feb 2018 14:18:02 +0100 Subject: [PATCH 697/823] Examples: GLFW: Added support for mouse cursors (ImGui::GetMouseCursor() value and WM_SETCURSOR message handling). (#1495) --- .../opengl2_example/imgui_impl_glfw_gl2.cpp | 35 +++++++++++++++++-- .../opengl3_example/imgui_impl_glfw_gl3.cpp | 35 +++++++++++++++++-- .../vulkan_example/imgui_impl_glfw_vulkan.cpp | 35 ++++++++++++++++--- 3 files changed, 95 insertions(+), 10 deletions(-) diff --git a/examples/opengl2_example/imgui_impl_glfw_gl2.cpp b/examples/opengl2_example/imgui_impl_glfw_gl2.cpp index 42075e4f163d..19b2cdc329fa 100644 --- a/examples/opengl2_example/imgui_impl_glfw_gl2.cpp +++ b/examples/opengl2_example/imgui_impl_glfw_gl2.cpp @@ -19,6 +19,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2018-02-20: Inputs: Added support for mouse cursors (ImGui::GetMouseCursor() value and WM_SETCURSOR message handling). // 2018-02-20: Inputs: Renamed GLFW callbacks exposed in .h to not include GL2 in their name. // 2018-02-16: Misc: Obsoleted the io.RenderDrawListsFn callback and exposed ImGui_ImplGlfwGL2_RenderDrawData() in the .h file so you can call it yourself. // 2018-02-06: Misc: Removed call to ImGui::Shutdown() which is not available from 1.60 WIP, user needs to call CreateContext/DestroyContext themselves. @@ -45,10 +46,13 @@ #include #endif -// Data +// GLFW data static GLFWwindow* g_Window = NULL; static double g_Time = 0.0f; static bool g_MouseJustPressed[3] = { false, false, false }; +static GLFWcursor* g_MouseCursors[ImGuiMouseCursor_Count_] = { 0 }; + +// OpenGL data static GLuint g_FontTexture = 0; // OpenGL2 Render function. @@ -259,6 +263,16 @@ bool ImGui_ImplGlfwGL2_Init(GLFWwindow* window, bool install_callbacks) io.ImeWindowHandle = glfwGetWin32Window(g_Window); #endif + // Load cursors + // FIXME: GLFW doesn't expose suitable cursors for ResizeAll, ResizeNESW, ResizeNWSE. We revert to arrow cursor for those. + g_MouseCursors[ImGuiMouseCursor_Arrow] = glfwCreateStandardCursor(GLFW_ARROW_CURSOR); + g_MouseCursors[ImGuiMouseCursor_TextInput] = glfwCreateStandardCursor(GLFW_IBEAM_CURSOR); + g_MouseCursors[ImGuiMouseCursor_ResizeAll] = glfwCreateStandardCursor(GLFW_ARROW_CURSOR); + g_MouseCursors[ImGuiMouseCursor_ResizeNS] = glfwCreateStandardCursor(GLFW_VRESIZE_CURSOR); + g_MouseCursors[ImGuiMouseCursor_ResizeEW] = glfwCreateStandardCursor(GLFW_HRESIZE_CURSOR); + g_MouseCursors[ImGuiMouseCursor_ResizeNESW] = glfwCreateStandardCursor(GLFW_ARROW_CURSOR); + g_MouseCursors[ImGuiMouseCursor_ResizeNWSE] = glfwCreateStandardCursor(GLFW_ARROW_CURSOR); + if (install_callbacks) ImGui_ImplGlfw_InstallCallbacks(window); @@ -267,6 +281,12 @@ bool ImGui_ImplGlfwGL2_Init(GLFWwindow* window, bool install_callbacks) void ImGui_ImplGlfwGL2_Shutdown() { + // Destroy GLFW mouse cursors + for (ImGuiMouseCursor cursor_n = 0; cursor_n < ImGuiMouseCursor_Count_; cursor_n++) + glfwDestroyCursor(g_MouseCursors[cursor_n]); + memset(g_MouseCursors, 0, sizeof(g_MouseCursors)); + + // Destroy OpenGL objects ImGui_ImplGlfwGL2_InvalidateDeviceObjects(); } @@ -317,8 +337,17 @@ void ImGui_ImplGlfwGL2_NewFrame() g_MouseJustPressed[i] = false; } - // Hide OS mouse cursor if ImGui is drawing it - glfwSetInputMode(g_Window, GLFW_CURSOR, io.MouseDrawCursor ? GLFW_CURSOR_HIDDEN : GLFW_CURSOR_NORMAL); + // Update mouse cursor + ImGuiMouseCursor cursor = ImGui::GetMouseCursor(); + if (io.MouseDrawCursor || cursor == ImGuiMouseCursor_None) + { + glfwSetInputMode(g_Window, GLFW_CURSOR, GLFW_CURSOR_HIDDEN); + } + else + { + glfwSetInputMode(g_Window, GLFW_CURSOR, GLFW_CURSOR_NORMAL); + glfwSetCursor(g_Window, g_MouseCursors[cursor] ? g_MouseCursors[cursor] : g_MouseCursors[ImGuiMouseCursor_Arrow]); + } // Start the frame. This call will update the io.WantCaptureMouse, io.WantCaptureKeyboard flag that you can use to dispatch inputs (or not) to your application. ImGui::NewFrame(); diff --git a/examples/opengl3_example/imgui_impl_glfw_gl3.cpp b/examples/opengl3_example/imgui_impl_glfw_gl3.cpp index 16f89643a4a9..65356846855b 100644 --- a/examples/opengl3_example/imgui_impl_glfw_gl3.cpp +++ b/examples/opengl3_example/imgui_impl_glfw_gl3.cpp @@ -13,6 +13,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2018-02-20: Inputs: Added support for mouse cursors (ImGui::GetMouseCursor() value and WM_SETCURSOR message handling). // 2018-02-20: Inputs: Renamed GLFW callbacks exposed in .h to not include GL3 in their name. // 2018-02-16: Misc: Obsoleted the io.RenderDrawListsFn callback and exposed ImGui_ImplGlfwGL3_RenderDrawData() in the .h file so you can call it yourself. // 2018-02-06: Misc: Removed call to ImGui::Shutdown() which is not available from 1.60 WIP, user needs to call CreateContext/DestroyContext themselves. @@ -42,10 +43,13 @@ #include #endif -// Data +// GLFW data static GLFWwindow* g_Window = NULL; static double g_Time = 0.0f; static bool g_MouseJustPressed[3] = { false, false, false }; +static GLFWcursor* g_MouseCursors[ImGuiMouseCursor_Count_] = { 0 }; + +// OpenGL3 data static GLuint g_FontTexture = 0; static int g_ShaderHandle = 0, g_VertHandle = 0, g_FragHandle = 0; static int g_AttribLocationTex = 0, g_AttribLocationProjMtx = 0; @@ -374,6 +378,16 @@ bool ImGui_ImplGlfwGL3_Init(GLFWwindow* window, bool install_callbacks) io.ImeWindowHandle = glfwGetWin32Window(g_Window); #endif + // Load cursors + // FIXME: GLFW doesn't expose suitable cursors for ResizeAll, ResizeNESW, ResizeNWSE. We revert to arrow cursor for those. + g_MouseCursors[ImGuiMouseCursor_Arrow] = glfwCreateStandardCursor(GLFW_ARROW_CURSOR); + g_MouseCursors[ImGuiMouseCursor_TextInput] = glfwCreateStandardCursor(GLFW_IBEAM_CURSOR); + g_MouseCursors[ImGuiMouseCursor_ResizeAll] = glfwCreateStandardCursor(GLFW_ARROW_CURSOR); + g_MouseCursors[ImGuiMouseCursor_ResizeNS] = glfwCreateStandardCursor(GLFW_VRESIZE_CURSOR); + g_MouseCursors[ImGuiMouseCursor_ResizeEW] = glfwCreateStandardCursor(GLFW_HRESIZE_CURSOR); + g_MouseCursors[ImGuiMouseCursor_ResizeNESW] = glfwCreateStandardCursor(GLFW_ARROW_CURSOR); + g_MouseCursors[ImGuiMouseCursor_ResizeNWSE] = glfwCreateStandardCursor(GLFW_ARROW_CURSOR); + if (install_callbacks) ImGui_ImplGlfw_InstallCallbacks(window); @@ -382,6 +396,12 @@ bool ImGui_ImplGlfwGL3_Init(GLFWwindow* window, bool install_callbacks) void ImGui_ImplGlfwGL3_Shutdown() { + // Destroy GLFW mouse cursors + for (ImGuiMouseCursor cursor_n = 0; cursor_n < ImGuiMouseCursor_Count_; cursor_n++) + glfwDestroyCursor(g_MouseCursors[cursor_n]); + memset(g_MouseCursors, 0, sizeof(g_MouseCursors)); + + // Destroy OpenGL objects ImGui_ImplGlfwGL3_InvalidateDeviceObjects(); } @@ -432,8 +452,17 @@ void ImGui_ImplGlfwGL3_NewFrame() g_MouseJustPressed[i] = false; } - // Hide OS mouse cursor if ImGui is drawing it - glfwSetInputMode(g_Window, GLFW_CURSOR, io.MouseDrawCursor ? GLFW_CURSOR_HIDDEN : GLFW_CURSOR_NORMAL); + // Update mouse cursor + ImGuiMouseCursor cursor = ImGui::GetMouseCursor(); + if (io.MouseDrawCursor || cursor == ImGuiMouseCursor_None) + { + glfwSetInputMode(g_Window, GLFW_CURSOR, GLFW_CURSOR_HIDDEN); + } + else + { + glfwSetInputMode(g_Window, GLFW_CURSOR, GLFW_CURSOR_NORMAL); + glfwSetCursor(g_Window, g_MouseCursors[cursor] ? g_MouseCursors[cursor] : g_MouseCursors[ImGuiMouseCursor_Arrow]); + } // Gamepad navigation mapping [BETA] memset(io.NavInputs, 0, sizeof(io.NavInputs)); diff --git a/examples/vulkan_example/imgui_impl_glfw_vulkan.cpp b/examples/vulkan_example/imgui_impl_glfw_vulkan.cpp index 3b3a1f025243..a2f02b2b46bc 100644 --- a/examples/vulkan_example/imgui_impl_glfw_vulkan.cpp +++ b/examples/vulkan_example/imgui_impl_glfw_vulkan.cpp @@ -10,6 +10,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2018-02-20: Inputs: Added support for mouse cursors (ImGui::GetMouseCursor() value and WM_SETCURSOR message handling). // 2018-02-20: Inputs: Renamed GLFW callbacks exposed in .h to not include Vulkan in their name. // 2018-02-16: Misc: Obsoleted the io.RenderDrawListsFn callback, ImGui_ImplGlfwVulkan_Render() calls ImGui_ImplGlfwVulkan_RenderDrawData() itself. // 2018-02-06: Misc: Removed call to ImGui::Shutdown() which is not available from 1.60 WIP, user needs to call CreateContext/DestroyContext themselves. @@ -37,12 +38,13 @@ #include #endif -// GLFW Data +// GLFW data static GLFWwindow* g_Window = NULL; static double g_Time = 0.0f; static bool g_MouseJustPressed[3] = { false, false, false }; +static GLFWcursor* g_MouseCursors[ImGuiMouseCursor_Count_] = { 0 }; -// Vulkan Data +// Vulkan data static VkAllocationCallbacks* g_Allocator = NULL; static VkPhysicalDevice g_Gpu = VK_NULL_HANDLE; static VkDevice g_Device = VK_NULL_HANDLE; @@ -797,6 +799,16 @@ bool ImGui_ImplGlfwVulkan_Init(GLFWwindow* window, bool install_callbacks, Im io.ImeWindowHandle = glfwGetWin32Window(g_Window); #endif + // Load cursors + // FIXME: GLFW doesn't expose suitable cursors for ResizeAll, ResizeNESW, ResizeNWSE. We revert to arrow cursor for those. + g_MouseCursors[ImGuiMouseCursor_Arrow] = glfwCreateStandardCursor(GLFW_ARROW_CURSOR); + g_MouseCursors[ImGuiMouseCursor_TextInput] = glfwCreateStandardCursor(GLFW_IBEAM_CURSOR); + g_MouseCursors[ImGuiMouseCursor_ResizeAll] = glfwCreateStandardCursor(GLFW_ARROW_CURSOR); + g_MouseCursors[ImGuiMouseCursor_ResizeNS] = glfwCreateStandardCursor(GLFW_VRESIZE_CURSOR); + g_MouseCursors[ImGuiMouseCursor_ResizeEW] = glfwCreateStandardCursor(GLFW_HRESIZE_CURSOR); + g_MouseCursors[ImGuiMouseCursor_ResizeNESW] = glfwCreateStandardCursor(GLFW_ARROW_CURSOR); + g_MouseCursors[ImGuiMouseCursor_ResizeNWSE] = glfwCreateStandardCursor(GLFW_ARROW_CURSOR); + if (install_callbacks) ImGui_ImplGlfw_InstallCallbacks(window); @@ -807,6 +819,12 @@ bool ImGui_ImplGlfwVulkan_Init(GLFWwindow* window, bool install_callbacks, Im void ImGui_ImplGlfwVulkan_Shutdown() { + // Destroy GLFW mouse cursors + for (ImGuiMouseCursor cursor_n = 0; cursor_n < ImGuiMouseCursor_Count_; cursor_n++) + glfwDestroyCursor(g_MouseCursors[cursor_n]); + memset(g_MouseCursors, 0, sizeof(g_MouseCursors)); + + // Destroy Vulkan objects ImGui_ImplGlfwVulkan_InvalidateDeviceObjects(); } @@ -846,8 +864,17 @@ void ImGui_ImplGlfwVulkan_NewFrame() g_MouseJustPressed[i] = false; } - // Hide OS mouse cursor if ImGui is drawing it - glfwSetInputMode(g_Window, GLFW_CURSOR, io.MouseDrawCursor ? GLFW_CURSOR_HIDDEN : GLFW_CURSOR_NORMAL); + // Update mouse cursor + ImGuiMouseCursor cursor = ImGui::GetMouseCursor(); + if (io.MouseDrawCursor || cursor == ImGuiMouseCursor_None) + { + glfwSetInputMode(g_Window, GLFW_CURSOR, GLFW_CURSOR_HIDDEN); + } + else + { + glfwSetInputMode(g_Window, GLFW_CURSOR, GLFW_CURSOR_NORMAL); + glfwSetCursor(g_Window, g_MouseCursors[cursor] ? g_MouseCursors[cursor] : g_MouseCursors[ImGuiMouseCursor_Arrow]); + } // Start the frame. This call will update the io.WantCaptureMouse, io.WantCaptureKeyboard flag that you can use to dispatch inputs (or not) to your application. ImGui::NewFrame(); From daddd09cd588d828c2362172e8404e8ef16c468b Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 20 Feb 2018 14:23:22 +0100 Subject: [PATCH 698/823] Examples: Mouse cursor handling comments/tweaks to homogenize. (#1495) --- .../opengl2_example/imgui_impl_glfw_gl2.cpp | 4 +-- .../opengl3_example/imgui_impl_glfw_gl3.cpp | 4 +-- .../imgui_impl_sdl_gl2.cpp | 29 ++++++++++--------- .../imgui_impl_sdl_gl3.cpp | 29 ++++++++++--------- .../vulkan_example/imgui_impl_glfw_vulkan.cpp | 4 +-- 5 files changed, 38 insertions(+), 32 deletions(-) diff --git a/examples/opengl2_example/imgui_impl_glfw_gl2.cpp b/examples/opengl2_example/imgui_impl_glfw_gl2.cpp index 19b2cdc329fa..259e5a2aff46 100644 --- a/examples/opengl2_example/imgui_impl_glfw_gl2.cpp +++ b/examples/opengl2_example/imgui_impl_glfw_gl2.cpp @@ -337,7 +337,7 @@ void ImGui_ImplGlfwGL2_NewFrame() g_MouseJustPressed[i] = false; } - // Update mouse cursor + // Update OS/hardware mouse cursor if imgui isn't drawing a software cursor ImGuiMouseCursor cursor = ImGui::GetMouseCursor(); if (io.MouseDrawCursor || cursor == ImGuiMouseCursor_None) { @@ -345,8 +345,8 @@ void ImGui_ImplGlfwGL2_NewFrame() } else { - glfwSetInputMode(g_Window, GLFW_CURSOR, GLFW_CURSOR_NORMAL); glfwSetCursor(g_Window, g_MouseCursors[cursor] ? g_MouseCursors[cursor] : g_MouseCursors[ImGuiMouseCursor_Arrow]); + glfwSetInputMode(g_Window, GLFW_CURSOR, GLFW_CURSOR_NORMAL); } // Start the frame. This call will update the io.WantCaptureMouse, io.WantCaptureKeyboard flag that you can use to dispatch inputs (or not) to your application. diff --git a/examples/opengl3_example/imgui_impl_glfw_gl3.cpp b/examples/opengl3_example/imgui_impl_glfw_gl3.cpp index 65356846855b..84c1118bc406 100644 --- a/examples/opengl3_example/imgui_impl_glfw_gl3.cpp +++ b/examples/opengl3_example/imgui_impl_glfw_gl3.cpp @@ -452,7 +452,7 @@ void ImGui_ImplGlfwGL3_NewFrame() g_MouseJustPressed[i] = false; } - // Update mouse cursor + // Update OS/hardware mouse cursor if imgui isn't drawing a software cursor ImGuiMouseCursor cursor = ImGui::GetMouseCursor(); if (io.MouseDrawCursor || cursor == ImGuiMouseCursor_None) { @@ -460,8 +460,8 @@ void ImGui_ImplGlfwGL3_NewFrame() } else { - glfwSetInputMode(g_Window, GLFW_CURSOR, GLFW_CURSOR_NORMAL); glfwSetCursor(g_Window, g_MouseCursors[cursor] ? g_MouseCursors[cursor] : g_MouseCursors[ImGuiMouseCursor_Arrow]); + glfwSetInputMode(g_Window, GLFW_CURSOR, GLFW_CURSOR_NORMAL); } // Gamepad navigation mapping [BETA] diff --git a/examples/sdl_opengl2_example/imgui_impl_sdl_gl2.cpp b/examples/sdl_opengl2_example/imgui_impl_sdl_gl2.cpp index 769ebb9fd531..c99aaa08bfba 100644 --- a/examples/sdl_opengl2_example/imgui_impl_sdl_gl2.cpp +++ b/examples/sdl_opengl2_example/imgui_impl_sdl_gl2.cpp @@ -44,7 +44,7 @@ static Uint64 g_Time = 0; static bool g_MousePressed[3] = { false, false, false }; static GLuint g_FontTexture = 0; -static SDL_Cursor* g_SdlCursors[ImGuiMouseCursor_Count_] = { 0 }; +static SDL_Cursor* g_MouseCursors[ImGuiMouseCursor_Count_] = { 0 }; // OpenGL2 Render function. // (this used to be set in io.RenderDrawListsFn and called by ImGui::Render(), but you can now call this directly from your main loop) @@ -252,13 +252,13 @@ bool ImGui_ImplSdlGL2_Init(SDL_Window* window) io.GetClipboardTextFn = ImGui_ImplSdlGL2_GetClipboardText; io.ClipboardUserData = NULL; - g_SdlCursors[ImGuiMouseCursor_Arrow] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_ARROW); - g_SdlCursors[ImGuiMouseCursor_TextInput] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_IBEAM); - g_SdlCursors[ImGuiMouseCursor_ResizeAll] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZEALL); - g_SdlCursors[ImGuiMouseCursor_ResizeNS] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZENS); - g_SdlCursors[ImGuiMouseCursor_ResizeEW] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZEWE); - g_SdlCursors[ImGuiMouseCursor_ResizeNESW] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZENESW); - g_SdlCursors[ImGuiMouseCursor_ResizeNWSE] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZENWSE); + g_MouseCursors[ImGuiMouseCursor_Arrow] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_ARROW); + g_MouseCursors[ImGuiMouseCursor_TextInput] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_IBEAM); + g_MouseCursors[ImGuiMouseCursor_ResizeAll] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZEALL); + g_MouseCursors[ImGuiMouseCursor_ResizeNS] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZENS); + g_MouseCursors[ImGuiMouseCursor_ResizeEW] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZEWE); + g_MouseCursors[ImGuiMouseCursor_ResizeNESW] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZENESW); + g_MouseCursors[ImGuiMouseCursor_ResizeNWSE] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZENWSE); #ifdef _WIN32 SDL_SysWMinfo wmInfo; @@ -274,10 +274,13 @@ bool ImGui_ImplSdlGL2_Init(SDL_Window* window) void ImGui_ImplSdlGL2_Shutdown() { - ImGui_ImplSdlGL2_InvalidateDeviceObjects(); - + // Destroy SDL mouse cursors for (ImGuiMouseCursor cursor_n = 0; cursor_n < ImGuiMouseCursor_Count_; cursor_n++) - SDL_FreeCursor(g_SdlCursors[cursor_n]); + SDL_FreeCursor(g_MouseCursors[cursor_n]); + memset(g_MouseCursors, 0, sizeof(g_MouseCursors)); + + // Destroy OpenGL objects + ImGui_ImplSdlGL2_InvalidateDeviceObjects(); } void ImGui_ImplSdlGL2_NewFrame(SDL_Window *window) @@ -326,7 +329,7 @@ void ImGui_ImplSdlGL2_NewFrame(SDL_Window *window) io.MousePos = ImVec2((float)mx, (float)my); #endif - // Hide OS mouse cursor if ImGui is drawing it + // Update OS/hardware mouse cursor if imgui isn't drawing a software cursor ImGuiMouseCursor cursor = ImGui::GetMouseCursor(); if (io.MouseDrawCursor || cursor == ImGuiMouseCursor_None) { @@ -334,7 +337,7 @@ void ImGui_ImplSdlGL2_NewFrame(SDL_Window *window) } else { - SDL_SetCursor(g_SdlCursors[cursor]); + SDL_SetCursor(g_MouseCursors[cursor] ? g_MouseCursors[cursor] : g_MouseCursors[ImGuiMouseCursor_Arrow]); SDL_ShowCursor(1); } diff --git a/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.cpp b/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.cpp index 585439abdcc4..f9c4be03e643 100644 --- a/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.cpp +++ b/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.cpp @@ -46,7 +46,7 @@ static int g_ShaderHandle = 0, g_VertHandle = 0, g_FragHandle = 0; static int g_AttribLocationTex = 0, g_AttribLocationProjMtx = 0; static int g_AttribLocationPosition = 0, g_AttribLocationUV = 0, g_AttribLocationColor = 0; static unsigned int g_VboHandle = 0, g_VaoHandle = 0, g_ElementsHandle = 0; -static SDL_Cursor* g_SdlCursors[ImGuiMouseCursor_Count_] = { 0 }; +static SDL_Cursor* g_MouseCursors[ImGuiMouseCursor_Count_] = { 0 }; // This is the main rendering function that you have to implement and provide to ImGui (via setting up 'RenderDrawListsFn' in the ImGuiIO structure) // Note that this implementation is little overcomplicated because we are saving/setting up/restoring every OpenGL state explicitly, in order to be able to run within any OpenGL engine that doesn't do so. @@ -366,13 +366,13 @@ bool ImGui_ImplSdlGL3_Init(SDL_Window* window) io.GetClipboardTextFn = ImGui_ImplSdlGL3_GetClipboardText; io.ClipboardUserData = NULL; - g_SdlCursors[ImGuiMouseCursor_Arrow] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_ARROW); - g_SdlCursors[ImGuiMouseCursor_TextInput] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_IBEAM); - g_SdlCursors[ImGuiMouseCursor_ResizeAll] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZEALL); - g_SdlCursors[ImGuiMouseCursor_ResizeNS] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZENS); - g_SdlCursors[ImGuiMouseCursor_ResizeEW] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZEWE); - g_SdlCursors[ImGuiMouseCursor_ResizeNESW] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZENESW); - g_SdlCursors[ImGuiMouseCursor_ResizeNWSE] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZENWSE); + g_MouseCursors[ImGuiMouseCursor_Arrow] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_ARROW); + g_MouseCursors[ImGuiMouseCursor_TextInput] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_IBEAM); + g_MouseCursors[ImGuiMouseCursor_ResizeAll] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZEALL); + g_MouseCursors[ImGuiMouseCursor_ResizeNS] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZENS); + g_MouseCursors[ImGuiMouseCursor_ResizeEW] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZEWE); + g_MouseCursors[ImGuiMouseCursor_ResizeNESW] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZENESW); + g_MouseCursors[ImGuiMouseCursor_ResizeNWSE] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZENWSE); #ifdef _WIN32 SDL_SysWMinfo wmInfo; @@ -388,10 +388,13 @@ bool ImGui_ImplSdlGL3_Init(SDL_Window* window) void ImGui_ImplSdlGL3_Shutdown() { - ImGui_ImplSdlGL3_InvalidateDeviceObjects(); - + // Destroy SDL mouse cursors for (ImGuiMouseCursor cursor_n = 0; cursor_n < ImGuiMouseCursor_Count_; cursor_n++) - SDL_FreeCursor(g_SdlCursors[cursor_n]); + SDL_FreeCursor(g_MouseCursors[cursor_n]); + memset(g_MouseCursors, 0, sizeof(g_MouseCursors)); + + // Destroy OpenGL objects + ImGui_ImplSdlGL3_InvalidateDeviceObjects(); } void ImGui_ImplSdlGL3_NewFrame(SDL_Window* window) @@ -440,7 +443,7 @@ void ImGui_ImplSdlGL3_NewFrame(SDL_Window* window) io.MousePos = ImVec2((float)mx, (float)my); #endif - // Hide OS mouse cursor if ImGui is drawing it + // Update OS/hardware mouse cursor if imgui isn't drawing a software cursor ImGuiMouseCursor cursor = ImGui::GetMouseCursor(); if (io.MouseDrawCursor || cursor == ImGuiMouseCursor_None) { @@ -448,7 +451,7 @@ void ImGui_ImplSdlGL3_NewFrame(SDL_Window* window) } else { - SDL_SetCursor(g_SdlCursors[cursor]); + SDL_SetCursor(g_MouseCursors[cursor] ? g_MouseCursors[cursor] : g_MouseCursors[ImGuiMouseCursor_Arrow]); SDL_ShowCursor(1); } diff --git a/examples/vulkan_example/imgui_impl_glfw_vulkan.cpp b/examples/vulkan_example/imgui_impl_glfw_vulkan.cpp index a2f02b2b46bc..8f9fa654a04b 100644 --- a/examples/vulkan_example/imgui_impl_glfw_vulkan.cpp +++ b/examples/vulkan_example/imgui_impl_glfw_vulkan.cpp @@ -864,7 +864,7 @@ void ImGui_ImplGlfwVulkan_NewFrame() g_MouseJustPressed[i] = false; } - // Update mouse cursor + // Update OS/hardware mouse cursor if imgui isn't drawing a software cursor ImGuiMouseCursor cursor = ImGui::GetMouseCursor(); if (io.MouseDrawCursor || cursor == ImGuiMouseCursor_None) { @@ -872,8 +872,8 @@ void ImGui_ImplGlfwVulkan_NewFrame() } else { - glfwSetInputMode(g_Window, GLFW_CURSOR, GLFW_CURSOR_NORMAL); glfwSetCursor(g_Window, g_MouseCursors[cursor] ? g_MouseCursors[cursor] : g_MouseCursors[ImGuiMouseCursor_Arrow]); + glfwSetInputMode(g_Window, GLFW_CURSOR, GLFW_CURSOR_NORMAL); } // Start the frame. This call will update the io.WantCaptureMouse, io.WantCaptureKeyboard flag that you can use to dispatch inputs (or not) to your application. From 98c2ca557c78392942ab2674186ccb5062458430 Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 20 Feb 2018 14:40:12 +0100 Subject: [PATCH 699/823] Update .travis.yml PPA source for glfw in the end of getting a newer version of GLFW --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 62e27968f6f9..005b6f832789 100644 --- a/.travis.yml +++ b/.travis.yml @@ -9,7 +9,7 @@ compiler: - clang before_install: - - if [ $TRAVIS_OS_NAME == linux ]; then sudo add-apt-repository -y ppa:keithw/glfw3 && sudo apt-get update -qq && sudo apt-get install -y --no-install-recommends libglfw3-dev libxrandr-dev libxi-dev libxxf86vm-dev libsdl2-dev; fi + - if [ $TRAVIS_OS_NAME == linux ]; then sudo add-apt-repository -y ppa:pyglfw/pyglfw && sudo apt-get update -qq && sudo apt-get install -y --no-install-recommends libglfw3-dev libxrandr-dev libxi-dev libxxf86vm-dev libsdl2-dev; fi - if [ $TRAVIS_OS_NAME == osx ]; then brew update && brew install glfw3 && brew install sdl2; fi script: From 3186acdf8c104867d3e8b07ca4d8942aad695ea0 Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 20 Feb 2018 14:56:43 +0100 Subject: [PATCH 700/823] Trying to download and build GLFW since APT repository are unreliable --- .travis.yml | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 005b6f832789..517bc56e1640 100644 --- a/.travis.yml +++ b/.travis.yml @@ -9,8 +9,19 @@ compiler: - clang before_install: - - if [ $TRAVIS_OS_NAME == linux ]; then sudo add-apt-repository -y ppa:pyglfw/pyglfw && sudo apt-get update -qq && sudo apt-get install -y --no-install-recommends libglfw3-dev libxrandr-dev libxi-dev libxxf86vm-dev libsdl2-dev; fi - - if [ $TRAVIS_OS_NAME == osx ]; then brew update && brew install glfw3 && brew install sdl2; fi + - if [ $TRAVIS_OS_NAME == linux ]; then + sudo apt-get update -qq + sudo apt-get install -y --no-install-recommends libxrandr-dev libxi-dev libxxf86vm-dev libsdl2-dev + wget https://github.com/glfw/glfw/releases/download/3.2.1/glfw-3.2.1.zip + unzip glfw-3.2.1.zip && cd glfw-3.2.1; + cmake -DCMAKE_INSTALL_PREFIX=$HOME -DBUILD_SHARED_LIBS=true -DGLFW_BUILD_EXAMPLES=false -DGLFW_BUILD_TESTS=false -DGLFW_BUILD_DOCS=false .; + sudo make -j $CPU_NUM install && cd .. + fi + - if [ $TRAVIS_OS_NAME == osx ]; then + brew update + brew install glfw3 + brew install sdl2 + fi script: - make -C examples/opengl2_example From 32bbd8be96c0f9114469ab1d10103cf90bb6f49f Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 20 Feb 2018 15:07:34 +0100 Subject: [PATCH 701/823] Update .travis.yml --- .travis.yml | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/.travis.yml b/.travis.yml index 517bc56e1640..3f62b7fac5a2 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,4 +1,6 @@ language: cpp +sudo: required +dist: trusty os: - linux @@ -10,17 +12,17 @@ compiler: before_install: - if [ $TRAVIS_OS_NAME == linux ]; then - sudo apt-get update -qq - sudo apt-get install -y --no-install-recommends libxrandr-dev libxi-dev libxxf86vm-dev libsdl2-dev - wget https://github.com/glfw/glfw/releases/download/3.2.1/glfw-3.2.1.zip - unzip glfw-3.2.1.zip && cd glfw-3.2.1; + sudo apt-get update -qq; + sudo apt-get install -y --no-install-recommends libxrandr-dev libxi-dev libxxf86vm-dev libsdl2-dev; + wget https://github.com/glfw/glfw/releases/download/3.2.1/glfw-3.2.1.zip; + unzip glfw-3.2.1.zip && cd glfw-3.2.1; cmake -DCMAKE_INSTALL_PREFIX=$HOME -DBUILD_SHARED_LIBS=true -DGLFW_BUILD_EXAMPLES=false -DGLFW_BUILD_TESTS=false -DGLFW_BUILD_DOCS=false .; - sudo make -j $CPU_NUM install && cd .. + sudo make -j $CPU_NUM install && cd ..; fi - if [ $TRAVIS_OS_NAME == osx ]; then - brew update - brew install glfw3 - brew install sdl2 + brew update; + brew install glfw3; + brew install sdl2; fi script: From 201408a119e951350a6e09df52a029fdca3ff535 Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 20 Feb 2018 15:12:17 +0100 Subject: [PATCH 702/823] Update .travis.yml --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 3f62b7fac5a2..f4de9ecae3d7 100644 --- a/.travis.yml +++ b/.travis.yml @@ -16,7 +16,7 @@ before_install: sudo apt-get install -y --no-install-recommends libxrandr-dev libxi-dev libxxf86vm-dev libsdl2-dev; wget https://github.com/glfw/glfw/releases/download/3.2.1/glfw-3.2.1.zip; unzip glfw-3.2.1.zip && cd glfw-3.2.1; - cmake -DCMAKE_INSTALL_PREFIX=$HOME -DBUILD_SHARED_LIBS=true -DGLFW_BUILD_EXAMPLES=false -DGLFW_BUILD_TESTS=false -DGLFW_BUILD_DOCS=false .; + cmake -DBUILD_SHARED_LIBS=true -DGLFW_BUILD_EXAMPLES=false -DGLFW_BUILD_TESTS=false -DGLFW_BUILD_DOCS=false .; sudo make -j $CPU_NUM install && cd ..; fi - if [ $TRAVIS_OS_NAME == osx ]; then From 9c20a40b36dfdde2d26b119bd6f342d8a4372d92 Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 20 Feb 2018 15:49:17 +0100 Subject: [PATCH 703/823] Examples: OpenGL: Cast call to glPolygonMode(). (#1628). --- examples/opengl2_example/imgui_impl_glfw_gl2.cpp | 2 +- examples/opengl3_example/imgui_impl_glfw_gl3.cpp | 2 +- examples/sdl_opengl2_example/imgui_impl_sdl_gl2.cpp | 2 +- examples/sdl_opengl3_example/imgui_impl_sdl_gl3.cpp | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/examples/opengl2_example/imgui_impl_glfw_gl2.cpp b/examples/opengl2_example/imgui_impl_glfw_gl2.cpp index 259e5a2aff46..f78b77be8e80 100644 --- a/examples/opengl2_example/imgui_impl_glfw_gl2.cpp +++ b/examples/opengl2_example/imgui_impl_glfw_gl2.cpp @@ -134,7 +134,7 @@ void ImGui_ImplGlfwGL2_RenderDrawData(ImDrawData* draw_data) glMatrixMode(GL_PROJECTION); glPopMatrix(); glPopAttrib(); - glPolygonMode(GL_FRONT, last_polygon_mode[0]); glPolygonMode(GL_BACK, last_polygon_mode[1]); + glPolygonMode(GL_FRONT, (GLenum)last_polygon_mode[0]); glPolygonMode(GL_BACK, (GLenum)last_polygon_mode[1]); glViewport(last_viewport[0], last_viewport[1], (GLsizei)last_viewport[2], (GLsizei)last_viewport[3]); glScissor(last_scissor_box[0], last_scissor_box[1], (GLsizei)last_scissor_box[2], (GLsizei)last_scissor_box[3]); } diff --git a/examples/opengl3_example/imgui_impl_glfw_gl3.cpp b/examples/opengl3_example/imgui_impl_glfw_gl3.cpp index 84c1118bc406..72cc4bf6daba 100644 --- a/examples/opengl3_example/imgui_impl_glfw_gl3.cpp +++ b/examples/opengl3_example/imgui_impl_glfw_gl3.cpp @@ -158,7 +158,7 @@ void ImGui_ImplGlfwGL3_RenderDrawData(ImDrawData* draw_data) if (last_enable_cull_face) glEnable(GL_CULL_FACE); else glDisable(GL_CULL_FACE); if (last_enable_depth_test) glEnable(GL_DEPTH_TEST); else glDisable(GL_DEPTH_TEST); if (last_enable_scissor_test) glEnable(GL_SCISSOR_TEST); else glDisable(GL_SCISSOR_TEST); - glPolygonMode(GL_FRONT_AND_BACK, last_polygon_mode[0]); + glPolygonMode(GL_FRONT_AND_BACK, (GLenum)last_polygon_mode[0]); glViewport(last_viewport[0], last_viewport[1], (GLsizei)last_viewport[2], (GLsizei)last_viewport[3]); glScissor(last_scissor_box[0], last_scissor_box[1], (GLsizei)last_scissor_box[2], (GLsizei)last_scissor_box[3]); } diff --git a/examples/sdl_opengl2_example/imgui_impl_sdl_gl2.cpp b/examples/sdl_opengl2_example/imgui_impl_sdl_gl2.cpp index c99aaa08bfba..c7eeaa912b47 100644 --- a/examples/sdl_opengl2_example/imgui_impl_sdl_gl2.cpp +++ b/examples/sdl_opengl2_example/imgui_impl_sdl_gl2.cpp @@ -125,7 +125,7 @@ void ImGui_ImplSdlGL2_RenderDrawData(ImDrawData* draw_data) glMatrixMode(GL_PROJECTION); glPopMatrix(); glPopAttrib(); - glPolygonMode(GL_FRONT, last_polygon_mode[0]); glPolygonMode(GL_BACK, last_polygon_mode[1]); + glPolygonMode(GL_FRONT, (GLenum)last_polygon_mode[0]); glPolygonMode(GL_BACK, (GLenum)last_polygon_mode[1]); glViewport(last_viewport[0], last_viewport[1], (GLsizei)last_viewport[2], (GLsizei)last_viewport[3]); glScissor(last_scissor_box[0], last_scissor_box[1], (GLsizei)last_scissor_box[2], (GLsizei)last_scissor_box[3]); } diff --git a/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.cpp b/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.cpp index f9c4be03e643..4b870ade929c 100644 --- a/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.cpp +++ b/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.cpp @@ -150,7 +150,7 @@ void ImGui_ImplSdlGL3_RenderDrawData(ImDrawData* draw_data) if (last_enable_cull_face) glEnable(GL_CULL_FACE); else glDisable(GL_CULL_FACE); if (last_enable_depth_test) glEnable(GL_DEPTH_TEST); else glDisable(GL_DEPTH_TEST); if (last_enable_scissor_test) glEnable(GL_SCISSOR_TEST); else glDisable(GL_SCISSOR_TEST); - glPolygonMode(GL_FRONT_AND_BACK, last_polygon_mode[0]); + glPolygonMode(GL_FRONT_AND_BACK, (GLenum)last_polygon_mode[0]); glViewport(last_viewport[0], last_viewport[1], (GLsizei)last_viewport[2], (GLsizei)last_viewport[3]); glScissor(last_scissor_box[0], last_scissor_box[1], (GLsizei)last_scissor_box[2], (GLsizei)last_scissor_box[3]); } From 16ff9faf51b99f3e9bd862afb69cce46c0658bb9 Mon Sep 17 00:00:00 2001 From: omar Date: Wed, 21 Feb 2018 13:12:13 +0100 Subject: [PATCH 704/823] Update issue_template.md --- .github/issue_template.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/.github/issue_template.md b/.github/issue_template.md index a8745fad2731..e47ef9e892dd 100644 --- a/.github/issue_template.md +++ b/.github/issue_template.md @@ -1,2 +1,7 @@ -(Please read guidelines in https://github.com/ocornut/imgui/blob/master/.github/CONTRIBUTING.md then delete this line) +(Please carefully read guidelines in [CONTRIBUTING.md](https://github.com/ocornut/imgui/blob/master/.github/CONTRIBUTING.md) then delete this line) +You can include code this way: +```cpp +ImGui::Begin("Hello"); +ImGui::ThisIsMoreCode(); +``` From 2c3c5125b3e166dfd3d5b2ad0d4a4414e5a86df3 Mon Sep 17 00:00:00 2001 From: omar Date: Wed, 21 Feb 2018 21:33:58 +0100 Subject: [PATCH 705/823] Drag and Drop: BeginDragDropSource(): temporarily removed the optional mouse_button=0 parameter because it is really usable in typical conditions at the moment. (#143, #1637) --- imgui.cpp | 4 +++- imgui.h | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index d6d9f40f680d..c0b8b0c2de00 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -250,6 +250,7 @@ Here is a change-log of API breaking changes, if you are using one of the functions listed, expect to have to fix some code. Also read releases logs https://github.com/ocornut/imgui/releases for more details. + - 2018/02/18 (1.60) - BeginDragDropSource(): temporarily removed the optional mouse_button=0 parameter because it is really usable in typical conditions at the moment. - 2018/02/16 (1.60) - obsoleted the io.RenderDrawListsFn callback, you can call your graphics engine render function after ImGui::Render(). Use ImGui::GetDrawData() to retrieve the ImDrawData* to display. - 2018/02/07 (1.60) - reorganized context handling to be more explicit, - YOU NOW NEED TO CALL ImGui::CreateContext() AT THE BEGINNING OF YOUR APP, AND CALL ImGui::DestroyContext() AT THE END. @@ -12744,7 +12745,7 @@ void ImGui::ClearDragDrop() // Call when current ID is active. // When this returns true you need to: a) call SetDragDropPayload() exactly once, b) you may render the payload visual/description, c) call EndDragDropSource() -bool ImGui::BeginDragDropSource(ImGuiDragDropFlags flags, int mouse_button) +bool ImGui::BeginDragDropSource(ImGuiDragDropFlags flags) { ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; @@ -12752,6 +12753,7 @@ bool ImGui::BeginDragDropSource(ImGuiDragDropFlags flags, int mouse_button) bool source_drag_active = false; ImGuiID source_id = 0; ImGuiID source_parent_id = 0; + int mouse_button = 0; if (!(flags & ImGuiDragDropFlags_SourceExtern)) { source_id = window->DC.LastItemId; diff --git a/imgui.h b/imgui.h index 7629e06c874f..9b051356ff0a 100644 --- a/imgui.h +++ b/imgui.h @@ -452,7 +452,7 @@ namespace ImGui // Drag and Drop // [BETA API] Missing Demo code. API may evolve. - IMGUI_API bool BeginDragDropSource(ImGuiDragDropFlags flags = 0, int mouse_button = 0); // call when the current item is active. If this return true, you can call SetDragDropPayload() + EndDragDropSource() + IMGUI_API bool BeginDragDropSource(ImGuiDragDropFlags flags = 0); // call when the current item is active. If this return true, you can call SetDragDropPayload() + EndDragDropSource() IMGUI_API bool SetDragDropPayload(const char* type, const void* data, size_t size, ImGuiCond cond = 0);// type is a user defined string of maximum 12 characters. Strings starting with '_' are reserved for dear imgui internal types. Data is copied and held by imgui. IMGUI_API void EndDragDropSource(); // only call EndDragDropSource() if BeginDragDropSource() returns true! IMGUI_API bool BeginDragDropTarget(); // call after submitting an item that may receive an item. If this returns true, you can call AcceptDragDropPayload() + EndDragDropTarget() From 9b9d9321cf08253eae5b13d8f14d7ceb162efdf7 Mon Sep 17 00:00:00 2001 From: omar Date: Wed, 21 Feb 2018 22:46:49 +0100 Subject: [PATCH 706/823] Examples: SDL: Using %SDL2_DIR% in the .vcproj instead of %SDL_DIR%, the earlier is more standard. --- examples/sdl_opengl2_example/build_win32.bat | 2 +- .../sdl_opengl2_example.vcxproj | 16 ++++++++-------- examples/sdl_opengl3_example/build_win32.bat | 2 +- .../sdl_opengl3_example.vcxproj | 16 ++++++++-------- 4 files changed, 18 insertions(+), 18 deletions(-) diff --git a/examples/sdl_opengl2_example/build_win32.bat b/examples/sdl_opengl2_example/build_win32.bat index 799561dec6c5..6fe8cb9a7fcf 100644 --- a/examples/sdl_opengl2_example/build_win32.bat +++ b/examples/sdl_opengl2_example/build_win32.bat @@ -1,3 +1,3 @@ @REM Build for Visual Studio compiler. Run your copy of vcvars32.bat or vcvarsall.bat to setup command-line compiler. mkdir Debug -cl /nologo /Zi /MD /I ..\.. /I ..\libs\gl3w /I %SDL_DIR%\include main.cpp imgui_impl_sdl_gl2.cpp ..\..\imgui*.cpp ..\libs\gl3w\GL\gl3w.c /FeDebug/sdl_opengl2_example.exe /FoDebug/ /link /libpath:%SDL_DIR%\lib\x86 SDL2.lib SDL2main.lib opengl32.lib /subsystem:console +cl /nologo /Zi /MD /I ..\.. /I ..\libs\gl3w /I %SDL2_DIR%\include main.cpp imgui_impl_sdl_gl2.cpp ..\..\imgui*.cpp ..\libs\gl3w\GL\gl3w.c /FeDebug/sdl_opengl2_example.exe /FoDebug/ /link /libpath:%SDL2_DIR%\lib\x86 SDL2.lib SDL2main.lib opengl32.lib /subsystem:console diff --git a/examples/sdl_opengl2_example/sdl_opengl2_example.vcxproj b/examples/sdl_opengl2_example/sdl_opengl2_example.vcxproj index ad83c48150df..1f9f817748fc 100644 --- a/examples/sdl_opengl2_example/sdl_opengl2_example.vcxproj +++ b/examples/sdl_opengl2_example/sdl_opengl2_example.vcxproj @@ -85,11 +85,11 @@ Level4 Disabled - %SDL_DIR%\include;$(SolutionDir)\libs\gl3w;..\..;%(AdditionalIncludeDirectories) + %SDL2_DIR%\include;$(SolutionDir)\libs\gl3w;..\..;%(AdditionalIncludeDirectories) true - %SDL_DIR%\lib\x86;%(AdditionalLibraryDirectories) + %SDL2_DIR%\lib\x86;%(AdditionalLibraryDirectories) opengl32.lib;SDL2.lib;SDL2main.lib;%(AdditionalDependencies) Console msvcrt.lib @@ -99,11 +99,11 @@ Level4 Disabled - %SDL_DIR%\include;$(SolutionDir)\libs\gl3w;..\..;%(AdditionalIncludeDirectories) + %SDL2_DIR%\include;$(SolutionDir)\libs\gl3w;..\..;%(AdditionalIncludeDirectories) true - %SDL_DIR%\lib\x64;%(AdditionalLibraryDirectories) + %SDL2_DIR%\lib\x64;%(AdditionalLibraryDirectories) opengl32.lib;SDL2.lib;SDL2main.lib;%(AdditionalDependencies) Console msvcrt.lib @@ -115,14 +115,14 @@ MaxSpeed true true - %SDL_DIR%\include;$(SolutionDir)\libs\gl3w;..\..;%(AdditionalIncludeDirectories) + %SDL2_DIR%\include;$(SolutionDir)\libs\gl3w;..\..;%(AdditionalIncludeDirectories) false
true true true - %SDL_DIR%\lib\x86;%(AdditionalLibraryDirectories) + %SDL2_DIR%\lib\x86;%(AdditionalLibraryDirectories) opengl32.lib;SDL2.lib;SDL2main.lib;%(AdditionalDependencies) Console @@ -135,14 +135,14 @@ MaxSpeed true true - %SDL_DIR%\include;$(SolutionDir)\libs\gl3w;..\..;%(AdditionalIncludeDirectories) + %SDL2_DIR%\include;$(SolutionDir)\libs\gl3w;..\..;%(AdditionalIncludeDirectories) false
true true true - %SDL_DIR%\lib\x64;%(AdditionalLibraryDirectories) + %SDL2_DIR%\lib\x64;%(AdditionalLibraryDirectories) opengl32.lib;SDL2.lib;SDL2main.lib;%(AdditionalDependencies) Console diff --git a/examples/sdl_opengl3_example/build_win32.bat b/examples/sdl_opengl3_example/build_win32.bat index 43567542dc1d..aec9584e49df 100644 --- a/examples/sdl_opengl3_example/build_win32.bat +++ b/examples/sdl_opengl3_example/build_win32.bat @@ -1,3 +1,3 @@ @REM Build for Visual Studio compiler. Run your copy of vcvars32.bat or vcvarsall.bat to setup command-line compiler. mkdir Debug -cl /nologo /Zi /MD /I ..\.. /I ..\libs\gl3w /I %SDL_DIR%\include main.cpp imgui_impl_sdl_gl3.cpp ..\..\imgui*.cpp ..\libs\gl3w\GL\gl3w.c /FeDebug/sdl_opengl3_example.exe /FoDebug/ /link /libpath:%SDL_DIR%\lib\x86 SDL2.lib SDL2main.lib opengl32.lib /subsystem:console +cl /nologo /Zi /MD /I ..\.. /I ..\libs\gl3w /I %SDL2_DIR%\include main.cpp imgui_impl_sdl_gl3.cpp ..\..\imgui*.cpp ..\libs\gl3w\GL\gl3w.c /FeDebug/sdl_opengl3_example.exe /FoDebug/ /link /libpath:%SDL2_DIR%\lib\x86 SDL2.lib SDL2main.lib opengl32.lib /subsystem:console diff --git a/examples/sdl_opengl3_example/sdl_opengl3_example.vcxproj b/examples/sdl_opengl3_example/sdl_opengl3_example.vcxproj index 1ac4d0acc893..7bae65a8d8ce 100644 --- a/examples/sdl_opengl3_example/sdl_opengl3_example.vcxproj +++ b/examples/sdl_opengl3_example/sdl_opengl3_example.vcxproj @@ -85,11 +85,11 @@ Level4 Disabled - %SDL_DIR%\include;$(SolutionDir)\libs\gl3w;..\..;%(AdditionalIncludeDirectories) + %SDL2_DIR%\include;$(SolutionDir)\libs\gl3w;..\..;%(AdditionalIncludeDirectories) true - %SDL_DIR%\lib\x86;%(AdditionalLibraryDirectories) + %SDL2_DIR%\lib\x86;%(AdditionalLibraryDirectories) opengl32.lib;SDL2.lib;SDL2main.lib;%(AdditionalDependencies) Console msvcrt.lib @@ -99,11 +99,11 @@ Level4 Disabled - %SDL_DIR%\include;$(SolutionDir)\libs\gl3w;..\..;%(AdditionalIncludeDirectories) + %SDL2_DIR%\include;$(SolutionDir)\libs\gl3w;..\..;%(AdditionalIncludeDirectories) true - %SDL_DIR%\lib\x64;%(AdditionalLibraryDirectories) + %SDL2_DIR%\lib\x64;%(AdditionalLibraryDirectories) opengl32.lib;SDL2.lib;SDL2main.lib;%(AdditionalDependencies) Console msvcrt.lib @@ -115,14 +115,14 @@ MaxSpeed true true - %SDL_DIR%\include;$(SolutionDir)\libs\gl3w;..\..;%(AdditionalIncludeDirectories) + %SDL2_DIR%\include;$(SolutionDir)\libs\gl3w;..\..;%(AdditionalIncludeDirectories) false
true true true - %SDL_DIR%\lib\x86;%(AdditionalLibraryDirectories) + %SDL2_DIR%\lib\x86;%(AdditionalLibraryDirectories) opengl32.lib;SDL2.lib;SDL2main.lib;%(AdditionalDependencies) Console @@ -135,14 +135,14 @@ MaxSpeed true true - %SDL_DIR%\include;$(SolutionDir)\libs\gl3w;..\..;%(AdditionalIncludeDirectories) + %SDL2_DIR%\include;$(SolutionDir)\libs\gl3w;..\..;%(AdditionalIncludeDirectories) false
true true true - %SDL_DIR%\lib\x64;%(AdditionalLibraryDirectories) + %SDL2_DIR%\lib\x64;%(AdditionalLibraryDirectories) opengl32.lib;SDL2.lib;SDL2main.lib;%(AdditionalDependencies) Console From 493ec0bc9886fbe7ea2e5453408355f0cbe2a4e0 Mon Sep 17 00:00:00 2001 From: omar Date: Wed, 21 Feb 2018 23:13:53 +0100 Subject: [PATCH 707/823] Simplified .gitignore list --- examples/.gitignore | 50 ++++++++++----------------------------------- 1 file changed, 11 insertions(+), 39 deletions(-) diff --git a/examples/.gitignore b/examples/.gitignore index 7a6e9f4f35aa..ff44bccb746f 100644 --- a/examples/.gitignore +++ b/examples/.gitignore @@ -1,42 +1,8 @@ build/* -Debug/* -Release/* -ipch/* -x64/* -directx9_example/Debug/* -directx9_example/Release/* -directx9_example/ipch/* -directx9_example/x64/* -directx10_example/Debug/* -directx10_example/Release/* -directx10_example/ipch/* -directx10_example/x64/* -directx11_example/Debug/* -directx11_example/Release/* -directx11_example/ipch/* -directx11_example/x64/* -opengl2_example/Debug/* -opengl2_example/Release/* -opengl2_example/ipch/* -opengl2_example/x64/* -opengl2_example/opengl_example -opengl3_example/Debug/* -opengl3_example/Release/* -opengl3_example/ipch/* -opengl3_example/x64/* -opengl3_example/opengl3_example -sdl_opengl2_example/Debug/* -sdl_opengl2_example/Release/* -sdl_opengl2_example/ipch/* -sdl_opengl2_example/x64/* -sdl_opengl3_example/Debug/* -sdl_opengl3_example/Release/* -sdl_opengl3_example/ipch/* -sdl_opengl3_example/x64/* -vulkan_example/Debug/* -vulkan_example/Release/* -vulkan_example/ipch/* -vulkan_example/x64/* +*/Debug/* +*/Release/* +*/ipch/* +*/x64/* *.opensdf *.sdf *.suo @@ -49,5 +15,11 @@ vulkan_example/x64/* *.VC.db *.VC.VC.opendb -## Ini files +## Unix executables +opengl2_example/opengl2_example +opengl3_example/opengl3_example +sdl_opengl2_example/sdl_opengl2_example +sdl_opengl3_example/sdl_opengl3_example + +## Dear ImGui Ini files imgui.ini From f43068c5438eee187a36992cb93b96e7edd5408d Mon Sep 17 00:00:00 2001 From: omar Date: Thu, 22 Feb 2018 13:15:16 +0100 Subject: [PATCH 708/823] Examples: DirectX10, DirectX11: Simplified main example code. --- examples/directx10_example/main.cpp | 10 +--------- examples/directx11_example/main.cpp | 10 +--------- 2 files changed, 2 insertions(+), 18 deletions(-) diff --git a/examples/directx10_example/main.cpp b/examples/directx10_example/main.cpp index 4edf8be62c9e..346fd35e29e4 100644 --- a/examples/directx10_example/main.cpp +++ b/examples/directx10_example/main.cpp @@ -16,17 +16,9 @@ static ID3D10RenderTargetView* g_mainRenderTargetView = NULL; void CreateRenderTarget() { - DXGI_SWAP_CHAIN_DESC sd; - g_pSwapChain->GetDesc(&sd); - - // Create the render target ID3D10Texture2D* pBackBuffer; - D3D10_RENDER_TARGET_VIEW_DESC render_target_view_desc; - ZeroMemory(&render_target_view_desc, sizeof(render_target_view_desc)); - render_target_view_desc.Format = sd.BufferDesc.Format; - render_target_view_desc.ViewDimension = D3D10_RTV_DIMENSION_TEXTURE2D; g_pSwapChain->GetBuffer(0, __uuidof(ID3D10Texture2D), (LPVOID*)&pBackBuffer); - g_pd3dDevice->CreateRenderTargetView(pBackBuffer, &render_target_view_desc, &g_mainRenderTargetView); + g_pd3dDevice->CreateRenderTargetView(pBackBuffer, NULL, &g_mainRenderTargetView); pBackBuffer->Release(); } diff --git a/examples/directx11_example/main.cpp b/examples/directx11_example/main.cpp index 2ded0a9026a2..518aa7c27274 100644 --- a/examples/directx11_example/main.cpp +++ b/examples/directx11_example/main.cpp @@ -16,17 +16,9 @@ static ID3D11RenderTargetView* g_mainRenderTargetView = NULL; void CreateRenderTarget() { - DXGI_SWAP_CHAIN_DESC sd; - g_pSwapChain->GetDesc(&sd); - - // Create the render target ID3D11Texture2D* pBackBuffer; - D3D11_RENDER_TARGET_VIEW_DESC render_target_view_desc; - ZeroMemory(&render_target_view_desc, sizeof(render_target_view_desc)); - render_target_view_desc.Format = sd.BufferDesc.Format; - render_target_view_desc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D; g_pSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&pBackBuffer); - g_pd3dDevice->CreateRenderTargetView(pBackBuffer, &render_target_view_desc, &g_mainRenderTargetView); + g_pd3dDevice->CreateRenderTargetView(pBackBuffer, NULL, &g_mainRenderTargetView); pBackBuffer->Release(); } From b28995b66702e10c0ec369e0a3ff0426d0e9cba3 Mon Sep 17 00:00:00 2001 From: omar Date: Thu, 22 Feb 2018 15:39:49 +0100 Subject: [PATCH 709/823] Nav: Internals: Exposed NavMoveRequestCancel in imgui_internal.h (#1640) --- imgui.cpp | 4 ++-- imgui_internal.h | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index c0b8b0c2de00..7f5049a04816 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2349,7 +2349,7 @@ static bool NavMoveRequestButNoResultYet() return g.NavMoveRequest && g.NavMoveResultLocal.ID == 0 && g.NavMoveResultOther.ID == 0; } -static void NavMoveRequestCancel() +void ImGui::NavMoveRequestCancel() { ImGuiContext& g = *GImGui; g.NavMoveRequest = false; @@ -5006,7 +5006,7 @@ static void NavProcessMoveRequestWrapAround(ImGuiWindow* window) if ((g.NavMoveDir == ImGuiDir_Up || g.NavMoveDir == ImGuiDir_Down) && g.NavMoveRequestForward == ImGuiNavForward_None && g.NavLayer == 0) { g.NavMoveRequestForward = ImGuiNavForward_ForwardQueued; - NavMoveRequestCancel(); + ImGui::NavMoveRequestCancel(); g.NavWindow->NavRectRel[0].Min.y = g.NavWindow->NavRectRel[0].Max.y = ((g.NavMoveDir == ImGuiDir_Up) ? ImMax(window->SizeFull.y, window->SizeContents.y) : 0.0f) - window->Scroll.y; } } diff --git a/imgui_internal.h b/imgui_internal.h index 77d621bb8d53..c2c055504a84 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -1066,6 +1066,7 @@ namespace ImGui IMGUI_API void BeginTooltipEx(ImGuiWindowFlags extra_flags, bool override_previous_tooltip = true); IMGUI_API void NavInitWindow(ImGuiWindow* window, bool force_reinit); + IMGUI_API void NavMoveRequestCancel(); IMGUI_API void ActivateItem(ImGuiID id); // Remotely activate a button, checkbox, tree node etc. given its unique ID. activation is queued and processed on the next frame when the item is encountered again. IMGUI_API float GetNavInputAmount(ImGuiNavInput n, ImGuiInputReadMode mode); From 94466745bb6491449d4d71ca88b4bfdf823088e4 Mon Sep 17 00:00:00 2001 From: Podgorskiy Date: Wed, 21 Feb 2018 23:18:25 -0500 Subject: [PATCH 710/823] A tiny optimization to ImLineClosestPoint. Removed unnecessary sqrtf call. ab_lenSqr -> ab_len_sqr Moved line where ab_len_sqr is computed after the first return --- imgui.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index d6d9f40f680d..3451eb9faaa3 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -950,14 +950,13 @@ ImVec2 ImLineClosestPoint(const ImVec2& a, const ImVec2& b, const ImVec2& p) { ImVec2 ap = p - a; ImVec2 ab_dir = b - a; - float ab_len = sqrtf(ab_dir.x * ab_dir.x + ab_dir.y * ab_dir.y); - ab_dir *= 1.0f / ab_len; float dot = ap.x * ab_dir.x + ap.y * ab_dir.y; if (dot < 0.0f) return a; - if (dot > ab_len) + float ab_len_sqr = ab_dir.x * ab_dir.x + ab_dir.y * ab_dir.y; + if (dot > ab_len_sqr) return b; - return a + ab_dir * dot; + return a + ab_dir * dot / ab_len_sqr; } bool ImTriangleContainsPoint(const ImVec2& a, const ImVec2& b, const ImVec2& c, const ImVec2& p) From 913f3692a25e578db81d20dc6e576efe342c69ca Mon Sep 17 00:00:00 2001 From: omar Date: Thu, 22 Feb 2018 22:25:30 +0100 Subject: [PATCH 711/823] Examples: DirectX12: Removed from current solution which is meant to be VS2010 compatible for now (will change soon). --- examples/imgui_examples.sln | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/examples/imgui_examples.sln b/examples/imgui_examples.sln index 04851d7c09ca..6ae2e4f16ea8 100644 --- a/examples/imgui_examples.sln +++ b/examples/imgui_examples.sln @@ -1,14 +1,14 @@  -Microsoft Visual Studio Solution File, Format Version 11.00 -# Visual Studio 2010 +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 14 +VisualStudioVersion = 14.0.25420.1 +MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "opengl2_example", "opengl2_example\opengl2_example.vcxproj", "{9CDA7840-B7A5-496D-A527-E95571496D18}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "directx9_example", "directx9_example\directx9_example.vcxproj", "{4165A294-21F2-44CA-9B38-E3F935ABADF5}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "directx11_example", "directx11_example\directx11_example.vcxproj", "{9F316E83-5AE5-4939-A723-305A94F48005}" EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "directx12_example", "directx12_example\directx12_example.vcxproj", "{B4CF9797-519D-4AFE-A8F4-5141A6B521D3}" -EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "opengl3_example", "opengl3_example\opengl3_example.vcxproj", "{4A1FB5EA-22F5-42A8-AB92-1D2DF5D47FB9}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "directx10_example", "directx10_example\directx10_example.vcxproj", "{345A953E-A004-4648-B442-DC5F9F11068C}" @@ -45,14 +45,6 @@ Global {9F316E83-5AE5-4939-A723-305A94F48005}.Release|Win32.Build.0 = Release|Win32 {9F316E83-5AE5-4939-A723-305A94F48005}.Release|x64.ActiveCfg = Release|x64 {9F316E83-5AE5-4939-A723-305A94F48005}.Release|x64.Build.0 = Release|x64 - {B4CF9797-519D-4AFE-A8F4-5141A6B521D3}.Debug|Win32.ActiveCfg = Debug|Win32 - {B4CF9797-519D-4AFE-A8F4-5141A6B521D3}.Debug|Win32.Build.0 = Debug|Win32 - {B4CF9797-519D-4AFE-A8F4-5141A6B521D3}.Debug|x64.ActiveCfg = Debug|x64 - {B4CF9797-519D-4AFE-A8F4-5141A6B521D3}.Debug|x64.Build.0 = Debug|x64 - {B4CF9797-519D-4AFE-A8F4-5141A6B521D3}.Release|Win32.ActiveCfg = Release|Win32 - {B4CF9797-519D-4AFE-A8F4-5141A6B521D3}.Release|Win32.Build.0 = Release|Win32 - {B4CF9797-519D-4AFE-A8F4-5141A6B521D3}.Release|x64.ActiveCfg = Release|x64 - {B4CF9797-519D-4AFE-A8F4-5141A6B521D3}.Release|x64.Build.0 = Release|x64 {4A1FB5EA-22F5-42A8-AB92-1D2DF5D47FB9}.Debug|Win32.ActiveCfg = Debug|Win32 {4A1FB5EA-22F5-42A8-AB92-1D2DF5D47FB9}.Debug|Win32.Build.0 = Debug|Win32 {4A1FB5EA-22F5-42A8-AB92-1D2DF5D47FB9}.Debug|x64.ActiveCfg = Debug|x64 From 9be7d048c83c77a2c9694a899143d0f44778d799 Mon Sep 17 00:00:00 2001 From: omar Date: Thu, 22 Feb 2018 22:18:59 +0100 Subject: [PATCH 712/823] Examples: DirectX12: Merge, various styling tweaks, update for 1.60 wip, synchronized Win32 features with other examples. (#301) --- README.md | 3 +- examples/README.txt | 4 +- .../directx12_example.vcxproj | 2 +- .../directx12_example/imgui_impl_dx12.cpp | 205 ++++++++++++------ examples/directx12_example/imgui_impl_dx12.h | 29 ++- examples/directx12_example/main.cpp | 135 +++++++----- 6 files changed, 228 insertions(+), 150 deletions(-) diff --git a/README.md b/README.md index a51632c09424..51e9193a1d14 100644 --- a/README.md +++ b/README.md @@ -123,11 +123,10 @@ Languages: (third-party bindinds) - Rust: [imgui-rs](https://github.com/Gekkio/imgui-rs) Frameworks: -- DirectX 9, DirectX 10, DirectX 11: [examples/](https://github.com/ocornut/imgui/tree/master/examples) +- DirectX 9, DirectX 10, DirectX 11, DirectX 12: [examples/](https://github.com/ocornut/imgui/tree/master/examples) - OpenGL 2/3 (with GLFW or SDL): [examples/](https://github.com/ocornut/imgui/tree/master/examples) - Vulkan (with GLFW): [examples/](https://github.com/ocornut/imgui/tree/master/examples) - Allegro 5, iOS, Marmalade: [examples/](https://github.com/ocornut/imgui/tree/master/examples) -- Unmerged PR: DirectX12: [#301](https://github.com/ocornut/imgui/pull/301) - Unmerged PR: SDL2 + OpenGLES + Emscripten: [#336](https://github.com/ocornut/imgui/pull/336) - Unmerged PR: FreeGlut + OpenGL2: [#801](https://github.com/ocornut/imgui/pull/801) - Unmerged PR: Native Win32 and OSX: [#281](https://github.com/ocornut/imgui/pull/281) diff --git a/examples/README.txt b/examples/README.txt index 7c2506c26769..13660c31311e 100644 --- a/examples/README.txt +++ b/examples/README.txt @@ -4,8 +4,8 @@ Binaries of some of those demos: http://www.miracleworld.net/imgui/binaries Third party languages and frameworks bindings: https://github.com/ocornut/imgui/wiki/Links (languages: C, C#, ChaiScript, D, Go, Haxe, Odin, Python, Rust, Lua, Pascal) -(frameworks: DX12, OpenGLES, FreeGlut, Cinder, Cocos2d-x, SFML, GML/GameMaker Studio, Irrlicht, Ogre, - OpenSceneGraph, openFrameworks, LOVE, NanoRT, Qt3d, SFML, Unreal Engine 4, etc.) +(other frameworks: OpenGLES, FreeGlut, Cinder, Cocos2d-x, SFML, GML/GameMaker Studio, Irrlicht, + Ogre, OpenSceneGraph, openFrameworks, LOVE, NanoRT, Qt3d, SFML, Unreal Engine 4, etc.) (extras: RemoteImGui, ImWindow, imgui_wm, etc.) diff --git a/examples/directx12_example/directx12_example.vcxproj b/examples/directx12_example/directx12_example.vcxproj index 37b7327eccb1..d3962a31734a 100644 --- a/examples/directx12_example/directx12_example.vcxproj +++ b/examples/directx12_example/directx12_example.vcxproj @@ -21,7 +21,7 @@ {b4cf9797-519d-4afe-a8f4-5141a6b521d3} directx12_example - 10.0.10240.0 + 10.0.16299.0 diff --git a/examples/directx12_example/imgui_impl_dx12.cpp b/examples/directx12_example/imgui_impl_dx12.cpp index b0b65d7d5135..2da3624d37e6 100644 --- a/examples/directx12_example/imgui_impl_dx12.cpp +++ b/examples/directx12_example/imgui_impl_dx12.cpp @@ -1,18 +1,43 @@ // ImGui Win32 + DirectX12 binding -// In this binding, ImTextureID is used to store a 'D3D12_GPU_DESCRIPTOR_HANDLE' texture identifier. Read the FAQ about ImTextureID in imgui.cpp. +// FIXME: 64-bit only for now! (Because sizeof(ImTextureId) == sizeof(void*)) + +// Implemented features: +// [X] User texture binding. Use 'D3D12_GPU_DESCRIPTOR_HANDLE' as ImTextureID. Read the FAQ about ImTextureID in imgui.cpp. // You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this. // If you use this binding you'll need to call 4 functions: ImGui_ImplXXXX_Init(), ImGui_ImplXXXX_NewFrame(), ImGui::Render() and ImGui_ImplXXXX_Shutdown(). // If you are new to ImGui, see examples/README.txt and documentation at the top of imgui.cpp. // https://github.com/ocornut/imgui -#include +// CHANGELOG +// (minor and older changes stripped away, please see git history for details) +// 2018-02-22: Merged into master with all Win32 code synchronized to other examples. + +#include "imgui.h" #include "imgui_impl_dx12.h" // DirectX #include #include +// Win32 data +static HWND g_hWnd = 0; +static INT64 g_Time = 0; +static INT64 g_TicksPerSecond = 0; +static ImGuiMouseCursor g_LastMouseCursor = ImGuiMouseCursor_Count_; + +// DirectX data +static ID3D12Device* g_pd3dDevice = NULL; +static ID3D12GraphicsCommandList* g_pd3dCommandList = NULL; +static ID3D10Blob* g_pVertexShaderBlob = NULL; +static ID3D10Blob* g_pPixelShaderBlob = NULL; +static ID3D12RootSignature* g_pRootSignature = NULL; +static ID3D12PipelineState* g_pPipelineState = NULL; +static DXGI_FORMAT g_RTVFormat = DXGI_FORMAT_UNKNOWN; +static ID3D12Resource* g_pFontTextureResource = NULL; +static D3D12_CPU_DESCRIPTOR_HANDLE g_hFontSrvCpuDescHandle = {}; +static D3D12_GPU_DESCRIPTOR_HANDLE g_hFontSrvGpuDescHandle = {}; + struct FrameResources { ID3D12Resource* IB; @@ -20,40 +45,21 @@ struct FrameResources int VertexBufferSize; int IndexBufferSize; }; - -// Data -static INT64 g_Time = 0; -static INT64 g_TicksPerSecond = 0; - -static HWND g_hWnd = 0; -static ID3D12Device* g_pd3dDevice = NULL; -static ID3D12GraphicsCommandList* g_pd3dCommandList = NULL; -static ID3D10Blob* g_pVertexShaderBlob = NULL; -static ID3D10Blob* g_pPixelShaderBlob = NULL; -static ID3D12RootSignature* g_pRootSignature = NULL; -static ID3D12PipelineState* g_pPipelineState = NULL; -static DXGI_FORMAT g_RTVFormat = DXGI_FORMAT_UNKNOWN; -static ID3D12Resource* g_pFontTextureResource = NULL; -static D3D12_CPU_DESCRIPTOR_HANDLE g_hFontSrvCpuDescHandle = {}; -static D3D12_GPU_DESCRIPTOR_HANDLE g_hFontSrvGpuDescHandle = {}; - -static FrameResources* g_pFrameResources = NULL; -static UINT g_numFramesInFlight = 0; -static UINT g_frameIndex = UINT_MAX; +static FrameResources* g_pFrameResources = NULL; +static UINT g_numFramesInFlight = 0; +static UINT g_frameIndex = UINT_MAX; struct VERTEX_CONSTANT_BUFFER { float mvp[4][4]; }; -// 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) -void ImGui_ImplDX12_RenderDrawLists(ImDrawData* draw_data) +// Render function +// (this used to be set in io.RenderDrawListsFn and called by ImGui::Render(), but you can now call this directly from your main loop) +void ImGui_ImplDX12_RenderDrawData(ImDrawData* draw_data) { - // NOTE: I'm assuming that this only get's called once per frame! If not, - // we can't just re-allocate the IB or VB, we'll have to do a proper - // allocator. + // NOTE: I'm assuming that this only get's called once per frame! + // If not, we can't just re-allocate the IB or VB, we'll have to do a proper allocator. g_frameIndex = g_frameIndex + 1; FrameResources* frameResources = &g_pFrameResources[g_frameIndex % g_numFramesInFlight]; ID3D12Resource* g_pVB = frameResources->VB; @@ -215,49 +221,106 @@ void ImGui_ImplDX12_RenderDrawLists(ImDrawData* draw_data) } } -IMGUI_API LRESULT ImGui_ImplDX12_WndProcHandler(HWND, UINT msg, WPARAM wParam, LPARAM lParam) +static void ImGui_ImplWin32_UpdateMouseCursor() { + ImGuiIO& io = ImGui::GetIO(); + ImGuiMouseCursor imgui_cursor = io.MouseDrawCursor ? ImGuiMouseCursor_None : ImGui::GetMouseCursor(); + if (imgui_cursor == ImGuiMouseCursor_None) + { + // Hide OS mouse cursor if imgui is drawing it or if it wants no cursor + ::SetCursor(NULL); + } + else + { + // Hardware cursor type + LPTSTR win32_cursor = IDC_ARROW; + switch (imgui_cursor) + { + case ImGuiMouseCursor_Arrow: win32_cursor = IDC_ARROW; break; + case ImGuiMouseCursor_TextInput: win32_cursor = IDC_IBEAM; break; + case ImGuiMouseCursor_ResizeAll: win32_cursor = IDC_SIZEALL; break; + case ImGuiMouseCursor_ResizeEW: win32_cursor = IDC_SIZEWE; break; + case ImGuiMouseCursor_ResizeNS: win32_cursor = IDC_SIZENS; break; + case ImGuiMouseCursor_ResizeNESW: win32_cursor = IDC_SIZENESW; break; + case ImGuiMouseCursor_ResizeNWSE: win32_cursor = IDC_SIZENWSE; break; + } + ::SetCursor(::LoadCursor(NULL, win32_cursor)); + } +} + +// Process Win32 mouse/keyboard inputs. +// You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs. +// - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application. +// - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application. +// Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags. +// PS: In this Win32 handler, we use the capture API (GetCapture/SetCapture/ReleaseCapture) to be able to read mouse coordinations when dragging mouse outside of our window bounds. +// PS: We treat DBLCLK messages as regular mouse down messages, so this code will work on windows classes that have the CS_DBLCLKS flag set. Our own example app code doesn't set this flag. +IMGUI_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + if (ImGui::GetCurrentContext() == NULL) + return 0; + ImGuiIO& io = ImGui::GetIO(); switch (msg) { - case WM_LBUTTONDOWN: - io.MouseDown[0] = true; - return true; + case WM_LBUTTONDOWN: case WM_LBUTTONDBLCLK: + case WM_RBUTTONDOWN: case WM_RBUTTONDBLCLK: + case WM_MBUTTONDOWN: case WM_MBUTTONDBLCLK: + { + int button = 0; + if (msg == WM_LBUTTONDOWN || msg == WM_LBUTTONDBLCLK) button = 0; + if (msg == WM_RBUTTONDOWN || msg == WM_RBUTTONDBLCLK) button = 1; + if (msg == WM_MBUTTONDOWN || msg == WM_MBUTTONDBLCLK) button = 2; + if (!ImGui::IsAnyMouseDown() && ::GetCapture() == NULL) + ::SetCapture(hwnd); + io.MouseDown[button] = true; + return 0; + } 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_MBUTTONDOWN: - io.MouseDown[2] = true; - return true; case WM_MBUTTONUP: - io.MouseDown[2] = false; - return true; + { + int button = 0; + if (msg == WM_LBUTTONUP) button = 0; + if (msg == WM_RBUTTONUP) button = 1; + if (msg == WM_MBUTTONUP) button = 2; + io.MouseDown[button] = false; + if (!ImGui::IsAnyMouseDown() && ::GetCapture() == hwnd) + ::ReleaseCapture(); + return 0; + } case WM_MOUSEWHEEL: io.MouseWheel += GET_WHEEL_DELTA_WPARAM(wParam) > 0 ? +1.0f : -1.0f; - return true; + return 0; + case WM_MOUSEHWHEEL: + io.MouseWheelH += GET_WHEEL_DELTA_WPARAM(wParam) > 0 ? +1.0f : -1.0f; + return 0; case WM_MOUSEMOVE: io.MousePos.x = (signed short)(lParam); io.MousePos.y = (signed short)(lParam >> 16); - return true; + return 0; case WM_KEYDOWN: + case WM_SYSKEYDOWN: if (wParam < 256) io.KeysDown[wParam] = 1; - return true; + return 0; case WM_KEYUP: + case WM_SYSKEYUP: if (wParam < 256) io.KeysDown[wParam] = 0; - return true; + return 0; 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; + case WM_SETCURSOR: + if (LOWORD(lParam) == HTCLIENT) + { + ImGui_ImplWin32_UpdateMouseCursor(); + return 1; + } + return 0; } return 0; } @@ -317,16 +380,14 @@ static void ImGui_ImplDX12_CreateFontsTexture() ID3D12Resource* uploadBuffer = NULL; HRESULT hr = g_pd3dDevice->CreateCommittedResource(&props, D3D12_HEAP_FLAG_NONE, &desc, D3D12_RESOURCE_STATE_GENERIC_READ, NULL, IID_PPV_ARGS(&uploadBuffer)); - assert(SUCCEEDED(hr)); + IM_ASSERT(SUCCEEDED(hr)); void* mapped = NULL; D3D12_RANGE range = { 0, uploadSize }; hr = uploadBuffer->Map(0, &range, &mapped); - assert(SUCCEEDED(hr)); - for (int y = 0; y < height; ++y) - { + IM_ASSERT(SUCCEEDED(hr)); + for (int y = 0; y < height; y++) memcpy((void*) ((uintptr_t) mapped + y * uploadPitch), pixels + y * width * 4, width * 4); - } uploadBuffer->Unmap(0, &range); D3D12_TEXTURE_COPY_LOCATION srcLocation = {}; @@ -353,10 +414,10 @@ static void ImGui_ImplDX12_CreateFontsTexture() ID3D12Fence* fence = NULL; hr = g_pd3dDevice->CreateFence(0, D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS(&fence)); - assert(SUCCEEDED(hr)); + IM_ASSERT(SUCCEEDED(hr)); HANDLE event = CreateEvent(0, 0, 0, 0); - assert(event != NULL); + IM_ASSERT(event != NULL); D3D12_COMMAND_QUEUE_DESC queueDesc = {}; queueDesc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT; @@ -365,25 +426,25 @@ static void ImGui_ImplDX12_CreateFontsTexture() ID3D12CommandQueue* cmdQueue = NULL; hr = g_pd3dDevice->CreateCommandQueue(&queueDesc, IID_PPV_ARGS(&cmdQueue)); - assert(SUCCEEDED(hr)); + IM_ASSERT(SUCCEEDED(hr)); ID3D12CommandAllocator* cmdAlloc = NULL; hr = g_pd3dDevice->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, IID_PPV_ARGS(&cmdAlloc)); - assert(SUCCEEDED(hr)); + IM_ASSERT(SUCCEEDED(hr)); ID3D12GraphicsCommandList* cmdList = NULL; hr = g_pd3dDevice->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT, cmdAlloc, NULL, IID_PPV_ARGS(&cmdList)); - assert(SUCCEEDED(hr)); + IM_ASSERT(SUCCEEDED(hr)); cmdList->CopyTextureRegion(&dstLocation, 0, 0, 0, &srcLocation, NULL); cmdList->ResourceBarrier(1, &barrier); hr = cmdList->Close(); - assert(SUCCEEDED(hr)); + IM_ASSERT(SUCCEEDED(hr)); cmdQueue->ExecuteCommandLists(1, (ID3D12CommandList* const*) &cmdList); hr = cmdQueue->Signal(fence, 1); - assert(SUCCEEDED(hr)); + IM_ASSERT(SUCCEEDED(hr)); fence->SetEventOnCompletion(1, event); WaitForSingleObject(event, INFINITE); @@ -622,7 +683,7 @@ void ImGui_ImplDX12_InvalidateDeviceObjects() if (g_pRootSignature) { g_pRootSignature->Release(); g_pRootSignature = NULL; } if (g_pPipelineState) { g_pPipelineState->Release(); g_pPipelineState = NULL; } if (g_pFontTextureResource) { g_pFontTextureResource->Release(); g_pFontTextureResource = NULL; ImGui::GetIO().Fonts->TexID = NULL; } // We copied g_pFontTextureView to io.Fonts->TexID so let's clear that as well. - for (UINT i = 0; i < g_numFramesInFlight; ++i) + for (UINT i = 0; i < g_numFramesInFlight; i++) { if (g_pFrameResources[i].IB) { g_pFrameResources[i].IB->Release(); g_pFrameResources[i].IB = NULL; } if (g_pFrameResources[i].VB) { g_pFrameResources[i].VB->Release(); g_pFrameResources[i].VB = NULL; } @@ -644,7 +705,7 @@ bool ImGui_ImplDX12_Init(void* hwnd, int num_frames_in_flight, g_numFramesInFlight = num_frames_in_flight; g_frameIndex = UINT_MAX; - for (int i = 0; i < num_frames_in_flight; ++i) + for (int i = 0; i < num_frames_in_flight; i++) { g_pFrameResources[i].IB = NULL; g_pFrameResources[i].VB = NULL; @@ -667,8 +728,10 @@ bool ImGui_ImplDX12_Init(void* hwnd, int num_frames_in_flight, io.KeyMap[ImGuiKey_PageDown] = VK_NEXT; io.KeyMap[ImGuiKey_Home] = VK_HOME; io.KeyMap[ImGuiKey_End] = VK_END; + io.KeyMap[ImGuiKey_Insert] = VK_INSERT; io.KeyMap[ImGuiKey_Delete] = VK_DELETE; io.KeyMap[ImGuiKey_Backspace] = VK_BACK; + io.KeyMap[ImGuiKey_Space] = VK_SPACE; io.KeyMap[ImGuiKey_Enter] = VK_RETURN; io.KeyMap[ImGuiKey_Escape] = VK_ESCAPE; io.KeyMap[ImGuiKey_A] = 'A'; @@ -678,7 +741,6 @@ bool ImGui_ImplDX12_Init(void* hwnd, int num_frames_in_flight, io.KeyMap[ImGuiKey_Y] = 'Y'; io.KeyMap[ImGuiKey_Z] = 'Z'; - io.RenderDrawListsFn = ImGui_ImplDX12_RenderDrawLists; // Alternatively you can set this to NULL and call ImGui::GetDrawData() after ImGui::Render() to get the same ImDrawData pointer. io.ImeWindowHandle = g_hWnd; return true; @@ -687,7 +749,6 @@ bool ImGui_ImplDX12_Init(void* hwnd, int num_frames_in_flight, void ImGui_ImplDX12_Shutdown() { ImGui_ImplDX12_InvalidateDeviceObjects(); - ImGui::Shutdown(); delete[] g_pFrameResources; g_pd3dDevice = NULL; g_hWnd = (HWND)0; @@ -737,10 +798,14 @@ void ImGui_ImplDX12_NewFrame(ID3D12GraphicsCommandList* command_list) SetCursorPos(pos.x, pos.y); } - // Hide OS mouse cursor if ImGui is drawing it - if (io.MouseDrawCursor) - SetCursor(NULL); + // Update OS mouse cursor with the cursor requested by imgui + ImGuiMouseCursor mouse_cursor = io.MouseDrawCursor ? ImGuiMouseCursor_None : ImGui::GetMouseCursor(); + if (g_LastMouseCursor != mouse_cursor) + { + g_LastMouseCursor = mouse_cursor; + ImGui_ImplWin32_UpdateMouseCursor(); + } - // Start the frame + // Start the frame. This call will update the io.WantCaptureMouse, io.WantCaptureKeyboard flag that you can use to dispatch inputs (or not) to your application. ImGui::NewFrame(); } diff --git a/examples/directx12_example/imgui_impl_dx12.h b/examples/directx12_example/imgui_impl_dx12.h index 059d73e1f0a7..628bbd497a1f 100644 --- a/examples/directx12_example/imgui_impl_dx12.h +++ b/examples/directx12_example/imgui_impl_dx12.h @@ -1,5 +1,8 @@ // ImGui Win32 + DirectX12 binding -// In this binding, ImTextureID is used to store a 'D3D12_GPU_DESCRIPTOR_HANDLE' texture identifier. Read the FAQ about ImTextureID in imgui.cpp. +// FIXME: 64-bit only for now! (Because sizeof(ImTextureId) == sizeof(void*)) + +// Implemented features: +// [X] User texture binding. Use 'D3D12_GPU_DESCRIPTOR_HANDLE' as ImTextureID. Read the FAQ about ImTextureID in imgui.cpp. // You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this. // If you use this binding you'll need to call 4 functions: ImGui_ImplXXXX_Init(), ImGui_ImplXXXX_NewFrame(), ImGui::Render() and ImGui_ImplXXXX_Shutdown(). @@ -12,22 +15,18 @@ struct ID3D12GraphicsCommandList; struct D3D12_CPU_DESCRIPTOR_HANDLE; struct D3D12_GPU_DESCRIPTOR_HANDLE; -// cmdList is the command list that the implementation will use to render the -// GUI. -// -// Before calling ImGui::Render(), caller must prepare cmdList by resetting it -// and setting the appropriate render target and descriptor heap that contains -// fontSrvCpuDescHandle/fontSrvGpuDescHandle. -// -// fontSrvCpuDescHandle and fontSrvGpuDescHandle are handles to a single SRV -// descriptor to use for the internal font texture. -IMGUI_API bool ImGui_ImplDX12_Init(void* hwnd, int numFramesInFlight, +// cmd_list is the command list that the implementation will use to render imgui draw lists. +// Before calling the render function, caller must prepare cmd_list by resetting it and setting the appropriate +// render target and descriptor heap that contains font_srv_cpu_desc_handle/font_srv_gpu_desc_handle. +// font_srv_cpu_desc_handle and font_srv_gpu_desc_handle are handles to a single SRV descriptor to use for the internal font texture. +IMGUI_API bool ImGui_ImplDX12_Init(void* hwnd, int num_frames_in_flight, ID3D12Device* device, DXGI_FORMAT rtv_format, - D3D12_CPU_DESCRIPTOR_HANDLE fontSrvCpuDescHandle, - D3D12_GPU_DESCRIPTOR_HANDLE fontSrvGpuDescHandle); + D3D12_CPU_DESCRIPTOR_HANDLE font_srv_cpu_desc_handle, + D3D12_GPU_DESCRIPTOR_HANDLE font_srv_gpu_desc_handle); IMGUI_API void ImGui_ImplDX12_Shutdown(); -IMGUI_API void ImGui_ImplDX12_NewFrame(ID3D12GraphicsCommandList* cmdList); +IMGUI_API void ImGui_ImplDX12_NewFrame(ID3D12GraphicsCommandList* cmd_list); +IMGUI_API void ImGui_ImplDX12_RenderDrawData(ImDrawData* draw_data); // Use if you want to reset your rendering device without losing ImGui state. IMGUI_API void ImGui_ImplDX12_InvalidateDeviceObjects(); @@ -37,5 +36,5 @@ IMGUI_API bool ImGui_ImplDX12_CreateDeviceObjects(); // 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. /* -IMGUI_API LRESULT ImGui_ImplDX12_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); +IMGUI_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); */ diff --git a/examples/directx12_example/main.cpp b/examples/directx12_example/main.cpp index 51b9da4e250d..7e6d67193130 100644 --- a/examples/directx12_example/main.cpp +++ b/examples/directx12_example/main.cpp @@ -1,19 +1,19 @@ -// ImGui - standalone example application for DirectX 11 +// ImGui - standalone example application for DirectX 12 // If you are new to ImGui, see examples/README.txt and documentation at the top of imgui.cpp. +// FIXME: 64-bit only for now! (Because sizeof(ImTextureId) == sizeof(void*)) -#include +#include "imgui.h" #include "imgui_impl_dx12.h" #include #include #include -#define D3D11_CREATE_DEVICE_DEBUG 2 +#define DX12_ENABLE_DEBUG_LAYER 0 struct FrameContext { ID3D12CommandAllocator* CommandAllocator; UINT64 FenceValue; - bool FenceSignalled; }; // Data @@ -29,7 +29,7 @@ static ID3D12CommandQueue* g_pd3dCommandQueue = NULL; static ID3D12GraphicsCommandList* g_pd3dCommandList = NULL; static ID3D12Fence* g_fence = NULL; static HANDLE g_fenceEvent = NULL; -static UINT64 g_fenceLastSignalledValue = 0; +static UINT64 g_fenceLastSignaledValue = 0; static IDXGISwapChain3* g_pSwapChain = NULL; static HANDLE g_hSwapChainWaitableObject = NULL; static ID3D12Resource* g_mainRenderTargetResource[NUM_BACK_BUFFERS] = {}; @@ -37,19 +37,11 @@ static D3D12_CPU_DESCRIPTOR_HANDLE g_mainRenderTargetDescriptor[NUM_BACK_BUFFER void CreateRenderTarget() { - DXGI_SWAP_CHAIN_DESC sd; - g_pSwapChain->GetDesc(&sd); - - // Create the render target ID3D12Resource* pBackBuffer; - D3D12_RENDER_TARGET_VIEW_DESC render_target_view_desc; - ZeroMemory(&render_target_view_desc, sizeof(render_target_view_desc)); - render_target_view_desc.Format = sd.BufferDesc.Format; - render_target_view_desc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2D; - for (UINT i = 0; i < NUM_BACK_BUFFERS; ++i) + for (UINT i = 0; i < NUM_BACK_BUFFERS; i++) { g_pSwapChain->GetBuffer(i, IID_PPV_ARGS(&pBackBuffer)); - g_pd3dDevice->CreateRenderTargetView(pBackBuffer, &render_target_view_desc, g_mainRenderTargetDescriptor[i]); + g_pd3dDevice->CreateRenderTargetView(pBackBuffer, NULL, g_mainRenderTargetDescriptor[i]); g_mainRenderTargetResource[i] = pBackBuffer; } } @@ -60,7 +52,7 @@ void WaitForLastSubmittedFrame() UINT64 fenceValue = frameCtxt->FenceValue; if (fenceValue == 0) - return; // no fence was signalled + return; // No fence was signaled frameCtxt->FenceValue = 0; if (g_fence->GetCompletedValue() >= fenceValue) @@ -75,15 +67,12 @@ FrameContext* WaitForNextFrameResources() UINT nextFrameIndex = g_frameIndex + 1; g_frameIndex = nextFrameIndex; - HANDLE waitableObjects[] = { - g_hSwapChainWaitableObject, - NULL, - }; + HANDLE waitableObjects[] = { g_hSwapChainWaitableObject, NULL }; DWORD numWaitableObjects = 1; FrameContext* frameCtxt = &g_frameContext[nextFrameIndex % NUM_FRAMES_IN_FLIGHT]; UINT64 fenceValue = frameCtxt->FenceValue; - if (fenceValue != 0) // means no fence was signalled + if (fenceValue != 0) // means no fence was signaled { frameCtxt->FenceValue = 0; g_fence->SetEventOnCompletion(fenceValue, g_fenceEvent); @@ -125,7 +114,7 @@ void CleanupRenderTarget() { WaitForLastSubmittedFrame(); - for (UINT i = 0; i < NUM_BACK_BUFFERS; ++i) + for (UINT i = 0; i < NUM_BACK_BUFFERS; i++) if (g_mainRenderTargetResource[i]) { g_mainRenderTargetResource[i]->Release(); g_mainRenderTargetResource[i] = NULL; } } @@ -149,11 +138,7 @@ HRESULT CreateDeviceD3D(HWND hWnd) sd.Stereo = FALSE; } - UINT createDeviceFlags = 0; - //createDeviceFlags |= D3D11_CREATE_DEVICE_DEBUG; - D3D_FEATURE_LEVEL featureLevel; - featureLevel = D3D_FEATURE_LEVEL_11_0; - if (createDeviceFlags & D3D11_CREATE_DEVICE_DEBUG) + if (DX12_ENABLE_DEBUG_LAYER) { ID3D12Debug* dx12Debug = NULL; if (SUCCEEDED(D3D12GetDebugInterface(IID_PPV_ARGS(&dx12Debug)))) @@ -162,6 +147,8 @@ HRESULT CreateDeviceD3D(HWND hWnd) dx12Debug->Release(); } } + + D3D_FEATURE_LEVEL featureLevel = D3D_FEATURE_LEVEL_11_0; if (D3D12CreateDevice(NULL, featureLevel, IID_PPV_ARGS(&g_pd3dDevice)) != S_OK) return E_FAIL; @@ -176,7 +163,8 @@ HRESULT CreateDeviceD3D(HWND hWnd) SIZE_T rtvDescriptorSize = g_pd3dDevice->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_RTV); D3D12_CPU_DESCRIPTOR_HANDLE rtvHandle = g_pd3dRtvDescHeap->GetCPUDescriptorHandleForHeapStart(); - for (UINT i = 0; i < NUM_BACK_BUFFERS; ++i) { + for (UINT i = 0; i < NUM_BACK_BUFFERS; i++) + { g_mainRenderTargetDescriptor[i] = rtvHandle; rtvHandle.ptr += rtvDescriptorSize; } @@ -200,11 +188,9 @@ HRESULT CreateDeviceD3D(HWND hWnd) return E_FAIL; } - for (UINT i = 0; i < NUM_FRAMES_IN_FLIGHT; ++i) - { + for (UINT i = 0; i < NUM_FRAMES_IN_FLIGHT; i++) if (g_pd3dDevice->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, IID_PPV_ARGS(&g_frameContext[i].CommandAllocator)) != S_OK) return E_FAIL; - } if (g_pd3dDevice->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT, g_frameContext[0].CommandAllocator, NULL, IID_PPV_ARGS(&g_pd3dCommandList)) != S_OK || g_pd3dCommandList->Close() != S_OK) @@ -240,7 +226,7 @@ void CleanupDeviceD3D() CleanupRenderTarget(); if (g_pSwapChain) { g_pSwapChain->Release(); g_pSwapChain = NULL; } if (g_hSwapChainWaitableObject != NULL) { CloseHandle(g_hSwapChainWaitableObject); } - for (UINT i = 0; i < NUM_FRAMES_IN_FLIGHT; ++i) + for (UINT i = 0; i < NUM_FRAMES_IN_FLIGHT; i++) if (g_frameContext[i].CommandAllocator) { g_frameContext[i].CommandAllocator->Release(); g_frameContext[i].CommandAllocator = NULL; } if (g_pd3dCommandQueue) { g_pd3dCommandQueue->Release(); g_pd3dCommandQueue = NULL; } if (g_pd3dCommandList) { g_pd3dCommandList->Release(); g_pd3dCommandList = NULL; } @@ -251,10 +237,10 @@ void CleanupDeviceD3D() if (g_pd3dDevice) { g_pd3dDevice->Release(); g_pd3dDevice = NULL; } } -extern LRESULT ImGui_ImplDX12_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); +extern LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); LRESULT WINAPI WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { - if (ImGui_ImplDX12_WndProcHandler(hWnd, msg, wParam, lParam)) + if (ImGui_ImplWin32_WndProcHandler(hWnd, msg, wParam, lParam)) return true; switch (msg) @@ -283,7 +269,7 @@ LRESULT WINAPI WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) int main(int, char**) { // Create application window - WNDCLASSEX wc = { sizeof(WNDCLASSEX), CS_CLASSDC, WndProc, 0L, 0L, GetModuleHandle(NULL), NULL, LoadCursor(NULL, IDC_ARROW), NULL, NULL, _T("ImGui Example"), NULL }; + WNDCLASSEX wc = { sizeof(WNDCLASSEX), CS_CLASSDC, WndProc, 0L, 0L, GetModuleHandle(NULL), NULL, NULL, NULL, NULL, _T("ImGui Example"), NULL }; RegisterClassEx(&wc); HWND hwnd = CreateWindow(_T("ImGui Example"), _T("ImGui DirectX12 Example"), WS_OVERLAPPEDWINDOW, 100, 100, 1280, 800, NULL, NULL, wc.hInstance, NULL); @@ -300,30 +286,46 @@ int main(int, char**) UpdateWindow(hwnd); // Setup ImGui binding + ImGui::CreateContext(); + ImGuiIO& io = ImGui::GetIO(); (void)io; + //io.NavFlags |= ImGuiNavFlags_EnableKeyboard; // Enable Keyboard Controls ImGui_ImplDX12_Init(hwnd, NUM_FRAMES_IN_FLIGHT, g_pd3dDevice, DXGI_FORMAT_R8G8B8A8_UNORM, g_pd3dSrvDescHeap->GetCPUDescriptorHandleForHeapStart(), g_pd3dSrvDescHeap->GetGPUDescriptorHandleForHeapStart()); + // Setup style + ImGui::StyleColorsDark(); + //ImGui::StyleColorsClassic(); + // Load Fonts - // (there is a default font, this is only if you want to change it. see extra_fonts/README.txt for more details) - //ImGuiIO& io = ImGui::GetIO(); + // - If no fonts are loaded, dear imgui will use the default font. You can also load multiple fonts and use ImGui::PushFont()/PopFont() to select them. + // - AddFontFromFileTTF() will return the ImFont* so you can store it if you need to select the font among multiple. + // - If the file cannot be loaded, the function will return NULL. Please handle those errors in your application (e.g. use an assertion, or display an error and quit). + // - The fonts will be rasterized at a given size (w/ oversampling) and stored into a texture when calling ImFontAtlas::Build()/GetTexDataAsXXXX(), which ImGui_ImplXXXX_NewFrame below will call. + // - Read 'misc/fonts/README.txt' for more instructions and details. + // - Remember that in C/C++ if you want to include a backslash \ in a string literal you need to write a double backslash \\ ! //io.Fonts->AddFontDefault(); - //io.Fonts->AddFontFromFileTTF("../../extra_fonts/Cousine-Regular.ttf", 15.0f); - //io.Fonts->AddFontFromFileTTF("../../extra_fonts/DroidSans.ttf", 16.0f); - //io.Fonts->AddFontFromFileTTF("../../extra_fonts/ProggyClean.ttf", 13.0f); - //io.Fonts->AddFontFromFileTTF("../../extra_fonts/ProggyTiny.ttf", 10.0f); - //io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf", 18.0f, NULL, io.Fonts->GetGlyphRangesJapanese()); - - bool show_test_window = true; + //io.Fonts->AddFontFromFileTTF("../../misc/fonts/Roboto-Medium.ttf", 16.0f); + //io.Fonts->AddFontFromFileTTF("../../misc/fonts/Cousine-Regular.ttf", 15.0f); + //io.Fonts->AddFontFromFileTTF("../../misc/fonts/DroidSans.ttf", 16.0f); + //io.Fonts->AddFontFromFileTTF("../../misc/fonts/ProggyTiny.ttf", 10.0f); + //ImFont* font = io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf", 18.0f, NULL, io.Fonts->GetGlyphRangesJapanese()); + //IM_ASSERT(font != NULL); + + bool show_demo_window = true; bool show_another_window = false; - ImVec4 clear_col = ImColor(114, 144, 154); + ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f); // Main loop MSG msg; ZeroMemory(&msg, sizeof(msg)); while (msg.message != WM_QUIT) { + // You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs. + // - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application. + // - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application. + // Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags. if (PeekMessage(&msg, NULL, 0U, 0U, PM_REMOVE)) { TranslateMessage(&msg); @@ -332,31 +334,41 @@ int main(int, char**) } ImGui_ImplDX12_NewFrame(g_pd3dCommandList); - // 1. Show a simple window - // Tip: if we don't call ImGui::Begin()/ImGui::End() the widgets appears in a window automatically called "Debug" + // 1. Show a simple window. + // Tip: if we don't call ImGui::Begin()/ImGui::End() the widgets automatically appears in a window called "Debug". { static float f = 0.0f; - ImGui::Text("Hello, world!"); - ImGui::SliderFloat("float", &f, 0.0f, 1.0f); - ImGui::ColorEdit3("clear color", (float*)&clear_col); - if (ImGui::Button("Test Window")) show_test_window ^= 1; - if (ImGui::Button("Another Window")) show_another_window ^= 1; + static int counter = 0; + ImGui::Text("Hello, world!"); // Display some text (you can use a format string too) + ImGui::SliderFloat("float", &f, 0.0f, 1.0f); // Edit 1 float using a slider from 0.0f to 1.0f + ImGui::ColorEdit3("clear color", (float*)&clear_color); // Edit 3 floats representing a color + + ImGui::Checkbox("Demo Window", &show_demo_window); // Edit bools storing our windows open/close state + ImGui::Checkbox("Another Window", &show_another_window); + + if (ImGui::Button("Button")) // Buttons return true when clicked (NB: most widgets return true when edited/activated) + counter++; + ImGui::SameLine(); + ImGui::Text("counter = %d", counter); + ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate); } - // 2. Show another simple window, this time using an explicit Begin/End pair + // 2. Show another simple window. In most cases you will use an explicit Begin/End pair to name your windows. if (show_another_window) { ImGui::Begin("Another Window", &show_another_window); ImGui::Text("Hello from another window!"); + if (ImGui::Button("Close Me")) + show_another_window = false; ImGui::End(); } - // 3. Show the ImGui test window. Most of the sample code is in ImGui::ShowTestWindow() - if (show_test_window) + // 3. Show the ImGui demo window. Most of the sample code is in ImGui::ShowDemoWindow(). Read its code to learn more about Dear ImGui! + if (show_demo_window) { - ImGui::SetNextWindowPos(ImVec2(650, 20), ImGuiCond_FirstUseEver); // 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::SetNextWindowPos(ImVec2(650, 20), ImGuiCond_FirstUseEver); // Normally user code doesn't need/want to call this because positions are saved in .ini file anyway. Here we just want to make the demo initial state a bit more friendly! + ImGui::ShowDemoWindow(&show_demo_window); } // Rendering @@ -374,10 +386,11 @@ int main(int, char**) g_pd3dCommandList->Reset(frameCtxt->CommandAllocator, NULL); g_pd3dCommandList->ResourceBarrier(1, &barrier); - g_pd3dCommandList->ClearRenderTargetView(g_mainRenderTargetDescriptor[backBufferIdx], (float*)&clear_col, 0, NULL); + g_pd3dCommandList->ClearRenderTargetView(g_mainRenderTargetDescriptor[backBufferIdx], (float*)&clear_color, 0, NULL); g_pd3dCommandList->OMSetRenderTargets(1, &g_mainRenderTargetDescriptor[backBufferIdx], FALSE, NULL); g_pd3dCommandList->SetDescriptorHeaps(1, &g_pd3dSrvDescHeap); ImGui::Render(); + ImGui_ImplDX12_RenderDrawData(ImGui::GetDrawData()); barrier.Transition.StateBefore = D3D12_RESOURCE_STATE_RENDER_TARGET; barrier.Transition.StateAfter = D3D12_RESOURCE_STATE_PRESENT; g_pd3dCommandList->ResourceBarrier(1, &barrier); @@ -388,13 +401,15 @@ int main(int, char**) g_pSwapChain->Present(1, 0); // Present with vsync //g_pSwapChain->Present(0, 0); // Present without vsync - auto fenceValue = g_fenceLastSignalledValue + 1; + UINT64 fenceValue = g_fenceLastSignaledValue + 1; g_pd3dCommandQueue->Signal(g_fence, fenceValue); - g_fenceLastSignalledValue = fenceValue; + g_fenceLastSignaledValue = fenceValue; frameCtxt->FenceValue = fenceValue; } ImGui_ImplDX12_Shutdown(); + ImGui::DestroyContext(); + CleanupDeviceD3D(); UnregisterClass(_T("ImGui Example"), wc.hInstance); From 7e24ce0956a2d65df8a0a30661e493ca45276b2d Mon Sep 17 00:00:00 2001 From: omar Date: Thu, 22 Feb 2018 23:04:28 +0100 Subject: [PATCH 713/823] Examples: DirectX12: Fixed shutdown issue. (#301) --- examples/directx12_example/main.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/directx12_example/main.cpp b/examples/directx12_example/main.cpp index 7e6d67193130..6a4b78d85e84 100644 --- a/examples/directx12_example/main.cpp +++ b/examples/directx12_example/main.cpp @@ -396,7 +396,7 @@ int main(int, char**) g_pd3dCommandList->ResourceBarrier(1, &barrier); g_pd3dCommandList->Close(); - g_pd3dCommandQueue->ExecuteCommandLists(1, (ID3D12CommandList* const*) &g_pd3dCommandList); + g_pd3dCommandQueue->ExecuteCommandLists(1, (ID3D12CommandList* const*)&g_pd3dCommandList); g_pSwapChain->Present(1, 0); // Present with vsync //g_pSwapChain->Present(0, 0); // Present without vsync @@ -407,9 +407,9 @@ int main(int, char**) frameCtxt->FenceValue = fenceValue; } + WaitForLastSubmittedFrame(); ImGui_ImplDX12_Shutdown(); ImGui::DestroyContext(); - CleanupDeviceD3D(); UnregisterClass(_T("ImGui Example"), wc.hInstance); From 63be3e7c82630d5ed3a33d1b665d33f08beff8ba Mon Sep 17 00:00:00 2001 From: omar Date: Thu, 22 Feb 2018 23:20:37 +0100 Subject: [PATCH 714/823] Update README.txt --- examples/README.txt | 30 ++++++++++++++---------------- 1 file changed, 14 insertions(+), 16 deletions(-) diff --git a/examples/README.txt b/examples/README.txt index 13660c31311e..171c338150b3 100644 --- a/examples/README.txt +++ b/examples/README.txt @@ -13,7 +13,7 @@ TL;DR; - Newcomers, read 'PROGRAMMER GUIDE' in imgui.cpp for notes on how to setup ImGui in your codebase. - If you are using of the backend provided here, so you can copy the imgui_impl_xxx.cpp/h files to your project and use them unmodified. - - To LEARN how the library is setup, you may refer to 'opengl2_example' because is the simplest one to read. + - To LEARN how to setup imgui, you may refer to 'opengl2_example' because is the simplest one to read. However, do NOT USE the 'opengl2_example' if your code is using any modern GL3+ calls. Mixing old fixed-pipeline OpenGL2 and modern OpenGL3+ is going to make everything more complicated. Read comments below for details. If you are not sure, in doubt, use 'opengl3_example'. @@ -53,15 +53,15 @@ opengl2_example/ **DO NOT USE THIS CODE IF YOUR CODE/ENGINE IS USING MODERN OPENGL (SHADERS, VBO, VAO, etc.)** **Prefer using the code in the opengl3_example/ folder** GLFW + OpenGL example (legacy, fixed pipeline). - This code is mostly provided as a reference to learn how ImGui integration works, because it is shorter to read. - If your code is using GL3+ context or any semi modern OpenGL calls, using this is likely to make everything more - complicated, will require your code to reset every single OpenGL attributes to their initial state, and might - confuse your GPU driver. + This code is mostly provided as a reference to learn how ImGui integration works, because it is shorter. + If your code is using GL3+ context or any semi modern OpenGL calls, using this renderer is likely to + make things more complicated, will require your code to several OpenGL attributes to their initial state, + and might confuse your GPU driver. opengl3_example/ GLFW + OpenGL example (programmable pipeline, binding modern functions with GL3W). This uses more modern OpenGL calls and custom shaders. - Prefer using that if you are using modern OpenGL in your application (anything with shaders, vbo, vao, etc.). + Prefer using that if you are using modern OpenGL in your application (anything with shaders). directx9_example/ DirectX9 example, Windows only. @@ -76,7 +76,7 @@ directx11_example/ directx12_example/ DirectX12 example, Windows only. - This is quite long and tedious, because: DirectX12. + This is quite longer and tedious, because: DirectX12. apple_example/ OSX & iOS example. @@ -87,15 +87,15 @@ sdl_opengl2_example/ **DO NOT USE THIS CODE IF YOUR CODE/ENGINE IS USING MODERN OPENGL (SHADERS, VBO, VAO, etc.)** **Prefer using the code in the sdl_opengl3_example/ folder** SDL2 + OpenGL example (legacy, fixed pipeline). - This code is mostly provided as a reference to learn how ImGui integration works, because it is shorter to read. - If your code is using GL3+ context or any semi modern OpenGL calls, using this is likely to make everything more - complicated, will require your code to reset every single OpenGL attributes to their initial state, and might - confuse your GPU driver. + This code is mostly provided as a reference to learn how ImGui integration works, because it is shorter. + If your code is using GL3+ context or any semi modern OpenGL calls, using this renderer is likely to + make things more complicated, will require your code to several OpenGL attributes to their initial state, + and might confuse your GPU driver. sdl_opengl3_example/ SDL2 + OpenGL3 example. This uses more modern OpenGL calls and custom shaders. - Prefer using that if you are using modern OpenGL in your application (anything with shaders, vbo, vao, etc.). + Prefer using that if you are using modern OpenGL in your application (anything with shaders). allegro5_example/ Allegro 5 example. @@ -104,7 +104,5 @@ marmalade_example/ Marmalade example using IwGx vulkan_example/ - Vulkan example. - This is quite long and tedious, because: Vulkan. - -TODO: Apple, SDL GL2/GL3, Allegro, Marmalade, Vulkan examples do not honor the io.WantMoveMouse flag. + Vulkan example. + This is quite longer and tedious, because: Vulkan. From 288351a8019cea3dcbbc8d42d55768b5e80d39bf Mon Sep 17 00:00:00 2001 From: omar Date: Fri, 23 Feb 2018 00:00:43 +0100 Subject: [PATCH 715/823] Examples: DirectX12: Tweaked assertion to more accurately represent what it wants to say. (#301) --- examples/directx12_example/imgui_impl_dx12.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/directx12_example/imgui_impl_dx12.cpp b/examples/directx12_example/imgui_impl_dx12.cpp index 2da3624d37e6..beb48b9cb167 100644 --- a/examples/directx12_example/imgui_impl_dx12.cpp +++ b/examples/directx12_example/imgui_impl_dx12.cpp @@ -471,7 +471,7 @@ static void ImGui_ImplDX12_CreateFontsTexture() } // Store our identifier - static_assert(sizeof(void*) >= sizeof(g_hFontSrvGpuDescHandle.ptr), "Can't pack descriptor handle into TexID"); + static_assert(sizeof(ImTextureID) >= sizeof(g_hFontSrvGpuDescHandle.ptr), "Can't pack descriptor handle into TexID"); io.Fonts->TexID = (void *)g_hFontSrvGpuDescHandle.ptr; } From 79969931e6a016f0d733732edaf2bce5c8d83197 Mon Sep 17 00:00:00 2001 From: omar Date: Fri, 23 Feb 2018 00:01:34 +0100 Subject: [PATCH 716/823] ImDrawList: PushTextureID(): Removed unnecessary param by reference. --- imgui.h | 2 +- imgui_draw.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/imgui.h b/imgui.h index 9b051356ff0a..2f874c6fcac9 100644 --- a/imgui.h +++ b/imgui.h @@ -1505,7 +1505,7 @@ struct ImDrawList IMGUI_API void PushClipRect(ImVec2 clip_rect_min, ImVec2 clip_rect_max, bool intersect_with_current_clip_rect = false); // Render-level scissoring. This is passed down to your render function but not used for CPU-side coarse clipping. Prefer using higher-level ImGui::PushClipRect() to affect logic (hit-testing and widget culling) IMGUI_API void PushClipRectFullScreen(); IMGUI_API void PopClipRect(); - IMGUI_API void PushTextureID(const ImTextureID& texture_id); + IMGUI_API void PushTextureID(ImTextureID texture_id); IMGUI_API void PopTextureID(); inline ImVec2 GetClipRectMin() const { const ImVec4& cr = _ClipRectStack.back(); return ImVec2(cr.x, cr.y); } inline ImVec2 GetClipRectMax() const { const ImVec4& cr = _ClipRectStack.back(); return ImVec2(cr.z, cr.w); } diff --git a/imgui_draw.cpp b/imgui_draw.cpp index 118acabc5f27..7a38af8bb458 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -450,7 +450,7 @@ void ImDrawList::PopClipRect() UpdateClipRect(); } -void ImDrawList::PushTextureID(const ImTextureID& texture_id) +void ImDrawList::PushTextureID(ImTextureID texture_id) { _TextureIdStack.push_back(texture_id); UpdateTextureID(); From 6662fe7b185aab29aa4b2c5e08784e9da75bc700 Mon Sep 17 00:00:00 2001 From: omar Date: Fri, 23 Feb 2018 11:07:51 +0100 Subject: [PATCH 717/823] stb_truetype: Fixed unused variable warnings for configuration where asserts are disabled. (#1642) --- stb_truetype.h | 1 + 1 file changed, 1 insertion(+) diff --git a/stb_truetype.h b/stb_truetype.h index a08e929f9f3d..f65deb50346e 100644 --- a/stb_truetype.h +++ b/stb_truetype.h @@ -2463,6 +2463,7 @@ static stbtt_int32 stbtt__GetGlyphGPOSInfoAdvance(const stbtt_fontinfo *info, i if (valueFormat2 != 0) return 0; STBTT_assert(coverageIndex < pairSetCount); + STBTT__NOTUSED(pairSetCount); needle=glyph2; r=pairValueCount-1; From d749d49903fb0eb56b08961d989ed90a9d97c28b Mon Sep 17 00:00:00 2001 From: omar Date: Fri, 23 Feb 2018 12:37:49 +0100 Subject: [PATCH 718/823] Examples: OpenGL3: Create the VAO in the render function so the setup can more easily be used with multiple shared GL context. (#1217) --- .../opengl3_example/imgui_impl_glfw_gl3.cpp | 32 ++++++++-------- .../imgui_impl_sdl_gl3.cpp | 38 ++++++++++--------- 2 files changed, 38 insertions(+), 32 deletions(-) diff --git a/examples/opengl3_example/imgui_impl_glfw_gl3.cpp b/examples/opengl3_example/imgui_impl_glfw_gl3.cpp index 72cc4bf6daba..85c76684a489 100644 --- a/examples/opengl3_example/imgui_impl_glfw_gl3.cpp +++ b/examples/opengl3_example/imgui_impl_glfw_gl3.cpp @@ -13,6 +13,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2018-02-23: OpenGL: Create the VAO in the render function so the setup can more easily be used with multiple shared GL context. // 2018-02-20: Inputs: Added support for mouse cursors (ImGui::GetMouseCursor() value and WM_SETCURSOR message handling). // 2018-02-20: Inputs: Renamed GLFW callbacks exposed in .h to not include GL3 in their name. // 2018-02-16: Misc: Obsoleted the io.RenderDrawListsFn callback and exposed ImGui_ImplGlfwGL3_RenderDrawData() in the .h file so you can call it yourself. @@ -54,7 +55,7 @@ static GLuint g_FontTexture = 0; static int g_ShaderHandle = 0, g_VertHandle = 0, g_FragHandle = 0; static int g_AttribLocationTex = 0, g_AttribLocationProjMtx = 0; static int g_AttribLocationPosition = 0, g_AttribLocationUV = 0, g_AttribLocationColor = 0; -static unsigned int g_VboHandle = 0, g_VaoHandle = 0, g_ElementsHandle = 0; +static unsigned int g_VboHandle = 0, g_ElementsHandle = 0; // OpenGL3 Render function. // (this used to be set in io.RenderDrawListsFn and called by ImGui::Render(), but you can now call this directly from your main loop) @@ -113,9 +114,22 @@ void ImGui_ImplGlfwGL3_RenderDrawData(ImDrawData* draw_data) glUseProgram(g_ShaderHandle); glUniform1i(g_AttribLocationTex, 0); glUniformMatrix4fv(g_AttribLocationProjMtx, 1, GL_FALSE, &ortho_projection[0][0]); - glBindVertexArray(g_VaoHandle); glBindSampler(0, 0); // Rely on combined texture/sampler state. + // Recreate the VAO every time + // (This is to easily allow multiple GL contexts. VAO are not shared among GL contexts, and we don't track creation/deletion of windows so we don't have an obvious key to use to cache them.) + GLuint vao_handle = 0; + glGenVertexArrays(1, &vao_handle); + glBindVertexArray(vao_handle); + glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle); + glEnableVertexAttribArray(g_AttribLocationPosition); + glEnableVertexAttribArray(g_AttribLocationUV); + glEnableVertexAttribArray(g_AttribLocationColor); + glVertexAttribPointer(g_AttribLocationPosition, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)IM_OFFSETOF(ImDrawVert, pos)); + glVertexAttribPointer(g_AttribLocationUV, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)IM_OFFSETOF(ImDrawVert, uv)); + glVertexAttribPointer(g_AttribLocationColor, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(ImDrawVert), (GLvoid*)IM_OFFSETOF(ImDrawVert, col)); + + // Draw for (int n = 0; n < draw_data->CmdListsCount; n++) { const ImDrawList* cmd_list = draw_data->CmdLists[n]; @@ -289,17 +303,6 @@ bool ImGui_ImplGlfwGL3_CreateDeviceObjects() glGenBuffers(1, &g_VboHandle); glGenBuffers(1, &g_ElementsHandle); - glGenVertexArrays(1, &g_VaoHandle); - glBindVertexArray(g_VaoHandle); - glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle); - glEnableVertexAttribArray(g_AttribLocationPosition); - glEnableVertexAttribArray(g_AttribLocationUV); - glEnableVertexAttribArray(g_AttribLocationColor); - - glVertexAttribPointer(g_AttribLocationPosition, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)IM_OFFSETOF(ImDrawVert, pos)); - glVertexAttribPointer(g_AttribLocationUV, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)IM_OFFSETOF(ImDrawVert, uv)); - glVertexAttribPointer(g_AttribLocationColor, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(ImDrawVert), (GLvoid*)IM_OFFSETOF(ImDrawVert, col)); - ImGui_ImplGlfwGL3_CreateFontsTexture(); // Restore modified GL state @@ -312,10 +315,9 @@ bool ImGui_ImplGlfwGL3_CreateDeviceObjects() void ImGui_ImplGlfwGL3_InvalidateDeviceObjects() { - if (g_VaoHandle) glDeleteVertexArrays(1, &g_VaoHandle); if (g_VboHandle) glDeleteBuffers(1, &g_VboHandle); if (g_ElementsHandle) glDeleteBuffers(1, &g_ElementsHandle); - g_VaoHandle = g_VboHandle = g_ElementsHandle = 0; + g_VboHandle = g_ElementsHandle = 0; if (g_ShaderHandle && g_VertHandle) glDetachShader(g_ShaderHandle, g_VertHandle); if (g_VertHandle) glDeleteShader(g_VertHandle); diff --git a/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.cpp b/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.cpp index 4b870ade929c..2434ceac4409 100644 --- a/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.cpp +++ b/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.cpp @@ -12,6 +12,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2018-02-23: OpenGL: Create the VAO in the render function so the setup can more easily be used with multiple shared GL context. // 2018-02-16: Inputs: Added support for mouse cursors, honoring ImGui::GetMouseCursor() value. // 2018-02-16: Misc: Obsoleted the io.RenderDrawListsFn callback and exposed ImGui_ImplSdlGL3_RenderDrawData() in the .h file so you can call it yourself. // 2018-02-06: Misc: Removed call to ImGui::Shutdown() which is not available from 1.60 WIP, user needs to call CreateContext/DestroyContext themselves. @@ -38,15 +39,17 @@ #include #include // This example is using gl3w to access OpenGL functions (because it is small). You may use glew/glad/glLoadGen/etc. whatever already works for you. -// Data +// SDL data static Uint64 g_Time = 0; static bool g_MousePressed[3] = { false, false, false }; +static SDL_Cursor* g_MouseCursors[ImGuiMouseCursor_Count_] = { 0 }; + +// OpenGL data static GLuint g_FontTexture = 0; static int g_ShaderHandle = 0, g_VertHandle = 0, g_FragHandle = 0; static int g_AttribLocationTex = 0, g_AttribLocationProjMtx = 0; static int g_AttribLocationPosition = 0, g_AttribLocationUV = 0, g_AttribLocationColor = 0; -static unsigned int g_VboHandle = 0, g_VaoHandle = 0, g_ElementsHandle = 0; -static SDL_Cursor* g_MouseCursors[ImGuiMouseCursor_Count_] = { 0 }; +static unsigned int g_VboHandle = 0,g_ElementsHandle = 0; // This is the main rendering function that you have to implement and provide to ImGui (via setting up 'RenderDrawListsFn' in the ImGuiIO structure) // Note that this implementation is little overcomplicated because we are saving/setting up/restoring every OpenGL state explicitly, in order to be able to run within any OpenGL engine that doesn't do so. @@ -105,9 +108,22 @@ void ImGui_ImplSdlGL3_RenderDrawData(ImDrawData* draw_data) glUseProgram(g_ShaderHandle); glUniform1i(g_AttribLocationTex, 0); glUniformMatrix4fv(g_AttribLocationProjMtx, 1, GL_FALSE, &ortho_projection[0][0]); - glBindVertexArray(g_VaoHandle); glBindSampler(0, 0); // Rely on combined texture/sampler state. + // Recreate the VAO every time + // (This is to easily allow multiple GL contexts. VAO are not shared among GL contexts, and we don't track creation/deletion of windows so we don't have an obvious key to use to cache them.) + GLuint vao_handle = 0; + glGenVertexArrays(1, &vao_handle); + glBindVertexArray(vao_handle); + glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle); + glEnableVertexAttribArray(g_AttribLocationPosition); + glEnableVertexAttribArray(g_AttribLocationUV); + glEnableVertexAttribArray(g_AttribLocationColor); + glVertexAttribPointer(g_AttribLocationPosition, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)IM_OFFSETOF(ImDrawVert, pos)); + glVertexAttribPointer(g_AttribLocationUV, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)IM_OFFSETOF(ImDrawVert, uv)); + glVertexAttribPointer(g_AttribLocationColor, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(ImDrawVert), (GLvoid*)IM_OFFSETOF(ImDrawVert, col)); + + // Draw for (int n = 0; n < draw_data->CmdListsCount; n++) { const ImDrawList* cmd_list = draw_data->CmdLists[n]; @@ -289,17 +305,6 @@ bool ImGui_ImplSdlGL3_CreateDeviceObjects() glGenBuffers(1, &g_VboHandle); glGenBuffers(1, &g_ElementsHandle); - glGenVertexArrays(1, &g_VaoHandle); - glBindVertexArray(g_VaoHandle); - glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle); - glEnableVertexAttribArray(g_AttribLocationPosition); - glEnableVertexAttribArray(g_AttribLocationUV); - glEnableVertexAttribArray(g_AttribLocationColor); - - glVertexAttribPointer(g_AttribLocationPosition, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)IM_OFFSETOF(ImDrawVert, pos)); - glVertexAttribPointer(g_AttribLocationUV, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)IM_OFFSETOF(ImDrawVert, uv)); - glVertexAttribPointer(g_AttribLocationColor, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(ImDrawVert), (GLvoid*)IM_OFFSETOF(ImDrawVert, col)); - ImGui_ImplSdlGL3_CreateFontsTexture(); // Restore modified GL state @@ -312,10 +317,9 @@ bool ImGui_ImplSdlGL3_CreateDeviceObjects() void ImGui_ImplSdlGL3_InvalidateDeviceObjects() { - if (g_VaoHandle) glDeleteVertexArrays(1, &g_VaoHandle); if (g_VboHandle) glDeleteBuffers(1, &g_VboHandle); if (g_ElementsHandle) glDeleteBuffers(1, &g_ElementsHandle); - g_VaoHandle = g_VboHandle = g_ElementsHandle = 0; + g_VboHandle = g_ElementsHandle = 0; if (g_ShaderHandle && g_VertHandle) glDetachShader(g_ShaderHandle, g_VertHandle); if (g_VertHandle) glDeleteShader(g_VertHandle); From d7f97922b883aec0c873e0e405c46b154d382120 Mon Sep 17 00:00:00 2001 From: omar Date: Fri, 23 Feb 2018 22:46:14 +0100 Subject: [PATCH 719/823] Examples: Fix d749d49903fb0eb56b08961d989ed90a9d97c28b missing the deletion code. (#1217) --- examples/opengl3_example/imgui_impl_glfw_gl3.cpp | 1 + examples/sdl_opengl3_example/imgui_impl_sdl_gl3.cpp | 1 + 2 files changed, 2 insertions(+) diff --git a/examples/opengl3_example/imgui_impl_glfw_gl3.cpp b/examples/opengl3_example/imgui_impl_glfw_gl3.cpp index 85c76684a489..ce8030b17f4b 100644 --- a/examples/opengl3_example/imgui_impl_glfw_gl3.cpp +++ b/examples/opengl3_example/imgui_impl_glfw_gl3.cpp @@ -157,6 +157,7 @@ void ImGui_ImplGlfwGL3_RenderDrawData(ImDrawData* draw_data) idx_buffer_offset += pcmd->ElemCount; } } + glDeleteVertexArrays(1, &vao_handle); // Restore modified GL state glUseProgram(last_program); diff --git a/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.cpp b/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.cpp index 2434ceac4409..d5bd364cae44 100644 --- a/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.cpp +++ b/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.cpp @@ -151,6 +151,7 @@ void ImGui_ImplSdlGL3_RenderDrawData(ImDrawData* draw_data) idx_buffer_offset += pcmd->ElemCount; } } + glDeleteVertexArrays(1, &vao_handle); // Restore modified GL state glUseProgram(last_program); From 403b2d7d59f84ec0e6abfd247b762007dd5dbc54 Mon Sep 17 00:00:00 2001 From: omar Date: Sun, 25 Feb 2018 13:02:25 +0100 Subject: [PATCH 720/823] ImDrawList: Better looking non-AA rectangle (lower-right corner and rounding). (#1646) --- imgui_draw.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/imgui_draw.cpp b/imgui_draw.cpp index 7a38af8bb458..9ba63056f90e 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -982,7 +982,10 @@ void ImDrawList::AddRect(const ImVec2& a, const ImVec2& b, ImU32 col, float roun { if ((col & IM_COL32_A_MASK) == 0) return; - PathRect(a + ImVec2(0.5f,0.5f), b - ImVec2(0.5f,0.5f), rounding, rounding_corners_flags); + if (Flags & ImDrawListFlags_AntiAliasedLines) + PathRect(a + ImVec2(0.5f,0.5f), b - ImVec2(0.50f,0.50f), rounding, rounding_corners_flags); + else + PathRect(a + ImVec2(0.5f,0.5f), b - ImVec2(0.49f,0.49f), rounding, rounding_corners_flags); // Better looking lower-right corner and rounded non-AA shapes. PathStroke(col, true, thickness); } From 27667fc0351025f0de6936767ed9a421f94a9d50 Mon Sep 17 00:00:00 2001 From: omar Date: Sun, 25 Feb 2018 13:45:47 +0100 Subject: [PATCH 721/823] TreeNode: Renamed Beta ImGuiTreeNodeFlags_NavCloseFromChild to ImGuiTreeNodeFlags_NavLeftJumpsBackHere. (#1079) --- imgui.cpp | 10 +++++----- imgui.h | 2 +- imgui_internal.h | 4 ++-- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 5d4c87c1dfdc..7475120bf042 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -6060,7 +6060,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) window->DC.TextWrapPosStack.resize(0); window->DC.ColumnsSet = NULL; window->DC.TreeDepth = 0; - window->DC.TreeDepthMayCloseOnPop = 0x00; + window->DC.TreeDepthMayJumpToParentOnPop = 0x00; window->DC.StateStorage = &window->StateStorage; window->DC.GroupStack.resize(0); window->MenuColumns.Update(3, style.ItemSpacing.x, window_just_activated_by_user); @@ -8020,8 +8020,8 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l // Store a flag for the current depth to tell if we will allow closing this node when navigating one of its child. // For this purpose we essentially compare if g.NavIdIsAlive went from 0 to 1 between TreeNode() and TreePop(). // This is currently only support 32 level deep and we are fine with (1 << Depth) overflowing into a zero. - if (is_open && !g.NavIdIsAlive && (flags & ImGuiTreeNodeFlags_NavCloseFromChild) && !(flags & ImGuiTreeNodeFlags_NoTreePushOnOpen)) - window->DC.TreeDepthMayCloseOnPop |= (1 << window->DC.TreeDepth); + if (is_open && !g.NavIdIsAlive && (flags & ImGuiTreeNodeFlags_NavLeftJumpsBackHere) && !(flags & ImGuiTreeNodeFlags_NoTreePushOnOpen)) + window->DC.TreeDepthMayJumpToParentOnPop |= (1 << window->DC.TreeDepth); bool item_add = ItemAdd(interact_bb, id); window->DC.LastItemStatusFlags |= ImGuiItemStatusFlags_HasDisplayRect; @@ -12689,12 +12689,12 @@ void ImGui::TreePop() window->DC.TreeDepth--; if (g.NavMoveDir == ImGuiDir_Left && g.NavWindow == window && NavMoveRequestButNoResultYet()) - if (g.NavIdIsAlive && (window->DC.TreeDepthMayCloseOnPop & (1 << window->DC.TreeDepth))) + if (g.NavIdIsAlive && (window->DC.TreeDepthMayJumpToParentOnPop & (1 << window->DC.TreeDepth))) { SetNavID(window->IDStack.back(), g.NavLayer); NavMoveRequestCancel(); } - window->DC.TreeDepthMayCloseOnPop &= (1 << window->DC.TreeDepth) - 1; + window->DC.TreeDepthMayJumpToParentOnPop &= (1 << window->DC.TreeDepth) - 1; PopID(); } diff --git a/imgui.h b/imgui.h index 2f874c6fcac9..bd63a2b0c9db 100644 --- a/imgui.h +++ b/imgui.h @@ -611,7 +611,7 @@ enum ImGuiTreeNodeFlags_ ImGuiTreeNodeFlags_FramePadding = 1 << 10, // Use FramePadding (even for an unframed text node) to vertically align text baseline to regular widget height. Equivalent to calling AlignTextToFramePadding(). //ImGuITreeNodeFlags_SpanAllAvailWidth = 1 << 11, // FIXME: TODO: Extend hit box horizontally even if not framed //ImGuiTreeNodeFlags_NoScrollOnOpen = 1 << 12, // FIXME: TODO: Disable automatic scroll on TreePop() if node got just open and contents is not visible - ImGuiTreeNodeFlags_NavCloseFromChild = 1 << 13, // (WIP) Nav: left direction may close this TreeNode() when focusing on any child (items submitted between TreeNode and TreePop) + ImGuiTreeNodeFlags_NavLeftJumpsBackHere = 1 << 13, // (WIP) Nav: left direction may move to this TreeNode() from any of its child (items submitted between TreeNode and TreePop) ImGuiTreeNodeFlags_CollapsingHeader = ImGuiTreeNodeFlags_Framed | ImGuiTreeNodeFlags_NoAutoOpenOnLog // Obsolete names (will be removed) diff --git a/imgui_internal.h b/imgui_internal.h index c2c055504a84..221e5d46984d 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -834,7 +834,7 @@ struct IMGUI_API ImGuiDrawContext float PrevLineTextBaseOffset; float LogLinePosY; int TreeDepth; - ImU32 TreeDepthMayCloseOnPop; // Store a copy of !g.NavIdIsAlive for TreeDepth 0..31 + ImU32 TreeDepthMayJumpToParentOnPop; // Store a copy of !g.NavIdIsAlive for TreeDepth 0..31 ImGuiID LastItemId; ImGuiItemStatusFlags LastItemStatusFlags; ImRect LastItemRect; // Interaction rect @@ -874,7 +874,7 @@ struct IMGUI_API ImGuiDrawContext CurrentLineTextBaseOffset = PrevLineTextBaseOffset = 0.0f; LogLinePosY = -1.0f; TreeDepth = 0; - TreeDepthMayCloseOnPop = 0x00; + TreeDepthMayJumpToParentOnPop = 0x00; LastItemId = 0; LastItemStatusFlags = 0; LastItemRect = LastItemDisplayRect = ImRect(); From 133f06d658763e4e65361881e01a9fb0756b262a Mon Sep 17 00:00:00 2001 From: omar Date: Sat, 24 Feb 2018 16:56:15 +0100 Subject: [PATCH 722/823] Changelog: Added Changelog with info from 1.48 to 1.53. Haven't added 1.53..current yet. --- CHANGELOG.txt | 582 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 582 insertions(+) create mode 100644 CHANGELOG.txt diff --git a/CHANGELOG.txt b/CHANGELOG.txt new file mode 100644 index 000000000000..fd2f57590ee7 --- /dev/null +++ b/CHANGELOG.txt @@ -0,0 +1,582 @@ +dear imgui +CHANGELOG + +----------------------------------------------------------------------- + +This document holds the programmer changelog that we also use in release notes. +We generally fold multiple commits pertaining to the same topic as a single entry and simplify a few things. + +Release notes: (with links and screenshots) + https://github.com/ocornut/imgui/releases + +Changes to the examples/bindings are included within the individual .cpp files in examples. + +Individual commits: + https://github.com/ocornut/imgui/commits/master + +Report issues, ask questions: + https://github.com/ocornut/imgui/issues + +----------------------------------------------------------------------- + +WHEN TO UPDATE? + +It is generally safe to sync to the latest commit in master. The library is fairly stable and regressions tends to be fixed fast when reported. +Keeping your copy of dear imgui updated once in a while is recommended. + +HOW TO UPDATE? + +- Overwrite every file except imconfig.h (if you have modified it). +- You may also locally branch to modify imconfig.h and merge latest into your branch. +- Read the `Breaking Changes` section (in imgui.cpp or here in the Changelog). +- If you have a problem with a missing function/symbols, search for its name in the code, there will likely be a comment about it. +- If you are dropping this repository in your codebase, please leave the demo and text files in there, they will be useful. +- You may diff your previous Changelog with the one you just copied and read that diff. +- You may enable `IMGUI_DISABLE_OBSOLETE_FUNCTIONS` in imconfig.h to forcefully disable legacy names and symbols. Doing it every once in a while is a good way to make sure you are not using obsolete symbols. Dear ImGui is in active development API updates have a little more frequent lately. They are carefully documented and should not affect all users. +- Please report any issue! + +----------------------------------------------------------------------- + +VERSION 1.60 WIP (Latest, currently in development) + + + +----------------------------------------------------------------------- + +VERSION 1.53 (Released 2017-12-25) +Decorated log: https://github.com/ocornut/imgui/releases/tag/v1.53 + +Breaking Changes: + +- Renamed the emblematic `ShowTestWindow()` function to `ShowDemoWindow()`. Kept redirection function (will obsolete). +- Renamed `GetItemsLineHeightWithSpacing()` to `GetFrameHeightWithSpacing()` for consistency. Kept redirection function (will obsolete). +- Renamed `ImGuiTreeNodeFlags_AllowOverlapMode` flag to `ImGuiTreeNodeFlags_AllowItemOverlap`. Kept redirection enum (will obsolete). +- Obsoleted `IsRootWindowFocused()` in favor of using `IsWindowFocused(ImGuiFocusedFlags_RootWindow)`. Kept redirection function (will obsolete). (#1382) +- Obsoleted `IsRootWindowOrAnyChildFocused()` in favor of using `IsWindowFocused(ImGuiFocusedFlags_RootAndChildWindows)`. Kept redirection function (will obsolete). (#1382) +- Obsoleted `IsRootWindowOrAnyChildHovered()` in favor of using `IsWindowHovered(ImGuiHoveredFlags_RootAndChildWindows)`. Kept redirection function (will obsolete). (#1382) +- Obsoleted `SetNextWindowContentWidth() in favor of using `SetNextWindowContentSize()`. Kept redirection function (will obsolete). +- Renamed `ImGuiTextBuffer::append()` helper to `appendf()`, and `appendv()` to `appendfv()` for consistency. If you copied the 'Log' demo in your code, it uses appendv() so that needs to be renamed. +- ImDrawList: Removed 'bool anti_aliased = true' final parameter of `ImDrawList::AddPolyline()` and `ImDrawList::AddConvexPolyFilled()`. Prefer manipulating ImDrawList::Flags if you need to toggle them during the frame. +- Style, ImDrawList: Renamed `style.AntiAliasedShapes` to `style.AntiAliasedFill` for consistency and as a way to explicitly break code that manipulate those flag at runtime. You can now manipulate ImDrawList::Flags. +- Style, Begin: Removed `ImGuiWindowFlags_ShowBorders` window flag. Borders are now fully set up in the ImGuiStyle structure (see e.g. `style.FrameBorderSize`, `style.WindowBorderSize`). Use `ImGui::ShowStyleEditor()` to look them up. + Please note that the style system will keep evolving (hopefully stabilizing in Q1 2018), and so custom styles will probably subtly break over time. + It is recommended that you use the `StyleColorsClassic()`, `StyleColorsDark()`, `StyleColorsLight()` functions. Also see `ShowStyleSelector()`. +- Style: Removed `ImGuiCol_ComboBg` in favor of combo boxes using `ImGuiCol_PopupBg` for consistency. Combo are normal popups. +- Style: Renamed `ImGuiCol_ChildWindowBg` to `ImGuiCol_ChildBg`. +- Style: Renamed `style.ChildWindowRounding` to `style.ChildRounding`, `ImGuiStyleVar_ChildWindowRounding` to `ImGuiStyleVar_ChildRounding`. +- Removed obsolete redirection functions: SetScrollPosHere() - marked obsolete in v1.42, July 2015. +- Removed obsolete redirection functions: GetWindowFont(), GetWindowFontSize() - marked obsolete in v1.48, March 2016. + +Other Changes: + +- Added `io.OptCursorBlink` option to allow disabling cursor blinking. (#1427) +- Added `GetOverlayDrawList()` helper to quickly get access to a ImDrawList that will be rendered in front of every windows. +- Added `GetFrameHeight()` helper which returns `(FontSize + style.FramePadding.y * 2)`. +- DragDrop: Added Beta API to easily use drag and drop patterns between imgui widgets. + - Setup a source on a widget with `BeginDragDropSource()`, `SetDragDropPayload()`, `EndDragDropSource()` functions. + - Receive data with `BeginDragDropTarget()`, `AcceptDragDropPayload()`, `EndDragDropTarget()`. + - See ImGuiDragDropFlags for various options. + - The ColorEdit4() and ColorButton() widgets now support Drag and Drop. + - The API is tagged as Beta as it still may be subject to small changes. +- DragDrop: When drag and drop is active, tree nodes and collapsing header can be opened by hovering on them for 0.7 seconds. +- Renamed io.OSXBehaviors to io.OptMacOSXBehaviors. Should not affect users as the compile-time default is usually enough. (#473, #650) +- Style: Added StyleColorsDark() style. (#707) [@dougbinks] +- Style: Added StyleColorsLight() style. Best used with frame borders + thicker font than the default font. (#707) +- Style: Added style.PopupRounding setting. (#1112) +- Style: Added style.FrameBorderSize, style.WindowBorderSize. Removed ImGuiWindowFlags_ShowBorders window flag! Borders are now fully set up in the ImGuiStyle structure. Use ImGui::ShowStyleEditor() to look them up. (#707, fix #819, #1031) +- Style: Various small changes to the classic style (most noticeably, buttons are now using blue shades). (#707) +- Style: Renamed ImGuiCol_ChildWindowBg to ImGuiCol_ChildBg. +- Style: Renamed style.ChildWindowRounding to style.ChildRounding, ImGuiStyleVar_ChildWindowRounding to ImGuiStyleVar_ChildRounding. +- Style: Removed ImGuiCol_ComboBg in favor of combo boxes using ImGuiCol_PopupBg for consistency. (#707) +- Style: Made the ScaleAllSizes() helper rounds down every values so they are aligned on integers. +- Focus: Added SetItemDefaultFocus(), which in the current (master) branch behave the same as doing `if (IsWindowAppearing()) SetScrollHere()`. + In the navigation branch this will also set the default focus. Prefer using this when creating combo boxes with `BeginCombo()` so your code will be forward-compatible with gamepad/keyboard navigation features. (#787) +- Combo: Popup grows horizontally to accomodate for contents that is larger then the parent combo button. +- Combo: Added BeginCombo()/EndCombo() API which allows use to submit content of any form and manage your selection state without relying on indices. +- Combo: Added ImGuiComboFlags_PopupAlignLeft flag to BeginCombo() to prioritize keeping the popup on the left side (for small-button-looking combos). +- Combo: Added ImGuiComboFlags_HeightSmall, ImGuiComboFlags_HeightLarge, ImGuiComboFlags_HeightLargest to easily provide desired popup height. +- Combo: You can use SetNextWindowSizeConstraints() before BeginCombo() to specify specific popup width/height constraints. +- Combo: Offset popup position by border size so that a double border isn't so visible. (#707) +- Combo: Recycling windows by using a stack number instead of a unique id, wasting less memory (like menus do). +- InputText: Added ImGuiInputTextFlags_NoUndoRedo flag. (#1506, #1508) [@ibachar] +- Window: Fixed auto-resize allocating too much space for scrollbar when SizeContents is bigger than maximum window size (fixes c0547d3). (#1417) +- Window: Child windows with MenuBar use regular WindowPadding.y so layout look consistent as child or as a regular window. +- Window: Begin(): Fixed appending into a child window with a second Begin() from a different window stack querying the wrong window for the window->Collapsed test. +- Window: Calling IsItemActive(), IsItemHovered() etc. after a call to Begin() provides item data for the title bar, so you can easily test if the title bar is being hovered, etc. (#823) +- Window: Made it possible to use SetNextWindowPos() on a child window. +- Window: Fixed a one frame glitch. When an appearing window claimed the focus themselves, the title bar wouldn't use the focused color for one frame. +- Window: Added ImGuiWindowFlags_ResizeFromAnySide flag to resize from any borders or from the lower-left corner of a window. This requires your backend to honor GetMouseCursor() requests for full usability. (#822) +- Window: Sizing fixes when useing SetNextWindowSize() on individual axises. +- Window: Made mouse wheel scrolling accomodate better to windows that are smaller than the scroll step. +- Window: SetNextWindowContentSize() adjust for the size of decorations (title bar/menu bar), but _not_ for borders are we consistently make borders not affect layout. + If you need a non-child window of an exact size with border enabled but zero window padding, you'll need to accodomate for the border size yourself. +- Window: Using the ImGuiWindowFlags_NoScrollWithMouse flag on a child window forwards the mouse wheel event to the parent window, unless either ImGuiWindowFlags_NoInputs or ImGuiWindowFlags_NoScrollbar are also set. (#1380, #1502) +- Window: Active Modal window always set the WantCaptureKeyboard flag. (#744) +- Window: Moving window doesn't use accumulating MouseDelta so straying out of imgui boundaries keeps moved imgui window at the same cursor-relative position. +- IsWindowFocused(): Added ImGuiFocusedFlags_ChildWindows flag to include child windows in the focused test. (#1382). +- IsWindowFocused(): Added ImGuiFocusedFlags_RootWindow flag to start focused test from the root (top-most) window. Obsolete IsRootWindowFocused(). (#1382) +- IsWindowHovered(): Added ImGuiHoveredFlags_ChildWindows flag to include child windows in the hovered test. (#1382). +- IsWindowHovered(): Added ImGuiHoveredFlags_RootWindow flag to start hovered test from the root (top-most) window. The combination of both flags obsoletes IsRootWindowOrAnyChildHovered(). (#1382) +- IsWindowHovered(): Fixed return value when an item is active to use the same logic as IsItemHovered(). (#1382, #1404) +- IsWindowHovered(): Always return true when current window is being moved. (#1382) +- Scrollbar: Fixed issues with vertical scrollbar flickering/appearing, typically when manually resizing and using a pattern of filling available height (e.g. full sized BeginChild). +- Scrollbar: Minor graphical fix for when scrollbar don't have enough visible space to display the full grab. +- Scrolling: Fixed padding and scrolling asymetry where lower/right sides of a window wouldn't use WindowPadding properly + causing minor scrolling glitches. +- Tree: TreePush with zero arguments was ambiguous. Resolved by making it call TreePush(const void*). [@JasonWilkins] +- Tree: Renamed ImGuiTreeNodeFlags_AllowOverlapMode to ImGuiTreeNodeFlags_AllowItemOverlap. (#600, #1330) +- MenuBar: Fixed minor rendering issues on the right size when resizing a window very small and using rounded window corners. +- MenuBar: better software clipping to handle small windows, in particular child window don't have minimum constraints so we need to render clipped menus better. +- BeginMenu(): Tweaked the Arrow/Triangle displayed on child menu items. +- Columns: Clipping columns borders on Y axis on CPU because some Linux GPU drivers appears to be unhappy with triangle spanning large regions. (#125) +- Columns: Added ImGuiColumnsFlags_GrowParentContentsSize to internal API to restore old content sizes behavior (may be obsolete). (#1444, #125) +- Columns: Columns width is no longer lost when dragging a column to the right side of the window, until releasing the mouse button you have a chance to save them. (#1499, #125). [@ggtucker] +- Columns: Fixed dragging when using a same of columns multiple times in the frame. (#125) +- Indent(), Unindent(): Allow passing negative values. +- ColorEdit4(): Made IsItemActive() return true when picker popup is active. (#1489) +- ColorEdit4(): Tweaked tooltip so that the color button aligns more correctly with text. +- ColorEdit4(): Support drag and drop. Color buttons can be used as drag sources, and ColorEdit widgets as drag targets. (#143) +- ColorPicker4(): Fixed continously returning true when holding mouse button on the sat/value/alpha locations. We only return true on value change. (#1489) +- NewFrame(): using literal strings in the most-frequently firing IM_ASSERT expressions to increase the odd of programmers seeing them (especially those who don't use a debugger). +- NewFrame() now asserts if neither Render or EndFrame have been called. Exposed EndFrame(). Made it legal to call EndFrame() more than one. (#1423) +- ImGuiStorage: Added BuildSortByKey() helper to rebuild storage from stratch. +- ImFont: Added GetDebugName() helper. +- ImFontAtlas: Added missing Thai punctuation in the GetGlyphRangesThai() ranges. (#1396) [@nProtect] +- ImDrawList: Removed 'bool anti_aliased = true' final parameter of ImDrawList::AddPolyline() and ImDrawList::AddConvexPolyFilled(). Anti-aliasing is controlled via the regular style.AntiAliased flags. +- ImDrawList: Added ImDrawList::AddImageRounded() helper. (#845) [@thedmd] +- ImDrawList: Refactored to make ImDrawList independant of ImGui. Removed static variable in PathArcToFast() which caused linking issues to some. +- ImDrawList: Exposed ImDrawCornerFlags, replaced occurences of ~0 with an explicit ImDrawCornerFlags_All. NB: Inversed BotLeft (prev 1<<3, now 1<<2) and BotRight (prev 1<<2, now 1<<3). +- ImVector: Added ImVector::push_front() helper. +- ImVector: Added ImVector::contains() helper. +- ImVector: insert() uses grow_capacity() instead of using grow policy inconsistent with push_back(). +- Internals: Remove requirement to define IMGUI_DEFINE_PLACEMENT_NEW to use the IM_PLACEMENT_NEW macro. (#1103) +- Internals: ButtonBehavior: Fixed ImGuiButtonFlags_NoHoldingActiveID flag from incorrectly setting the ActiveIdClickOffset field. + This had no known effect within imgui code but could have affected custom drag and drop patterns. And it is more correct this way! (#1418) +- Internals: ButtonBehavior: Fixed ImGuiButtonFlags_AllowOverlapMode to avoid temporarily activating widgets on click before they have been correctly double-hovered. (#319, #600) +- Internals: Added SplitterBehavior() helper. (#319) +- Internals: Added IM_NEW(), IM_DELETE() helpers. (#484, #504, #1517) +- Internals: Basic refactor of the settings API which now allows external elements to be loaded/saved. +- Demo: Added ShowFontSelector() showing loaded fonts. +- Demo: Added ShowStyleSelector() to select among default styles. (#707) +- Demo: Renamed the emblematic ShowTestWindow() function to ShowDemoWindow(). +- Demo: Style Editor: Added a "Simplified settings" sections with checkboxes for border size and frame rounding. (#707, #1019) +- Demo: Style Editor: Added combo box to select stock styles and select current font when multiple are loaded. (#707) +- Demo: Style Editor: Using local storage so Save/Revert button makes more sense without code passing its storage. Aadded horizontal scroll bar. Fixed Save/Revert button to be always accessible. (#1211) +- Demo: Console: Fixed context menu issue. (#1404) +- Demo: Console: Fixed incorrect positioning which was hidden by a minor scroll issue (this would affect people who copied the Console code as is). +- Demo: Constrained Resize: Added more test cases. (#1417) +- Demo: Custom Rendering: Fixed clipping rectangle extruding out of parent window. +- Demo: Layout: Removed unnecessary and misleading BeginChild/EndChild calls. +- Demo: The "Color Picker with Palette" demo supports drag and drop. (#143) +- Demo: Display better mouse cursor info for debugging backends. +- Demo: Stopped using rand() function in demo code. +- Examples: Added a handful of extra comments (about fonts, third-party libraries used in the examples, etc.). +- Examples: DirectX9: Handle loss of D3D9 device (D3DERR_DEVICELOST). (#1464) +- Examples: Added null_example/ which is helpful for quick testing on multiple compilers/settings without relying on graphics library. +- Fix for using alloca() in "Clang with Microsoft Codechain" mode. +- Various fixes, optimizations, comments. + +----------------------------------------------------------------------- + +VERSION 1.52 (2017-10-27) +Decorated log: https://github.com/ocornut/imgui/releases/tag/v1.52 + +Breaking Changes: + +- IO: `io.MousePos` needs to be set to ImVec2(-FLT_MAX,-FLT_MAX) when mouse is unavailable/missing, instead of ImVec2(-1,-1) as previously) This is needed so we can clear `io.MouseDelta` field when the mouse is made available again. +- Renamed `AlignFirstTextHeightToWidgets()` to `AlignTextToFramePadding()`. Kept inline redirection function (will obsolete). +- Obsoleted the legacy 5 parameters version of Begin(). Please avoid using it. If you need a transparent window background, uses `PushStyleColor()`. The old size parameter there was also misleading and equivalent to calling `SetNextWindowSize(size, ImGuiCond_FirstTimeEver)`. Kept inline redirection function (will obsolete). +- Obsoleted `IsItemHoveredRect()`, `IsMouseHoveringWindow()` in favor of using the newly introduced flags of `IsItemHovered()` and `IsWindowHovered()`. Kept inline redirection function (will obsolete). (#1382) +- Removed `IsItemRectHovered()`, `IsWindowRectHovered()` recently introduced in 1.51 which were merely the more consistent/correct names for the above functions which are now obsolete anyway. (#1382) +- Changed `IsWindowHovered()` default parameters behavior to return false if an item is active in another window (e.g. click-dragging item from another window to this window). You can use the newly introduced IsWindowHovered() flags to requests this specific behavior if you need it. (#1382) +- Renamed imconfig.h's `IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCS`/`IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCS` to `IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCTIONS`/`IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS` for consistency. + +Other Changes: + +- ProgressBar: fixed rendering when straddling rounded area. (#1296) +- SliderFloat, DragFloat: Using scientific notation e.g. "%.1e" in the displayed format string doesn't mistakenly trigger rounding of the value. [@MomentsInGraphics] +- Combo, InputFloat, InputInt: Made the small button on the right side align properly with the equivalent colored button of ColorEdit4(). +- IO: Tweaked logic for `io.WantCaptureMouse` so it now outputs false when e.g. hovering over void while an InputText() is active. (#621) [@pdoane] +- IO: Fixed `io.WantTextInput` from mistakenly outputting true when an activated Drag or Slider was previously turned into an InputText(). (#1317) +- Misc: Added flags to `IsItemHovered()`, `IsWindowHovered()` to access advanced hovering-test behavior. Generally useful for popups and drag'n drop behaviors: (relates to ~#439, #1013, #143, #925) + - `ImGuiHoveredFlags_AllowWhenBlockedByPopup` + - `ImGuiHoveredFlags_AllowWhenBlockedByActiveItem` + - `ImGuiHoveredFlags_AllowWhenOverlapped` + - `ImGuiHoveredFlags_RectOnly` +- Input: Added `IsMousePosValid()` helper. +- Input: Added `GetKeyPressedAmount()` to easily measure press count when the repeat rate is faster than the frame rate. +- Input/Focus: Disabled TAB and Shift+TAB when CTRL key is held. +- Checkbox: Now rendering a tick mark instead of a full square. +- ColorEdit4: Added "Copy as..." option in context menu. (#346) +- ColorPicker: Improved ColorPicker hue wheel color interpolation. (#1313) [@thevaber] +- ColorButton: Reduced bordering artefact that would be particularly visible with an opaque Col_FrameBg and FrameRounding enabled. +- ColorButton: Fixed rendering color button with a checkerboard if the transparency comes from the global style.Alpha and not from the actual source color. +- TreeNode: Added `ImGuiTreeNodeFlags_FramePadding` flag to conveniently create a tree node with full padding at the beginning of a line, without having to call `AlignTextToFramePadding()`. +- Trees: Fixed calling `SetNextTreeNodeOpen()` on a collapsed window leaking to the first tree node item of the next frame. +- Layout: Horizontal layout is automatically enforced in a menu bar, so you can use non-MenuItem elements without calling SameLine(). +- Separator: Output a vertical separator when used inside a menu bar (or in general when horizontal layout is active, but that isn't exposed yet!). +- Windows: Added `IsWindowAppearing()` helper (helpful e.g. as a condition before initializing some of your own things.). +- Windows: Fixed title bar color of top-most window under a modal window. +- Windows: Fixed not being able to move a window by clicking on one of its child window. (#1337, #635) +- Windows: Fixed `Begin()` auto-fit calculation code that predict the presence of a scrollbar so it works better when window size constraints are used. +- Windows: Fixed calling `Begin()` more than once per frame setting `window_just_activated_by_user` which in turn would set enable the Appearing condition for that frame. +- Windows: The implicit "Debug" window now uses a "Debug##Default" identifier instead of "Debug" to allow user creating a window called "Debug" without losing their custom flags. +- Windows: Made the `ImGuiWindowFlags_NoMove` flag properly inherited from parent to child. In a setup with ParentWindow (no flag) -> Child (NoMove) -> SubChild (no flag), the user won't be able to move the parent window by clicking on SubChild. (#1381) +- Popups: Popups can be closed with a right-click anywhere, without altering focus under the popup. (~#439) +- Popups: `BeginPopupContextItem()`, `BeginPopupContextWindow()` are now setup to allow reopening a context menu by right-clicking again. (~#439) +- Popups: `BeginPopupContextItem()` now supports a NULL string identifier and uses the last item ID if available. +- Popups: Added `OpenPopupOnItemClick()` helper which mimic `BeginPopupContextItem()` but doesn't do the BeginPopup(). +- MenuItem: Only activating on mouse release. [@Urmeli0815] (was already fixed in nav branch). +- MenuItem: Made tick mark thicker (thick mark?). +- MenuItem: Tweaks to be usable inside a menu bar (nb: it looks like a regular menu and thus is misleading, prefer using Button() and regular widgets in menu bar if you need to). (#1387) +- ImDrawList: Fixed a rare draw call merging bug which could lead to undisplayed triangles. (#1172, #1368) +- ImDrawList: Fixed a rare bug in `ChannelsMerge()` when all contents has been clipped, leading to an extraneous draw call being created. (#1172, #1368) +- ImFont: Added `AddGlyph()` building helper for use by custom atlas builders. +- ImFontAtlas: Added support for CustomRect API to submit custom rectangles to be packed into the atlas. You can map them as font glyphs, or use them for custom purposes. + After the atlas is built you can query the position of your rectangles in the texture and then copy your data there. You can use this features to create e.g. full color font-mapped icons. +- ImFontAtlas: Fixed fall-back handling when merging fonts, if a glyph was missing from the second font input it could have used a glyph from the first one. (#1349) [@inolen] +- ImFontAtlas: Fixed memory leak on build failure case when stbtt_InitFont failed (generally due to incorrect or supported font type). (#1391) (@Moka42) +- ImFontConfig: Added `RasterizerMultiply` option to alter the brightness of individual fonts at rasterization time, which may help increasing readability for some. +- ImFontConfig: Added `RasterizerFlags` to pass options to custom rasterizer (e.g. the [imgui_freetype](https://github.com/ocornut/imgui_club/tree/master/imgui_freetype) rasterizer in imgui_club has such options). +- ImVector: added resize() variant with initialization value. +- Misc: Changed the internal name formatting of child windows identifier to use slashes (instead of dots) as separator, more readable. +- Misc: Fixed compilation with `IMGUI_DISABLE_OBSOLETE_FUNCTIONS` defined. +- Misc: Marked all format+va_list functions with format attribute so GCC/Clang can warn about misuses. +- Misc: Fixed compilation on NetBSD due to missing alloca.h (#1319) [@RyuKojiro] +- Misc: Improved warnings compilation for newer versions of Clang. (#1324) (@waywardmonkeys) +- Misc: Added `io.WantMoveMouse flags` (from Nav branch) and honored in Examples applications. Currently unused but trying to spread Examples applications code that supports it. +- Misc: Added `IMGUI_DISABLE_FORMAT_STRING_FUNCTIONS` support in imconfig.h to allow user reimplementing the `ImFormatString()` functions e.g. to use stb_printf(). (#1038) +- Misc: [Windows] Fixed default Win32 `SetClipboardText()` handler leaving the Win32 clipboard handler unclosed on failure. [@pdoane] +- Style: Added `ImGuiStyle::ScaleAllSizes(float)` helper to make it easier to have application transition e.g. from low to high DPI with a matching style. +- Metrics: Draw window bounding boxes when hovering Pos/Size; List all draw layers; Trimming empty commands like Render() does. +- Examples: OpenGL3: Save and restore sampler state. (#1145) [@nlguillemot] +- Examples: OpenGL2, OpenGL3: Save and restore polygon mode. (#1307) [@JJscott] +- Examples: DirectX11: Allow creating device with feature level 10 since we don't really need much for that example. (#1333) +- Examples: DirectX9/10/12: Using the Win32 SetCapture/ReleaseCapture API to read mouse coordinates when they are out of bounds. (#1375) [@Gargaj, @ocornut] +- Tools: Fixed binary_to_compressed_c tool to return 0 when successful. (#1350) [@benvanik] +- Internals: Exposed more helpers and unfinished features in imgui_internal.h. (use at your own risk!). +- Internals: A bunch of internal refactoring, hopefully haven't broken anything! Merged a bunch of internal changes from the upcoming Navigation branch. +- Various tweaks, fixes and documentation changes. + +Beta Navigation Branch: +(Lots of work has been done toward merging the Beta Gamepad/Keyboard Navigation branch (#787) in master.) +(Please note that this branch is always kept up to date with master. If you are using the navigation branch, some of the changes include:) +- Nav: Added `#define IMGUI_HAS_NAV` in imgui.h to ease sharing code between both branches. (#787) +- Nav: MainMenuBar now releases focus when user gets out of the menu layer. (#787) +- Nav: When applying focus to a window with only menus, the menu layer is automatically activated. (#787) +- Nav: Added `ImGuiNavInput_KeyMenu` (~Alt key) aside from ImGuiNavInput_PadMenu input as it is one differentiator of pad vs keyboard that was detrimental to the keyboard experience. Although isn't officially supported, it makes the current experience better. (#787) +- Nav: Move requests now wrap vertically inside Menus and Popups. (#787) +- Nav: Allow to collapse tree nodes with NavLeft and open them with NavRight. (#787, #1079). +- Nav: It's now possible to navigate sibling of a menu-bar while navigating inside one of their child. If a Left<>Right navigation request fails to find a match we forward the request to the root menu. (#787, #126) +- Nav: Fixed `SetItemDefaultFocus` from stealing default focus when we are initializing default focus for a menu bar layer. (#787) +- Nav: Support for fall-back horizontal scrolling with PadLeft/PadRight (nb: fall-back scrolling is only used to navigate windows that have no interactive items). (#787) +- Nav: Fixed tool-tip from being selectable in the window selection list. (#787) +- Nav: `CollapsingHeader(bool*)` variant: fixed for `IsItemHovered()` not working properly in the nav branch. (#600, #787) +- Nav: InputText: Fixed using Up/Down history callback feature when Nav is enabled. (#787) +- Nav: InputTextMultiline: Fixed navigation/selection. Disabled selecting all when activating a multi-line text editor. (#787) +- Nav: More consistently drawing a (thin) navigation rectangle hover filled frames such as tree nodes, collapsing header, menus. (#787) +- Nav: Various internal refactoring. + +----------------------------------------------------------------------- + +VERSION 1.51 (2017-08-24) +Decorated log: https://github.com/ocornut/imgui/releases/tag/v1.51 + +Breaking Changes: + +Work on dear imgui has been gradually resuming. It means that fixes and new features should be tackled at a faster rate than last year. However, in order to move forward with the library and get rid of some cruft, I have taken the liberty to be a little bit more aggressive than usual with API breaking changes. Read the details below and search for those names in your code! In the grand scheme of things, those changes are small and should not affect everyone, but this is technically our most aggressive release so far in term of API breakage. If you want to be extra forward-facing, you can enable `#define IMGUI_DISABLE_OBSOLETE_FUNCTIONS` in your imconfig.h to disable the obsolete names/redirection. + +- Renamed `IsItemHoveredRect()` to `IsItemRectHovered()`. Kept inline redirection function (will obsolete). +- Renamed `IsMouseHoveringWindow()` to `IsWindowRectHovered()` for consistency. Kept inline redirection function (will obsolete). +- Renamed `IsMouseHoveringAnyWindow()` to `IsAnyWindowHovered()` for consistency. Kept inline redirection function (will obsolete). +- Renamed `ImGuiCol_Columns***` enums to `ImGuiCol_Separator***`. Kept redirection enums (will obsolete). +- Renamed `ImGuiSetCond***` types and enums to `ImGuiCond***`. Kept redirection enums (will obsolete). +- Renamed `GetStyleColName()` to `GetStyleColorName()` for consistency. Unlikely to be used by end-user! +- Added `PushStyleColor(ImGuiCol idx, ImU32 col)` overload, which _might_ cause an "ambiguous call" compilation error if you are using ImColor() with implicit cast. Cast to ImU32 or ImVec4 explicily to fix. +- Marked the weird `IMGUI_ONCE_UPON_A_FRAME` helper macro as obsolete. Prefer using the more explicit `ImGuiOnceUponAFrame`. +- Changed `ColorEdit4(const char* label, float col[4], bool show_alpha = true)` signature to `ColorEdit4(const char* label, float col[4], ImGuiColorEditFlags flags = 0)`, where flags 0x01 is a safe no-op (hello dodgy backward compatibility!). The new `ColorEdit4`/`ColorPicker4` functions have lots of available flags! Check and run the demo window, under "Color/Picker Widgets", to understand the various new options. +- Changed signature of `ColorButton(ImVec4 col, bool small_height = false, bool outline_border = true)` to `ColorButton(const char* desc_id, ImVec4 col, ImGuiColorEditFlags flags = 0, ImVec2 size = ImVec2(0,0))`. This function was rarely used and was very dodgy (no explicit ID!). +- Changed `BeginPopupContextWindow(bool also_over_items=true, const char* str_id=NULL, int mouse_button=1)` signature to `(const char* str_id=NULL, int mouse_button=1, bool also_over_items=true)`. This is perhaps the most aggressive change in this update, but note that the majority of users relied on default parameters completely, so this will affect only a fraction of users of this already rarely used function. +- Removed `IsPosHoveringAnyWindow()`, which was partly broken and misleading. In the vast majority of cases, people using that function wanted to use `io.WantCaptureMouse` flag. Replaced with IM_ASSERT + comment redirecting user to `io.WantCaptureMouse`. (#1237) +- Removed the old `ValueColor()` helpers, they are equivalent to calling `Text(label)` + `SameLine()` + `ColorButton()`. +- Removed `ColorEditMode()` and `ImGuiColorEditMode` type in favor of `ImGuiColorEditFlags` and parameters to the various Color*() functions. The `SetColorEditOptions()` function allows to initialize default but the user can still change them with right-click context menu. Commenting out your old call to `ColorEditMode()` may just be fine! + +Other Changes: + +- Added flags to `ColorEdit3()`, `ColorEdit4()`. The color edit widget now has a context-menu and access to the color picker. (#346) +- Added flags to `ColorButton()`. (#346) +- Added `ColorPicker3()`, `ColorPicker4()`. The API along with those of the updated `ColorEdit4()` was designed so you may use them in various situation and hopefully compose your own picker if required. There are a bunch of available flags, check the Demo window and comment for `ImGuiColorEditFlags_`. Some of the options it supports are: two color picker types (hue bar + sat/val rectangle, hue wheel + rotating sat/val triangle), display as u8 or float, lifting 0.0..1.0 constraints (currently rgba only), context menus, alpha bar, background checkerboard options, preview tooltip, basic revert. For simple use, calling the existing `ColorEdit4()` function as you did before will be enough, as you can now open the color picker from there. (#346) [@r-lyeh, @nem0, @thennequin, @dariomanesku and @ocornut] +- Added `SetColorEditOptions()` to set default color options (e.g. if you want HSV over RGBA, float over u8, select a default picker mode etc. at startup time without a user intervention. Note that the user can still change options with the context menu unless disabled with `ImGuiColorFlags_NoOptions` or explicitly enforcing a display type/picker mode etc.). +- Added user-facing `IsPopupOpen()` function. (#891) [@mkeeter] +- Added `GetColorU32(u32)` variant that perform the style alpha multiply without a floating-point round trip, and helps makes code more consistent when using ImDrawList APIs. +- Added `PushStyleColor(ImGuiCol idx, ImU32 col)` overload. +- Added `GetStyleColorVec4(ImGuiCol idx)` which is equivalent to accessing `ImGui::GetStyle().Colors[idx]` (aka return the raw style color without alpha alteration). +- ImFontAtlas: Added `GlyphRangesBuilder` helper class, which makes it easier to build custom glyph ranges from your app/game localization data, or add into existing glyph ranges. +- ImFontAtlas: Added `TexGlyphPadding` option. (#1282) [@jadwallis] +- ImFontAtlas: Made it possible to override size of AddFontDefault() (even if it isn't really recommended!). +- ImDrawList: Added `GetClipRectMin()`, `GetClipRectMax()` helpers. +- Fixed Ini saving crash if the ImGuiWindowFlags_NoSavedSettings gets removed from a window after its creation (unlikely!). (#1000) +- Fixed `PushID()`/`PopID()` from marking parent window as Accessed (which needlessly woke up the root "Debug" window when used outside of a regular window). (#747) +- Fixed an assert when calling `CloseCurrentPopup()` twice in a row. [@nem0] +- Window size can be loaded from .ini data even if ImGuiWindowFlags_NoResize flag is set. (#1048, #1056) +- Columns: Added `SetColumnWidth()`. (#913) [@ggtucker] +- Columns: Dragging a column preserve its width by default. (#913) [@ggtucker] +- Columns: Fixed first column appearing wider than others. (#1266) +- Columns: Fixed allocating space on the right-most side with the assumption of a vertical scrollbar. The space is only allocated when needed. (#125, #913, #893, #1138) +- Columns: Fixed the right-most column from registering its content width to the parent window, which led to various issues when using auto-resizing window or e.g. horizonal scrolling. (#519, #125, #913) +- Columns: Refactored some of the columns code internally toward a better API (not yet exposed) + minor optimizations. (#913) [@ggtucker, @ocornut] +- Popups: Most popups windows can be moved by the user after appearing (if they don't have explicit positions provided by caller, or e.g. sub-menu popup). The previous restriction was totally arbitrary. (#1252) +- Tooltip: `SetTooltip()` is expanded immediately into a window, honoring current font / styling setting. Add internal mechanism to override tooltips. (#862) +- PlotHistogram: bars are drawn based on zero-line, so negative values are going under. (#828) +- Scrolling: Fixed return values of `GetScrollMaxX()`, `GetScrollMaxY()` when both scrollbars were enabled. Tweak demo to display more data. (#1271) [@degracode] +- Scrolling: Fixes for Vertical Scrollbar not automatically getting enabled if enabled Horizontal Scrollbar straddle the vertical limit. (#1271, #246) +- Scrolling: `SetScrollHere()`, `SetScrollFromPosY()`: Fixed Y scroll aiming when Horizontal Scrollbar is enabled. (#665). +- [Windows] Clipboard: Fixed not closing win32 clipboard on early open failure path. (#1264) +- Removed an unnecessary dependency on int64_t which failed on some older compilers. +- Demo: Rearranged everything under Widgets in a more consistent way. +- Demo: Columns: Added Horizontal Scrolling demo. Tweaked another Columns demo. (#519, #125, #913) +- Examples: OpenGL: Various makefiles for MINGW, Linux. (#1209, #1229, #1209) [@fr500, @acda] +- Examples: Enabled vsync by default in example applications, so it doesn't confuse people that the sample run at 2000+ fps and waste an entire CPU. (#1213, #1151). +- Various other small fixes, tweaks, comments, optimizations. + +----------------------------------------------------------------------- + +VERSION 1.50 (2017-06-02) +Decorated log: https://github.com/ocornut/imgui/releases/tag/v1.50 + +Breaking Changes: + + - Added a void* user_data parameter to Clipboard function handlers. (#875) + - SameLine(x) with x>0.0f is now relative to left of column/group if any, and not always to left of window. This was sort of always the intent and hopefully breakage should be minimal. + - Renamed ImDrawList::PathFill() - rarely used directly - to ImDrawList::PathFillConvex() for clarity and consistency. + - Removed ImFontConfig::MergeGlyphCenterV in favor of a more multipurpose ImFontConfig::GlyphOffset. + - Style: style.WindowTitleAlign is now a ImVec2 (ImGuiAlign enum was removed). set to (0.5f,0.5f) for horizontal+vertical centering, (0.0f,0.0f) for upper-left, etc. + - BeginChild(const char*) now applies the stack id to the provided label, consistently with other functions as it should always have been. It shouldn't affect you unless (extremely unlikely) you were appending multiple times to a same child from different locations of the stack id. If that's the case, generate an id with GetId() and use it instead of passing string to BeginChild(). + +Other Changes: + +- InputText(): Added support for CTRL+Backspace (delete word). +- InputText(): OSX uses Super+Arrows for home/end. Add Shortcut+Backspace support. (#650) [@michaelbartnett] +- InputText(): Got rid of individual OSX-specific options in ImGuiIO, added a single io.OSXBehaviors flag. (#473, #650) +- InputText(): Fixed pressing home key on last character when it isn't a trailing \n (#588, #815) +- InputText(): Fixed state corruption/crash bug in stb_textedit.h redo logic when exhausting undo/redo char buffer. (#715. #681) +- InputTextMultiline(): Fixed Ctrl+DownArrow moving scrolling out of bounds. +- InputTextMultiline(): Scrollbar fix for when input and latched internal buffers differs in a way that affects vertical scrollbar existence. (#725) +- ImFormatString(): Fixed an overflow handling bug with implementation of vsnprintf() that do not return -1. (#793) +- BeginChild(const char*) now applies stack id to provided label, consistent with other widgets. (#894, #713) +- SameLine() with explicit X position is relative to left of group/columns. (ref #746, #125, #630) +- SliderInt(), SliderFloat() supports reverse direction (where v_min > v_max). (#854) +- SliderInt(), SliderFloat() better support for when v_min==v_max. (#919) +- SliderInt(), SliderFloat() enforces writing back value when interacting, to be consistent with other widgets. (#919) +- SliderInt, SliderFloat(): Fixed edge case where style.GrabMinSize being bigger than slider width can lead to a division by zero. (#919) +- Added IsRectVisible() variation with explicit start-end positions. (#768) [@thedmd] +- Fixed TextUnformatted() clipping bug in the large-text path when horizontal scroll has been applied. (#692, #246) +- Fixed minor text clipping issue in window title when using font straying above usual line. (#699) +- Fixed SetCursorScreenPos() fixed not adjusting CursorMaxPos as well. +- Fixed scrolling offset when using SetScrollY(), SetScrollFromPosY(), SetScrollHere() with menu bar. +- Fixed using IsItemActive() after EndGroup() or any widget using groups. (#840, #479) +- Fixed IsItemActive() lagging by one frame on initial widget activation. (#840) +- Fixed Separator() zero-height bounding box resulting in clipping when laying exactly on top line of clipping rectangle (#860) +- Fixed PlotLines() PlotHistogram() calling with values_count == 0. +- Fixed clicking on a window's void while staying still overzealously marking .ini settings as dirty. (#923) +- Fixed assert triggering when a window has zero rendering but has a callback. (#810) +- Scrollbar: Fixed rendering when sizes are negative to reduce glitches (which can happen with certain style settings and zero WindowMinSize). +- EndGroup(): Made IsItemHovered() work when an item was activated within the group. (#849) +- BulletText(): Fixed stopping to display formatted string after the '##' mark. +- Closing the focused window restore focus to the first active root window in descending z-order .(part of #727) +- Word-wrapping: Fixed a bug where we never wrapped after a 1 character word. [@sronsse] +- Word-wrapping: Fixed TextWrapped() overriding wrap position if one is already set. (#690) +- Word-wrapping: Fixed incorrect testing for negative wrap coordinates, they are perfectly legal. (#706) +- ImGuiListClipper: fixed automatic-height calc path dumbly having user display element 0 twice. (#661, #716) +- ImGuiListClipper: Fix to behave within column. (#661, #662, #716) +- ImDrawList: Renamed ImDrawList::PathFill() to ImDrawList::PathFillConvex() for clarity. (BREAKING API) +- Columns: End() avoid calling Columns(1) if no columns set is open, not sure why it wasn't the case already (pros: faster, cons: exercise less code). +- ColorButton(): Fix ColorButton showing wrong hex value for alpha. (#1068) [@codecat] +- ColorEdit4(): better preserve inputting value out of 0..255 range, display then clamped in Hexadecimal form. +- Shutdown() clear out some remaining pointers for sanity. (#836) +- Added IMGUI_USE_BGRA_PACKED_COLOR option in imconfig.h (#767, #844) [@thedmd] +- Style: Removed the inconsistent shadow under RenderCollapseTriangle() (~#707) +- Style: Added ButtonTextAlign, ImGuiStyleVar_ButtonTextAlign. (#842) +- ImFont: Allowing to use up to 0xFFFE glyphs in same font (increased from previous 0x8000). +- ImFont: Added GetGlyphRangesThai() helper. [@nProtect] +- ImFont: CalcWordWrapPositionA() fixed font scaling with fallback character. +- ImFont: Calculate and store the approximate texture surface to get an idea of how costly each source font is. +- ImFontConfig: Added GlyphOffset to explicitely offset glyphs at font build time, useful for merged fonts. Removed MergeGlyphCenterV. (BREAKING API) +- Clarified asserts in CheckStacksSize() when there is a stack mismatch. +- Context: Support for #define-ing GImGui and IMGUI_SET_CURRENT_CONTEXT_FUNC to enable custom thread-based hackery (#586) +- Updated stb_truetype.h to 1.14 (added OTF support, removed warnings). (#883, #976) +- Updated stb_rect_pack.h to 0.10 (removed warnings). (#883) +- Added ImGuiMouseCursor_None enum value for convenient usage by app/binding. +- Clipboard: Added a void* user_data parameter to Clipboard function handlers. (#875) (BREAKING API) +- Internals: Refactor internal text alignment options to use ImVec2, removed ImGuiAlign. (#842, #222) +- Internals: Renamed ImLoadFileToMemory to ImFileLoadToMemory to be consistent with ImFileOpen + fix mismatching .h name. (#917) +- Windows: Fixed Windows default clipboard handler leaving its buffer unfreed on application's exit. (#714) +- Windows: No default IME handler when compiling for Windows using GCC. (#738) +- Windows: Now using _wfopen() instead of fopen() to allow passing in paths/filenames with UTF-8 characters. (#917) +- Tools: binary_to_compressed_c: Avoid ?? trigraphs sequences in string outputs which break some older compilers. (#839) +- Demo: Added an extra 3-way columns demo. +- Demo: ShowStyleEditor: show font character map / grid in more details. +- Demo: Console: Fixed a completion bug when multiple candidates are equals and match until the end. +- Demo: Fixed 1-byte off overflow in the ShowStyleEditor() combo usage. (#783) [@bear24rw] +- Examples: Accessing ImVector fields directly, feel less stl-ey. (#810) +- Examples: OpenGL*: Saving/restoring existing scissor rectangle for completeness. (#807) +- Examples: OpenGL*: Saving/restoring active texture number (the value modified by glActiveTexture). (#1087, #1088, #1116) +- Examples: OpenGL*: Saving/restoring separate color/alpha blend functions correctly. (#1120) [@greggman] +- Examples: OpenGL2: Uploading font texture as RGBA32 to increase compatibility with users shaders for beginners. (#824) +- Examples: Vulkan: Countless fixes and improvements. (#785, #804, #910, #1017, #1039, #1041, #1042, #1043, #1080) [@martty, @Loftilus, @ParticlePeter, @SaschaWillems] +- Examples: DirectX9/10/10: Only call SetCursor(NULL) is io.MouseDrawCursor is set. (#585, #909) +- Examples: DirectX9: Explicitely setting viewport to match that other examples are doing. (#937) +- Examples: GLFW+OpenGL3: Fixed Shutdown() calling GL functions with NULL parameters if NewFrame was never called. (#800) +- Examples: GLFW+OpenGL2: Renaming opengl_example/ to opengl2_example/ for clarity. +- Examples: SDL+OpenGL: explicitly setting GL_UNPACK_ROW_LENGTH to reduce issues because SDL changes it. (#752) +- Examples: SDL2: Added build .bat files for Win32. +- Added various links to language/engine bindings. +- Various other minor fixes, tweaks, comments, optimizations. + +----------------------------------------------------------------------- + +VERSION 1.49 (2016-05-09) +Decorated log: https://github.com/ocornut/imgui/releases/tag/v1.49 + +Breaking Changes: + +- Renamed `SetNextTreeNodeOpened()` to `SetNextTreeNodeOpen()` for consistency, no redirection. +- Removed confusing set of `GetInternalState()`, `GetInternalStateSize()`, `SetInternalState()` functions. Now using `CreateContext()`, `DestroyContext()`, `GetCurrentContext()`, `SetCurrentContext()`. If you were using multiple contexts the change should be obvious and trivial. +- Obsoleted old signature of `CollapsingHeader(const char* label, const char* str_id = NULL, bool display_frame = true, bool default_open = false)`, as extra parameters were badly designed and rarely used. Most uses were using 1 parameter and shouldn't affect you. You can replace the "default_open = true" flag in new API with `CollapsingHeader(label, ImGuiTreeNodeFlags_DefaultOpen)`. +- Changed `ImDrawList::PushClipRect(ImVec4 rect)` to `ImDraw::PushClipRect(Imvec2 min,ImVec2 max,bool intersect_with_current_clip_rect=false)`. Note that higher-level `ImGui::PushClipRect()` is preferable because it will clip at logic/widget level, whereas `ImDrawList::PushClipRect()` only affect your renderer. +- Title bar (using ImGuiCol_TitleBg/ImGuiCol_TitleBgActive colors) isn't rendered over a window background (ImGuiCol_WindowBg color) anymore (see #655). If your TitleBg/TitleBgActive alpha was 1.0f or you are using the default theme it will not affect you. However if your TitleBg/TitleBgActive alpha was <1.0f you need to tweak your custom theme to readjust for the fact that we don't draw a WindowBg background behind the title bar. + This helper function will convert an old TitleBg/TitleBgActive color into a new one with the same visual output, given the OLD color and the OLD WindowBg color. (Or If this is confusing, just pick the RGB value from title bar from an old screenshot and apply this as TitleBg/TitleBgActive. Or you may just create TitleBgActive from a tweaked TitleBg color.) + + ImVec4 ConvertTitleBgCol(const ImVec4& win_bg_col, const ImVec4& title_bg_col) + { + float new_a = 1.0f - ((1.0f - win_bg_col.w) * (1.0f - title_bg_col.w)); + float k = title_bg_col.w / new_a; + return ImVec4((win_bg_col.x * win_bg_col.w + title_bg_col.x) * k, (win_bg_col.y * win_bg_col.w + title_bg_col.y) * k, (win_bg_col.z * win_bg_col.w + title_bg_col.z) * k, new_a); + } + +Other changes: + +- New version of ImGuiListClipper helper calculates item height automatically. See comments and demo code. (#662, #661, #660) +- Added SetNextWindowSizeConstraints() to enable basic min/max and programmatic size constraints on window. Added demo. (#668) +- Added PushClipRect()/PopClipRect() (previously part of imgui_internal.h). Changed ImDrawList::PushClipRect() prototype. (#610) +- Added IsRootWindowOrAnyChildHovered() helper. (#615) +- Added TreeNodeEx() functions. (#581, #600, #190) +- Added ImGuiTreeNodeFlags_Selected flag to display treenode as "selected". (#581, #190) +- Added ImGuiTreeNodeFlags_AllowOverlapMode flag. (#600) +- Added ImGuiTreeNodeFlags_NoTreePushOnOpen flag (#590). +- Added ImGuiTreeNodeFlags_NoAutoOpenOnLog flag (previously private). +- Added ImGuiTreeNodeFlags_DefaultOpen flag (previously private). +- Added ImGuiTreeNodeFlags_OpenOnDoubleClick flag. +- Added ImGuiTreeNodeFlags_OpenOnArrow flag. +- Added ImGuiTreeNodeFlags_Leaf flag, always opened, no arrow, for convenience. For simple use case prefer using TreeAdvanceToLabelPos()+Text(). +- Added ImGuiTreeNodeFlags_Bullet flag, to add a bullet to Leaf node or replace Arrow with a bullet. +- Added TreeAdvanceToLabelPos(), GetTreeNodeToLabelSpacing() helpers. (#581, #324) +- Added CreateContext()/DestroyContext()/GetCurrentContext()/SetCurrentContext(). Obsoleted nearly identical GetInternalState()/SetInternalState() functions. (#586, #269) +- Added NewLine() to undo a SameLine() and as a shy reminder that horizontal layout support hasn't been implemented yet. +- Added IsItemClicked() helper. (#581) +- Added CollapsingHeader() variant with close button. (#600) +- Fixed MenuBar missing lower border when borders are enabled. +- InputText(): Fixed clipping of cursor rendering in case it gets out of the box (which can be forced w/ ImGuiInputTextFlags_NoHorizontalScroll. (#601) +- Style: Changed default IndentSpacing from 22 to 21. (#581, #324) +- Style: Fixed TitleBg/TitleBgActive color being rendered above WindowBg color, which was inconsistent and causing visual artefact. (#655) + This broke the meaning of TitleBg and TitleBgActive. Only affect values where Alpha<1.0f. Fixed default theme. Read comments in "API BREAKING CHANGES" section to convert. +- Relative rendering of order of Child windows creation is preserved, to allow more control with overlapping childs. (#595) +- Fixed GetWindowContentRegionMax() being off by ScrollbarSize amount when explicit SizeContents is set. +- Indent(), Unindent(): optional non-default indenting width. (#324, #581) +- Bullet(), BulletText(): Slightly bigger. Less polygons. +- ButtonBehavior(): fixed subtle old bug when a repeating button would also return true on mouse release (barely noticeable unless RepeatRate is set to be very slow). (#656) +- BeginMenu(): a menu that becomes disabled while open gets closed down, facilitate user's code. (#126) +- BeginGroup(): fixed using within Columns set. (#630) +- Fixed a lag in reading the currently hovered window when dragging a window. (#635) +- Obsoleted 4 parameters version of CollapsingHeader(). Refactored code into TreeNodeBehavior. (#600, #579) +- Scrollbar: minor fix for top-right rounding of scrollbar background when window has menubar but no title bar. +- MenuItem(): checkmark render in disabled color when menu item is disabled. +- Fixed clipping rectangle floating point representation to ensure renderer-side float point operations yield correct results in typical DirectX/GL settings. (#582, 597) +- Fixed GetFrontMostModalRootWindow(), fixing missing fade-out when a combo pop was used stacked over a modal window. (#604) +- ImDrawList: Added AddQuad(), AddQuadFilled() helpers. +- ImDrawList: AddText() refactor, moving some code to ImFont, reserving less unused vertices when large vertical clipping occurs. +- ImFont: Added RenderChar() helper. +- ImFont: Added AddRemapChar() helper. (#609) +- ImFontConfig: Clarified persistence requirement of GlyphRanges array. (#651) +- ImGuiStorage: Added bool helper functions for completeness. +- AddFontFromMemoryCompressedTTF(): Fix font config propagation. (#587) +- Renamed majority of use of the word "opened" to "open" for clarity. Renamed SetNextTreeNodeOpened() to SetNextTreeNodeOpen(). (#625, #579) +- Examples: OpenGL3: Saving/restoring glActiveTexture() state. (#602) +- Examples: DirectX9: save/restore all device state. +- Examples: DirectX9: Removed dependency on d3dx9.h, d3dx9.lib, dxguid.lib so it can be used in a DirectXMath.h only environment. (#611) +- Examples: DirectX10/X11: Apply depth-stencil state (no use of depth buffer). (#640, #636) +- Examples: DirectX11/X11: Added comments on removing dependency on D3DCompiler. (#638) +- Examples: SDL: Initialize video+timer subsystem only. +- Examples: Apple/iOS: lowered xcode project deployment target from 10.7 to 10.11. (#598, #575) + +----------------------------------------------------------------------- + +VERSION 1.48 (2016-04-09) +Decorated log: https://github.com/ocornut/imgui/releases/tag/v1.48 + +Breaking Changes: + +- Consistently honoring exact width passed to PushItemWidth() (when positive), previously it would add extra FramePadding.x*2 over that width. Some hand-tuned layout may be affected slightly. (#346) +- Style: removed `style.WindowFillAlphaDefault` which was confusing and redundant, baked alpha into `ImGuiCol_WindowBg` color. If you had a custom WindowBg color but didn't change WindowFillAlphaDefault, multiply WindowBg alpha component by 0.7. Renamed `ImGuiCol_TooltipBg` to `ImGuiCol_PopupBG`, applies to other types of popups. `bg_alpha` parameter of 5-parameters version of Begin() is an override. (#337) +- InputText(): Added BufTextLen field in ImGuiTextEditCallbackData. Requesting user to update it if the buffer is modified in the callback. Added a temporary length-check assert to minimize panic for the 3 people using the callback. (#541) +- Renamed GetWindowFont() to GetFont(), GetWindowFontSize() to GetFontSize(). Kept inline redirection function (will obsolete). (#340) + +Other Changes: + +- Consistently honoring exact width passed to PushItemWidth(), previously it would add extra FramePadding.x*2 over that width. Some hand-tuned layout may be affected slightly. (#346) +- Fixed clipping of child windows within parent not taking account of child outer clipping boundaries (including scrollbar, etc.). (#506) +- TextUnformatted(): Fixed rare crash bug with large blurb of text (2k+) not finished with a '\n' and fully above the clipping Y line. (#535) +- IO: Added 'KeySuper' field to hold Cmd keyboard modifiers for OS X. Updated all examples accordingly. (#473) +- Added ImGuiWindowFlags_ForceVerticalScrollbar, ImGuiWindowFlags_ForceHorizontalScrollbar flags. (#476) +- Added IM_COL32 macros to generate a U32 packed color, convenient for direct use of ImDrawList api. (#346) +- Added GetFontTexUvWhitePixel() helper, convenient for direct use of ImDrawList api. +- Selectable(): Added ImGuiSelectableFlags_AllowDoubleClick flag to allow user reacting on double-click. (@zapolnov) (#516) +- Begin(): made the close button explicitly set the boolean to false instead of toggling it. (#499) +- BeginChild()/EndChild(): fixed incorrect layout to allow widgets submitted after an auto-fitted child window. (#540) +- BeginChild(): Added ImGuiWindowFlags_AlwaysUseWindowPadding flag to ensure non-bordered child window uses window padding. (#462) +- Fixed InputTextMultiLine(), ListBox(), BeginChildFrame(), ProgressBar(): outer frame not honoring bordering. (#462, #503) +- Fixed Image(), ImageButtion() rendering a rectangle 1 px too large on each axis. (#457) +- SetItemAllowOverlap(): Promoted from imgui_internal.h to public imgui.h api. (#517) +- Combo(): Right-most button stays highlighted when popup is open. +- Combo(): Display popup above if there's isn't enough space below / or select largest side. (#505) +- DragFloat(), SliderFloat(), InputFloat(): fixed cases of erroneously returning true repeatedly after a text input modification (e.g. "0.0" --> "0.000" would keep returning true). (#564) +- DragFloat(): Always apply value when mouse is held/widget active, so that an always-reseting variable (e.g. non saved local) can be passed. +- InputText(): OS X friendly behaviors: Word movement uses Alt key; Shortcuts uses Cmd key; Double-clicking text select a single word; Jumping to next word sets cursor to end of current word instead of beginning of current word. (@zhiayang), (#473) +- InputText(): Added BufTextLen in ImGuiTextEditCallbackData. Requesting user to maintain it if buffer is modified. Zero-ing structure properly before use. (#541) +- CheckboxFlags(): Added support for testing/setting multiple flags at the same time. (@DMartinek) (#555) +- TreeNode(), CollapsingHeader() fixed not being able to use "##" sequence in a formatted label. +- ColorEdit4(): Empty label doesn't add InnerSpacing.x, matching behavior of other widgets. (#346) +- ColorEdit4(): Removed unnecessary calls to scanf() when idle in hexadecimal edit mode. +- BeginPopupContextItem(), BeginPopupContextWindow(): added early out optimization. +- CaptureKeyboardFromApp() / CaptureMouseFromApp(): added argument to allow clearing the capture flag. (#533) +- ImDrawList: Fixed index-overflow check broken by AddText() casting current index back to ImDrawIdx. (#514) +- ImDrawList: Fixed incorrect removal of trailing draw command if it is a callback command. +- ImDrawList: Allow windows with only a callback only to be functional. (#524) +- ImDrawList: Fixed ImDrawList::AddRect() which used to render a rectangle 1 px too large on each axis. (#457) +- ImDrawList: Fixed ImDrawList::AddCircle() to fit precisely within bounding box like AddCircleFilled() and AddRectFilled(). (#457) +- ImDrawList: AddCircle(), AddRect() takes optional thickness parameter. +- ImDrawList: Added AddTriangle(). +- ImDrawList: Added PrimQuadUV() helper to ease custom rendering of textured quads (require primitive reserve). +- ImDrawList: Allow AddText(ImFont\* font, float font_size, ...) variant to take NULL/0.0f as default. +- ImFontAtlas: heuristic increase default texture width up for large number of glyphs. (#491) +- ImTextBuffer: Fixed empty() helper which was utterly broken. +- Metrics: allow to inspect individual triangles in drawcalls. +- Demo: added more draw primitives in the Custom Rendering example. (#457) +- Demo: extra comments and example for PushItemWidth(-1) patterns. +- Demo: InputText password demo filters out blanks. (#515) +- Demo: Fixed malloc/free mismatch and leak when destructing demo console, if it has been used. (@fungos) (#536) +- Demo: plot code doesn't use ImVector to avoid heap allocation and be more friendly to custom allocator users. (#538) +- Fixed compilation on DragonFly BSD (@mneumann) (#563) +- Examples: Vulkan: Added a Vulkan example (@Loftilus) (#549) +- Examples: DX10, DX11: Saving/restoring most device state so dropping render function in your codebase shouldn't have DX device side-effects. (#570) +- Examples: DX10, DX11: Fixed ImGui_ImplDX??_NewFrame() from recreating device objects if render isn't called (g_pVB not set). +- Examples: OpenGL3: Fix BindVertexArray/BindBuffer order. (@nlguillemot) (#527) +- Examples: OpenGL: skip rendering and calling glViewport() if we have zero-fixed buffer. (#486) +- Examples: SDL2+OpenGL3: Fix context creation options. Made ImGui_ImplSdlGL3_NewFrame() signature match GL2 one. (#468, #463) +- Examples: SDL2+OpenGL2/3: Fix for high-dpi displays. (@nickgravelyn) +- Various extra comments and clarification in the code. +- Various other fixes and optimisations. + +----------------------------------------------------------------------- + +For older version, see https://github.com/ocornut/imgui/releases + From bd267ad7396d8141531dc800a2d27e712710dd3c Mon Sep 17 00:00:00 2001 From: omar Date: Sun, 25 Feb 2018 14:14:17 +0100 Subject: [PATCH 723/823] Changelog: Added all change infos since 1.53 up to the current version. --- CHANGELOG.txt | 125 ++++++++++++++++++++++++++++++++++++++++++++++++-- imgui.cpp | 2 +- 2 files changed, 122 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.txt b/CHANGELOG.txt index fd2f57590ee7..a0f0e2a7ffb9 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -4,7 +4,7 @@ CHANGELOG ----------------------------------------------------------------------- This document holds the programmer changelog that we also use in release notes. -We generally fold multiple commits pertaining to the same topic as a single entry and simplify a few things. +We generally fold multiple commits pertaining to the same topic as a single entry, and simplify various things. Release notes: (with links and screenshots) https://github.com/ocornut/imgui/releases @@ -39,7 +39,124 @@ HOW TO UPDATE? VERSION 1.60 WIP (Latest, currently in development) - +The gamepad/keyboard navigation branch (which has been in the work since July 2016) has been merged. +Gamepad/keyboard navigation is still marked as Beta and has to be enabled explicitely. +Various internal refactors have also been done, as part of the navigation work and as part of the upcoing viewport/docking work. + +Breaking Changes: +(IN PROGRESS, WILL ADD TO THIS LIST AS WE WORK ON 1.60) + + - BeginDragDropSource(): temporarily removed the optional mouse_button=0 parameter because it is not really usable in many situations at the moment. + - Obsoleted the io.RenderDrawListsFn callback, you can call your graphics engine render function after ImGui::Render(). Use ImGui::GetDrawData() to retrieve the ImDrawData* to display. + - Reorganized context handling to be more explicit, + - YOU NOW NEED TO CALL ImGui::CreateContext() AT THE BEGINNING OF YOUR APP, AND CALL ImGui::DestroyContext() AT THE END. + - removed Shutdown() function, as DestroyContext() serve this purpose. + - you may pass a ImFontAtlas* pointer to CreateContext() to share a font atlas between contexts. Otherwhise CreateContext() will create its own font atlas instance. + - removed allocator parameters from CreateContext(), they are now setup with SetAllocatorFunctions(), and shared by all contexts. + - removed the default global context and font atlas instance, which were confusing for users of DLL reloading and users of multiple contexts. + - Moved sample TTF files from extra_fonts/ to misc/fonts/. If you loaded files directly from the imgui repo you may need to update your paths. + - Obsoleted IsAnyWindowHovered() in favor of IsWindowHovered(ImGuiHoveredFlags_AnyWindow). Kept redirection function (will obsolete). + - Obsoleted IsAnyWindowFocused() in favor of IsWindowFocused(ImGuiFocusedFlags_AnyWindow). Kept redirection function (will obsolete). + - Renamed ImGuiSizeConstraintCallback to ImGuiSizeCallback, ImGuiSizeConstraintCallbackData to ImGuiSizeCallbackData. + - Removed CalcItemRectClosestPoint() which was weird and not really used by anyone except demo code. If you need it it's easy to replicate on your side. + +Other Changes: +(IN PROGRESS, WILL ADD TO THIS LIST AS WE WORK ON 1.60) + +- Navigation: merged in the gamepad/keyboard navigation (about one million changes!). (#787, #323) + The initial focus was to support game controllers, but keyboard is becoming increasingly and decently usable. + - To use Keyboard Navigation: + - Set io.NavFlags |= ImGuiNavFlags_EnableKeyboard to enable. NewFrame() will automatically fill io.NavInputs[] based on your io.KeyDown[] + io.KeyMap[] arrays. + - When keyboard navigation is active (io.NavActive + NavFlags_EnableKeyboard), the io.WantCaptureKeyboard flag will be set. + For more advanced uses, you may want to read from io.NavActive or io.NavVisible. Read imgui.cpp for more details. + - To use Gamepad Navigation: + - Set io.NavFlags |= ImGuiNavFlags_EnableGamepad to enable. Fill the io.NavInputs[] fields before calling NewFrame(). Note that io.NavInputs[] is cleared by EndFrame(). + - See https://github.com/ocornut/imgui/issues/1599 for recommended gamepad mapping. + - See 'enum ImGuiNavInput_' in imgui.h for a description of inputs. Read imgui.cpp for more details. +- Navigation: SetItemDefaultFocus() sets the navigation position in addition to scrolling. (#787) +- Navigation: Added IsItemFocused(), added IsAnyItemFocused(). (#787) +- Navigation: Added window flags: ImGuiWindowFlags_NoNav (ImGuiWindowFlags_NoNavInputs | ImGuiWindowFlags_NoNavFocus). +- Navigation: Style: Added ImGuiCol_NavHighlight, ImGuiCol_NavWindowingHighlight colors. (#787) +- Navigation: TreeNode: Added ImGuiTreeNodeFlags_NavLeftJumpsBackHere flag to allow Nav Left direction to jump back to parent tree node from any of its child. (#1079) +- Navigation: IO: Added io.NavFlags (input), io.NavActive (output), io.NavVisible (output). (#787) +- Context: Removed the default global context and font atlas instances, which caused various problems to users of multiple contexts and DLL users. (#1565) + YOU NOW NEED TO CALL ImGui::CreateContext() AT THE BEGINNING OF YOUR APP, AND CALL ImGui::DestroyContext() AT THE END. Existing apps will assert/crash without it. +- Context: Removed allocator parameters from CreateContext(), they are now setup with SetAllocatorFunctions() and shared by all contexts. (#1565, #586, #992, #1007, #1558) +- Context: You may pass a ImFontAtlas to CreateContext() to specify a font atlas to share. Shared font atlas are not owned by the context and not destroyed along with it. +- Context: Added IMGUI_DISABLE_DEFAULT_ALLOCATORS to disable linking with malloc/free. (#1565, #586, #992, #1007, #1558) +- IO: Added ImGuiKey_Insert, ImGuiKey_Space keys. Setup in all example bindings. (#1541) +- IO: Added Horizontal Mouse Wheel support for horizontal scrolling. (#1463) [@tseeker] +- IO: Added IsAnyMouseDown() helper which is helpful for bindings to handle mouse capturing. +- Window: Clicking on a window with the ImGuiWIndowFlags_NoMove flags takes an ActiveId so we can't hover something else when dragging afterwards. (ref #1381, #1337) +- Window: IsWindowHovered(): Added ImGuiHoveredFlags_AnyWindow, ImGuiFocusedFlags_AnyWindow flags (See Breaking Changes). Added to demo. (#1382) +- Window: Added SetNextWindowBgAlpha() helper. Particularly helpul since the legacy 5-parameters version of Begin() has been marked as obsolete in 1.53. (#1567) +- Window: Fixed SetNextWindowContentSize() with 0.0f on Y axis (or SetNextWindowContentWidth()) overwriting the contents size. Got broken on Dec 10 (1.53). (#1363) +- Window: CloseButton: Fixed cross positioning being a little off. +- InputText: Added alternative clipboard shortcuts: Shift+Delete (cut), Ctrl+Insert (copy), Shift+Insert (paste). (#1541) +- InputText: Fixed losing Cursor X position when clicking outside on an item that's submitted after the InputText(). It was only noticeable when restoring focus programmatically. (#1418, #1554) +- Style: Enable window border by default. (#707) +- Style: Exposed ImGuiStyleVar_WindowTitleAlign, ImGuiStyleVar_ScrollbarSize, ImGuiStyleVar_ScrollbarRounding, ImGuiStyleVar_GrabRounding + added an assert to reduce accidental breakage. (#1181) +- Style: Added style.MouseCursorScale help when using the software mouse cursor facility. (#939). +- Popup: OpenPopup() Always reopen existing popup. (Removed imgui_internal.h's OpenPopupEx() which was used for this.) (#1497, #1533). +- Popup: BeginPopupContextItem(), BeginPopupContextWindow(), BeginPopupContextVoid(), OpenPopupOnItemClick() all react on mouse release instead of mouse press. (~#439) +- Popup: Better handling of user mistakenly calling OpenPopup() every frame (with reopen_existing option). The error will now be more visible and easier to understand. (#1497) +- Popup: BeginPopup(): Exposed extra_flags parameter that are passed through to Begin(). (#1533) +- Popup: BeginPopupModal: fixed the conditional test for SetNextWindowPos() which was polling the wrong window, which in practice made the test succeed all the time. +- Tooltip: BeginTooltip() sets NoInputs flag. +- Scrollbar: Fixed ScrollbarY enable test after ScrollbarX has been enabled being a little off (small regression from Nov 2017). (#1574) +- Scrollbar: Fixed ScrollbarX enable test subtracting WindowPadding.x (this has been there since the addition of horizontal scroll bar!). +- Columns: Clear offsets data when columns count changed. (#1525) +- Columns: Fixed a memory leak of ImGuiColumnsSet's Columns vector. (#1529) [@unprompted] +- MenuBar: Fixed menu bar pushing a clipping rect outside of its allocated bound (usually unnoticeable). +- TreeNode: nodes with the ImGuiTreeNodeFlags_Leaf flag correctly disable highlight when DragDrop is active. (#143, #581) +- Drag and Drop: Increased payload type string to 12 characters instead of 8. (#143) +- Drag and Drop: TreeNode as drop target displays rectangle over full frame. (#1597, #143) +- DragFloat: Fix/workaround for backends which do not preserve a valid mouse position when dragged out of bounds. (#1559) +- PlotLines: plot a flat line if scale_min==scale_max. (#1621) +- ImFontAtlas: Handle stb_truetype stbtt_InitFont() and stbtt_PackBegin() possible failures more gracefully, GetTexDataAsRGBA32() won't crash during conversion. (#1527) +- ImFontAtlas: Moved mouse cursor data out of ImGuiContext, fix drawing them with multiple contexts. Also remove the last remaining undesirable dependency on ImGui in imgui_draw.cpp. (#939) +- ImFontAtlas: Added ImFontAtlasFlags_NoPowerOfTwoHeight flag to disable padding font height to nearest power of two. (#1613) +- ImFontAtlas: Added ImFontAtlasFlags_NoMouseCursors flag to disable baking software mouse cursors, mostly to save texture memory on very low end hardware. (#1613) +- ImDrawList: Fixed AddRect() with antialiasing disabled (lower-right corner pixel was often missing, rounding looks a little better.) (#1646) +- Misc: Functions passed to libc qsort are explicitely marked cdecl to support compiling with vectorcall as the default calling convention. (#1230, #1611) [@RandyGaul] +- Misc: ImVec2: added [] operator. This is becoming desirable for some types of code, better added sooner than later. +- Misc: Exposed IM_OFFSETOF() helper in imgui.h. +- Misc: NewFrame(): Added an assert to detect incorrect filling of the io.KeyMap[] array earlier. (#1555) +- Misc: Added obsolete redirection function GetItemsLineHeightWithSpacing() (which redirects to GetFrameHeightWithSpacing()), as intended and stated in docs of 1.53. +- Misc: Added misc/natvis/imgui.natvis for visual studio debugger users to easily visualizer imgui internal types. Added to examples projects. +- Misc: Added IMGUI_USER_CONFIG to define a custom configuration filename. (#255, #1573, #1144, #41) +- Misc: Updated stb_rect_pack from 0.10 to 0.11 (minor changes). +- Fonts: Updated stb_truetype from 1.14 to stb_truetype 1.19. (w/ include fix from some platforms #1622) +- Fonts: Added optional FreeType rasterizer in misc/freetype. Moved from imgui_club repo. (#618) [@Vuhdo, @mikesart, @ocornut] +- Fonts: Moved extra_fonts/ to misc/fonts/. +- Demo: Improved Selectable() examples. (#1528) +- Demo: Tweaked the Child demos, added a menu bar to the second child to test some navigation functions. +- Demo: Console: Using ImGuiCol_Text to be more friendly to color changes. +- Demo: Using IM_COL32() instead of ImColor() in ImDrawList centric contexts. Trying to phase out use of the ImColor helper whenever possible. +- Examples: Files in examples/ now include their own changelog so it is easier to occasionally update your bindings if needed. +- Examples: Using Dark theme by default. (#707). Tweaked demo code. +- Examples: Added support for horizontal mouse wheel for API that allows it. (#1463) +- Examples: DirectX12: Added DirectX 12 example. (#301) [@jdm3] +- Examples: OpenGL3+GLFW,SDL: Changed GLSL shader version to 150 (#1466, #1504). +- Examples: OpenGL3+GLFW,SDL: Creating VAO in the render function so it can be more easily used by multiple shared OpenGL contexts. (#1217) +- Examples: OpenGL3+GLFW: Using 3.2 context instead of 3.3. (#1466) +- Examples: OpenGL: Setting up glPixelStorei() explicitly before uploading texture. +- Examples: OpenGL: Calls to glPolygonMode() are casting parameters as GLEnum to not fail with more strict bindings. (#1628) [@ilia-glushchenko] +- Examples: Win32 (DirectX9,10,11,12): Added support for mouse cursor shapes. (#1495) +- Examples: Win32 (DirectX9,10,11,12: Support for windows using the CS_DBLCLKS class flag by handling the double-click messages (WM_LBUTTONDBLCLK etc.). (#1538, #754) [@ndandoulakis] +- Examples: Win32 (DirectX9,10,11,12): Made the Win32 proc handlers not assert if there is no active context yet, to be more flexible with creation order. (#1565) +- Examples: GLFW: Added support for mouse cursor shapes (the diagonal resize cursors are unfortunately not supported by GLFW at the moment. (#1495) +- Examples: SDL: Added support for mouse cursor shapes. (#1626) [@olls] +- Examples: SDL: Using SDL_CaptureMouse() to retrieve coordinates outside of client area when dragging (SDL 2.0.4+ only, otherwise using SDL_WINDOW_INPUT_FOCUS instead of previously SDL_WINDOW_MOUSE_FOCUS). (#1559) +- Examples: SDL: Enabled vsync by default so people don't come at us with demoes running at 2000 FPS burning a cpu core. +- Examples: SDL: Using SDL_GetPerformanceCounter() / SDL_GetPerformanceFrequency() to handle framerate over 1000 FPS properly. (#996) +- Examples: SDL: Using scancode exclusively instead of a confusing mixture of scancodes and keycodes. +- Examples: SDL: Visual Studio: Added .vcxproj file. Using %SDL2_DIR% in the default .vcxproj and build files instead of %SDL_DIR%, the earlier being more standard. +- Examples: Vulkan: Visual Studio: Added .vcxproj file. +- Examples: Apple: Fixed filenames in OSX xcode project. Various other Mac friendly fixes. [@gerryhernandez etc.] +- Examples: Visual Studio: Disabled extraneous function-level check in Release build. +- Internals: Lots of refactoring! +- Various minor fixes, tweaks, optimizations, comments. ----------------------------------------------------------------------- @@ -72,13 +189,13 @@ Other Changes: - Added `io.OptCursorBlink` option to allow disabling cursor blinking. (#1427) - Added `GetOverlayDrawList()` helper to quickly get access to a ImDrawList that will be rendered in front of every windows. - Added `GetFrameHeight()` helper which returns `(FontSize + style.FramePadding.y * 2)`. -- DragDrop: Added Beta API to easily use drag and drop patterns between imgui widgets. +- Drag and Drop: Added Beta API to easily use drag and drop patterns between imgui widgets. - Setup a source on a widget with `BeginDragDropSource()`, `SetDragDropPayload()`, `EndDragDropSource()` functions. - Receive data with `BeginDragDropTarget()`, `AcceptDragDropPayload()`, `EndDragDropTarget()`. - See ImGuiDragDropFlags for various options. - The ColorEdit4() and ColorButton() widgets now support Drag and Drop. - The API is tagged as Beta as it still may be subject to small changes. -- DragDrop: When drag and drop is active, tree nodes and collapsing header can be opened by hovering on them for 0.7 seconds. +- Drag and Drop: When drag and drop is active, tree nodes and collapsing header can be opened by hovering on them for 0.7 seconds. - Renamed io.OSXBehaviors to io.OptMacOSXBehaviors. Should not affect users as the compile-time default is usually enough. (#473, #650) - Style: Added StyleColorsDark() style. (#707) [@dougbinks] - Style: Added StyleColorsLight() style. Best used with frame borders + thicker font than the default font. (#707) diff --git a/imgui.cpp b/imgui.cpp index 7475120bf042..c53edb8414b2 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -250,7 +250,7 @@ Here is a change-log of API breaking changes, if you are using one of the functions listed, expect to have to fix some code. Also read releases logs https://github.com/ocornut/imgui/releases for more details. - - 2018/02/18 (1.60) - BeginDragDropSource(): temporarily removed the optional mouse_button=0 parameter because it is really usable in typical conditions at the moment. + - 2018/02/18 (1.60) - BeginDragDropSource(): temporarily removed the optional mouse_button=0 parameter because it is not really usable in many situations at the moment. - 2018/02/16 (1.60) - obsoleted the io.RenderDrawListsFn callback, you can call your graphics engine render function after ImGui::Render(). Use ImGui::GetDrawData() to retrieve the ImDrawData* to display. - 2018/02/07 (1.60) - reorganized context handling to be more explicit, - YOU NOW NEED TO CALL ImGui::CreateContext() AT THE BEGINNING OF YOUR APP, AND CALL ImGui::DestroyContext() AT THE END. From 5427eca960fc95249cf290eff124e6d27e16bf04 Mon Sep 17 00:00:00 2001 From: omar Date: Sun, 25 Feb 2018 19:05:31 +0100 Subject: [PATCH 724/823] Compacted some old Breaking Changes notes (Pre July 2015 stuff) --- imgui.cpp | 32 ++++++++------------------------ 1 file changed, 8 insertions(+), 24 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index c53edb8414b2..4b387f4522ef 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -340,18 +340,11 @@ this necessary change will break your rendering function! the fix should be very easy. sorry for that :( - if you are using a vanilla copy of one of the imgui_impl_XXXX.cpp provided in the example, you just need to update your copy and you can ignore the rest. - the signature of the io.RenderDrawListsFn handler has changed! - ImGui_XXXX_RenderDrawLists(ImDrawList** const cmd_lists, int cmd_lists_count) - became: - ImGui_XXXX_RenderDrawLists(ImDrawData* draw_data). - argument 'cmd_lists' -> 'draw_data->CmdLists' - argument 'cmd_lists_count' -> 'draw_data->CmdListsCount' - ImDrawList 'commands' -> 'CmdBuffer' - ImDrawList 'vtx_buffer' -> 'VtxBuffer' - ImDrawList n/a -> 'IdxBuffer' (new) - ImDrawCmd 'vtx_count' -> 'ElemCount' - ImDrawCmd 'clip_rect' -> 'ClipRect' - ImDrawCmd 'user_callback' -> 'UserCallback' - ImDrawCmd 'texture_id' -> 'TextureId' + old: ImGui_XXXX_RenderDrawLists(ImDrawList** const cmd_lists, int cmd_lists_count) + new: ImGui_XXXX_RenderDrawLists(ImDrawData* draw_data). + argument: 'cmd_lists' becomes 'draw_data->CmdLists', 'cmd_lists_count' becomes 'draw_data->CmdListsCount' + ImDrawList: 'commands' becomes 'CmdBuffer', 'vtx_buffer' becomes 'VtxBuffer', 'IdxBuffer' is new. + ImDrawCmd: 'vtx_count' becomes 'ElemCount', 'clip_rect' becomes 'ClipRect', 'user_callback' becomes 'UserCallback', 'texture_id' becomes 'TextureId'. - each ImDrawList now contains both a vertex buffer and an index buffer. For each command, render ElemCount/3 triangles using indices from the index buffer. - if you REALLY cannot render indexed primitives, you can call the draw_data->DeIndexAllBuffers() method to de-index the buffers. This is slow and a waste of CPU/GPU. Prefer using indexed rendering! - refer to code in the examples/ folder or ask on the GitHub if you are unsure of how to upgrade. please upgrade! @@ -382,18 +375,9 @@ - 2015/01/19 (1.30) - renamed ImGuiStorage::GetIntPtr()/GetFloatPtr() to GetIntRef()/GetIntRef() because Ptr was conflicting with actual pointer storage functions. - 2015/01/11 (1.30) - big font/image API change! now loads TTF file. allow for multiple fonts. no need for a PNG loader. (1.30) - removed GetDefaultFontData(). uses io.Fonts->GetTextureData*() API to retrieve uncompressed pixels. - this sequence: - const void* png_data; - unsigned int png_size; - ImGui::GetDefaultFontData(NULL, NULL, &png_data, &png_size); - // - became: - unsigned char* pixels; - int width, height; - io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); - // - io.Fonts->TexID = (your_texture_identifier); - you now have much more flexibility to load multiple TTF fonts and manage the texture buffer for internal needs. + font init: const void* png_data; unsigned int png_size; ImGui::GetDefaultFontData(NULL, NULL, &png_data, &png_size); <..Upload texture to GPU..> + became: unsigned char* pixels; int width, height; io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); <..Upload texture to GPU>; io.Fonts->TexId = YourTextureIdentifier; + you now more flexibility to load multiple TTF fonts and manage the texture buffer for internal needs. it is now recommended that you sample the font texture with bilinear interpolation. (1.30) - added texture identifier in ImDrawCmd passed to your render function (we can now render images). make sure to set io.Fonts->TexID. (1.30) - removed IO.PixelCenterOffset (unnecessary, can be handled in user projection matrix) From c7835dd1892ab11750cd6917b37b74e426fe13b9 Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 26 Feb 2018 13:10:34 +0100 Subject: [PATCH 725/823] ImRect: Removed misleading IsFinite() function used by some Nav code. --- imgui.cpp | 4 ++-- imgui_internal.h | 1 - 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 4b387f4522ef..3a6d681ecd9b 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -3211,7 +3211,7 @@ static void ImGui::NavUpdate() } // For scoring we use a single segment on the left side our current item bounding box (not touching the edge to avoid box overlap with zero-spaced items) - ImRect nav_rect_rel = (g.NavWindow && g.NavWindow->NavRectRel[g.NavLayer].IsFinite()) ? g.NavWindow->NavRectRel[g.NavLayer] : ImRect(0,0,0,0); + ImRect nav_rect_rel = (g.NavWindow && !g.NavWindow->NavRectRel[g.NavLayer].IsInverted()) ? g.NavWindow->NavRectRel[g.NavLayer] : ImRect(0,0,0,0); g.NavScoringRectScreen = g.NavWindow ? ImRect(g.NavWindow->Pos + nav_rect_rel.Min, g.NavWindow->Pos + nav_rect_rel.Max) : GetViewportRect(); g.NavScoringRectScreen.Min.x = ImMin(g.NavScoringRectScreen.Min.x + 1.0f, g.NavScoringRectScreen.Max.x); g.NavScoringRectScreen.Max.x = g.NavScoringRectScreen.Min.x; @@ -13202,7 +13202,7 @@ void ImGui::ShowMetricsWindow(bool* p_open) ImGui::BulletText("Active: %d, WriteAccessed: %d", window->Active, window->WriteAccessed); ImGui::BulletText("NavLastIds: 0x%08X,0x%08X, NavLayerActiveMask: %X", window->NavLastIds[0], window->NavLastIds[1], window->DC.NavLayerActiveMask); ImGui::BulletText("NavLastChildNavWindow: %s", window->NavLastChildNavWindow ? window->NavLastChildNavWindow->Name : "NULL"); - if (window->NavRectRel[0].IsFinite()) + if (window->NavRectRel[0].IsInverted()) ImGui::BulletText("NavRectRel[0]: (%.1f,%.1f)(%.1f,%.1f)", window->NavRectRel[0].Min.x, window->NavRectRel[0].Min.y, window->NavRectRel[0].Max.x, window->NavRectRel[0].Max.y); else ImGui::BulletText("NavRectRel[0]: "); diff --git a/imgui_internal.h b/imgui_internal.h index 221e5d46984d..ddbbf0d77e84 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -341,7 +341,6 @@ struct IMGUI_API ImRect void Floor() { Min.x = (float)(int)Min.x; Min.y = (float)(int)Min.y; Max.x = (float)(int)Max.x; Max.y = (float)(int)Max.y; } void FixInverted() { if (Min.x > Max.x) ImSwap(Min.x, Max.x); if (Min.y > Max.y) ImSwap(Min.y, Max.y); } bool IsInverted() const { return Min.x > Max.x || Min.y > Max.y; } - bool IsFinite() const { return Min.x != FLT_MAX; } }; // Stacked color modifier, backup of modified data so we can restore it From a869e944b0671f406f3359ebb18a3947edbe1ab2 Mon Sep 17 00:00:00 2001 From: Hossam Ayman Date: Mon, 26 Feb 2018 17:31:02 +0200 Subject: [PATCH 726/823] README.md typo fix --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 51e9193a1d14..1190405ac4fa 100644 --- a/README.md +++ b/README.md @@ -107,7 +107,7 @@ Integrating Dear ImGui within your custom engine is a matter of 1) wiring mouse/ _NB: those third-party bindings may be more or less maintained, more or less close to the original API (as people who create language bindings sometimes haven't used the C++ API themselves.. for the good reason that they aren't C++ users). Dear ImGui was designed with C++ in mind and some of the subtleties may be lost in translation with other languages. If your language supports it, I would suggest replicating the function overloading and default parameters used in the original, else the API may be harder to use. In doubt, please check the original C++ version first!_ -Languages: (third-party bindinds) +Languages: (third-party bindings) - C: [cimgui](https://github.com/Extrawurst/cimgui) - C#/.Net: [ImGui.NET](https://github.com/mellinoe/ImGui.NET) - ChaiScript: [imgui-chaiscript](https://github.com/JuJuBoSc/imgui-chaiscript) From 2c9f45bbe7260139b4fdb3c0285ecf170cdd4522 Mon Sep 17 00:00:00 2001 From: omar Date: Wed, 28 Feb 2018 18:51:40 +0100 Subject: [PATCH 727/823] Renamed ImGuiNavFlags io.NavFlags to ImGuiConfigFlags io.ConfigFlags. (#787) --- CHANGELOG.txt | 8 +++--- README.md | 2 +- examples/allegro5_example/main.cpp | 2 +- .../directx10_example/imgui_impl_dx10.cpp | 2 +- examples/directx10_example/main.cpp | 2 +- .../directx11_example/imgui_impl_dx11.cpp | 2 +- examples/directx11_example/main.cpp | 2 +- examples/directx12_example/main.cpp | 2 +- examples/directx9_example/main.cpp | 2 +- examples/marmalade_example/main.cpp | 2 +- .../opengl2_example/imgui_impl_glfw_gl2.cpp | 2 +- examples/opengl2_example/main.cpp | 2 +- .../opengl3_example/imgui_impl_glfw_gl3.cpp | 8 +++--- .../opengl3_example/imgui_impl_glfw_gl3.h | 2 +- examples/opengl3_example/main.cpp | 4 +-- examples/sdl_opengl2_example/main.cpp | 2 +- examples/sdl_opengl3_example/main.cpp | 2 +- examples/vulkan_example/main.cpp | 3 +- imgui.cpp | 28 +++++++++---------- imgui.h | 22 +++++++-------- imgui_demo.cpp | 6 ++-- imgui_internal.h | 4 +-- 22 files changed, 56 insertions(+), 55 deletions(-) diff --git a/CHANGELOG.txt b/CHANGELOG.txt index a0f0e2a7ffb9..06ee3c3ba087 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -66,11 +66,11 @@ Other Changes: - Navigation: merged in the gamepad/keyboard navigation (about one million changes!). (#787, #323) The initial focus was to support game controllers, but keyboard is becoming increasingly and decently usable. - To use Keyboard Navigation: - - Set io.NavFlags |= ImGuiNavFlags_EnableKeyboard to enable. NewFrame() will automatically fill io.NavInputs[] based on your io.KeyDown[] + io.KeyMap[] arrays. - - When keyboard navigation is active (io.NavActive + NavFlags_EnableKeyboard), the io.WantCaptureKeyboard flag will be set. + - Set io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard to enable. NewFrame() will automatically fill io.NavInputs[] based on your io.KeyDown[] + io.KeyMap[] arrays. + - When keyboard navigation is active (io.NavActive + ImGuiConfigFlags_NavEnableKeyboard), the io.WantCaptureKeyboard flag will be set. For more advanced uses, you may want to read from io.NavActive or io.NavVisible. Read imgui.cpp for more details. - To use Gamepad Navigation: - - Set io.NavFlags |= ImGuiNavFlags_EnableGamepad to enable. Fill the io.NavInputs[] fields before calling NewFrame(). Note that io.NavInputs[] is cleared by EndFrame(). + - Set io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad to enable. Fill the io.NavInputs[] fields before calling NewFrame(). Note that io.NavInputs[] is cleared by EndFrame(). - See https://github.com/ocornut/imgui/issues/1599 for recommended gamepad mapping. - See 'enum ImGuiNavInput_' in imgui.h for a description of inputs. Read imgui.cpp for more details. - Navigation: SetItemDefaultFocus() sets the navigation position in addition to scrolling. (#787) @@ -78,7 +78,7 @@ Other Changes: - Navigation: Added window flags: ImGuiWindowFlags_NoNav (ImGuiWindowFlags_NoNavInputs | ImGuiWindowFlags_NoNavFocus). - Navigation: Style: Added ImGuiCol_NavHighlight, ImGuiCol_NavWindowingHighlight colors. (#787) - Navigation: TreeNode: Added ImGuiTreeNodeFlags_NavLeftJumpsBackHere flag to allow Nav Left direction to jump back to parent tree node from any of its child. (#1079) -- Navigation: IO: Added io.NavFlags (input), io.NavActive (output), io.NavVisible (output). (#787) +- Navigation: IO: Added io.ConfigFlags (input), io.NavActive (output), io.NavVisible (output). (#787) - Context: Removed the default global context and font atlas instances, which caused various problems to users of multiple contexts and DLL users. (#1565) YOU NOW NEED TO CALL ImGui::CreateContext() AT THE BEGINNING OF YOUR APP, AND CALL ImGui::DestroyContext() AT THE END. Existing apps will assert/crash without it. - Context: Removed allocator parameters from CreateContext(), they are now setup with SetAllocatorFunctions() and shared by all contexts. (#1565, #586, #992, #1007, #1558) diff --git a/README.md b/README.md index 1190405ac4fa..da7979635baf 100644 --- a/README.md +++ b/README.md @@ -248,7 +248,7 @@ See the FAQ in imgui.cpp for answers. How do you use Dear ImGui on a platform that may not have a mouse or keyboard? -You can control Dear ImGui with a gamepad, see the explanation in imgui.cpp about how to use the navigation feature (short version: map your gamepad inputs into the `io.NavInputs[]` array and set `io.NavFlags |= ImGuiNavFlags_EnableGamepad`). +You can control Dear ImGui with a gamepad, see the explanation in imgui.cpp about how to use the navigation feature (short version: map your gamepad inputs into the `io.NavInputs[]` array and set `io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad`). You can share your computer mouse seamlessy with your console/tablet/phone using [Synergy](http://synergy-project.org). This is the prefered solution for developer productivity. In particular, their [micro-synergy-client](https://github.com/symless/micro-synergy-client) repo there is _uSynergy.c_ sources for a small embeddable that you can use on any platform to connect to your host PC. You may also use a third party solution such as [Remote ImGui](https://github.com/JordiRos/remoteimgui). diff --git a/examples/allegro5_example/main.cpp b/examples/allegro5_example/main.cpp index 1478573cce9b..6169ebca2ce0 100644 --- a/examples/allegro5_example/main.cpp +++ b/examples/allegro5_example/main.cpp @@ -25,8 +25,8 @@ int main(int, char**) // Setup ImGui binding ImGui::CreateContext(); ImGuiIO& io = ImGui::GetIO(); (void)io; + //io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls ImGui_ImplA5_Init(display); - //io.NavFlags |= ImGuiNavFlags_EnableKeyboard; // Enable Keyboard Controls // Setup style ImGui::StyleColorsDark(); diff --git a/examples/directx10_example/imgui_impl_dx10.cpp b/examples/directx10_example/imgui_impl_dx10.cpp index ed1efeef56d3..caef5e1b5116 100644 --- a/examples/directx10_example/imgui_impl_dx10.cpp +++ b/examples/directx10_example/imgui_impl_dx10.cpp @@ -14,7 +14,7 @@ // 2018-02-16: Misc: Obsoleted the io.RenderDrawListsFn callback and exposed ImGui_ImplDX10_RenderDrawData() in the .h file so you can call it yourself. // 2018-02-06: Misc: Removed call to ImGui::Shutdown() which is not available from 1.60 WIP, user needs to call CreateContext/DestroyContext themselves. // 2018-02-06: Inputs: Added mapping for ImGuiKey_Space. -// 2018-02-06: Inputs: Honoring the io.WantMoveMouse by repositioning the mouse by using navigation and ImGuiNavFlags_MoveMouse is set. +// 2018-02-06: Inputs: Honoring the io.WantMoveMouse by repositioning the mouse (when using navigation and ImGuiConfigFlags_NavMoveMouse is set). // 2018-01-20: Inputs: Added Horizontal Mouse Wheel support. // 2018-01-08: Inputs: Added mapping for ImGuiKey_Insert. // 2018-01-05: Inputs: Added WM_LBUTTONDBLCLK double-click handlers for window classes with the CS_DBLCLKS flag. diff --git a/examples/directx10_example/main.cpp b/examples/directx10_example/main.cpp index 346fd35e29e4..f1afdf66aba0 100644 --- a/examples/directx10_example/main.cpp +++ b/examples/directx10_example/main.cpp @@ -114,8 +114,8 @@ int main(int, char**) // Setup ImGui binding ImGui::CreateContext(); ImGuiIO& io = ImGui::GetIO(); (void)io; + //io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls ImGui_ImplDX10_Init(hwnd, g_pd3dDevice); - //io.NavFlags |= ImGuiNavFlags_EnableKeyboard; // Enable Keyboard Controls // Setup style ImGui::StyleColorsDark(); diff --git a/examples/directx11_example/imgui_impl_dx11.cpp b/examples/directx11_example/imgui_impl_dx11.cpp index 84dcdbee49c1..c7f312c6d15b 100644 --- a/examples/directx11_example/imgui_impl_dx11.cpp +++ b/examples/directx11_example/imgui_impl_dx11.cpp @@ -14,7 +14,7 @@ // 2018-02-16: Misc: Obsoleted the io.RenderDrawListsFn callback and exposed ImGui_ImplDX11_RenderDrawData() in the .h file so you can call it yourself. // 2018-02-06: Misc: Removed call to ImGui::Shutdown() which is not available from 1.60 WIP, user needs to call CreateContext/DestroyContext themselves. // 2018-02-06: Inputs: Added mapping for ImGuiKey_Space. -// 2018-02-06: Inputs: Honoring the io.WantMoveMouse by repositioning the mouse by using navigation and ImGuiNavFlags_MoveMouse is set. +// 2018-02-06: Inputs: Honoring the io.WantMoveMouse by repositioning the mouse (when using navigation and ImGuiConfigFlags_NavMoveMouse is set). // 2018-01-20: Inputs: Added Horizontal Mouse Wheel support. // 2018-01-08: Inputs: Added mapping for ImGuiKey_Insert. // 2018-01-05: Inputs: Added WM_LBUTTONDBLCLK double-click handlers for window classes with the CS_DBLCLKS flag. diff --git a/examples/directx11_example/main.cpp b/examples/directx11_example/main.cpp index 518aa7c27274..d9ef40d1fe19 100644 --- a/examples/directx11_example/main.cpp +++ b/examples/directx11_example/main.cpp @@ -117,8 +117,8 @@ int main(int, char**) // Setup ImGui binding ImGui::CreateContext(); ImGuiIO& io = ImGui::GetIO(); (void)io; + //io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls ImGui_ImplDX11_Init(hwnd, g_pd3dDevice, g_pd3dDeviceContext); - //io.NavFlags |= ImGuiNavFlags_EnableKeyboard; // Enable Keyboard Controls // Setup style ImGui::StyleColorsDark(); diff --git a/examples/directx12_example/main.cpp b/examples/directx12_example/main.cpp index 6a4b78d85e84..65fe70b5984d 100644 --- a/examples/directx12_example/main.cpp +++ b/examples/directx12_example/main.cpp @@ -288,7 +288,7 @@ int main(int, char**) // Setup ImGui binding ImGui::CreateContext(); ImGuiIO& io = ImGui::GetIO(); (void)io; - //io.NavFlags |= ImGuiNavFlags_EnableKeyboard; // Enable Keyboard Controls + //io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls ImGui_ImplDX12_Init(hwnd, NUM_FRAMES_IN_FLIGHT, g_pd3dDevice, DXGI_FORMAT_R8G8B8A8_UNORM, g_pd3dSrvDescHeap->GetCPUDescriptorHandleForHeapStart(), diff --git a/examples/directx9_example/main.cpp b/examples/directx9_example/main.cpp index f4c7a9f0c6a2..fce9482e822b 100644 --- a/examples/directx9_example/main.cpp +++ b/examples/directx9_example/main.cpp @@ -77,8 +77,8 @@ int main(int, char**) // Setup ImGui binding ImGui::CreateContext(); ImGuiIO& io = ImGui::GetIO(); (void)io; + //io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls ImGui_ImplDX9_Init(hwnd, g_pd3dDevice); - //io.NavFlags |= ImGuiNavFlags_EnableKeyboard; // Enable Keyboard Controls // Setup style ImGui::StyleColorsDark(); diff --git a/examples/marmalade_example/main.cpp b/examples/marmalade_example/main.cpp index f2ddae404829..cb9113edf862 100644 --- a/examples/marmalade_example/main.cpp +++ b/examples/marmalade_example/main.cpp @@ -19,8 +19,8 @@ int main(int, char**) // Setup ImGui binding ImGui::CreateContext(); ImGuiIO& io = ImGui::GetIO(); (void)io; + //io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls ImGui_Marmalade_Init(true); - //io.NavFlags |= ImGuiNavFlags_EnableKeyboard; // Enable Keyboard Controls // Setup style ImGui::StyleColorsDark(); diff --git a/examples/opengl2_example/imgui_impl_glfw_gl2.cpp b/examples/opengl2_example/imgui_impl_glfw_gl2.cpp index f78b77be8e80..03d7659e06bc 100644 --- a/examples/opengl2_example/imgui_impl_glfw_gl2.cpp +++ b/examples/opengl2_example/imgui_impl_glfw_gl2.cpp @@ -24,7 +24,7 @@ // 2018-02-16: Misc: Obsoleted the io.RenderDrawListsFn callback and exposed ImGui_ImplGlfwGL2_RenderDrawData() in the .h file so you can call it yourself. // 2018-02-06: Misc: Removed call to ImGui::Shutdown() which is not available from 1.60 WIP, user needs to call CreateContext/DestroyContext themselves. // 2018-02-06: Inputs: Added mapping for ImGuiKey_Space. -// 2018-01-25: Inputs: Honoring the io.WantMoveMouse by repositioning the mouse by using navigation and ImGuiNavFlags_MoveMouse is set. +// 2018-02-06: Inputs: Honoring the io.WantMoveMouse by repositioning the mouse (when using navigation and ImGuiConfigFlags_NavMoveMouse is set). // 2018-01-20: Inputs: Added Horizontal Mouse Wheel support. // 2018-01-18: Inputs: Added mapping for ImGuiKey_Insert. // 2018-01-09: Misc: Renamed imgui_impl_glfw.* to imgui_impl_glfw_gl2.*. diff --git a/examples/opengl2_example/main.cpp b/examples/opengl2_example/main.cpp index caae8c2b66c9..370606888e3c 100644 --- a/examples/opengl2_example/main.cpp +++ b/examples/opengl2_example/main.cpp @@ -29,8 +29,8 @@ int main(int, char**) // Setup ImGui binding ImGui::CreateContext(); ImGuiIO& io = ImGui::GetIO(); (void)io; + //io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls ImGui_ImplGlfwGL2_Init(window, true); - //io.NavFlags |= ImGuiNavFlags_EnableKeyboard; // Enable Keyboard Controls // Setup style ImGui::StyleColorsDark(); diff --git a/examples/opengl3_example/imgui_impl_glfw_gl3.cpp b/examples/opengl3_example/imgui_impl_glfw_gl3.cpp index ce8030b17f4b..40b0c4d41b4a 100644 --- a/examples/opengl3_example/imgui_impl_glfw_gl3.cpp +++ b/examples/opengl3_example/imgui_impl_glfw_gl3.cpp @@ -4,7 +4,7 @@ // Implemented features: // [X] User texture binding. Cast 'GLuint' OpenGL texture identifier as void*/ImTextureID. Read the FAQ about ImTextureID in imgui.cpp. -// [X] Gamepad navigation mapping. Enable with 'io.NavFlags |= ImGuiNavFlags_EnableGamepad'. +// [X] Gamepad navigation mapping. Enable with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'. // You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this. // If you use this binding you'll need to call 4 functions: ImGui_ImplXXXX_Init(), ImGui_ImplXXXX_NewFrame(), ImGui::Render() and ImGui_ImplXXXX_Shutdown(). @@ -19,8 +19,8 @@ // 2018-02-16: Misc: Obsoleted the io.RenderDrawListsFn callback and exposed ImGui_ImplGlfwGL3_RenderDrawData() in the .h file so you can call it yourself. // 2018-02-06: Misc: Removed call to ImGui::Shutdown() which is not available from 1.60 WIP, user needs to call CreateContext/DestroyContext themselves. // 2018-02-06: Inputs: Added mapping for ImGuiKey_Space. -// 2018-01-25: Inputs: Added gamepad support if ImGuiNavFlags_EnableGamepad is set. -// 2018-01-25: Inputs: Honoring the io.WantMoveMouse by repositioning the mouse by using navigation and ImGuiNavFlags_MoveMouse is set. +// 2018-01-25: Inputs: Added gamepad support if ImGuiConfigFlags_NavEnableGamepad is set. +// 2018-01-25: Inputs: Honoring the io.WantMoveMouse by repositioning the mouse (when using navigation and ImGuiConfigFlags_NavMoveMouse is set). // 2018-01-20: Inputs: Added Horizontal Mouse Wheel support. // 2018-01-18: Inputs: Added mapping for ImGuiKey_Insert. // 2018-01-07: OpenGL: Changed GLSL shader version from 330 to 150. (Also changed GL context from 3.3 to 3.2 in example's main.cpp) @@ -469,7 +469,7 @@ void ImGui_ImplGlfwGL3_NewFrame() // Gamepad navigation mapping [BETA] memset(io.NavInputs, 0, sizeof(io.NavInputs)); - if (io.NavFlags & ImGuiNavFlags_EnableGamepad) + if (io.ConfigFlags & ImGuiConfigFlags_NavEnableGamepad) { // Update gamepad inputs #define MAP_BUTTON(NAV_NO, BUTTON_NO) { if (buttons_count > BUTTON_NO && buttons[BUTTON_NO] == GLFW_PRESS) io.NavInputs[NAV_NO] = 1.0f; } diff --git a/examples/opengl3_example/imgui_impl_glfw_gl3.h b/examples/opengl3_example/imgui_impl_glfw_gl3.h index 71ea4122c8ab..6cbbe4a5cdba 100644 --- a/examples/opengl3_example/imgui_impl_glfw_gl3.h +++ b/examples/opengl3_example/imgui_impl_glfw_gl3.h @@ -4,7 +4,7 @@ // Implemented features: // [X] User texture binding. Cast 'GLuint' OpenGL texture identifier as void*/ImTextureID. Read the FAQ about ImTextureID in imgui.cpp. -// [X] Gamepad navigation mapping. Enable with 'io.NavFlags |= ImGuiNavFlags_EnableGamepad'. +// [X] Gamepad navigation mapping. Enable with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'. // You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this. // If you use this binding you'll need to call 4 functions: ImGui_ImplXXXX_Init(), ImGui_ImplXXXX_NewFrame(), ImGui::Render() and ImGui_ImplXXXX_Shutdown(). diff --git a/examples/opengl3_example/main.cpp b/examples/opengl3_example/main.cpp index a5f59e8aaf22..143dcc596967 100644 --- a/examples/opengl3_example/main.cpp +++ b/examples/opengl3_example/main.cpp @@ -34,9 +34,9 @@ int main(int, char**) // Setup ImGui binding ImGui::CreateContext(); ImGuiIO& io = ImGui::GetIO(); (void)io; + //io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls + //io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; // Enable Gamepad Controls ImGui_ImplGlfwGL3_Init(window, true); - //io.NavFlags |= ImGuiNavFlags_EnableKeyboard; // Enable Keyboard Controls - //io.NavFlags |= ImGuiNavFlags_EnableGamepad; // Enable Gamepad Controls // Setup style ImGui::StyleColorsDark(); diff --git a/examples/sdl_opengl2_example/main.cpp b/examples/sdl_opengl2_example/main.cpp index 8f4ca93dcb13..2dfdd72bc8ba 100644 --- a/examples/sdl_opengl2_example/main.cpp +++ b/examples/sdl_opengl2_example/main.cpp @@ -36,8 +36,8 @@ int main(int, char**) // Setup ImGui binding ImGui::CreateContext(); ImGuiIO& io = ImGui::GetIO(); (void)io; + //io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls ImGui_ImplSdlGL2_Init(window); - //io.NavFlags |= ImGuiNavFlags_EnableKeyboard; // Enable Keyboard Controls // Setup style ImGui::StyleColorsDark(); diff --git a/examples/sdl_opengl3_example/main.cpp b/examples/sdl_opengl3_example/main.cpp index a3fc625c2512..4426fcdebf46 100644 --- a/examples/sdl_opengl3_example/main.cpp +++ b/examples/sdl_opengl3_example/main.cpp @@ -36,8 +36,8 @@ int main(int, char**) // Setup ImGui binding ImGui::CreateContext(); ImGuiIO& io = ImGui::GetIO(); (void)io; + //io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls ImGui_ImplSdlGL3_Init(window); - //io.NavFlags |= ImGuiNavFlags_EnableKeyboard; // Setup style ImGui::StyleColorsDark(); diff --git a/examples/vulkan_example/main.cpp b/examples/vulkan_example/main.cpp index be5fe528498f..ca6479269f7e 100644 --- a/examples/vulkan_example/main.cpp +++ b/examples/vulkan_example/main.cpp @@ -624,8 +624,9 @@ int main(int, char**) init_data.pipeline_cache = g_PipelineCache; init_data.descriptor_pool = g_DescriptorPool; init_data.check_vk_result = check_vk_result; + + //io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls ImGui_ImplGlfwVulkan_Init(window, true, &init_data); - //io.NavFlags |= ImGuiNavFlags_EnableKeyboard; // Enable Keyboard Controls // Setup style ImGui::StyleColorsDark(); diff --git a/imgui.cpp b/imgui.cpp index 3a6d681ecd9b..be0f532d56d1 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -216,15 +216,15 @@ - Ask questions and report issues at https://github.com/ocornut/imgui/issues/787 - The initial focus was to support game controllers, but keyboard is becoming increasingly and decently usable. - Keyboard: - - Set io.NavFlags |= ImGuiNavFlags_EnableKeyboard to enable. NewFrame() will automatically fill io.NavInputs[] based on your io.KeyDown[] + io.KeyMap[] arrays. - - When keyboard navigation is active (io.NavActive + NavFlags_EnableKeyboard), the io.WantCaptureKeyboard flag will be set. + - Set io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard to enable. NewFrame() will automatically fill io.NavInputs[] based on your io.KeyDown[] + io.KeyMap[] arrays. + - When keyboard navigation is active (io.NavActive + ImGuiConfigFlags_NavEnableKeyboard), the io.WantCaptureKeyboard flag will be set. For more advanced uses, you may want to read from: - io.NavActive: true when a window is focused and it doesn't have the ImGuiWindowFlags_NoNavInputs flag set. - io.NavVisible: true when the navigation cursor is visible (and usually goes false when mouse is used). - or query focus information with e.g. IsWindowFocused(), IsItemFocused() etc. functions. Please reach out if you think the game vs navigation input sharing could be improved. - Gamepad: - - Set io.NavFlags |= ImGuiNavFlags_EnableGamepad to enable. Fill the io.NavInputs[] fields before calling NewFrame(). Note that io.NavInputs[] is cleared by EndFrame(). + - Set io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad to enable. Fill the io.NavInputs[] fields before calling NewFrame(). Note that io.NavInputs[] is cleared by EndFrame(). - See 'enum ImGuiNavInput_' in imgui.h for a description of inputs. For each entry of io.NavInputs[], set the following values: 0.0f= not held. 1.0f= fully held. Pass intermediate 0.0f..1.0f values for analog triggers/sticks. - We uses a simple >0.0f test for activation testing, and won't attempt to test for a dead-zone. @@ -234,11 +234,11 @@ - Mouse: - PS4 users: Consider emulating a mouse cursor with DualShock4 touch pad or a spare analog stick as a mouse-emulation fallback. - Consoles/Tablet/Phone users: Consider using Synergy host (on your computer) + uSynergy.c (in your console/tablet/phone app) to use your PC mouse/keyboard. - - On a TV/console system where readability may be lower or mouse inputs may be awkward, you may want to set the ImGuiNavFlags_MoveMouse flag in io.NavFlags. - Enabling ImGuiNavFlags_MoveMouse instructs dear imgui to move your mouse cursor along with navigation movements. + - On a TV/console system where readability may be lower or mouse inputs may be awkward, you may want to set the ImGuiConfigFlags_NavMoveMouse flag. + Enabling ImGuiConfigFlags_NavMoveMouse instructs dear imgui to move your mouse cursor along with navigation movements. When enabled, the NewFrame() function may alter 'io.MousePos' and set 'io.WantMoveMouse' to notify you that it wants the mouse cursor to be moved. When that happens your back-end NEEDS to move the OS or underlying mouse cursor on the next frame. Some of the binding in examples/ do that. - (If you set the ImGuiNavFlags_MoveMouse flag but don't honor 'io.WantMoveMouse' properly, imgui will misbehave as it will see your mouse as moving back and forth.) + (If you set the NavMoveMouse flag but don't honor 'io.WantMoveMouse' properly, imgui will misbehave as it will see your mouse as moving back and forth!) (In a setup when you may not have easy control over the mouse cursor, e.g. uSynergy.c doesn't expose moving remote mouse cursor, you may want to set a boolean to ignore your other external mouse positions until the external source is moved again.) @@ -847,7 +847,7 @@ ImGuiIO::ImGuiIO() // Settings DisplaySize = ImVec2(-1.0f, -1.0f); DeltaTime = 1.0f/60.0f; - NavFlags = 0x00; + ConfigFlags = 0x00; IniSavingRate = 5.0f; IniFilename = "imgui.ini"; LogFilename = "imgui_log.txt"; @@ -2810,7 +2810,7 @@ static void ImGui::NavUpdateWindowing() bool apply_toggle_layer = false; bool start_windowing_with_gamepad = !g.NavWindowingTarget && IsNavInputPressed(ImGuiNavInput_Menu, ImGuiInputReadMode_Pressed); - bool start_windowing_with_keyboard = !g.NavWindowingTarget && g.IO.KeyCtrl && IsKeyPressedMap(ImGuiKey_Tab) && (g.IO.NavFlags & ImGuiNavFlags_EnableKeyboard); + bool start_windowing_with_keyboard = !g.NavWindowingTarget && g.IO.KeyCtrl && IsKeyPressedMap(ImGuiKey_Tab) && (g.IO.ConfigFlags & ImGuiConfigFlags_NavEnableKeyboard); if (start_windowing_with_gamepad || start_windowing_with_keyboard) if (ImGuiWindow* window = g.NavWindow ? g.NavWindow : FindWindowNavigable(g.Windows.Size - 1, -INT_MAX, -1)) { @@ -2965,7 +2965,7 @@ static void ImGui::NavUpdate() // Update Keyboard->Nav inputs mapping memset(g.IO.NavInputs + ImGuiNavInput_InternalStart_, 0, (ImGuiNavInput_COUNT - ImGuiNavInput_InternalStart_) * sizeof(g.IO.NavInputs[0])); - if (g.IO.NavFlags & ImGuiNavFlags_EnableKeyboard) + if (g.IO.ConfigFlags & ImGuiConfigFlags_NavEnableKeyboard) { #define NAV_MAP_KEY(_KEY, _NAV_INPUT) if (g.IO.KeyMap[_KEY] != -1 && IsKeyDown(g.IO.KeyMap[_KEY])) g.IO.NavInputs[_NAV_INPUT] = 1.0f; NAV_MAP_KEY(ImGuiKey_Space, ImGuiNavInput_Activate ); @@ -3037,7 +3037,7 @@ static void ImGui::NavUpdate() if (g.NavMousePosDirty && g.NavIdIsAlive) { // Set mouse position given our knowledge of the nav widget position from last frame - if (g.IO.NavFlags & ImGuiNavFlags_MoveMouse) + if (g.IO.ConfigFlags & ImGuiConfigFlags_NavMoveMouse) { g.IO.MousePos = g.IO.MousePosPrev = NavCalcPreferredMousePos(); g.IO.WantMoveMouse = true; @@ -3057,7 +3057,7 @@ static void ImGui::NavUpdate() NavUpdateWindowing(); // Set output flags for user application - g.IO.NavActive = (g.IO.NavFlags & (ImGuiNavFlags_EnableGamepad | ImGuiNavFlags_EnableKeyboard)) && g.NavWindow && !(g.NavWindow->Flags & ImGuiWindowFlags_NoNavInputs); + g.IO.NavActive = (g.IO.ConfigFlags & (ImGuiConfigFlags_NavEnableGamepad | ImGuiConfigFlags_NavEnableKeyboard)) && g.NavWindow && !(g.NavWindow->Flags & ImGuiWindowFlags_NoNavInputs); g.IO.NavVisible = (g.IO.NavActive && g.NavId != 0 && !g.NavDisableHighlight) || (g.NavWindowingTarget != NULL) || g.NavInitRequest; // Process NavCancel input (to close a popup, get back to parent, clear focus) @@ -3282,7 +3282,7 @@ void ImGui::NewFrame() IM_ASSERT(g.IO.KeyMap[n] >= -1 && g.IO.KeyMap[n] < IM_ARRAYSIZE(g.IO.KeysDown) && "io.KeyMap[] contains an out of bound value (need to be 0..512, or -1 for unmapped key)"); // Do a simple check for required key mapping (we intentionally do NOT check all keys to not pressure user into setting up everything, but Space is required and was super recently added in 1.60 WIP) - if (g.IO.NavFlags & ImGuiNavFlags_EnableKeyboard) + if (g.IO.ConfigFlags & ImGuiConfigFlags_NavEnableKeyboard) IM_ASSERT(g.IO.KeyMap[ImGuiKey_Space] != -1 && "ImGuiKey_Space is not mapped, required for keyboard navigation."); // Load settings on first frame @@ -3449,7 +3449,7 @@ void ImGui::NewFrame() g.IO.WantCaptureKeyboard = (g.WantCaptureKeyboardNextFrame != 0); else g.IO.WantCaptureKeyboard = (g.ActiveId != 0) || (modal_window != NULL); - if (g.IO.NavActive && (g.IO.NavFlags & ImGuiNavFlags_EnableKeyboard) && !(g.IO.NavFlags & ImGuiNavFlags_NoCaptureKeyboard)) + if (g.IO.NavActive && (g.IO.ConfigFlags & ImGuiConfigFlags_NavEnableKeyboard) && !(g.IO.ConfigFlags & ImGuiConfigFlags_NavNoCaptureKeyboard)) g.IO.WantCaptureKeyboard = true; g.IO.WantTextInput = (g.WantTextInputNextFrame != -1) ? (g.WantTextInputNextFrame != 0) : 0; @@ -5844,7 +5844,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) float sc = g.Style.MouseCursorScale; ImVec2 ref_pos = (!g.NavDisableHighlight && g.NavDisableMouseHover) ? NavCalcPreferredMousePos() : g.IO.MousePos; ImRect rect_to_avoid; - if (!g.NavDisableHighlight && g.NavDisableMouseHover && !(g.IO.NavFlags & ImGuiNavFlags_MoveMouse)) + if (!g.NavDisableHighlight && g.NavDisableMouseHover && !(g.IO.ConfigFlags & ImGuiConfigFlags_NavMoveMouse)) rect_to_avoid = ImRect(ref_pos.x - 16, ref_pos.y - 8, ref_pos.x + 16, ref_pos.y + 8); else rect_to_avoid = ImRect(ref_pos.x - 16, ref_pos.y - 8, ref_pos.x + 24 * sc, ref_pos.y + 24 * sc); // FIXME: Hard-coded based on mouse cursor shape expectation. Exact dimension not very important. diff --git a/imgui.h b/imgui.h index bd63a2b0c9db..598c92fae954 100644 --- a/imgui.h +++ b/imgui.h @@ -95,7 +95,7 @@ typedef int ImGuiComboFlags; // flags: for BeginCombo() typedef int ImGuiFocusedFlags; // flags: for IsWindowFocused() // enum ImGuiFocusedFlags_ typedef int ImGuiHoveredFlags; // flags: for IsItemHovered() etc. // enum ImGuiHoveredFlags_ typedef int ImGuiInputTextFlags; // flags: for InputText*() // enum ImGuiInputTextFlags_ -typedef int ImGuiNavFlags; // flags: for io.NavFlags // enum ImGuiNavFlags_ +typedef int ImGuiConfigFlags; // flags: for io.ConfigFlags // enum ImGuiConfigFlags_ typedef int ImGuiSelectableFlags; // flags: for Selectable() // enum ImGuiSelectableFlags_ typedef int ImGuiTreeNodeFlags; // flags: for TreeNode*(),CollapsingHeader()// enum ImGuiTreeNodeFlags_ typedef int ImGuiWindowFlags; // flags: for Begin*() // enum ImGuiWindowFlags_ @@ -710,8 +710,8 @@ enum ImGuiKey_ }; // [BETA] Gamepad/Keyboard directional navigation -// Keyboard: Set io.NavFlags |= ImGuiNavFlags_EnableKeyboard to enable. NewFrame() will automatically fill io.NavInputs[] based on your io.KeyDown[] + io.KeyMap[] arrays. -// Gamepad: Set io.NavFlags |= ImGuiNavFlags_EnableGamepad to enable. Fill the io.NavInputs[] fields before calling NewFrame(). Note that io.NavInputs[] is cleared by EndFrame(). +// Keyboard: Set io.ConfigFlags |= ImGuiConfigFlags_EnableKeyboard to enable. NewFrame() will automatically fill io.NavInputs[] based on your io.KeyDown[] + io.KeyMap[] arrays. +// Gamepad: Set io.ConfigFlags |= ImGuiConfigFlags_EnableGamepad to enable. Fill the io.NavInputs[] fields before calling NewFrame(). Note that io.NavInputs[] is cleared by EndFrame(). // Read instructions in imgui.cpp for more details. enum ImGuiNavInput_ { @@ -744,13 +744,13 @@ enum ImGuiNavInput_ ImGuiNavInput_InternalStart_ = ImGuiNavInput_KeyMenu_ }; -// [BETA] Gamepad/Keyboard directional navigation flags, stored in io.NavFlags -enum ImGuiNavFlags_ +// Configuration flags stored in io.ConfigFlags +enum ImGuiConfigFlags_ { - ImGuiNavFlags_EnableKeyboard = 1 << 0, // Master keyboard navigation enable flag. NewFrame() will automatically fill io.NavInputs[] based on io.KeyDown[]. - ImGuiNavFlags_EnableGamepad = 1 << 1, // Master gamepad navigation enable flag. This is mostly to instruct your imgui back-end to fill io.NavInputs[]. - ImGuiNavFlags_MoveMouse = 1 << 2, // Request navigation to allow moving the mouse cursor. May be useful on TV/console systems where moving a virtual mouse is awkward. Will update io.MousePos and set io.WantMoveMouse=true. If enabled you MUST honor io.WantMoveMouse requests in your binding, otherwise ImGui will react as if the mouse is jumping around back and forth. - ImGuiNavFlags_NoCaptureKeyboard = 1 << 3 // Do not set the io.WantCaptureKeyboard flag with io.NavActive is set. + ImGuiConfigFlags_NavEnableKeyboard = 1 << 0, // Master keyboard navigation enable flag. NewFrame() will automatically fill io.NavInputs[] based on io.KeyDown[]. + ImGuiConfigFlags_NavEnableGamepad = 1 << 1, // Master gamepad navigation enable flag. This is mostly to instruct your imgui back-end to fill io.NavInputs[]. + ImGuiConfigFlags_NavMoveMouse = 1 << 2, // Request navigation to allow moving the mouse cursor. May be useful on TV/console systems where moving a virtual mouse is awkward. Will update io.MousePos and set io.WantMoveMouse=true. If enabled you MUST honor io.WantMoveMouse requests in your binding, otherwise ImGui will react as if the mouse is jumping around back and forth. + ImGuiConfigFlags_NavNoCaptureKeyboard = 1 << 3 // Do not set the io.WantCaptureKeyboard flag with io.NavActive is set. }; // Enumeration for PushStyleColor() / PopStyleColor() @@ -953,7 +953,7 @@ struct ImGuiIO ImVec2 DisplaySize; // // Display size, in pixels. For clamping windows positions. float DeltaTime; // = 1.0f/60.0f // Time elapsed since last frame, in seconds. - ImGuiNavFlags NavFlags; // = 0x00 // See ImGuiNavFlags_. Gamepad/keyboard navigation options. + ImGuiConfigFlags ConfigFlags; // = 0 // See ImGuiConfigFlags_ enum. Gamepad/keyboard navigation options, etc. float IniSavingRate; // = 5.0f // Maximum time between saving positions/sizes to .ini file, in seconds. const char* IniFilename; // = "imgui.ini" // Path to .ini file. NULL to disable .ini saving. const char* LogFilename; // = "imgui_log.txt" // Path to .log file (default parameter to ImGui::LogToFile when no file is specified). @@ -1027,7 +1027,7 @@ struct ImGuiIO bool WantCaptureMouse; // When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application. This is set by ImGui when it wants to use your mouse (e.g. unclicked mouse is hovering a window, or a widget is active). bool WantCaptureKeyboard; // When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application. This is set by ImGui when it wants to use your keyboard inputs. bool WantTextInput; // Mobile/console: when io.WantTextInput is true, you may display an on-screen keyboard. This is set by ImGui when it wants textual keyboard input to happen (e.g. when a InputText widget is active). - bool WantMoveMouse; // MousePos has been altered, back-end should reposition mouse on next frame. Set only when ImGuiNavFlags_MoveMouse flag is enabled in io.NavFlags. + bool WantMoveMouse; // MousePos has been altered, back-end should reposition mouse on next frame. Set only when ImGuiConfigFlags_NavMoveMouse flag is enabled. bool NavActive; // Directional navigation is currently allowed (will handle ImGuiKey_NavXXX events) = a window is focused and it doesn't use the ImGuiWindowFlags_NoNavInputs flag. bool NavVisible; // Directional navigation is visible and allowed (will handle ImGuiKey_NavXXX events). float Framerate; // Application framerate estimation, in frame per second. Solely for convenience. Rolling average estimation based on IO.DeltaTime over 120 frames diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 2a1972781397..142d9499e546 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -1806,9 +1806,9 @@ void ImGui::ShowDemoWindow(bool* p_open) ImGui::Checkbox("io.MouseDrawCursor", &io.MouseDrawCursor); ImGui::SameLine(); ShowHelpMarker("Request ImGui to render a mouse cursor for you in software. Note that a mouse cursor rendered via your application GPU rendering path will feel more laggy than hardware cursor, but will be more in sync with your other visuals.\n\nSome desktop applications may use both kinds of cursors (e.g. enable software cursor only when resizing/dragging something)."); - ImGui::CheckboxFlags("io.NavFlags: EnableGamepad", (unsigned int *)&io.NavFlags, ImGuiNavFlags_EnableGamepad); - ImGui::CheckboxFlags("io.NavFlags: EnableKeyboard", (unsigned int *)&io.NavFlags, ImGuiNavFlags_EnableKeyboard); - ImGui::CheckboxFlags("io.NavFlags: MoveMouse", (unsigned int *)&io.NavFlags, ImGuiNavFlags_MoveMouse); + ImGui::CheckboxFlags("io.ConfigFlags: NavEnableGamepad", (unsigned int *)&io.ConfigFlags, ImGuiConfigFlags_NavEnableGamepad); + ImGui::CheckboxFlags("io.ConfigFlags: NavEnableKeyboard", (unsigned int *)&io.ConfigFlags, ImGuiConfigFlags_NavEnableKeyboard); + ImGui::CheckboxFlags("io.ConfigFlags: NavMoveMouse", (unsigned int *)&io.ConfigFlags, ImGuiConfigFlags_NavMoveMouse); ImGui::SameLine(); ShowHelpMarker("Request ImGui to move your move cursor when using gamepad/keyboard navigation. NewFrame() will change io.MousePos and set the io.WantMoveMouse flag, your backend will need to apply the new mouse position."); if (ImGui::TreeNode("Keyboard, Mouse & Navigation State")) diff --git a/imgui_internal.h b/imgui_internal.h index ddbbf0d77e84..9b82043692c2 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -633,8 +633,8 @@ struct ImGuiContext int NavLayer; // Layer we are navigating on. For now the system is hard-coded for 0=main contents and 1=menu/title bar, may expose layers later. int NavIdTabCounter; // == NavWindow->DC.FocusIdxTabCounter at time of NavId processing bool NavIdIsAlive; // Nav widget has been seen this frame ~~ NavRefRectRel is valid - bool NavMousePosDirty; // When set we will update mouse position if (NavFlags & ImGuiNavFlags_MoveMouse) if set (NB: this not enabled by default) - bool NavDisableHighlight; // When user starts using mouse, we hide gamepad/keyboard highlight (nb: but they are still available, which is why NavDisableHighlight isn't always != NavDisableMouseHover) + bool NavMousePosDirty; // When set we will update mouse position if (io.ConfigFlags & ImGuiConfigFlags_NavMoveMouse) if set (NB: this not enabled by default) + bool NavDisableHighlight; // When user starts using mouse, we hide gamepad/keyboard highlight (NB: but they are still available, which is why NavDisableHighlight isn't always != NavDisableMouseHover) bool NavDisableMouseHover; // When user starts using gamepad/keyboard, we hide mouse hovering highlight until mouse is touched again. bool NavAnyRequest; // ~~ NavMoveRequest || NavInitRequest bool NavInitRequest; // Init request for appearing window to select first item From b3594a6407853767571b4e71daae5ce90a3609ed Mon Sep 17 00:00:00 2001 From: omar Date: Wed, 28 Feb 2018 21:16:47 +0100 Subject: [PATCH 728/823] Added ImGuiConfigFlags_IsSRGB, ImGuiConfigFlags_IsTouchScreen (strictly for user storage) --- CHANGELOG.txt | 2 ++ imgui.h | 12 ++++++++---- imgui_demo.cpp | 6 ++---- 3 files changed, 12 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.txt b/CHANGELOG.txt index 06ee3c3ba087..5758770d2a49 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -126,6 +126,8 @@ Other Changes: - Misc: Added misc/natvis/imgui.natvis for visual studio debugger users to easily visualizer imgui internal types. Added to examples projects. - Misc: Added IMGUI_USER_CONFIG to define a custom configuration filename. (#255, #1573, #1144, #41) - Misc: Updated stb_rect_pack from 0.10 to 0.11 (minor changes). +- Misc: Added ImGuiConfigFlags_IsSRGB and ImGuiConfigFlags_IsTouchScreen user flags (for io.ConfigFlags). + (Those flags are not used by ImGui itself, they only exists to make it easy for the engine/back-end to pass information to the application in a standard manner.) - Fonts: Updated stb_truetype from 1.14 to stb_truetype 1.19. (w/ include fix from some platforms #1622) - Fonts: Added optional FreeType rasterizer in misc/freetype. Moved from imgui_club repo. (#618) [@Vuhdo, @mikesart, @ocornut] - Fonts: Moved extra_fonts/ to misc/fonts/. diff --git a/imgui.h b/imgui.h index 598c92fae954..0c39e69d8f65 100644 --- a/imgui.h +++ b/imgui.h @@ -90,12 +90,12 @@ typedef int ImDrawListFlags; // flags: for ImDrawList typedef int ImFontAtlasFlags; // flags: for ImFontAtlas // enum ImFontAtlasFlags_ typedef int ImGuiColorEditFlags; // flags: for ColorEdit*(), ColorPicker*() // enum ImGuiColorEditFlags_ typedef int ImGuiColumnsFlags; // flags: for *Columns*() // enum ImGuiColumnsFlags_ +typedef int ImGuiConfigFlags; // flags: for io.ConfigFlags // enum ImGuiConfigFlags_ typedef int ImGuiDragDropFlags; // flags: for *DragDrop*() // enum ImGuiDragDropFlags_ typedef int ImGuiComboFlags; // flags: for BeginCombo() // enum ImGuiComboFlags_ typedef int ImGuiFocusedFlags; // flags: for IsWindowFocused() // enum ImGuiFocusedFlags_ typedef int ImGuiHoveredFlags; // flags: for IsItemHovered() etc. // enum ImGuiHoveredFlags_ typedef int ImGuiInputTextFlags; // flags: for InputText*() // enum ImGuiInputTextFlags_ -typedef int ImGuiConfigFlags; // flags: for io.ConfigFlags // enum ImGuiConfigFlags_ typedef int ImGuiSelectableFlags; // flags: for Selectable() // enum ImGuiSelectableFlags_ typedef int ImGuiTreeNodeFlags; // flags: for TreeNode*(),CollapsingHeader()// enum ImGuiTreeNodeFlags_ typedef int ImGuiWindowFlags; // flags: for Begin*() // enum ImGuiWindowFlags_ @@ -710,8 +710,8 @@ enum ImGuiKey_ }; // [BETA] Gamepad/Keyboard directional navigation -// Keyboard: Set io.ConfigFlags |= ImGuiConfigFlags_EnableKeyboard to enable. NewFrame() will automatically fill io.NavInputs[] based on your io.KeyDown[] + io.KeyMap[] arrays. -// Gamepad: Set io.ConfigFlags |= ImGuiConfigFlags_EnableGamepad to enable. Fill the io.NavInputs[] fields before calling NewFrame(). Note that io.NavInputs[] is cleared by EndFrame(). +// Keyboard: Set io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard to enable. NewFrame() will automatically fill io.NavInputs[] based on your io.KeyDown[] + io.KeyMap[] arrays. +// Gamepad: Set io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad to enable. Fill the io.NavInputs[] fields before calling NewFrame(). Note that io.NavInputs[] is cleared by EndFrame(). // Read instructions in imgui.cpp for more details. enum ImGuiNavInput_ { @@ -750,7 +750,11 @@ enum ImGuiConfigFlags_ ImGuiConfigFlags_NavEnableKeyboard = 1 << 0, // Master keyboard navigation enable flag. NewFrame() will automatically fill io.NavInputs[] based on io.KeyDown[]. ImGuiConfigFlags_NavEnableGamepad = 1 << 1, // Master gamepad navigation enable flag. This is mostly to instruct your imgui back-end to fill io.NavInputs[]. ImGuiConfigFlags_NavMoveMouse = 1 << 2, // Request navigation to allow moving the mouse cursor. May be useful on TV/console systems where moving a virtual mouse is awkward. Will update io.MousePos and set io.WantMoveMouse=true. If enabled you MUST honor io.WantMoveMouse requests in your binding, otherwise ImGui will react as if the mouse is jumping around back and forth. - ImGuiConfigFlags_NavNoCaptureKeyboard = 1 << 3 // Do not set the io.WantCaptureKeyboard flag with io.NavActive is set. + ImGuiConfigFlags_NavNoCaptureKeyboard = 1 << 3, // Do not set the io.WantCaptureKeyboard flag with io.NavActive is set. + + // User storage (to allow your back-end/engine to communicate to code that may be shared between multiple projects. Those flags are not used by core ImGui) + ImGuiConfigFlags_IsSRGB = 1 << 20, // Back-end is SRGB-aware. + ImGuiConfigFlags_IsTouchScreen = 1 << 21 // Back-end is using a touch screen instead of a mouse. }; // Enumeration for PushStyleColor() / PopStyleColor() diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 142d9499e546..4addee557a23 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -2211,10 +2211,8 @@ void ImGui::ShowStyleEditor(ImGuiStyle* ref) ImGui::Text("Fallback character: '%c' (%d)", font->FallbackChar, font->FallbackChar); ImGui::Text("Texture surface: %d pixels (approx) ~ %dx%d", font->MetricsTotalSurface, (int)sqrtf((float)font->MetricsTotalSurface), (int)sqrtf((float)font->MetricsTotalSurface)); for (int config_i = 0; config_i < font->ConfigDataCount; config_i++) - { - ImFontConfig* cfg = &font->ConfigData[config_i]; - ImGui::BulletText("Input %d: \'%s\', Oversample: (%d,%d), PixelSnapH: %d", config_i, cfg->Name, cfg->OversampleH, cfg->OversampleV, cfg->PixelSnapH); - } + if (ImFontConfig* cfg = &font->ConfigData[config_i]) + ImGui::BulletText("Input %d: \'%s\', Oversample: (%d,%d), PixelSnapH: %d", config_i, cfg->Name, cfg->OversampleH, cfg->OversampleV, cfg->PixelSnapH); if (ImGui::TreeNode("Glyphs", "Glyphs (%d)", font->Glyphs.Size)) { // Display all glyphs of the fonts in separate pages of 256 characters From c994796e2648109a06dea6ca7bd583de70fd822e Mon Sep 17 00:00:00 2001 From: omar Date: Wed, 28 Feb 2018 21:45:02 +0100 Subject: [PATCH 729/823] Internal: Moved IM_NEWLINE helper to imgui_internal.h --- imgui.cpp | 7 ------- imgui_internal.h | 5 +++++ 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index be0f532d56d1..08a2fe904d0a 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -924,13 +924,6 @@ void ImGuiIO::AddInputCharactersUTF8(const char* utf8_chars) #define IM_F32_TO_INT8_UNBOUND(_VAL) ((int)((_VAL) * 255.0f + ((_VAL)>=0 ? 0.5f : -0.5f))) // Unsaturated, for display purpose #define IM_F32_TO_INT8_SAT(_VAL) ((int)(ImSaturate(_VAL) * 255.0f + 0.5f)) // Saturated, always output 0..255 -// Play it nice with Windows users. Notepad in 2015 still doesn't display text data with Unix-style \n. -#ifdef _WIN32 -#define IM_NEWLINE "\r\n" -#else -#define IM_NEWLINE "\n" -#endif - ImVec2 ImLineClosestPoint(const ImVec2& a, const ImVec2& b, const ImVec2& p) { ImVec2 ap = p - a; diff --git a/imgui_internal.h b/imgui_internal.h index 9b82043692c2..22504c4954b0 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -81,6 +81,11 @@ extern IMGUI_API ImGuiContext* GImGui; // Current implicit ImGui context pointe //----------------------------------------------------------------------------- #define IM_PI 3.14159265358979323846f +#ifdef _WIN32 +#define IM_NEWLINE "\r\n" // Play it nice with Windows users (2018: Notepad _still_ doesn't display files properly when they use Unix-style carriage returns) +#else +#define IM_NEWLINE "\n" +#endif // Helpers: UTF-8 <> wchar IMGUI_API int ImTextStrToUtf8(char* buf, int buf_size, const ImWchar* in_text, const ImWchar* in_text_end); // return output UTF-8 bytes count From 6797ee4b6839bfa83aa597415f5d5062359ef3e1 Mon Sep 17 00:00:00 2001 From: omar Date: Thu, 1 Mar 2018 13:03:12 +0100 Subject: [PATCH 730/823] Nav: Added links to PNG/PSD files for PS4 and Switch. Fixed suggested Joy-con mapping as per typical Nintendo-style mapping. (#787) --- imgui.cpp | 3 ++- imgui.h | 6 +++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 08a2fe904d0a..2a67d2836535 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -77,7 +77,7 @@ - ESCAPE to revert text to its original value. - You can apply arithmetic operators +,*,/ on numerical values. Use +- to subtract (because - would set a negative value!) - Controls are automatically adjusted for OSX to match standard OSX text editing operations. - - Gamepad navigation: see suggested mappings in imgui.h ImGuiNavInput_ + - Gamepad navigation: see suggested mappings in imgui.h ImGuiNavInput_ + download PNG/PSD at goo.gl/9LgVZW. PROGRAMMER GUIDE @@ -229,6 +229,7 @@ 0.0f= not held. 1.0f= fully held. Pass intermediate 0.0f..1.0f values for analog triggers/sticks. - We uses a simple >0.0f test for activation testing, and won't attempt to test for a dead-zone. Your code will probably need to transform your raw inputs (such as e.g. remapping your 0.2..0.9 raw input range to 0.0..1.0 imgui range, maybe a power curve, etc.). + - You can download PNG/PSD files depicting the gamepad controls for common controllers at: goo.gl/9LgVZW. - If you need to share inputs between your game and the imgui parts, the easiest approach is to go all-or-nothing, with a buttons combo to toggle the target. Please reach out if you think the game vs navigation input sharing could be improved. - Mouse: diff --git a/imgui.h b/imgui.h index 0c39e69d8f65..ba74a7b7023f 100644 --- a/imgui.h +++ b/imgui.h @@ -712,12 +712,12 @@ enum ImGuiKey_ // [BETA] Gamepad/Keyboard directional navigation // Keyboard: Set io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard to enable. NewFrame() will automatically fill io.NavInputs[] based on your io.KeyDown[] + io.KeyMap[] arrays. // Gamepad: Set io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad to enable. Fill the io.NavInputs[] fields before calling NewFrame(). Note that io.NavInputs[] is cleared by EndFrame(). -// Read instructions in imgui.cpp for more details. +// Read instructions in imgui.cpp for more details. Download PNG/PSD at goo.gl/9LgVZW. enum ImGuiNavInput_ { // Gamepad Mapping - ImGuiNavInput_Activate, // activate / open / toggle / tweak value // e.g. Circle (PS4), A (Xbox), B (Switch), Space (Keyboard) - ImGuiNavInput_Cancel, // cancel / close / exit // e.g. Cross (PS4), B (Xbox), A (Switch), Escape (Keyboard) + ImGuiNavInput_Activate, // activate / open / toggle / tweak value // e.g. Circle (PS4), A (Xbox), A (Switch), Space (Keyboard) + ImGuiNavInput_Cancel, // cancel / close / exit // e.g. Cross (PS4), B (Xbox), B (Switch), Escape (Keyboard) ImGuiNavInput_Input, // text input / on-screen keyboard // e.g. Triang.(PS4), Y (Xbox), X (Switch), Return (Keyboard) ImGuiNavInput_Menu, // tap: toggle menu / hold: focus, move, resize // e.g. Square (PS4), X (Xbox), Y (Switch), Alt (Keyboard) ImGuiNavInput_DpadLeft, // move / tweak / resize window (w/ PadMenu) // e.g. D-pad Left/Right/Up/Down (Gamepads), Arrow keys (Keyboard) From 551932697db596a7a476ca536d798f99a408a99d Mon Sep 17 00:00:00 2001 From: Sam Hocevar Date: Sat, 22 Oct 2016 13:02:58 +0200 Subject: [PATCH 731/823] Ensure `make clean` is idempotent. Prior to this, `make clean` would fail if the project was not already fully built, and a second invokation would always fail. --- examples/opengl2_example/Makefile | 2 +- examples/opengl3_example/Makefile | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/opengl2_example/Makefile b/examples/opengl2_example/Makefile index b0ee3152de1b..acff2506ed58 100644 --- a/examples/opengl2_example/Makefile +++ b/examples/opengl2_example/Makefile @@ -61,5 +61,5 @@ $(EXE): $(OBJS) $(CXX) -o $(EXE) $(OBJS) $(CXXFLAGS) $(LIBS) clean: - rm $(EXE) $(OBJS) + rm -f $(EXE) $(OBJS) diff --git a/examples/opengl3_example/Makefile b/examples/opengl3_example/Makefile index 133c0a64e0e7..cfe5802137e1 100644 --- a/examples/opengl3_example/Makefile +++ b/examples/opengl3_example/Makefile @@ -62,4 +62,4 @@ $(EXE): $(OBJS) $(CXX) -o $(EXE) $(OBJS) $(CXXFLAGS) $(LIBS) clean: - rm $(EXE) $(OBJS) + rm -f $(EXE) $(OBJS) From d4f63c38448dcc7681f485006f5858cd12dca435 Mon Sep 17 00:00:00 2001 From: Sam Hocevar Date: Sat, 22 Oct 2016 13:07:43 +0200 Subject: [PATCH 732/823] Use make variables $@ and $^ where appropriate. --- examples/opengl2_example/Makefile | 2 +- examples/opengl3_example/Makefile | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/opengl2_example/Makefile b/examples/opengl2_example/Makefile index acff2506ed58..5ea488ff4b55 100644 --- a/examples/opengl2_example/Makefile +++ b/examples/opengl2_example/Makefile @@ -58,7 +58,7 @@ all: $(EXE) @echo Build complete for $(ECHO_MESSAGE) $(EXE): $(OBJS) - $(CXX) -o $(EXE) $(OBJS) $(CXXFLAGS) $(LIBS) + $(CXX) -o $@ $^ $(CXXFLAGS) $(LIBS) clean: rm -f $(EXE) $(OBJS) diff --git a/examples/opengl3_example/Makefile b/examples/opengl3_example/Makefile index cfe5802137e1..56f1f8e2ea76 100644 --- a/examples/opengl3_example/Makefile +++ b/examples/opengl3_example/Makefile @@ -59,7 +59,7 @@ all: $(EXE) @echo Build complete for $(ECHO_MESSAGE) $(EXE): $(OBJS) - $(CXX) -o $(EXE) $(OBJS) $(CXXFLAGS) $(LIBS) + $(CXX) -o $@ $^ $(CXXFLAGS) $(LIBS) clean: rm -f $(EXE) $(OBJS) From b6f251103bc709c062a3d0f2926df390c34c38fc Mon Sep 17 00:00:00 2001 From: Sam Hocevar Date: Sat, 22 Oct 2016 13:26:39 +0200 Subject: [PATCH 733/823] Define SOURCES instead of OBJS in Makefiles. OBJS is still deduced from SOURCES, but this change gives better control over where the object files get actually written. --- examples/opengl2_example/Makefile | 5 +++-- examples/opengl3_example/Makefile | 7 ++++--- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/examples/opengl2_example/Makefile b/examples/opengl2_example/Makefile index 5ea488ff4b55..621227b1805a 100644 --- a/examples/opengl2_example/Makefile +++ b/examples/opengl2_example/Makefile @@ -15,8 +15,9 @@ #CXX = clang++ EXE = opengl2_example -OBJS = main.o imgui_impl_glfw_gl2.o -OBJS += ../../imgui.o ../../imgui_demo.o ../../imgui_draw.o +SOURCES = main.cpp imgui_impl_glfw_gl2.cpp +SOURCES += ../../imgui.cpp ../../imgui_demo.cpp ../../imgui_draw.cpp +OBJS = $(addsuffix .o, $(basename $(SOURCES))) UNAME_S := $(shell uname -s) diff --git a/examples/opengl3_example/Makefile b/examples/opengl3_example/Makefile index 56f1f8e2ea76..e2dd97615193 100644 --- a/examples/opengl3_example/Makefile +++ b/examples/opengl3_example/Makefile @@ -15,9 +15,10 @@ #CXX = clang++ EXE = opengl3_example -OBJS = main.o imgui_impl_glfw_gl3.o -OBJS += ../../imgui.o ../../imgui_demo.o ../../imgui_draw.o -OBJS += ../libs/gl3w/GL/gl3w.o +SOURCES = main.cpp imgui_impl_glfw_gl3.cpp +SOURCES += ../../imgui.cpp ../../imgui_demo.cpp ../../imgui_draw.cpp +SOURCES += ../libs/gl3w/GL/gl3w.c +OBJS = $(addsuffix .o, $(basename $(SOURCES))) UNAME_S := $(shell uname -s) From 124d8522b1693f4e5e6aeb86581588f2aa94bc22 Mon Sep 17 00:00:00 2001 From: Sam Hocevar Date: Sat, 22 Oct 2016 13:36:49 +0200 Subject: [PATCH 734/823] Do not store compiled objects outside the project tree. --- examples/opengl2_example/Makefile | 7 +++++-- examples/opengl3_example/Makefile | 10 ++++++++-- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/examples/opengl2_example/Makefile b/examples/opengl2_example/Makefile index 621227b1805a..aa7dbf47fd2b 100644 --- a/examples/opengl2_example/Makefile +++ b/examples/opengl2_example/Makefile @@ -17,7 +17,7 @@ EXE = opengl2_example SOURCES = main.cpp imgui_impl_glfw_gl2.cpp SOURCES += ../../imgui.cpp ../../imgui_demo.cpp ../../imgui_draw.cpp -OBJS = $(addsuffix .o, $(basename $(SOURCES))) +OBJS = $(addsuffix .o, $(basename $(notdir $(SOURCES)))) UNAME_S := $(shell uname -s) @@ -52,7 +52,10 @@ ifeq ($(findstring MINGW,$(UNAME_S)),MINGW) endif -.cpp.o: +%.o:%.cpp + $(CXX) $(CXXFLAGS) -c -o $@ $< + +%.o:../../%.cpp $(CXX) $(CXXFLAGS) -c -o $@ $< all: $(EXE) diff --git a/examples/opengl3_example/Makefile b/examples/opengl3_example/Makefile index e2dd97615193..008f2ca75d44 100644 --- a/examples/opengl3_example/Makefile +++ b/examples/opengl3_example/Makefile @@ -18,7 +18,7 @@ EXE = opengl3_example SOURCES = main.cpp imgui_impl_glfw_gl3.cpp SOURCES += ../../imgui.cpp ../../imgui_demo.cpp ../../imgui_draw.cpp SOURCES += ../libs/gl3w/GL/gl3w.c -OBJS = $(addsuffix .o, $(basename $(SOURCES))) +OBJS = $(addsuffix .o, $(basename $(notdir $(SOURCES)))) UNAME_S := $(shell uname -s) @@ -53,9 +53,15 @@ ifeq ($(findstring MINGW,$(UNAME_S)),MINGW) endif -.cpp.o: +%.o:%.cpp $(CXX) $(CXXFLAGS) -c -o $@ $< +%.o:../../%.cpp + $(CXX) $(CXXFLAGS) -c -o $@ $< + +%.o:../libs/gl3w/GL/%.c + $(CC) $(CFLAGS) -c -o $@ $< + all: $(EXE) @echo Build complete for $(ECHO_MESSAGE) From b37ef20c5c1491f90e75d5699281b2722b2b00fb Mon Sep 17 00:00:00 2001 From: omar Date: Thu, 1 Mar 2018 15:54:12 +0100 Subject: [PATCH 735/823] Makefile: updated sdl_opengl3_example with all changes from #885. --- examples/sdl_opengl3_example/Makefile | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/examples/sdl_opengl3_example/Makefile b/examples/sdl_opengl3_example/Makefile index 45f6a6631405..67f0f03b524e 100644 --- a/examples/sdl_opengl3_example/Makefile +++ b/examples/sdl_opengl3_example/Makefile @@ -15,9 +15,10 @@ #CXX = clang++ EXE = sdl_opengl3_example -OBJS = main.o imgui_impl_sdl_gl3.o -OBJS += ../../imgui.o ../../imgui_demo.o ../../imgui_draw.o -OBJS += ../libs/gl3w/GL/gl3w.o +SOURCES = main.cpp imgui_impl_sdl_gl3.cpp +SOURCES += ../../imgui.cpp ../../imgui_demo.cpp ../../imgui_draw.cpp +SOURCES += ../libs/gl3w/GL/gl3w.c +OBJS = $(addsuffix .o, $(basename $(notdir $(SOURCES)))) UNAME_S := $(shell uname -s) @@ -50,14 +51,20 @@ ifeq ($(findstring MINGW,$(UNAME_S)),MINGW) endif -.cpp.o: +%.o:%.cpp $(CXX) $(CXXFLAGS) -c -o $@ $< +%.o:../../%.cpp + $(CXX) $(CXXFLAGS) -c -o $@ $< + +%.o:../libs/gl3w/GL/%.c + $(CC) $(CFLAGS) -c -o $@ $< + all: $(EXE) @echo Build complete for $(ECHO_MESSAGE) $(EXE): $(OBJS) - $(CXX) -o $(EXE) $(OBJS) $(CXXFLAGS) $(LIBS) + $(CXX) -o $@ $^ $(CXXFLAGS) $(LIBS) clean: - rm $(EXE) $(OBJS) + rm -f $(EXE) $(OBJS) From df8a9c49eb6d9f134411eeffa0441f561aec3967 Mon Sep 17 00:00:00 2001 From: omar Date: Thu, 1 Mar 2018 16:29:32 +0100 Subject: [PATCH 736/823] Allow user to override ImTextureId. (#1641) --- imgui.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/imgui.h b/imgui.h index ba74a7b7023f..2e66090fb757 100644 --- a/imgui.h +++ b/imgui.h @@ -74,11 +74,14 @@ struct ImGuiListClipper; // Helper to manually clip large list of ite struct ImGuiPayload; // User data payload for drag and drop operations struct ImGuiContext; // ImGui context (opaque) +#ifndef ImTextureID +typedef void* ImTextureID; // user data to identify a texture (this is whatever to you want it to be! read the FAQ about ImTextureID in imgui.cpp) +#endif + // Typedefs and Enumerations (declared as int for compatibility and to not pollute the top of this file) typedef unsigned int ImU32; // 32-bit unsigned integer (typically used to store packed colors) typedef unsigned int ImGuiID; // unique ID used by widgets (typically hashed from a stack of string) typedef unsigned short ImWchar; // character for keyboard input/display -typedef void* ImTextureID; // user data to identify a texture (this is whatever to you want it to be! read the FAQ about ImTextureID in imgui.cpp) typedef int ImGuiCol; // enum: a color identifier for styling // enum ImGuiCol_ typedef int ImGuiCond; // enum: a condition for Set*() // enum ImGuiCond_ typedef int ImGuiKey; // enum: a key identifier (ImGui-side enum) // enum ImGuiKey_ From 11f13ab24fda03a431937976985cde96de1acda0 Mon Sep 17 00:00:00 2001 From: omar Date: Sat, 3 Mar 2018 19:08:22 +0100 Subject: [PATCH 737/823] Internal: renamed RenderTriangle() to RenderArrow(). --- imgui.cpp | 14 +++++++------- imgui_internal.h | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 2a67d2836535..126a3ca7eb79 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -4277,7 +4277,7 @@ void ImGui::RenderFrameBorder(ImVec2 p_min, ImVec2 p_max, float rounding) } // Render a triangle to denote expanded/collapsed state -void ImGui::RenderTriangle(ImVec2 p_min, ImGuiDir dir, float scale) +void ImGui::RenderArrow(ImVec2 p_min, ImGuiDir dir, float scale) { ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; @@ -6079,7 +6079,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) if (ButtonBehavior(bb, id, NULL, NULL)) window->CollapseToggleWanted = true; // Defer collapsing to next frame as we are too far in the Begin() function RenderNavHighlight(bb, id); - RenderTriangle(window->Pos + style.FramePadding, window->Collapsed ? ImGuiDir_Right : ImGuiDir_Down, 1.0f); + RenderArrow(window->Pos + style.FramePadding, window->Collapsed ? ImGuiDir_Right : ImGuiDir_Down, 1.0f); } // Close button @@ -7736,7 +7736,7 @@ bool ImGui::ArrowButton(ImGuiID id, ImGuiDir dir, ImVec2 padding, ImGuiButtonFla const ImU32 col = GetColorU32((hovered && held) ? ImGuiCol_ButtonActive : hovered ? ImGuiCol_ButtonHovered : ImGuiCol_Button); RenderNavHighlight(bb, id); RenderFrame(bb.Min, bb.Max, col, true, style.FrameRounding); - RenderTriangle(bb.Min + padding, dir, 1.0f); + RenderArrow(bb.Min + padding, dir, 1.0f); return pressed; } @@ -8066,7 +8066,7 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l // Framed type RenderFrame(frame_bb.Min, frame_bb.Max, col, true, style.FrameRounding); RenderNavHighlight(frame_bb, id, ImGuiNavHighlightFlags_TypeThin); - RenderTriangle(frame_bb.Min + ImVec2(padding.x, text_base_offset_y), is_open ? ImGuiDir_Down : ImGuiDir_Right, 1.0f); + RenderArrow(frame_bb.Min + ImVec2(padding.x, text_base_offset_y), is_open ? ImGuiDir_Down : ImGuiDir_Right, 1.0f); if (g.LogEnabled) { // NB: '##' is normally used to hide text (as a library-wide feature), so we need to specify the text range to make sure the ## aren't stripped out here. @@ -8093,7 +8093,7 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l if (flags & ImGuiTreeNodeFlags_Bullet) RenderBullet(frame_bb.Min + ImVec2(text_offset_x * 0.5f, g.FontSize*0.50f + text_base_offset_y)); else if (!(flags & ImGuiTreeNodeFlags_Leaf)) - RenderTriangle(frame_bb.Min + ImVec2(padding.x, g.FontSize*0.15f + text_base_offset_y), is_open ? ImGuiDir_Down : ImGuiDir_Right, 0.70f); + RenderArrow(frame_bb.Min + ImVec2(padding.x, g.FontSize*0.15f + text_base_offset_y), is_open ? ImGuiDir_Down : ImGuiDir_Right, 0.70f); if (g.LogEnabled) LogRenderedText(&text_pos, ">"); RenderText(text_pos, label, label_end, false); @@ -10598,7 +10598,7 @@ bool ImGui::BeginCombo(const char* label, const char* preview_value, ImGuiComboF RenderNavHighlight(frame_bb, id); RenderFrame(frame_bb.Min, frame_bb.Max, GetColorU32(ImGuiCol_FrameBg), true, style.FrameRounding); RenderFrame(ImVec2(frame_bb.Max.x-arrow_size, frame_bb.Min.y), frame_bb.Max, GetColorU32(popup_open || hovered ? ImGuiCol_ButtonHovered : ImGuiCol_Button), true, style.FrameRounding); // FIXME-ROUNDING - RenderTriangle(ImVec2(frame_bb.Max.x - arrow_size + style.FramePadding.y, frame_bb.Min.y + style.FramePadding.y), ImGuiDir_Down); + RenderArrow(ImVec2(frame_bb.Max.x - arrow_size + style.FramePadding.y, frame_bb.Min.y + style.FramePadding.y), ImGuiDir_Down); if (preview_value != NULL) RenderTextClipped(frame_bb.Min + style.FramePadding, value_bb.Max, preview_value, NULL, NULL, ImVec2(0.0f,0.0f)); if (label_size.x > 0) @@ -11150,7 +11150,7 @@ bool ImGui::BeginMenu(const char* label, bool enabled) float extra_w = ImMax(0.0f, GetContentRegionAvail().x - w); pressed = Selectable(label, menu_is_open, ImGuiSelectableFlags_Menu | ImGuiSelectableFlags_DontClosePopups | ImGuiSelectableFlags_DrawFillAvailWidth | (!enabled ? ImGuiSelectableFlags_Disabled : 0), ImVec2(w, 0.0f)); if (!enabled) PushStyleColor(ImGuiCol_Text, g.Style.Colors[ImGuiCol_TextDisabled]); - RenderTriangle(pos + ImVec2(window->MenuColumns.Pos[2] + extra_w + g.FontSize * 0.30f, 0.0f), ImGuiDir_Right); + RenderArrow(pos + ImVec2(window->MenuColumns.Pos[2] + extra_w + g.FontSize * 0.30f, 0.0f), ImGuiDir_Right); if (!enabled) PopStyleColor(); } diff --git a/imgui_internal.h b/imgui_internal.h index 22504c4954b0..3b8461c4b681 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -1098,7 +1098,7 @@ namespace ImGui IMGUI_API void RenderFrame(ImVec2 p_min, ImVec2 p_max, ImU32 fill_col, bool border = true, float rounding = 0.0f); IMGUI_API void RenderFrameBorder(ImVec2 p_min, ImVec2 p_max, float rounding = 0.0f); IMGUI_API void RenderColorRectWithAlphaCheckerboard(ImVec2 p_min, ImVec2 p_max, ImU32 fill_col, float grid_step, ImVec2 grid_off, float rounding = 0.0f, int rounding_corners_flags = ~0); - IMGUI_API void RenderTriangle(ImVec2 pos, ImGuiDir dir, float scale = 1.0f); + IMGUI_API void RenderArrow(ImVec2 pos, ImGuiDir dir, float scale = 1.0f); IMGUI_API void RenderBullet(ImVec2 pos); IMGUI_API void RenderCheckMark(ImVec2 pos, ImU32 col, float sz); IMGUI_API void RenderNavHighlight(const ImRect& bb, ImGuiID id, ImGuiNavHighlightFlags flags = ImGuiNavHighlightFlags_TypeDefault); // Navigation highlight From 839cdd37a31011992ec449d458b83de2b473e840 Mon Sep 17 00:00:00 2001 From: omar Date: Sat, 3 Mar 2018 19:23:48 +0100 Subject: [PATCH 738/823] Combo: Arrow button isn't displayed over frame color, so color is consistent with other button + the button doesn't have inner rounding. --- imgui.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 126a3ca7eb79..077be83fac5b 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -10596,8 +10596,9 @@ bool ImGui::BeginCombo(const char* label, const char* preview_value, ImGuiComboF const float arrow_size = GetFrameHeight(); const ImRect value_bb(frame_bb.Min, frame_bb.Max - ImVec2(arrow_size, 0.0f)); RenderNavHighlight(frame_bb, id); - RenderFrame(frame_bb.Min, frame_bb.Max, GetColorU32(ImGuiCol_FrameBg), true, style.FrameRounding); - RenderFrame(ImVec2(frame_bb.Max.x-arrow_size, frame_bb.Min.y), frame_bb.Max, GetColorU32(popup_open || hovered ? ImGuiCol_ButtonHovered : ImGuiCol_Button), true, style.FrameRounding); // FIXME-ROUNDING + window->DrawList->AddRectFilled(frame_bb.Min, ImVec2(frame_bb.Max.x - arrow_size, frame_bb.Max.y), GetColorU32(ImGuiCol_FrameBg), style.FrameRounding, ImDrawCornerFlags_Left); + window->DrawList->AddRectFilled(ImVec2(frame_bb.Max.x - arrow_size, frame_bb.Min.y), frame_bb.Max, GetColorU32(popup_open || hovered ? ImGuiCol_ButtonHovered : ImGuiCol_Button), style.FrameRounding, (w <= arrow_size) ? ImDrawCornerFlags_All : ImDrawCornerFlags_Right); + RenderFrameBorder(frame_bb.Min, frame_bb.Max, style.FrameRounding); RenderArrow(ImVec2(frame_bb.Max.x - arrow_size + style.FramePadding.y, frame_bb.Min.y + style.FramePadding.y), ImGuiDir_Down); if (preview_value != NULL) RenderTextClipped(frame_bb.Min + style.FramePadding, value_bb.Max, preview_value, NULL, NULL, ImVec2(0.0f,0.0f)); From 1549c5cf5e64686ee8247510e9a36abbec1d0427 Mon Sep 17 00:00:00 2001 From: omar Date: Sat, 3 Mar 2018 19:43:31 +0100 Subject: [PATCH 739/823] BeginCombo(): Added ImGuiComboFlags_NoArrowButton and ImGuiComboFlags_NoPreview flags + hover color matches drag and sliders. --- CHANGELOG.txt | 4 ++++ imgui.cpp | 23 +++++++++++++++-------- imgui.h | 2 ++ 3 files changed, 21 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.txt b/CHANGELOG.txt index 5758770d2a49..db2b85552565 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -112,6 +112,10 @@ Other Changes: - Drag and Drop: Increased payload type string to 12 characters instead of 8. (#143) - Drag and Drop: TreeNode as drop target displays rectangle over full frame. (#1597, #143) - DragFloat: Fix/workaround for backends which do not preserve a valid mouse position when dragged out of bounds. (#1559) +- Slider, Combo: Use ImGuiCol_FrameBgHovered color when hovered. (#1456) [@stfx] +- Combo: BeginCombo(): Added ImGuiComboFlags_NoArrowButton to disable the arrow button and only display the wide value preview box. +- Combo: BeginCombo(): Added ImGuiComboFlags_NoPreview to disable the preview and only display a square arrow button. +- Combo: Arrow button isn't displayed over frame background so its blended color matches other buttons. Left side of the button isn't rounded. - PlotLines: plot a flat line if scale_min==scale_max. (#1621) - ImFontAtlas: Handle stb_truetype stbtt_InitFont() and stbtt_PackBegin() possible failures more gracefully, GetTexDataAsRGBA32() won't crash during conversion. (#1527) - ImFontAtlas: Moved mouse cursor data out of ImGuiContext, fix drawing them with multiple contexts. Also remove the last remaining undesirable dependency on ImGui in imgui_draw.cpp. (#939) diff --git a/imgui.cpp b/imgui.cpp index b1a41449acfd..bf8c81d62518 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -8562,7 +8562,7 @@ bool ImGui::SliderBehavior(const ImRect& frame_bb, ImGuiID id, float* v, float v const ImGuiStyle& style = g.Style; // Draw frame - const ImU32 frame_col = GetColorU32((g.ActiveId == id ) ? ImGuiCol_FrameBgActive : g.HoveredId == id ? ImGuiCol_FrameBgHovered : ImGuiCol_FrameBg); + const ImU32 frame_col = GetColorU32(g.ActiveId == id ? ImGuiCol_FrameBgActive : g.HoveredId == id ? ImGuiCol_FrameBgHovered : ImGuiCol_FrameBg); RenderNavHighlight(frame_bb, id); RenderFrame(frame_bb.Min, frame_bb.Max, frame_col, true, style.FrameRounding); @@ -10573,16 +10573,19 @@ bool ImGui::BeginCombo(const char* label, const char* preview_value, ImGuiComboF ImGuiContext& g = *GImGui; ImGuiCond backup_next_window_size_constraint = g.NextWindowData.SizeConstraintCond; g.NextWindowData.SizeConstraintCond = 0; - + ImGuiWindow* window = GetCurrentWindow(); if (window->SkipItems) return false; + IM_ASSERT((flags & (ImGuiComboFlags_NoArrowButton | ImGuiComboFlags_NoPreview)) != (ImGuiComboFlags_NoArrowButton | ImGuiComboFlags_NoPreview)); // Can't use both flags together + const ImGuiStyle& style = g.Style; const ImGuiID id = window->GetID(label); - const float w = CalcItemWidth(); + const float arrow_size = (flags & ImGuiComboFlags_NoArrowButton) ? 0.0f : GetFrameHeight(); const ImVec2 label_size = CalcTextSize(label, NULL, true); + const float w = (flags & ImGuiComboFlags_NoPreview) ? arrow_size : CalcItemWidth(); const ImRect frame_bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(w, label_size.y + style.FramePadding.y*2.0f)); const ImRect total_bb(frame_bb.Min, frame_bb.Max + ImVec2(label_size.x > 0.0f ? style.ItemInnerSpacing.x + label_size.x : 0.0f, 0.0f)); ItemSize(total_bb, style.FramePadding.y); @@ -10593,14 +10596,18 @@ bool ImGui::BeginCombo(const char* label, const char* preview_value, ImGuiComboF bool pressed = ButtonBehavior(frame_bb, id, &hovered, &held); bool popup_open = IsPopupOpen(id); - const float arrow_size = GetFrameHeight(); const ImRect value_bb(frame_bb.Min, frame_bb.Max - ImVec2(arrow_size, 0.0f)); + const ImU32 frame_col = GetColorU32(hovered ? ImGuiCol_FrameBgHovered : ImGuiCol_FrameBg); RenderNavHighlight(frame_bb, id); - window->DrawList->AddRectFilled(frame_bb.Min, ImVec2(frame_bb.Max.x - arrow_size, frame_bb.Max.y), GetColorU32(ImGuiCol_FrameBg), style.FrameRounding, ImDrawCornerFlags_Left); - window->DrawList->AddRectFilled(ImVec2(frame_bb.Max.x - arrow_size, frame_bb.Min.y), frame_bb.Max, GetColorU32(popup_open || hovered ? ImGuiCol_ButtonHovered : ImGuiCol_Button), style.FrameRounding, (w <= arrow_size) ? ImDrawCornerFlags_All : ImDrawCornerFlags_Right); + if (!(flags & ImGuiComboFlags_NoPreview)) + window->DrawList->AddRectFilled(frame_bb.Min, ImVec2(frame_bb.Max.x - arrow_size, frame_bb.Max.y), frame_col, style.FrameRounding, ImDrawCornerFlags_Left); + if (!(flags & ImGuiComboFlags_NoArrowButton)) + { + window->DrawList->AddRectFilled(ImVec2(frame_bb.Max.x - arrow_size, frame_bb.Min.y), frame_bb.Max, GetColorU32((popup_open || hovered) ? ImGuiCol_ButtonHovered : ImGuiCol_Button), style.FrameRounding, (w <= arrow_size) ? ImDrawCornerFlags_All : ImDrawCornerFlags_Right); + RenderArrow(ImVec2(frame_bb.Max.x - arrow_size + style.FramePadding.y, frame_bb.Min.y + style.FramePadding.y), ImGuiDir_Down); + } RenderFrameBorder(frame_bb.Min, frame_bb.Max, style.FrameRounding); - RenderArrow(ImVec2(frame_bb.Max.x - arrow_size + style.FramePadding.y, frame_bb.Min.y + style.FramePadding.y), ImGuiDir_Down); - if (preview_value != NULL) + if (preview_value != NULL && !(flags & ImGuiComboFlags_NoPreview)) RenderTextClipped(frame_bb.Min + style.FramePadding, value_bb.Max, preview_value, NULL, NULL, ImVec2(0.0f,0.0f)); if (label_size.x > 0) RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, frame_bb.Min.y + style.FramePadding.y), label); diff --git a/imgui.h b/imgui.h index 2e66090fb757..07f6ec78669a 100644 --- a/imgui.h +++ b/imgui.h @@ -639,6 +639,8 @@ enum ImGuiComboFlags_ ImGuiComboFlags_HeightRegular = 1 << 2, // Max ~8 items visible (default) ImGuiComboFlags_HeightLarge = 1 << 3, // Max ~20 items visible ImGuiComboFlags_HeightLargest = 1 << 4, // As many fitting items as possible + ImGuiComboFlags_NoArrowButton = 1 << 5, // Display on the preview box without the square arrow button + ImGuiComboFlags_NoPreview = 1 << 6, // Display only a square arrow button ImGuiComboFlags_HeightMask_ = ImGuiComboFlags_HeightSmall | ImGuiComboFlags_HeightRegular | ImGuiComboFlags_HeightLarge | ImGuiComboFlags_HeightLargest }; From 8a4093f38b0b964c66e6e3111db9388e135c4e38 Mon Sep 17 00:00:00 2001 From: omar Date: Sat, 3 Mar 2018 20:08:03 +0100 Subject: [PATCH 740/823] Added ArrowButton(). Exposed ImGuiDir. --- CHANGELOG.txt | 1 + imgui.cpp | 38 ++++++++++++++++++++++++++++++++------ imgui.h | 15 ++++++++++++++- imgui_demo.cpp | 6 ++++++ imgui_internal.h | 10 ---------- 5 files changed, 53 insertions(+), 17 deletions(-) diff --git a/CHANGELOG.txt b/CHANGELOG.txt index db2b85552565..59e1aa617880 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -92,6 +92,7 @@ Other Changes: - Window: Added SetNextWindowBgAlpha() helper. Particularly helpul since the legacy 5-parameters version of Begin() has been marked as obsolete in 1.53. (#1567) - Window: Fixed SetNextWindowContentSize() with 0.0f on Y axis (or SetNextWindowContentWidth()) overwriting the contents size. Got broken on Dec 10 (1.53). (#1363) - Window: CloseButton: Fixed cross positioning being a little off. +- ArrowButton: Added ArrowButton() given a cardinal direction (e.g. ImGuiDir_Left). - InputText: Added alternative clipboard shortcuts: Shift+Delete (cut), Ctrl+Insert (copy), Shift+Insert (paste). (#1541) - InputText: Fixed losing Cursor X position when clicking outside on an item that's submitted after the InputText(). It was only noticeable when restoring focus programmatically. (#1418, #1554) - Style: Enable window border by default. (#707) diff --git a/imgui.cpp b/imgui.cpp index bf8c81d62518..1bf25b7007fe 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -4306,7 +4306,7 @@ void ImGui::RenderArrow(ImVec2 p_min, ImGuiDir dir, float scale) c = ImVec2(-0.500f,-0.866f) * r; break; case ImGuiDir_None: - case ImGuiDir_Count_: + case ImGuiDir_COUNT: IM_ASSERT(0); break; } @@ -5200,8 +5200,8 @@ static ImVec2 FindBestWindowPosForPopup(const ImVec2& ref_pos, const ImVec2& siz // Combo Box policy (we want a connecting edge) if (policy == ImGuiPopupPositionPolicy_ComboBox) { - const ImGuiDir dir_prefered_order[ImGuiDir_Count_] = { ImGuiDir_Down, ImGuiDir_Right, ImGuiDir_Left, ImGuiDir_Up }; - for (int n = (*last_dir != ImGuiDir_None) ? -1 : 0; n < ImGuiDir_Count_; n++) + const ImGuiDir dir_prefered_order[ImGuiDir_COUNT] = { ImGuiDir_Down, ImGuiDir_Right, ImGuiDir_Left, ImGuiDir_Up }; + for (int n = (*last_dir != ImGuiDir_None) ? -1 : 0; n < ImGuiDir_COUNT; n++) { const ImGuiDir dir = (n == -1) ? *last_dir : dir_prefered_order[n]; if (n != -1 && dir == *last_dir) // Already tried this direction? @@ -5219,8 +5219,8 @@ static ImVec2 FindBestWindowPosForPopup(const ImVec2& ref_pos, const ImVec2& siz } // Default popup policy - const ImGuiDir dir_prefered_order[ImGuiDir_Count_] = { ImGuiDir_Right, ImGuiDir_Down, ImGuiDir_Up, ImGuiDir_Left }; - for (int n = (*last_dir != ImGuiDir_None) ? -1 : 0; n < ImGuiDir_Count_; n++) + const ImGuiDir dir_prefered_order[ImGuiDir_COUNT] = { ImGuiDir_Right, ImGuiDir_Down, ImGuiDir_Up, ImGuiDir_Left }; + for (int n = (*last_dir != ImGuiDir_None) ? -1 : 0; n < ImGuiDir_COUNT; n++) { const ImGuiDir dir = (n == -1) ? *last_dir : dir_prefered_order[n]; if (n != -1 && dir == *last_dir) // Already tried this direction? @@ -7663,6 +7663,32 @@ bool ImGui::SmallButton(const char* label) return pressed; } +bool ImGui::ArrowButton(const char* str_id, ImGuiDir dir) +{ + ImGuiWindow* window = GetCurrentWindow(); + if (window->SkipItems) + return false; + + ImGuiContext& g = *GImGui; + const ImGuiID id = window->GetID(str_id); + float sz = ImGui::GetFrameHeight(); + const ImRect bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(sz, sz)); + ItemSize(bb); + if (!ItemAdd(bb, id)) + return false; + + bool hovered, held; + bool pressed = ButtonBehavior(bb, id, &hovered, &held); + + // Render + const ImU32 col = GetColorU32((hovered && held) ? ImGuiCol_ButtonActive : hovered ? ImGuiCol_ButtonHovered : ImGuiCol_Button); + RenderNavHighlight(bb, id); + RenderFrame(bb.Min, bb.Max, col, true, g.Style.FrameRounding); + RenderArrow(bb.Min + g.Style.FramePadding, dir); + + return pressed; +} + // Tip: use ImGui::PushID()/PopID() to push indices or pointers in the ID stack. // Then you can keep 'str_id' empty or the same for all your buttons (instead of creating a string based on a non-string id) bool ImGui::InvisibleButton(const char* str_id, const ImVec2& size_arg) @@ -11734,7 +11760,7 @@ static void RenderArrow(ImDrawList* draw_list, ImVec2 pos, ImVec2 half_sz, ImGui case ImGuiDir_Right: draw_list->AddTriangleFilled(ImVec2(pos.x - half_sz.x, pos.y + half_sz.y), ImVec2(pos.x - half_sz.x, pos.y - half_sz.y), pos, col); return; case ImGuiDir_Up: draw_list->AddTriangleFilled(ImVec2(pos.x + half_sz.x, pos.y + half_sz.y), ImVec2(pos.x - half_sz.x, pos.y + half_sz.y), pos, col); return; case ImGuiDir_Down: draw_list->AddTriangleFilled(ImVec2(pos.x - half_sz.x, pos.y - half_sz.y), ImVec2(pos.x + half_sz.x, pos.y - half_sz.y), pos, col); return; - case ImGuiDir_None: case ImGuiDir_Count_: break; // Fix warnings + case ImGuiDir_None: case ImGuiDir_COUNT: break; // Fix warnings } } diff --git a/imgui.h b/imgui.h index 07f6ec78669a..d2bf06820c10 100644 --- a/imgui.h +++ b/imgui.h @@ -78,11 +78,12 @@ struct ImGuiContext; // ImGui context (opaque) typedef void* ImTextureID; // user data to identify a texture (this is whatever to you want it to be! read the FAQ about ImTextureID in imgui.cpp) #endif -// Typedefs and Enumerations (declared as int for compatibility and to not pollute the top of this file) +// Typedefs and Enumerations (declared as int for compatibility with old C++ and to not pollute the top of this file) typedef unsigned int ImU32; // 32-bit unsigned integer (typically used to store packed colors) typedef unsigned int ImGuiID; // unique ID used by widgets (typically hashed from a stack of string) typedef unsigned short ImWchar; // character for keyboard input/display typedef int ImGuiCol; // enum: a color identifier for styling // enum ImGuiCol_ +typedef int ImGuiDir; // enum: a cardinal direction // enum ImGuiDir_ typedef int ImGuiCond; // enum: a condition for Set*() // enum ImGuiCond_ typedef int ImGuiKey; // enum: a key identifier (ImGui-side enum) // enum ImGuiKey_ typedef int ImGuiNavInput; // enum: an input identifier for navigation // enum ImGuiNavInput_ @@ -312,6 +313,7 @@ namespace ImGui // Widgets: Main IMGUI_API bool Button(const char* label, const ImVec2& size = ImVec2(0,0)); // button IMGUI_API bool SmallButton(const char* label); // button with FramePadding=(0,0) to easily embed within text + IMGUI_API bool ArrowButton(const char* str_id, ImGuiDir dir); IMGUI_API bool InvisibleButton(const char* str_id, const ImVec2& size); // button behavior without the visuals, useful to build custom behaviors using the public api (along with IsItemActive, IsItemHovered, etc.) IMGUI_API void Image(ImTextureID user_texture_id, const ImVec2& size, const ImVec2& uv0 = ImVec2(0,0), const ImVec2& uv1 = ImVec2(1,1), const ImVec4& tint_col = ImVec4(1,1,1,1), const ImVec4& border_col = ImVec4(0,0,0,0)); IMGUI_API bool ImageButton(ImTextureID user_texture_id, const ImVec2& size, const ImVec2& uv0 = ImVec2(0,0), const ImVec2& uv1 = ImVec2(1,1), int frame_padding = -1, const ImVec4& bg_col = ImVec4(0,0,0,0), const ImVec4& tint_col = ImVec4(1,1,1,1)); // <0 frame_padding uses default frame padding settings. 0 for no padding @@ -687,6 +689,17 @@ enum ImGuiDragDropFlags_ #define IMGUI_PAYLOAD_TYPE_COLOR_3F "_COL3F" // float[3] // Standard type for colors, without alpha. User code may use this type. #define IMGUI_PAYLOAD_TYPE_COLOR_4F "_COL4F" // float[4] // Standard type for colors. User code may use this type. +// A direction +enum ImGuiDir_ +{ + ImGuiDir_None = -1, + ImGuiDir_Left = 0, + ImGuiDir_Right = 1, + ImGuiDir_Up = 2, + ImGuiDir_Down = 3, + ImGuiDir_COUNT +}; + // User fill ImGuiIO.KeyMap[] array with indices into the ImGuiIO.KeysDown[512] array enum ImGuiKey_ { diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 4addee557a23..34dae8a741cd 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -300,6 +300,12 @@ void ImGui::ShowDemoWindow(bool* p_open) ImGui::PopID(); } + // Arrow buttons + float spacing = ImGui::GetStyle().ItemInnerSpacing.x; + if (ImGui::ArrowButton("##left", ImGuiDir_Left)) {} + ImGui::SameLine(0.0f, spacing); + if (ImGui::ArrowButton("##left", ImGuiDir_Right)) {} + ImGui::Text("Hover over me"); if (ImGui::IsItemHovered()) ImGui::SetTooltip("I am a tooltip"); diff --git a/imgui_internal.h b/imgui_internal.h index 3b8461c4b681..10ba85329ece 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -260,16 +260,6 @@ enum ImGuiDataType ImGuiDataType_Float2 }; -enum ImGuiDir -{ - ImGuiDir_None = -1, - ImGuiDir_Left = 0, - ImGuiDir_Right = 1, - ImGuiDir_Up = 2, - ImGuiDir_Down = 3, - ImGuiDir_Count_ -}; - enum ImGuiInputSource { ImGuiInputSource_None = 0, From 69e700f8694f89707b7aec91551f4a9546684040 Mon Sep 17 00:00:00 2001 From: omar Date: Sat, 3 Mar 2018 20:15:10 +0100 Subject: [PATCH 741/823] Renamed ImGuiStyleVar_Count_ to ImGuiStyleVar_COUNT for consistency with other enums. Added --- CHANGELOG.txt | 1 + examples/directx10_example/imgui_impl_dx10.cpp | 2 +- examples/directx11_example/imgui_impl_dx11.cpp | 2 +- examples/directx12_example/imgui_impl_dx12.cpp | 2 +- examples/directx9_example/imgui_impl_dx9.cpp | 2 +- examples/opengl2_example/imgui_impl_glfw_gl2.cpp | 4 ++-- examples/opengl3_example/imgui_impl_glfw_gl3.cpp | 4 ++-- examples/sdl_opengl2_example/imgui_impl_sdl_gl2.cpp | 4 ++-- examples/sdl_opengl3_example/imgui_impl_sdl_gl3.cpp | 4 ++-- examples/vulkan_example/imgui_impl_glfw_vulkan.cpp | 4 ++-- imgui.cpp | 7 ++++--- imgui.h | 11 ++++++++--- imgui_demo.cpp | 4 ++-- imgui_draw.cpp | 4 ++-- imgui_internal.h | 2 +- 15 files changed, 32 insertions(+), 25 deletions(-) diff --git a/CHANGELOG.txt b/CHANGELOG.txt index 59e1aa617880..6ce0cd553aac 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -55,6 +55,7 @@ Breaking Changes: - removed allocator parameters from CreateContext(), they are now setup with SetAllocatorFunctions(), and shared by all contexts. - removed the default global context and font atlas instance, which were confusing for users of DLL reloading and users of multiple contexts. - Moved sample TTF files from extra_fonts/ to misc/fonts/. If you loaded files directly from the imgui repo you may need to update your paths. + - Renamed ImGuiStyleVar_Count_ to ImGuiStyleVar_COUNT and ImGuiMouseCursor_Count_ to ImGuiMouseCursor_COUNT for consistency with other public enums. - Obsoleted IsAnyWindowHovered() in favor of IsWindowHovered(ImGuiHoveredFlags_AnyWindow). Kept redirection function (will obsolete). - Obsoleted IsAnyWindowFocused() in favor of IsWindowFocused(ImGuiFocusedFlags_AnyWindow). Kept redirection function (will obsolete). - Renamed ImGuiSizeConstraintCallback to ImGuiSizeCallback, ImGuiSizeConstraintCallbackData to ImGuiSizeCallbackData. diff --git a/examples/directx10_example/imgui_impl_dx10.cpp b/examples/directx10_example/imgui_impl_dx10.cpp index caef5e1b5116..cbf791be9cbe 100644 --- a/examples/directx10_example/imgui_impl_dx10.cpp +++ b/examples/directx10_example/imgui_impl_dx10.cpp @@ -37,7 +37,7 @@ static HWND g_hWnd = 0; static INT64 g_Time = 0; static INT64 g_TicksPerSecond = 0; -static ImGuiMouseCursor g_LastMouseCursor = ImGuiMouseCursor_Count_; +static ImGuiMouseCursor g_LastMouseCursor = ImGuiMouseCursor_COUNT; // DirectX data static ID3D10Device* g_pd3dDevice = NULL; diff --git a/examples/directx11_example/imgui_impl_dx11.cpp b/examples/directx11_example/imgui_impl_dx11.cpp index c7f312c6d15b..b100cf96f0d1 100644 --- a/examples/directx11_example/imgui_impl_dx11.cpp +++ b/examples/directx11_example/imgui_impl_dx11.cpp @@ -36,7 +36,7 @@ static HWND g_hWnd = 0; static INT64 g_Time = 0; static INT64 g_TicksPerSecond = 0; -static ImGuiMouseCursor g_LastMouseCursor = ImGuiMouseCursor_Count_; +static ImGuiMouseCursor g_LastMouseCursor = ImGuiMouseCursor_COUNT; // DirectX data static ID3D11Device* g_pd3dDevice = NULL; diff --git a/examples/directx12_example/imgui_impl_dx12.cpp b/examples/directx12_example/imgui_impl_dx12.cpp index beb48b9cb167..6c74dadf8532 100644 --- a/examples/directx12_example/imgui_impl_dx12.cpp +++ b/examples/directx12_example/imgui_impl_dx12.cpp @@ -24,7 +24,7 @@ static HWND g_hWnd = 0; static INT64 g_Time = 0; static INT64 g_TicksPerSecond = 0; -static ImGuiMouseCursor g_LastMouseCursor = ImGuiMouseCursor_Count_; +static ImGuiMouseCursor g_LastMouseCursor = ImGuiMouseCursor_COUNT; // DirectX data static ID3D12Device* g_pd3dDevice = NULL; diff --git a/examples/directx9_example/imgui_impl_dx9.cpp b/examples/directx9_example/imgui_impl_dx9.cpp index 194752fb8bc7..157c27d51f17 100644 --- a/examples/directx9_example/imgui_impl_dx9.cpp +++ b/examples/directx9_example/imgui_impl_dx9.cpp @@ -27,7 +27,7 @@ static HWND g_hWnd = 0; static INT64 g_Time = 0; static INT64 g_TicksPerSecond = 0; -static ImGuiMouseCursor g_LastMouseCursor = ImGuiMouseCursor_Count_; +static ImGuiMouseCursor g_LastMouseCursor = ImGuiMouseCursor_COUNT; // DirectX data static LPDIRECT3DDEVICE9 g_pd3dDevice = NULL; diff --git a/examples/opengl2_example/imgui_impl_glfw_gl2.cpp b/examples/opengl2_example/imgui_impl_glfw_gl2.cpp index 03d7659e06bc..89d2509f3ad1 100644 --- a/examples/opengl2_example/imgui_impl_glfw_gl2.cpp +++ b/examples/opengl2_example/imgui_impl_glfw_gl2.cpp @@ -50,7 +50,7 @@ static GLFWwindow* g_Window = NULL; static double g_Time = 0.0f; static bool g_MouseJustPressed[3] = { false, false, false }; -static GLFWcursor* g_MouseCursors[ImGuiMouseCursor_Count_] = { 0 }; +static GLFWcursor* g_MouseCursors[ImGuiMouseCursor_COUNT] = { 0 }; // OpenGL data static GLuint g_FontTexture = 0; @@ -282,7 +282,7 @@ bool ImGui_ImplGlfwGL2_Init(GLFWwindow* window, bool install_callbacks) void ImGui_ImplGlfwGL2_Shutdown() { // Destroy GLFW mouse cursors - for (ImGuiMouseCursor cursor_n = 0; cursor_n < ImGuiMouseCursor_Count_; cursor_n++) + for (ImGuiMouseCursor cursor_n = 0; cursor_n < ImGuiMouseCursor_COUNT; cursor_n++) glfwDestroyCursor(g_MouseCursors[cursor_n]); memset(g_MouseCursors, 0, sizeof(g_MouseCursors)); diff --git a/examples/opengl3_example/imgui_impl_glfw_gl3.cpp b/examples/opengl3_example/imgui_impl_glfw_gl3.cpp index 40b0c4d41b4a..e75719423fe4 100644 --- a/examples/opengl3_example/imgui_impl_glfw_gl3.cpp +++ b/examples/opengl3_example/imgui_impl_glfw_gl3.cpp @@ -48,7 +48,7 @@ static GLFWwindow* g_Window = NULL; static double g_Time = 0.0f; static bool g_MouseJustPressed[3] = { false, false, false }; -static GLFWcursor* g_MouseCursors[ImGuiMouseCursor_Count_] = { 0 }; +static GLFWcursor* g_MouseCursors[ImGuiMouseCursor_COUNT] = { 0 }; // OpenGL3 data static GLuint g_FontTexture = 0; @@ -400,7 +400,7 @@ bool ImGui_ImplGlfwGL3_Init(GLFWwindow* window, bool install_callbacks) void ImGui_ImplGlfwGL3_Shutdown() { // Destroy GLFW mouse cursors - for (ImGuiMouseCursor cursor_n = 0; cursor_n < ImGuiMouseCursor_Count_; cursor_n++) + for (ImGuiMouseCursor cursor_n = 0; cursor_n < ImGuiMouseCursor_COUNT; cursor_n++) glfwDestroyCursor(g_MouseCursors[cursor_n]); memset(g_MouseCursors, 0, sizeof(g_MouseCursors)); diff --git a/examples/sdl_opengl2_example/imgui_impl_sdl_gl2.cpp b/examples/sdl_opengl2_example/imgui_impl_sdl_gl2.cpp index c7eeaa912b47..ca224744ee14 100644 --- a/examples/sdl_opengl2_example/imgui_impl_sdl_gl2.cpp +++ b/examples/sdl_opengl2_example/imgui_impl_sdl_gl2.cpp @@ -44,7 +44,7 @@ static Uint64 g_Time = 0; static bool g_MousePressed[3] = { false, false, false }; static GLuint g_FontTexture = 0; -static SDL_Cursor* g_MouseCursors[ImGuiMouseCursor_Count_] = { 0 }; +static SDL_Cursor* g_MouseCursors[ImGuiMouseCursor_COUNT] = { 0 }; // OpenGL2 Render function. // (this used to be set in io.RenderDrawListsFn and called by ImGui::Render(), but you can now call this directly from your main loop) @@ -275,7 +275,7 @@ bool ImGui_ImplSdlGL2_Init(SDL_Window* window) void ImGui_ImplSdlGL2_Shutdown() { // Destroy SDL mouse cursors - for (ImGuiMouseCursor cursor_n = 0; cursor_n < ImGuiMouseCursor_Count_; cursor_n++) + for (ImGuiMouseCursor cursor_n = 0; cursor_n < ImGuiMouseCursor_COUNT; cursor_n++) SDL_FreeCursor(g_MouseCursors[cursor_n]); memset(g_MouseCursors, 0, sizeof(g_MouseCursors)); diff --git a/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.cpp b/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.cpp index d5bd364cae44..a0ca7e629612 100644 --- a/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.cpp +++ b/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.cpp @@ -42,7 +42,7 @@ // SDL data static Uint64 g_Time = 0; static bool g_MousePressed[3] = { false, false, false }; -static SDL_Cursor* g_MouseCursors[ImGuiMouseCursor_Count_] = { 0 }; +static SDL_Cursor* g_MouseCursors[ImGuiMouseCursor_COUNT] = { 0 }; // OpenGL data static GLuint g_FontTexture = 0; @@ -394,7 +394,7 @@ bool ImGui_ImplSdlGL3_Init(SDL_Window* window) void ImGui_ImplSdlGL3_Shutdown() { // Destroy SDL mouse cursors - for (ImGuiMouseCursor cursor_n = 0; cursor_n < ImGuiMouseCursor_Count_; cursor_n++) + for (ImGuiMouseCursor cursor_n = 0; cursor_n < ImGuiMouseCursor_COUNT; cursor_n++) SDL_FreeCursor(g_MouseCursors[cursor_n]); memset(g_MouseCursors, 0, sizeof(g_MouseCursors)); diff --git a/examples/vulkan_example/imgui_impl_glfw_vulkan.cpp b/examples/vulkan_example/imgui_impl_glfw_vulkan.cpp index 8f9fa654a04b..f982d643fc9a 100644 --- a/examples/vulkan_example/imgui_impl_glfw_vulkan.cpp +++ b/examples/vulkan_example/imgui_impl_glfw_vulkan.cpp @@ -42,7 +42,7 @@ static GLFWwindow* g_Window = NULL; static double g_Time = 0.0f; static bool g_MouseJustPressed[3] = { false, false, false }; -static GLFWcursor* g_MouseCursors[ImGuiMouseCursor_Count_] = { 0 }; +static GLFWcursor* g_MouseCursors[ImGuiMouseCursor_COUNT] = { 0 }; // Vulkan data static VkAllocationCallbacks* g_Allocator = NULL; @@ -820,7 +820,7 @@ bool ImGui_ImplGlfwVulkan_Init(GLFWwindow* window, bool install_callbacks, Im void ImGui_ImplGlfwVulkan_Shutdown() { // Destroy GLFW mouse cursors - for (ImGuiMouseCursor cursor_n = 0; cursor_n < ImGuiMouseCursor_Count_; cursor_n++) + for (ImGuiMouseCursor cursor_n = 0; cursor_n < ImGuiMouseCursor_COUNT; cursor_n++) glfwDestroyCursor(g_MouseCursors[cursor_n]); memset(g_MouseCursors, 0, sizeof(g_MouseCursors)); diff --git a/imgui.cpp b/imgui.cpp index 1bf25b7007fe..4195a8c56103 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -251,6 +251,7 @@ Here is a change-log of API breaking changes, if you are using one of the functions listed, expect to have to fix some code. Also read releases logs https://github.com/ocornut/imgui/releases for more details. + - 2018/03/03 (1.60) - Renamed ImGuiStyleVar_Count_ to ImGuiStyleVar_COUNT and ImGuiMouseCursor_Count_ to ImGuiMouseCursor_COUNT for consistency with other public enums. - 2018/02/18 (1.60) - BeginDragDropSource(): temporarily removed the optional mouse_button=0 parameter because it is not really usable in many situations at the moment. - 2018/02/16 (1.60) - obsoleted the io.RenderDrawListsFn callback, you can call your graphics engine render function after ImGui::Render(). Use ImGui::GetDrawData() to retrieve the ImDrawData* to display. - 2018/02/07 (1.60) - reorganized context handling to be more explicit, @@ -6597,8 +6598,8 @@ static const ImGuiStyleVarInfo GStyleVarInfo[] = static const ImGuiStyleVarInfo* GetStyleVarInfo(ImGuiStyleVar idx) { - IM_ASSERT(idx >= 0 && idx < ImGuiStyleVar_Count_); - IM_ASSERT(IM_ARRAYSIZE(GStyleVarInfo) == ImGuiStyleVar_Count_); + IM_ASSERT(idx >= 0 && idx < ImGuiStyleVar_COUNT); + IM_ASSERT(IM_ARRAYSIZE(GStyleVarInfo) == ImGuiStyleVar_COUNT); return &GStyleVarInfo[idx]; } @@ -13261,7 +13262,7 @@ void ImGui::ShowMetricsWindow(bool* p_open) } if (ImGui::TreeNode("Internal state")) { - const char* input_source_names[] = { "None", "Mouse", "Nav", "NavGamepad", "NavKeyboard" }; IM_ASSERT(IM_ARRAYSIZE(input_source_names) == ImGuiInputSource_Count_); + const char* input_source_names[] = { "None", "Mouse", "Nav", "NavGamepad", "NavKeyboard" }; IM_ASSERT(IM_ARRAYSIZE(input_source_names) == ImGuiInputSource_COUNT); ImGui::Text("HoveredWindow: '%s'", g.HoveredWindow ? g.HoveredWindow->Name : "NULL"); ImGui::Text("HoveredRootWindow: '%s'", g.HoveredRootWindow ? g.HoveredRootWindow->Name : "NULL"); ImGui::Text("HoveredId: 0x%08X/0x%08X (%.2f sec)", g.HoveredId, g.HoveredIdPreviousFrame, g.HoveredIdTimer); // Data is "in-flight" so depending on when the Metrics window is called we may see current frame information or not diff --git a/imgui.h b/imgui.h index d2bf06820c10..e6b3fe39ebf0 100644 --- a/imgui.h +++ b/imgui.h @@ -859,11 +859,11 @@ enum ImGuiStyleVar_ ImGuiStyleVar_GrabMinSize, // float GrabMinSize ImGuiStyleVar_GrabRounding, // float GrabRounding ImGuiStyleVar_ButtonTextAlign, // ImVec2 ButtonTextAlign - ImGuiStyleVar_Count_ + ImGuiStyleVar_COUNT // Obsolete names (will be removed) #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS - , ImGuiStyleVar_ChildWindowRounding = ImGuiStyleVar_ChildRounding + , ImGuiStyleVar_Count_ = ImGuiStyleVar_COUNT, ImGuiStyleVar_ChildWindowRounding = ImGuiStyleVar_ChildRounding #endif }; @@ -908,7 +908,12 @@ enum ImGuiMouseCursor_ ImGuiMouseCursor_ResizeEW, // When hovering over a vertical border or a column ImGuiMouseCursor_ResizeNESW, // When hovering over the bottom-left corner of a window ImGuiMouseCursor_ResizeNWSE, // When hovering over the bottom-right corner of a window - ImGuiMouseCursor_Count_ + ImGuiMouseCursor_COUNT + + // Obsolete names (will be removed) +#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS + , ImGuiMouseCursor_Count_ = ImGuiMouseCursor_COUNT +#endif }; // Condition for ImGui::SetWindow***(), SetNextWindow***(), SetNextTreeNode***() functions diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 34dae8a741cd..fe6d208c7c96 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -1993,12 +1993,12 @@ void ImGui::ShowDemoWindow(bool* p_open) if (ImGui::TreeNode("Mouse cursors")) { const char* mouse_cursors_names[] = { "Arrow", "TextInput", "Move", "ResizeNS", "ResizeEW", "ResizeNESW", "ResizeNWSE" }; - IM_ASSERT(IM_ARRAYSIZE(mouse_cursors_names) == ImGuiMouseCursor_Count_); + IM_ASSERT(IM_ARRAYSIZE(mouse_cursors_names) == ImGuiMouseCursor_COUNT); ImGui::Text("Current mouse cursor = %d: %s", ImGui::GetMouseCursor(), mouse_cursors_names[ImGui::GetMouseCursor()]); ImGui::Text("Hover to see mouse cursors:"); ImGui::SameLine(); ShowHelpMarker("Your application can render a different mouse cursor based on what ImGui::GetMouseCursor() returns. If software cursor rendering (io.MouseDrawCursor) is set ImGui will draw the right cursor for you, otherwise your backend needs to handle it."); - for (int i = 0; i < ImGuiMouseCursor_Count_; i++) + for (int i = 0; i < ImGuiMouseCursor_COUNT; i++) { char label[32]; sprintf(label, "Mouse cursor %d: %s", i, mouse_cursors_names[i]); diff --git a/imgui_draw.cpp b/imgui_draw.cpp index 9ba63056f90e..c939733d1f66 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -1349,7 +1349,7 @@ static const char FONT_ATLAS_DEFAULT_TEX_DATA_PIXELS[FONT_ATLAS_DEFAULT_TEX_DATA " - XX XX - " }; -static const ImVec2 FONT_ATLAS_DEFAULT_TEX_CURSOR_DATA[ImGuiMouseCursor_Count_][3] = +static const ImVec2 FONT_ATLAS_DEFAULT_TEX_CURSOR_DATA[ImGuiMouseCursor_COUNT][3] = { // Pos ........ Size ......... Offset ...... { ImVec2(0,3), ImVec2(12,19), ImVec2( 0, 0) }, // ImGuiMouseCursor_Arrow @@ -1622,7 +1622,7 @@ void ImFontAtlas::CalcCustomRectUV(const CustomRect* rect, ImVec2* out_uv_min, I bool ImFontAtlas::GetMouseCursorTexData(ImGuiMouseCursor cursor_type, ImVec2* out_offset, ImVec2* out_size, ImVec2 out_uv_border[2], ImVec2 out_uv_fill[2]) { - if (cursor_type <= ImGuiMouseCursor_None || cursor_type >= ImGuiMouseCursor_Count_) + if (cursor_type <= ImGuiMouseCursor_None || cursor_type >= ImGuiMouseCursor_COUNT) return false; if (Flags & ImFontAtlasFlags_NoMouseCursors) return false; diff --git a/imgui_internal.h b/imgui_internal.h index 10ba85329ece..dd0e08ad0527 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -267,7 +267,7 @@ enum ImGuiInputSource ImGuiInputSource_Nav, ImGuiInputSource_NavKeyboard, // Only used occasionally for storage, not tested/handled by most code ImGuiInputSource_NavGamepad, // " - ImGuiInputSource_Count_, + ImGuiInputSource_COUNT, }; // FIXME-NAV: Clarify/expose various repeat delay/rate From ee770af72c93172ff6f0feafd22c6f7f6db28be9 Mon Sep 17 00:00:00 2001 From: omar Date: Sun, 4 Mar 2018 16:06:43 +0100 Subject: [PATCH 742/823] Columns: Adding per-window display in Metrics. Tidying up, removing old code/comments. (#125, #1499, #1656) --- imgui.cpp | 30 +++++++++++++++++------------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 4195a8c56103..8d9611bfb42e 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -12384,7 +12384,7 @@ static float GetDraggedColumnOffset(ImGuiColumnsSet* columns, int column_index) // window creates a feedback loop because we store normalized positions. So while dragging we enforce absolute positioning. ImGuiContext& g = *GImGui; ImGuiWindow* window = g.CurrentWindow; - IM_ASSERT(column_index > 0); // We cannot drag column 0. If you get this assert you may have a conflict between the ID of your columns and another widgets. + IM_ASSERT(column_index > 0); // We are not supposed to drag column 0. IM_ASSERT(g.ActiveId == columns->ID + ImGuiID(column_index)); float x = g.IO.MousePos.x - g.ActiveIdClickOffset.x + GetColumnsRectHalfWidth() - window->Pos.x; @@ -12405,16 +12405,6 @@ float ImGui::GetColumnOffset(int column_index) column_index = columns->Current; IM_ASSERT(column_index < columns->Columns.Size); - /* - if (g.ActiveId) - { - ImGuiContext& g = *GImGui; - const ImGuiID column_id = columns->ColumnsSetId + ImGuiID(column_index); - if (g.ActiveId == column_id) - return GetDraggedColumnOffset(columns, column_index); - } - */ - const float t = columns->Columns[column_index].OffsetNorm; const float x_offset = ImLerp(columns->MinX, columns->MaxX, t); return x_offset; @@ -12524,7 +12514,6 @@ void ImGui::BeginColumns(const char* str_id, int columns_count, ImGuiColumnsFlag // Set state for first column const float content_region_width = (window->SizeContentsExplicit.x != 0.0f) ? (window->SizeContentsExplicit.x) : (window->Size.x -window->ScrollbarSizes.x); columns->MinX = window->DC.IndentX - g.Style.ItemSpacing.x; // Lock our horizontal range - //column->MaxX = content_region_width - window->Scroll.x - ((window->Flags & ImGuiWindowFlags_NoScrollbar) ? 0 : g.Style.ScrollbarSize);// - window->WindowPadding().x; columns->MaxX = content_region_width - window->Scroll.x; columns->StartPosY = window->DC.CursorPos.y; columns->StartMaxPosX = window->DC.CursorMaxPos.x; @@ -12640,7 +12629,7 @@ void ImGui::EndColumns() window->DC.CursorPos.x = (float)(int)(window->Pos.x + window->DC.IndentX + window->DC.ColumnsOffsetX); } -// [2017/12: This is currently the only public API, while we are working on making BeginColumns/EndColumns user-facing] +// [2018-03: This is currently the only public API, while we are working on making BeginColumns/EndColumns user-facing] void ImGui::Columns(int columns_count, const char* id, bool border) { ImGuiWindow* window = GetCurrentWindow(); @@ -13237,6 +13226,21 @@ void ImGui::ShowMetricsWindow(bool* p_open) ImGui::BulletText("NavRectRel[0]: "); if (window->RootWindow != window) NodeWindow(window->RootWindow, "RootWindow"); if (window->DC.ChildWindows.Size > 0) NodeWindows(window->DC.ChildWindows, "ChildWindows"); + if (window->ColumnsStorage.Size > 0 && ImGui::TreeNode("Columns", "Columns sets (%d)", window->ColumnsStorage.Size)) + { + for (int n = 0; n < window->ColumnsStorage.Size; n++) + { + const ImGuiColumnsSet* columns = &window->ColumnsStorage[n]; + if (ImGui::TreeNode((void*)columns->ID, "Columns Id: 0x%08X, Count: %d, Flags: 0x%04X", columns->ID, columns->Count, columns->Flags)) + { + ImGui::BulletText("Width: %.1f (MinX: %.1f, MaxX: %.1f)", columns->MaxX - columns->MinX, columns->MinX, columns->MaxX); + for (int column_n = 0; column_n < columns->Columns.Size; column_n++) + ImGui::BulletText("Column %02d: OffsetNorm %.3f (= %.1f px)", column_n, columns->Columns[column_n].OffsetNorm, OffsetNormToPixels(columns, columns->Columns[column_n].OffsetNorm)); + ImGui::TreePop(); + } + } + ImGui::TreePop(); + } ImGui::BulletText("Storage: %d bytes", window->StateStorage.Data.Size * (int)sizeof(ImGuiStorage::Pair)); ImGui::TreePop(); } From 968a8d2a3fecc3bf870a20f3e6a2f10dbe2cddab Mon Sep 17 00:00:00 2001 From: omar Date: Sun, 4 Mar 2018 16:57:44 +0100 Subject: [PATCH 743/823] Columns: Clamping MaxX above MinX. This shouldn't have much of a benefit / affect, but the internal values are more sane this way. (#125) --- imgui.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/imgui.cpp b/imgui.cpp index 8d9611bfb42e..27a82075e4e2 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -12514,7 +12514,7 @@ void ImGui::BeginColumns(const char* str_id, int columns_count, ImGuiColumnsFlag // Set state for first column const float content_region_width = (window->SizeContentsExplicit.x != 0.0f) ? (window->SizeContentsExplicit.x) : (window->Size.x -window->ScrollbarSizes.x); columns->MinX = window->DC.IndentX - g.Style.ItemSpacing.x; // Lock our horizontal range - columns->MaxX = content_region_width - window->Scroll.x; + columns->MaxX = ImMax(content_region_width - window->Scroll.x, columns->MinX + 1.0f); columns->StartPosY = window->DC.CursorPos.y; columns->StartMaxPosX = window->DC.CursorMaxPos.x; columns->CellMinY = columns->CellMaxY = window->DC.CursorPos.y; From bf7481eba01252f3e53590c7c592b86b318bcd52 Mon Sep 17 00:00:00 2001 From: omar Date: Sun, 4 Mar 2018 17:44:17 +0100 Subject: [PATCH 744/823] Columns: Extent stop at the right-most clipped pixel. The right-most column might appear a little wider but it's usable space matches the others. (#125). +9 Internal: Store InnerClipRect. --- imgui.cpp | 19 +++++++++---------- imgui_internal.h | 2 +- 2 files changed, 10 insertions(+), 11 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 27a82075e4e2..d999133641ee 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -6131,21 +6131,20 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) window->InnerRect.Max.y = window->Pos.y + window->Size.y - window->ScrollbarSizes.y - window->WindowBorderSize; //window->DrawList->AddRect(window->InnerRect.Min, window->InnerRect.Max, IM_COL32_WHITE); + // Inner clipping rectangle + // Force round operator last to ensure that e.g. (int)(max.x-min.x) in user's render code produce correct result. + window->InnerClipRect.Min.x = ImFloor(0.5f + window->InnerRect.Min.x + ImMax(0.0f, ImFloor(window->WindowPadding.x*0.5f - window->WindowBorderSize))); + window->InnerClipRect.Min.y = ImFloor(0.5f + window->InnerRect.Min.y); + window->InnerClipRect.Max.x = ImFloor(0.5f + window->InnerRect.Max.x - ImMax(0.0f, ImFloor(window->WindowPadding.x*0.5f - window->WindowBorderSize))); + window->InnerClipRect.Max.y = ImFloor(0.5f + window->InnerRect.Max.y); + // After Begin() we fill the last item / hovered data using the title bar data. Make that a standard behavior (to allow usage of context menus on title bar only, etc.). window->DC.LastItemId = window->MoveId; window->DC.LastItemStatusFlags = IsMouseHoveringRect(title_bar_rect.Min, title_bar_rect.Max, false) ? ImGuiItemStatusFlags_HoveredRect : 0; window->DC.LastItemRect = title_bar_rect; } - // Inner clipping rectangle - // Force round operator last to ensure that e.g. (int)(max.x-min.x) in user's render code produce correct result. - const float border_size = window->WindowBorderSize; - ImRect clip_rect; - clip_rect.Min.x = ImFloor(0.5f + window->InnerRect.Min.x + ImMax(0.0f, ImFloor(window->WindowPadding.x*0.5f - border_size))); - clip_rect.Min.y = ImFloor(0.5f + window->InnerRect.Min.y); - clip_rect.Max.x = ImFloor(0.5f + window->InnerRect.Max.x - ImMax(0.0f, ImFloor(window->WindowPadding.x*0.5f - border_size))); - clip_rect.Max.y = ImFloor(0.5f + window->InnerRect.Max.y); - PushClipRect(clip_rect.Min, clip_rect.Max, true); + PushClipRect(window->InnerClipRect.Min, window->InnerClipRect.Max, true); // Clear 'accessed' flag last thing (After PushClipRect which will set the flag. We want the flag to stay false when the default "Debug" window is unused) if (first_begin_of_the_frame) @@ -12512,7 +12511,7 @@ void ImGui::BeginColumns(const char* str_id, int columns_count, ImGuiColumnsFlag window->DC.ColumnsSet = columns; // Set state for first column - const float content_region_width = (window->SizeContentsExplicit.x != 0.0f) ? (window->SizeContentsExplicit.x) : (window->Size.x -window->ScrollbarSizes.x); + const float content_region_width = (window->SizeContentsExplicit.x != 0.0f) ? (window->SizeContentsExplicit.x) : (window->InnerClipRect.Max.x - window->Pos.x); columns->MinX = window->DC.IndentX - g.Style.ItemSpacing.x; // Lock our horizontal range columns->MaxX = ImMax(content_region_width - window->Scroll.x, columns->MinX + 1.0f); columns->StartPosY = window->DC.CursorPos.y; diff --git a/imgui_internal.h b/imgui_internal.h index dd0e08ad0527..79fc4d95849a 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -944,7 +944,7 @@ struct IMGUI_API ImGuiWindow ImVector IDStack; // ID stack. ID are hashes seeded with the value at the top of the stack ImRect ClipRect; // = DrawList->clip_rect_stack.back(). Scissoring / clipping rectangle. x1, y1, x2, y2. ImRect WindowRectClipped; // = WindowRect just after setup in Begin(). == window->Rect() for root window. - ImRect InnerRect; + ImRect InnerRect, InnerClipRect; int LastFrameActive; float ItemWidthDefault; ImGuiMenuColumns MenuColumns; // Simplified columns storage for menu items From 5ed45d0aec76ffae27e8089024c8b4531c7214e0 Mon Sep 17 00:00:00 2001 From: omar Date: Sun, 4 Mar 2018 17:55:59 +0100 Subject: [PATCH 745/823] Columns: Fixed destructive small resize. (#1656). The OffsetNorm clamp introduced by #913 was ok as it didn't write back into the storage, which #1499 started doing making it destructive. Right now I don't think the clamp is needed at all. It had uses (eg: hide the issue fixed by bf7481eba01252f3e53590c7c592b86b318bcd52). --- imgui.cpp | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index d999133641ee..bfbac41f720a 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -12537,19 +12537,10 @@ void ImGui::BeginColumns(const char* str_id, int columns_count, ImGuiColumnsFlag } } - for (int n = 0; n < columns_count + 1; n++) + for (int n = 0; n < columns_count; n++) { - // Clamp position - ImGuiColumnData* column = &columns->Columns[n]; - float t = column->OffsetNorm; - if (!(columns->Flags & ImGuiColumnsFlags_NoForceWithinWindow)) - t = ImMin(t, PixelsToOffsetNorm(columns, (columns->MaxX - columns->MinX) - g.Style.ColumnsMinSpacing * (columns->Count - n))); - column->OffsetNorm = t; - - if (n == columns_count) - continue; - // Compute clipping rectangle + ImGuiColumnData* column = &columns->Columns[n]; float clip_x1 = ImFloor(0.5f + window->Pos.x + GetColumnOffset(n) - 1.0f); float clip_x2 = ImFloor(0.5f + window->Pos.x + GetColumnOffset(n + 1) - 1.0f); column->ClipRect = ImRect(clip_x1, -FLT_MAX, clip_x2, +FLT_MAX); From 0ec356eb6e5471178ea543d02c28b59bb97d659a Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 5 Mar 2018 11:30:23 +0100 Subject: [PATCH 746/823] Comments, FAQ update. --- README.md | 7 +++---- imgui.cpp | 53 +++++++++++++++++++++++--------------------------- imgui.h | 11 ++++++----- imgui_draw.cpp | 2 +- 4 files changed, 34 insertions(+), 39 deletions(-) diff --git a/README.md b/README.md index da7979635baf..b5f4356350ec 100644 --- a/README.md +++ b/README.md @@ -231,18 +231,17 @@ See the [Software using dear imgui page](https://github.com/ocornut/imgui/wiki/S The library started its life and is best known as "ImGui" only due to the fact that I didn't give it a proper name when I released it. However, the term IMGUI (immediate-mode graphical user interface) was coined before and is being used in variety of other situations. It seemed confusing and unfair to hog the name. To reduce the ambiguity without affecting existing codebases, I have decided on an alternate, longer name "dear imgui" that people can use to refer to this specific library in ambiguous situations. -How can I help? +How can I tell whether to dispatch mouse/keyboard to imgui or to my application?
How can I display an image? What is ImTextureID, how does it works?
How can I have multiple widgets with the same label, or without any label? (Yes). A primer on labels and ID stack. -
How can I tell when Dear ImGui wants my mouse/keyboard inputs VS when I can pass them to my application?
How can I load a different font than the default?
How can I easily use icons in my application?
How can I load multiple fonts?
How can I display and input non-latin characters such as Chinese, Japanese, Korean, Cyrillic? -
How can I preserve my Dear ImGui context across reloading a DLL? (loss of the global/static variables)
How can I use the drawing facilities without an Dear ImGui window? (using ImDrawList API)
I integrated Dear ImGui in my engine and the text or lines are blurry..
I integrated Dear ImGui in my engine and some elements are disappearing when I move windows around.. +
How can I help? See the FAQ in imgui.cpp for answers. @@ -250,7 +249,7 @@ See the FAQ in imgui.cpp for answers. You can control Dear ImGui with a gamepad, see the explanation in imgui.cpp about how to use the navigation feature (short version: map your gamepad inputs into the `io.NavInputs[]` array and set `io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad`). -You can share your computer mouse seamlessy with your console/tablet/phone using [Synergy](http://synergy-project.org). This is the prefered solution for developer productivity. In particular, their [micro-synergy-client](https://github.com/symless/micro-synergy-client) repo there is _uSynergy.c_ sources for a small embeddable that you can use on any platform to connect to your host PC. You may also use a third party solution such as [Remote ImGui](https://github.com/JordiRos/remoteimgui). +You can share your computer mouse seamlessy with your console/tablet/phone using [Synergy](http://synergy-project.org). This is the prefered solution for developer productivity. In particular, their [micro-synergy-client](https://github.com/symless/micro-synergy-client) repo there is _uSynergy.c_ sources for a small embeddable that you can use on any platform to connect to your host PC using Synergy 1.x. You may also use a third party solution such as [Remote ImGui](https://github.com/JordiRos/remoteimgui). For touch inputs, you can increase the hit box of widgets (via the _style.TouchPadding_ setting) to accommodate a little for the lack of precision of touch inputs, but it is recommended you use a mouse or gamepad to allow optimising for screen real-estate and precision. diff --git a/imgui.cpp b/imgui.cpp index bfbac41f720a..64c2f4f9a863 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -23,18 +23,17 @@ - API BREAKING CHANGES (read me when you update!) - ISSUES & TODO LIST - FREQUENTLY ASKED QUESTIONS (FAQ), TIPS - - How can I help? + - How can I tell whether to dispatch mouse/keyboard to imgui or to my application? - How can I display an image? What is ImTextureID, how does it works? - How can I have multiple widgets with the same label? Can I have widget without a label? (Yes). A primer on labels and the ID stack. - - How can I tell when Dear ImGui wants my mouse/keyboard inputs VS when I can pass them to my application? - How can I load a different font than the default? - How can I easily use icons in my application? - How can I load multiple fonts? - How can I display and input non-latin characters such as Chinese, Japanese, Korean, Cyrillic? - - How can I preserve my Dear ImGui context across reloading a DLL? (loss of the global/static variables) - How can I use the drawing facilities without an ImGui window? (using ImDrawList API) - I integrated Dear ImGui in my engine and the text or lines are blurry.. - I integrated Dear ImGui in my engine and some elements are clipping or disappearing when I move windows around.. + - How can I help? - ISSUES & TODO-LIST - CODE @@ -234,7 +233,7 @@ Please reach out if you think the game vs navigation input sharing could be improved. - Mouse: - PS4 users: Consider emulating a mouse cursor with DualShock4 touch pad or a spare analog stick as a mouse-emulation fallback. - - Consoles/Tablet/Phone users: Consider using Synergy host (on your computer) + uSynergy.c (in your console/tablet/phone app) to use your PC mouse/keyboard. + - Consoles/Tablet/Phone users: Consider using a Synergy 1.x server (on your PC) + uSynergy.c (in your console/tablet/phone app) to share your PC mouse/keyboard. - On a TV/console system where readability may be lower or mouse inputs may be awkward, you may want to set the ImGuiConfigFlags_NavMoveMouse flag. Enabling ImGuiConfigFlags_NavMoveMouse instructs dear imgui to move your mouse cursor along with navigation movements. When enabled, the NewFrame() function may alter 'io.MousePos' and set 'io.WantMoveMouse' to notify you that it wants the mouse cursor to be moved. @@ -405,13 +404,18 @@ FREQUENTLY ASKED QUESTIONS (FAQ), TIPS ====================================== - Q: How can I help? - A: - If you are experienced with Dear ImGui and C++, look at the github issues, or TODO.txt and see how you want/can help! - - Convince your company to fund development time! Individual users: you can also become a Patron (patreon.com/imgui) or donate on PayPal! See README. - - Disclose your usage of dear imgui via a dev blog post, a tweet, a screenshot, a mention somewhere etc. - You may post screenshot or links in the gallery threads (github.com/ocornut/imgui/issues/1269). Visuals are ideal as they inspire other programmers. - But even without visuals, disclosing your use of dear imgui help the library grow credibility, and help other teams and programmers with taking decisions. - - If you have issues or if you need to hack into the library, even if you don't expect any support it is useful that you share your issues (on github or privately). + Q: How can I tell whether to dispatch mouse/keyboard to imgui or to my application? + A: You can read the 'io.WantCaptureMouse'/'io.WantCaptureKeyboard'/'io.WantTextInput' flags from the ImGuiIO structure. + - When 'io.WantCaptureMouse' is set, imgui wants to use your mouse state, and you may want to discard/hide the inputs from the rest of your application. + - When 'io.WantCaptureKeyboard' is set, imgui wants to use your keyboard state, and you may want to discard/hide the inputs from the rest of your application. + - When 'io.WantTextInput' is set to may want to notify your OS to popup an on-screen keyboard, if available (e.g. on a mobile phone, or console OS). + The 'io.WantCaptureMouse' is more accurate that any attempt to "check if the mouse is hovering a window" (don't do that!). + It handle mouse dragging correctly (both dragging that started over your application or over an imgui window) and handle e.g. modal windows blocking inputs. + Those flags are updated by ImGui::NewFrame(). Preferably read the flags after calling NewFrame() if you can afford it, but reading them before is also + perfectly fine, as the bool toggle fairly rarely. + (Advanced note: text input releases focus on Return 'KeyDown', so the following Return 'KeyUp' event that your application receive will typically + have 'io.WantCaptureKeyboard=false'. Depending on your application logic it may or not be inconvenient. You might want to track which key-downs + were for Dear ImGui, e.g. with an array of bool, and filter out the corresponding key-ups.) Q: How can I display an image? What is ImTextureID, how does it works? A: ImTextureID is a void* used to pass renderer-agnostic texture references around until it hits your render function. @@ -521,18 +525,6 @@ e.g. when displaying a list of objects, using indices or pointers as ID will preserve the node open/closed state differently. experiment and see what makes more sense! - Q: How can I tell when Dear ImGui wants my mouse/keyboard inputs VS when I can pass them to my application? - A: You can read the 'io.WantCaptureMouse'/'io.WantCaptureKeyboard'/'ioWantTextInput' flags from the ImGuiIO structure. - - When 'io.WantCaptureMouse' or 'io.WantCaptureKeyboard' flags are set you may want to discard/hide the inputs from the rest of your application. - - When 'io.WantTextInput' is set to may want to notify your OS to popup an on-screen keyboard, if available (e.g. on a mobile phone, or console OS). - Preferably read the flags after calling ImGui::NewFrame() to avoid them lagging by one frame. But reading those flags before calling NewFrame() is - also generally ok, as the bool toggles fairly rarely and you don't generally expect to interact with either Dear ImGui or your application during - the same frame when that transition occurs. Dear ImGui is tracking dragging and widget activity that may occur outside the boundary of a window, - so 'io.WantCaptureMouse' is more accurate and correct than checking if a window is hovered. - (Advanced note: text input releases focus on Return 'KeyDown', so the following Return 'KeyUp' event that your application receive will typically - have 'io.WantCaptureKeyboard=false'. Depending on your application logic it may or not be inconvenient. You might want to track which key-downs - were for Dear ImGui, e.g. with an array of bool, and filter out the corresponding key-ups.) - Q: How can I load a different font than the default? (default is an embedded version of ProggyClean.ttf, rendered at size 13) A: Use the font atlas to load the TTF/OTF file you want: ImGuiIO& io = ImGui::GetIO(); @@ -599,13 +591,9 @@ For languages using IME, on Windows you can copy the Hwnd of your application to io.ImeWindowHandle. The default implementation of io.ImeSetInputScreenPosFn() on Windows will set your IME position correctly. - Q: How can I preserve my Dear ImGui context across reloading a DLL? (loss of the global/static variables) - A: Create your own context 'ctx = CreateContext()' + 'SetCurrentContext(ctx)' and your own font atlas 'ctx->GetIO().Fonts = new ImFontAtlas()' - so you don't rely on the default globals. - Q: How can I use the drawing facilities without an ImGui window? (using ImDrawList API) - A: - You can create a dummy window. Call Begin() with NoTitleBar|NoResize|NoMove|NoScrollbar|NoSavedSettings|NoInputs flag, - push a ImGuiCol_WindowBg with zero alpha, then retrieve the ImDrawList* via GetWindowDrawList() and draw to it in any way you like. + A: - You can create a dummy window. Call SetNextWindowBgAlpha(0.0f), call Begin() with NoTitleBar|NoResize|NoMove|NoScrollbar|NoSavedSettings|NoInputs flags. + Then you can retrieve the ImDrawList* via GetWindowDrawList() and draw to it in any way you like. - You can call ImGui::GetOverlayDrawList() and use this draw list to display contents over every other imgui windows. - You can create your own ImDrawList instance. You'll need to initialize them ImGui::GetDrawListSharedData(), or create your own ImDrawListSharedData. @@ -617,6 +605,13 @@ A: You are probably mishandling the clipping rectangles in your render function. Rectangles provided by ImGui are defined as (x1=left,y1=top,x2=right,y2=bottom) and NOT as (x1,y1,width,height). + Q: How can I help? + A: - If you are experienced with Dear ImGui and C++, look at the github issues, or TODO.txt and see how you want/can help! + - Convince your company to fund development time! Individual users: you can also become a Patron (patreon.com/imgui) or donate on PayPal! See README. + - Disclose your usage of dear imgui via a dev blog post, a tweet, a screenshot, a mention somewhere etc. + You may post screenshot or links in the gallery threads (github.com/ocornut/imgui/issues/1269). Visuals are ideal as they inspire other programmers. + But even without visuals, disclosing your use of dear imgui help the library grow credibility, and help other teams and programmers with taking decisions. + - If you have issues or if you need to hack into the library, even if you don't expect any support it is useful that you share your issues (on github or privately). - tip: you can call Begin() multiple times with the same name during the same frame, it will keep appending to the same window. this is also useful to set yourself in the context of another window (to get/set other settings) diff --git a/imgui.h b/imgui.h index e6b3fe39ebf0..1111014210b0 100644 --- a/imgui.h +++ b/imgui.h @@ -487,7 +487,7 @@ namespace ImGui IMGUI_API ImVec2 GetItemRectSize(); // get size of last item, in screen space IMGUI_API void SetItemAllowOverlap(); // allow last item to be overlapped by a subsequent item. sometimes useful with invisible buttons, selectables, etc. to catch unused area. IMGUI_API bool IsWindowFocused(ImGuiFocusedFlags flags = 0); // is current window focused? or its root/child, depending on flags. see flags for options. - IMGUI_API bool IsWindowHovered(ImGuiHoveredFlags flags = 0); // is current window hovered (and typically: not blocked by a popup/modal)? see flags for options. + IMGUI_API bool IsWindowHovered(ImGuiHoveredFlags flags = 0); // is current window hovered (and typically: not blocked by a popup/modal)? see flags for options. NB: If you are trying to check whether your mouse should be dispatched to imgui or to your app, you should use the 'io.WantCaptureMouse' boolean for that! Please read the FAQ! IMGUI_API bool IsRectVisible(const ImVec2& size); // test if rectangle (of given size, starting from cursor position) is visible / not clipped. IMGUI_API bool IsRectVisible(const ImVec2& rect_min, const ImVec2& rect_max); // test if rectangle (in screen space) is visible / not clipped. to perform coarse clipping on user's side. IMGUI_API float GetTime(); @@ -656,6 +656,7 @@ enum ImGuiFocusedFlags_ }; // Flags for ImGui::IsItemHovered(), ImGui::IsWindowHovered() +// Note: If you are trying to check whether your mouse should be dispatched to imgui or to your app, you should use the 'io.WantCaptureMouse' boolean for that. Please read the FAQ! enum ImGuiHoveredFlags_ { ImGuiHoveredFlags_Default = 0, // Return true if directly over the item/window, not obstructed by another window, not obstructed by an active popup or modal blocking inputs under them. @@ -1665,10 +1666,10 @@ struct ImFontAtlas IMGUI_API ImFont* AddFontFromMemoryTTF(void* font_data, int font_size, float size_pixels, const ImFontConfig* font_cfg = NULL, const ImWchar* glyph_ranges = NULL); // Note: Transfer ownership of 'ttf_data' to ImFontAtlas! Will be deleted after Build(). Set font_cfg->FontDataOwnedByAtlas to false to keep ownership. IMGUI_API ImFont* AddFontFromMemoryCompressedTTF(const void* compressed_font_data, int compressed_font_size, float size_pixels, const ImFontConfig* font_cfg = NULL, const ImWchar* glyph_ranges = NULL); // 'compressed_font_data' still owned by caller. Compress with binary_to_compressed_c.cpp. IMGUI_API ImFont* AddFontFromMemoryCompressedBase85TTF(const char* compressed_font_data_base85, float size_pixels, const ImFontConfig* font_cfg = NULL, const ImWchar* glyph_ranges = NULL); // 'compressed_font_data_base85' still owned by caller. Compress with binary_to_compressed_c.cpp with -base85 parameter. - IMGUI_API void ClearTexData(); // Clear the CPU-side texture data. Saves RAM once the texture has been copied to graphics memory. - IMGUI_API void ClearInputData(); // Clear the input TTF data (inc sizes, glyph ranges) - IMGUI_API void ClearFonts(); // Clear the ImGui-side font data (glyphs storage, UV coordinates) - IMGUI_API void Clear(); // Clear all + IMGUI_API void ClearInputData(); // Clear input data (all ImFontConfig structures including sizes, TTF data, glyph ranges, etc.) = all the data used to build the texture and fonts. + IMGUI_API void ClearTexData(); // Clear output texture data (CPU side). Saves RAM once the texture has been copied to graphics memory. + IMGUI_API void ClearFonts(); // Clear output font data (glyphs storage, UV coordinates). + IMGUI_API void Clear(); // Clear all input and output. // Build atlas, retrieve pixel data. // User is in charge of copying the pixels into graphics memory (e.g. create a texture with your engine). Then store your texture handle with SetTexID(). diff --git a/imgui_draw.cpp b/imgui_draw.cpp index c939733d1f66..1a15a1407237 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -1391,7 +1391,7 @@ void ImFontAtlas::ClearInputData() ConfigData[i].FontData = NULL; } - // When clearing this we lose access to the font name and other information used to build the font. + // When clearing this we lose access to the font name and other information used to build the font. for (int i = 0; i < Fonts.Size; i++) if (Fonts[i]->ConfigData >= ConfigData.Data && Fonts[i]->ConfigData < ConfigData.Data + ConfigData.Size) { From 51afaf7117b9835376ac6f242453c492dc8843cb Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 5 Mar 2018 13:15:15 +0100 Subject: [PATCH 747/823] Fixed type cast warning. --- imgui.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/imgui.cpp b/imgui.cpp index 64c2f4f9a863..31e7ff9e17e3 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -13216,7 +13216,7 @@ void ImGui::ShowMetricsWindow(bool* p_open) for (int n = 0; n < window->ColumnsStorage.Size; n++) { const ImGuiColumnsSet* columns = &window->ColumnsStorage[n]; - if (ImGui::TreeNode((void*)columns->ID, "Columns Id: 0x%08X, Count: %d, Flags: 0x%04X", columns->ID, columns->Count, columns->Flags)) + if (ImGui::TreeNode((void*)(uintptr_t)columns->ID, "Columns Id: 0x%08X, Count: %d, Flags: 0x%04X", columns->ID, columns->Count, columns->Flags)) { ImGui::BulletText("Width: %.1f (MinX: %.1f, MaxX: %.1f)", columns->MaxX - columns->MinX, columns->MinX, columns->MaxX); for (int column_n = 0; column_n < columns->Columns.Size; column_n++) From 945f4d1ecd5806268de9674c3753feb7911fb935 Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 5 Mar 2018 16:16:27 +0100 Subject: [PATCH 748/823] Removed redundant semi colons. (#1653) --- imgui_demo.cpp | 2 +- imgui_draw.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/imgui_demo.cpp b/imgui_demo.cpp index fe6d208c7c96..713a929d89f7 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -2239,7 +2239,7 @@ void ImGui::ShowStyleEditor(ImGuiStyle* ref) { ImVec2 cell_p1(base_pos.x + (n % 16) * (cell_size.x + cell_spacing), base_pos.y + (n / 16) * (cell_size.y + cell_spacing)); ImVec2 cell_p2(cell_p1.x + cell_size.x, cell_p1.y + cell_size.y); - const ImFontGlyph* glyph = font->FindGlyph((ImWchar)(base+n));; + const ImFontGlyph* glyph = font->FindGlyph((ImWchar)(base+n)); draw_list->AddRect(cell_p1, cell_p2, glyph ? IM_COL32(255,255,255,100) : IM_COL32(255,255,255,50)); font->RenderChar(draw_list, cell_size.x, cell_p1, ImGui::GetColorU32(ImGuiCol_Text), (ImWchar)(base+n)); // We use ImFont::RenderChar as a shortcut because we don't have UTF-8 conversion functions available to generate a string. if (glyph && ImGui::IsMouseHoveringRect(cell_p1, cell_p2)) diff --git a/imgui_draw.cpp b/imgui_draw.cpp index 1a15a1407237..53f8160b1f7a 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -2056,7 +2056,7 @@ const ImWchar* ImFontAtlas::GetGlyphRangesJapanese() // Unpack int codepoint = 0x4e00; memcpy(full_ranges, base_ranges, sizeof(base_ranges)); - ImWchar* dst = full_ranges + IM_ARRAYSIZE(base_ranges);; + ImWchar* dst = full_ranges + IM_ARRAYSIZE(base_ranges); for (int n = 0; n < IM_ARRAYSIZE(offsets_from_0x4E00); n++, dst += 2) dst[0] = dst[1] = (ImWchar)(codepoint += (offsets_from_0x4E00[n] + 1)); dst[0] = 0; From cea7492babfbd561589a41858159b14f0ca2373e Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 5 Mar 2018 22:47:53 +0100 Subject: [PATCH 749/823] Render: Removed the code that disable render if style.Alpha is 0.0f, it is both incorrect (as style Alpha can be modified mid-frame), not really necessary (just tested that full Alpha = 0 will lead to empty draw lists!) and misleading (bulk of the work was already done). --- imgui.cpp | 83 ++++++++++++++++++++++++++----------------------------- 1 file changed, 39 insertions(+), 44 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 31e7ff9e17e3..775d61e31216 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -4028,52 +4028,47 @@ void ImGui::Render() ImGui::EndFrame(); g.FrameCountRendered = g.FrameCount; - // Skip render altogether if alpha is 0.0 - // Note that vertex buffers have been created and are wasted, so it is best practice that you don't create windows in the first place, or consistently respond to Begin() returning false. - if (g.Style.Alpha > 0.0f) - { - // Gather windows to render - g.IO.MetricsRenderVertices = g.IO.MetricsRenderIndices = g.IO.MetricsActiveWindows = 0; - g.DrawDataBuilder.Clear(); - ImGuiWindow* window_to_render_front_most = (g.NavWindowingTarget && !(g.NavWindowingTarget->Flags & ImGuiWindowFlags_NoBringToFrontOnFocus)) ? g.NavWindowingTarget : NULL; - for (int n = 0; n != g.Windows.Size; n++) - { - ImGuiWindow* window = g.Windows[n]; - if (window->Active && window->HiddenFrames <= 0 && (window->Flags & (ImGuiWindowFlags_ChildWindow)) == 0 && window != window_to_render_front_most) - AddWindowToDrawDataSelectLayer(window); - } - if (window_to_render_front_most && window_to_render_front_most->Active && window_to_render_front_most->HiddenFrames <= 0) // NavWindowingTarget is always temporarily displayed as the front-most window - AddWindowToDrawDataSelectLayer(window_to_render_front_most); - g.DrawDataBuilder.FlattenIntoSingleLayer(); - - // Draw software mouse cursor if requested - ImVec2 offset, size, uv[4]; - if (g.IO.MouseDrawCursor && g.IO.Fonts->GetMouseCursorTexData(g.MouseCursor, &offset, &size, &uv[0], &uv[2])) - { - const ImVec2 pos = g.IO.MousePos - offset; - const ImTextureID tex_id = g.IO.Fonts->TexID; - const float sc = g.Style.MouseCursorScale; - g.OverlayDrawList.PushTextureID(tex_id); - g.OverlayDrawList.AddImage(tex_id, pos + ImVec2(1,0)*sc, pos+ImVec2(1,0)*sc + size*sc, uv[2], uv[3], IM_COL32(0,0,0,48)); // Shadow - g.OverlayDrawList.AddImage(tex_id, pos + ImVec2(2,0)*sc, pos+ImVec2(2,0)*sc + size*sc, uv[2], uv[3], IM_COL32(0,0,0,48)); // Shadow - g.OverlayDrawList.AddImage(tex_id, pos, pos + size*sc, uv[2], uv[3], IM_COL32(0,0,0,255)); // Black border - g.OverlayDrawList.AddImage(tex_id, pos, pos + size*sc, uv[0], uv[1], IM_COL32(255,255,255,255)); // White fill - g.OverlayDrawList.PopTextureID(); - } - if (!g.OverlayDrawList.VtxBuffer.empty()) - AddDrawListToDrawData(&g.DrawDataBuilder.Layers[0], &g.OverlayDrawList); - - // Setup ImDrawData structure for end-user - SetupDrawData(&g.DrawDataBuilder.Layers[0], &g.DrawData); - g.IO.MetricsRenderVertices = g.DrawData.TotalVtxCount; - g.IO.MetricsRenderIndices = g.DrawData.TotalIdxCount; - - // Render. If user hasn't set a callback then they may retrieve the draw data via GetDrawData() + // Gather windows to render + g.IO.MetricsRenderVertices = g.IO.MetricsRenderIndices = g.IO.MetricsActiveWindows = 0; + g.DrawDataBuilder.Clear(); + ImGuiWindow* window_to_render_front_most = (g.NavWindowingTarget && !(g.NavWindowingTarget->Flags & ImGuiWindowFlags_NoBringToFrontOnFocus)) ? g.NavWindowingTarget : NULL; + for (int n = 0; n != g.Windows.Size; n++) + { + ImGuiWindow* window = g.Windows[n]; + if (window->Active && window->HiddenFrames <= 0 && (window->Flags & ImGuiWindowFlags_ChildWindow) == 0 && window != window_to_render_front_most) + AddWindowToDrawDataSelectLayer(window); + } + if (window_to_render_front_most && window_to_render_front_most->Active && window_to_render_front_most->HiddenFrames <= 0) // NavWindowingTarget is always temporarily displayed as the front-most window + AddWindowToDrawDataSelectLayer(window_to_render_front_most); + g.DrawDataBuilder.FlattenIntoSingleLayer(); + + // Draw software mouse cursor if requested + ImVec2 offset, size, uv[4]; + if (g.IO.MouseDrawCursor && g.IO.Fonts->GetMouseCursorTexData(g.MouseCursor, &offset, &size, &uv[0], &uv[2])) + { + const ImVec2 pos = g.IO.MousePos - offset; + const ImTextureID tex_id = g.IO.Fonts->TexID; + const float sc = g.Style.MouseCursorScale; + g.OverlayDrawList.PushTextureID(tex_id); + g.OverlayDrawList.AddImage(tex_id, pos + ImVec2(1,0)*sc, pos+ImVec2(1,0)*sc + size*sc, uv[2], uv[3], IM_COL32(0,0,0,48)); // Shadow + g.OverlayDrawList.AddImage(tex_id, pos + ImVec2(2,0)*sc, pos+ImVec2(2,0)*sc + size*sc, uv[2], uv[3], IM_COL32(0,0,0,48)); // Shadow + g.OverlayDrawList.AddImage(tex_id, pos, pos + size*sc, uv[2], uv[3], IM_COL32(0,0,0,255)); // Black border + g.OverlayDrawList.AddImage(tex_id, pos, pos + size*sc, uv[0], uv[1], IM_COL32(255,255,255,255)); // White fill + g.OverlayDrawList.PopTextureID(); + } + if (!g.OverlayDrawList.VtxBuffer.empty()) + AddDrawListToDrawData(&g.DrawDataBuilder.Layers[0], &g.OverlayDrawList); + + // Setup ImDrawData structure for end-user + SetupDrawData(&g.DrawDataBuilder.Layers[0], &g.DrawData); + g.IO.MetricsRenderVertices = g.DrawData.TotalVtxCount; + g.IO.MetricsRenderIndices = g.DrawData.TotalIdxCount; + + // Render. If user hasn't set a callback then they may retrieve the draw data via GetDrawData() #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS - if (g.DrawData.CmdListsCount > 0 && g.IO.RenderDrawListsFn != NULL) - g.IO.RenderDrawListsFn(&g.DrawData); + if (g.DrawData.CmdListsCount > 0 && g.IO.RenderDrawListsFn != NULL) + g.IO.RenderDrawListsFn(&g.DrawData); #endif - } } const char* ImGui::FindRenderedTextEnd(const char* text, const char* text_end) From a2ed3ee2cfdf3a763bc97e9eaf2d43b1be87364d Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 6 Mar 2018 19:48:30 +0100 Subject: [PATCH 750/823] Examples: OpenGL3: Added a way to override the glsl version number through the Init call. (#1667, #1466) --- .../opengl3_example/imgui_impl_glfw_gl3.cpp | 29 ++++++++++++++----- .../opengl3_example/imgui_impl_glfw_gl3.h | 2 +- .../imgui_impl_sdl_gl3.cpp | 24 +++++++++++---- .../sdl_opengl3_example/imgui_impl_sdl_gl3.h | 2 +- 4 files changed, 43 insertions(+), 14 deletions(-) diff --git a/examples/opengl3_example/imgui_impl_glfw_gl3.cpp b/examples/opengl3_example/imgui_impl_glfw_gl3.cpp index e75719423fe4..8a8b8ed96072 100644 --- a/examples/opengl3_example/imgui_impl_glfw_gl3.cpp +++ b/examples/opengl3_example/imgui_impl_glfw_gl3.cpp @@ -13,6 +13,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2018-03-06: OpenGL: Added const char* glsl_version parameter to ImGui_ImplGlfwGL3_Init() so user can override the GLSL version e.g. "#version 150". // 2018-02-23: OpenGL: Create the VAO in the render function so the setup can more easily be used with multiple shared GL context. // 2018-02-20: Inputs: Added support for mouse cursors (ImGui::GetMouseCursor() value and WM_SETCURSOR message handling). // 2018-02-20: Inputs: Renamed GLFW callbacks exposed in .h to not include GL3 in their name. @@ -31,6 +32,10 @@ // 2016-09-05: OpenGL: Fixed save and restore of current scissor rectangle. // 2016-04-30: OpenGL: Fixed save and restore of current GL_ACTIVE_TEXTURE. +#if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_WARNINGS) +#define _CRT_SECURE_NO_WARNINGS +#endif + #include "imgui.h" #include "imgui_impl_glfw_gl3.h" @@ -51,6 +56,7 @@ static bool g_MouseJustPressed[3] = { false, false, false }; static GLFWcursor* g_MouseCursors[ImGuiMouseCursor_COUNT] = { 0 }; // OpenGL3 data +static char g_GlslVersion[32] = "#version 150"; static GLuint g_FontTexture = 0; static int g_ShaderHandle = 0, g_VertHandle = 0, g_FragHandle = 0; static int g_AttribLocationTex = 0, g_AttribLocationProjMtx = 0; @@ -258,8 +264,7 @@ bool ImGui_ImplGlfwGL3_CreateDeviceObjects() glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &last_array_buffer); glGetIntegerv(GL_VERTEX_ARRAY_BINDING, &last_vertex_array); - const GLchar *vertex_shader = - "#version 150\n" + const GLchar* vertex_shader = "uniform mat4 ProjMtx;\n" "in vec2 Position;\n" "in vec2 UV;\n" @@ -274,7 +279,6 @@ bool ImGui_ImplGlfwGL3_CreateDeviceObjects() "}\n"; const GLchar* fragment_shader = - "#version 150\n" "uniform sampler2D Texture;\n" "in vec2 Frag_UV;\n" "in vec4 Frag_Color;\n" @@ -284,11 +288,14 @@ bool ImGui_ImplGlfwGL3_CreateDeviceObjects() " Out_Color = Frag_Color * texture( Texture, Frag_UV.st);\n" "}\n"; + const GLchar* vertex_shader_with_version[2] = { g_GlslVersion, vertex_shader }; + const GLchar* fragment_shader_with_version[2] = { g_GlslVersion, fragment_shader }; + g_ShaderHandle = glCreateProgram(); g_VertHandle = glCreateShader(GL_VERTEX_SHADER); g_FragHandle = glCreateShader(GL_FRAGMENT_SHADER); - glShaderSource(g_VertHandle, 1, &vertex_shader, 0); - glShaderSource(g_FragHandle, 1, &fragment_shader, 0); + glShaderSource(g_VertHandle, 2, vertex_shader_with_version, NULL); + glShaderSource(g_FragHandle, 2, fragment_shader_with_version, NULL); glCompileShader(g_VertHandle); glCompileShader(g_FragHandle); glAttachShader(g_ShaderHandle, g_VertHandle); @@ -347,12 +354,20 @@ static void ImGui_ImplGlfw_InstallCallbacks(GLFWwindow* window) glfwSetCharCallback(window, ImGui_ImplGlfw_CharCallback); } -bool ImGui_ImplGlfwGL3_Init(GLFWwindow* window, bool install_callbacks) +bool ImGui_ImplGlfwGL3_Init(GLFWwindow* window, bool install_callbacks, const char* glsl_version) { g_Window = window; + // Store GL version string so we can refer to it later in case we recreate shaders. + if (glsl_version == NULL) + glsl_version = "#version 150"; + IM_ASSERT((int)strlen(glsl_version) + 2 < IM_ARRAYSIZE(g_GlslVersion)); + strcpy(g_GlslVersion, glsl_version); + strcat(g_GlslVersion, "\n"); + + // Keyboard mapping. ImGui will use those indices to peek into the io.KeyDown[] array. ImGuiIO& io = ImGui::GetIO(); - io.KeyMap[ImGuiKey_Tab] = GLFW_KEY_TAB; // Keyboard mapping. ImGui will use those indices to peek into the io.KeyDown[] array. + io.KeyMap[ImGuiKey_Tab] = GLFW_KEY_TAB; io.KeyMap[ImGuiKey_LeftArrow] = GLFW_KEY_LEFT; io.KeyMap[ImGuiKey_RightArrow] = GLFW_KEY_RIGHT; io.KeyMap[ImGuiKey_UpArrow] = GLFW_KEY_UP; diff --git a/examples/opengl3_example/imgui_impl_glfw_gl3.h b/examples/opengl3_example/imgui_impl_glfw_gl3.h index 6cbbe4a5cdba..33b5329db9e3 100644 --- a/examples/opengl3_example/imgui_impl_glfw_gl3.h +++ b/examples/opengl3_example/imgui_impl_glfw_gl3.h @@ -13,7 +13,7 @@ struct GLFWwindow; -IMGUI_API bool ImGui_ImplGlfwGL3_Init(GLFWwindow* window, bool install_callbacks); +IMGUI_API bool ImGui_ImplGlfwGL3_Init(GLFWwindow* window, bool install_callbacks, const char* glsl_version = NULL); IMGUI_API void ImGui_ImplGlfwGL3_Shutdown(); IMGUI_API void ImGui_ImplGlfwGL3_NewFrame(); IMGUI_API void ImGui_ImplGlfwGL3_RenderDrawData(ImDrawData* draw_data); diff --git a/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.cpp b/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.cpp index a0ca7e629612..995948d0c765 100644 --- a/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.cpp +++ b/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.cpp @@ -12,6 +12,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2018-03-06: OpenGL: Added const char* glsl_version parameter to ImGui_ImplSdlGL3_Init() so user can override the GLSL version e.g. "#version 150". // 2018-02-23: OpenGL: Create the VAO in the render function so the setup can more easily be used with multiple shared GL context. // 2018-02-16: Inputs: Added support for mouse cursors, honoring ImGui::GetMouseCursor() value. // 2018-02-16: Misc: Obsoleted the io.RenderDrawListsFn callback and exposed ImGui_ImplSdlGL3_RenderDrawData() in the .h file so you can call it yourself. @@ -31,6 +32,10 @@ // 2016-09-05: OpenGL: Fixed save and restore of current scissor rectangle. // 2016-07-29: OpenGL: Explicitly setting GL_UNPACK_ROW_LENGTH to reduce issues because SDL changes it. (#752) +#if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_WARNINGS) +#define _CRT_SECURE_NO_WARNINGS +#endif + #include "imgui.h" #include "imgui_impl_sdl_gl3.h" @@ -45,6 +50,7 @@ static bool g_MousePressed[3] = { false, false, false }; static SDL_Cursor* g_MouseCursors[ImGuiMouseCursor_COUNT] = { 0 }; // OpenGL data +static char g_GlslVersion[32] = "#version 150"; static GLuint g_FontTexture = 0; static int g_ShaderHandle = 0, g_VertHandle = 0, g_FragHandle = 0; static int g_AttribLocationTex = 0, g_AttribLocationProjMtx = 0; @@ -261,7 +267,6 @@ bool ImGui_ImplSdlGL3_CreateDeviceObjects() glGetIntegerv(GL_VERTEX_ARRAY_BINDING, &last_vertex_array); const GLchar *vertex_shader = - "#version 150\n" "uniform mat4 ProjMtx;\n" "in vec2 Position;\n" "in vec2 UV;\n" @@ -276,7 +281,6 @@ bool ImGui_ImplSdlGL3_CreateDeviceObjects() "}\n"; const GLchar* fragment_shader = - "#version 150\n" "uniform sampler2D Texture;\n" "in vec2 Frag_UV;\n" "in vec4 Frag_Color;\n" @@ -286,11 +290,14 @@ bool ImGui_ImplSdlGL3_CreateDeviceObjects() " Out_Color = Frag_Color * texture( Texture, Frag_UV.st);\n" "}\n"; + const GLchar* vertex_shader_with_version[2] = { g_GlslVersion, vertex_shader }; + const GLchar* fragment_shader_with_version[2] = { g_GlslVersion, fragment_shader }; + g_ShaderHandle = glCreateProgram(); g_VertHandle = glCreateShader(GL_VERTEX_SHADER); g_FragHandle = glCreateShader(GL_FRAGMENT_SHADER); - glShaderSource(g_VertHandle, 1, &vertex_shader, 0); - glShaderSource(g_FragHandle, 1, &fragment_shader, 0); + glShaderSource(g_VertHandle, 2, vertex_shader_with_version, NULL); + glShaderSource(g_FragHandle, 2, fragment_shader_with_version, NULL); glCompileShader(g_VertHandle); glCompileShader(g_FragHandle); glAttachShader(g_ShaderHandle, g_VertHandle); @@ -341,8 +348,15 @@ void ImGui_ImplSdlGL3_InvalidateDeviceObjects() } } -bool ImGui_ImplSdlGL3_Init(SDL_Window* window) +bool ImGui_ImplSdlGL3_Init(SDL_Window* window, const char* glsl_version) { + // Store GL version string so we can refer to it later in case we recreate shaders. + if (glsl_version == NULL) + glsl_version = "#version 150"; + IM_ASSERT((int)strlen(glsl_version) + 2 < IM_ARRAYSIZE(g_GlslVersion)); + strcpy(g_GlslVersion, glsl_version); + strcat(g_GlslVersion, "\n"); + // Keyboard mapping. ImGui will use those indices to peek into the io.KeyDown[] array. ImGuiIO& io = ImGui::GetIO(); io.KeyMap[ImGuiKey_Tab] = SDL_SCANCODE_TAB; diff --git a/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.h b/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.h index fa111a1793b7..3aa00c3d1ac0 100644 --- a/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.h +++ b/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.h @@ -13,7 +13,7 @@ struct SDL_Window; typedef union SDL_Event SDL_Event; -IMGUI_API bool ImGui_ImplSdlGL3_Init(SDL_Window* window); +IMGUI_API bool ImGui_ImplSdlGL3_Init(SDL_Window* window, const char* glsl_version = NULL); IMGUI_API void ImGui_ImplSdlGL3_Shutdown(); IMGUI_API void ImGui_ImplSdlGL3_NewFrame(SDL_Window* window); IMGUI_API void ImGui_ImplSdlGL3_RenderDrawData(ImDrawData* draw_data); From 6190d794d40fd6c7776aca6989297a35f3356e73 Mon Sep 17 00:00:00 2001 From: omar Date: Wed, 7 Mar 2018 10:01:20 +0100 Subject: [PATCH 751/823] Update README.md --- README.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/README.md b/README.md index b5f4356350ec..5773278aa25d 100644 --- a/README.md +++ b/README.md @@ -145,8 +145,7 @@ Frameworks: - Unreal Engine 4: [segross/UnrealImGui](https://github.com/segross/UnrealImGui) or [sronsse/UnrealEngine_ImGui](https://github.com/sronsse/UnrealEngine_ImGui) - SFML: [imgui-sfml](https://github.com/EliasD/imgui-sfml) or [imgui-backends](https://github.com/Mischa-Alff/imgui-backends) -For other bindings: see [this page](https://github.com/ocornut/imgui/wiki/Links/). -Please contact me with the Issues tracker or Twitter to fix/update this list. +For other bindings: see [this page](https://github.com/ocornut/imgui/wiki/Links/). Also see [wiki](https://github.com/ocornut/imgui/wiki) for a few other links and ideas. Contact me if you would like to add to those lists. Roadmap ------- From 7fd62baa426b3f4a2d98c1510161bf1135dde7bc Mon Sep 17 00:00:00 2001 From: omar Date: Wed, 7 Mar 2018 11:50:56 +0100 Subject: [PATCH 752/823] Examples: Added Makefile for SDL+OpenGL2 example. (#1668) --- examples/sdl_opengl2_example/Makefile | 66 +++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) create mode 100644 examples/sdl_opengl2_example/Makefile diff --git a/examples/sdl_opengl2_example/Makefile b/examples/sdl_opengl2_example/Makefile new file mode 100644 index 000000000000..dc4d69f1ac81 --- /dev/null +++ b/examples/sdl_opengl2_example/Makefile @@ -0,0 +1,66 @@ +# +# Cross Platform Makefile +# Compatible with MSYS2/MINGW, Ubuntu 14.04.1 and Mac OS X +# +# You will need SDL2 (http://www.libsdl.org): +# Linux: +# apt-get install libsdl2-dev +# Mac OS X: +# brew install sdl2 +# MSYS2: +# pacman -S mingw-w64-i686-SDL +# + +#CXX = g++ +#CXX = clang++ + +EXE = sdl_opengl2_example +SOURCES = main.cpp imgui_impl_sdl_gl2.cpp +SOURCES += ../../imgui.cpp ../../imgui_demo.cpp ../../imgui_draw.cpp +OBJS = $(addsuffix .o, $(basename $(notdir $(SOURCES)))) + +UNAME_S := $(shell uname -s) + + +ifeq ($(UNAME_S), Linux) #LINUX + ECHO_MESSAGE = "Linux" + LIBS = -lGL -ldl `sdl2-config --libs` + + CXXFLAGS = -I../../ `sdl2-config --cflags` + CXXFLAGS += -Wall -Wformat + CFLAGS = $(CXXFLAGS) +endif + +ifeq ($(UNAME_S), Darwin) #APPLE + ECHO_MESSAGE = "Mac OS X" + LIBS = -framework OpenGL -framework Cocoa -framework IOKit -framework CoreVideo `sdl2-config --libs` + + CXXFLAGS = -I../../ -I/usr/local/include `sdl2-config --cflags` + CXXFLAGS += -Wall -Wformat + CFLAGS = $(CXXFLAGS) +endif + +ifeq ($(findstring MINGW,$(UNAME_S)),MINGW) + ECHO_MESSAGE = "Windows" + LIBS = -lgdi32 -lopengl32 -limm32 `pkg-config --static --libs sdl2` + + CXXFLAGS = -I../../ `pkg-config --cflags sdl2` + CXXFLAGS += -Wall -Wformat + CFLAGS = $(CXXFLAGS) +endif + + +%.o:%.cpp + $(CXX) $(CXXFLAGS) -c -o $@ $< + +%.o:../../%.cpp + $(CXX) $(CXXFLAGS) -c -o $@ $< + +all: $(EXE) + @echo Build complete for $(ECHO_MESSAGE) + +$(EXE): $(OBJS) + $(CXX) -o $@ $^ $(CXXFLAGS) $(LIBS) + +clean: + rm -f $(EXE) $(OBJS) From a1f3949d7174e4500308a6211c9781f85900bb16 Mon Sep 17 00:00:00 2001 From: omar Date: Thu, 8 Mar 2018 10:42:51 +0100 Subject: [PATCH 753/823] Drag and Drop: Increased payload data type to 32 characters. (#143) --- CHANGELOG.txt | 2 +- imgui.h | 4 ++-- imgui_internal.h | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.txt b/CHANGELOG.txt index 6ce0cd553aac..012f0fdec250 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -111,7 +111,7 @@ Other Changes: - Columns: Fixed a memory leak of ImGuiColumnsSet's Columns vector. (#1529) [@unprompted] - MenuBar: Fixed menu bar pushing a clipping rect outside of its allocated bound (usually unnoticeable). - TreeNode: nodes with the ImGuiTreeNodeFlags_Leaf flag correctly disable highlight when DragDrop is active. (#143, #581) -- Drag and Drop: Increased payload type string to 12 characters instead of 8. (#143) +- Drag and Drop: Increased payload type string to 32 characters instead of 8. (#143) - Drag and Drop: TreeNode as drop target displays rectangle over full frame. (#1597, #143) - DragFloat: Fix/workaround for backends which do not preserve a valid mouse position when dragged out of bounds. (#1559) - Slider, Combo: Use ImGuiCol_FrameBgHovered color when hovered. (#1456) [@stfx] diff --git a/imgui.h b/imgui.h index 1111014210b0..d1934ae8c45f 100644 --- a/imgui.h +++ b/imgui.h @@ -458,7 +458,7 @@ namespace ImGui // Drag and Drop // [BETA API] Missing Demo code. API may evolve. IMGUI_API bool BeginDragDropSource(ImGuiDragDropFlags flags = 0); // call when the current item is active. If this return true, you can call SetDragDropPayload() + EndDragDropSource() - IMGUI_API bool SetDragDropPayload(const char* type, const void* data, size_t size, ImGuiCond cond = 0);// type is a user defined string of maximum 12 characters. Strings starting with '_' are reserved for dear imgui internal types. Data is copied and held by imgui. + IMGUI_API bool SetDragDropPayload(const char* type, const void* data, size_t size, ImGuiCond cond = 0);// type is a user defined string of maximum 32 characters. Strings starting with '_' are reserved for dear imgui internal types. Data is copied and held by imgui. IMGUI_API void EndDragDropSource(); // only call EndDragDropSource() if BeginDragDropSource() returns true! IMGUI_API bool BeginDragDropTarget(); // call after submitting an item that may receive an item. If this returns true, you can call AcceptDragDropPayload() + EndDragDropTarget() IMGUI_API const ImGuiPayload* AcceptDragDropPayload(const char* type, ImGuiDragDropFlags flags = 0); // accept contents of a given type. If ImGuiDragDropFlags_AcceptBeforeDelivery is set you can peek into the payload before the mouse button is released. @@ -1348,7 +1348,7 @@ struct ImGuiPayload ImGuiID SourceId; // Source item id ImGuiID SourceParentId; // Source parent id (if available) int DataFrameCount; // Data timestamp - char DataType[12 + 1]; // Data type tag (short user-supplied string, 12 characters max) + char DataType[32+1]; // Data type tag (short user-supplied string, 32 characters max) bool Preview; // Set when AcceptDragDropPayload() was called and mouse has been hovering the target item (nb: handle overlapping drag targets) bool Delivery; // Set when AcceptDragDropPayload() was called and mouse button is released over the target item. diff --git a/imgui_internal.h b/imgui_internal.h index 79fc4d95849a..1ffa16006123 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -662,7 +662,7 @@ struct ImGuiContext ImGuiID DragDropAcceptIdPrev; // Target item id from previous frame (we need to store this to allow for overlapping drag and drop targets) int DragDropAcceptFrameCount; // Last time a target expressed a desire to accept the source ImVector DragDropPayloadBufHeap; // We don't expose the ImVector<> directly - unsigned char DragDropPayloadBufLocal[8]; + unsigned char DragDropPayloadBufLocal[8]; // Local buffer for small payloads // Widget state ImGuiTextEditState InputTextState; From 642c6748ac858099cf1994b5f5936d5f6db95c62 Mon Sep 17 00:00:00 2001 From: omar Date: Thu, 8 Mar 2018 11:15:27 +0100 Subject: [PATCH 754/823] Comments, Changelog --- CHANGELOG.txt | 16 ++++++++++------ imgui.cpp | 13 +++++++------ imgui.h | 2 +- 3 files changed, 18 insertions(+), 13 deletions(-) diff --git a/CHANGELOG.txt b/CHANGELOG.txt index 012f0fdec250..a33696e38fbd 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -104,11 +104,13 @@ Other Changes: - Popup: Better handling of user mistakenly calling OpenPopup() every frame (with reopen_existing option). The error will now be more visible and easier to understand. (#1497) - Popup: BeginPopup(): Exposed extra_flags parameter that are passed through to Begin(). (#1533) - Popup: BeginPopupModal: fixed the conditional test for SetNextWindowPos() which was polling the wrong window, which in practice made the test succeed all the time. -- Tooltip: BeginTooltip() sets NoInputs flag. +- Tooltip: BeginTooltip() sets ImGuiWindowFlags_NoInputs flag. - Scrollbar: Fixed ScrollbarY enable test after ScrollbarX has been enabled being a little off (small regression from Nov 2017). (#1574) - Scrollbar: Fixed ScrollbarX enable test subtracting WindowPadding.x (this has been there since the addition of horizontal scroll bar!). - Columns: Clear offsets data when columns count changed. (#1525) - Columns: Fixed a memory leak of ImGuiColumnsSet's Columns vector. (#1529) [@unprompted] +- Columns: Fixed resizing a window very small breaking some columns positioning (broken in 1.53). +- Columns: The available column extent takes consideration of the right-most clipped pixel, so the right-most column may look a little wider but will contain the same amount of visible contents. - MenuBar: Fixed menu bar pushing a clipping rect outside of its allocated bound (usually unnoticeable). - TreeNode: nodes with the ImGuiTreeNodeFlags_Leaf flag correctly disable highlight when DragDrop is active. (#143, #581) - Drag and Drop: Increased payload type string to 32 characters instead of 8. (#143) @@ -124,6 +126,9 @@ Other Changes: - ImFontAtlas: Added ImFontAtlasFlags_NoPowerOfTwoHeight flag to disable padding font height to nearest power of two. (#1613) - ImFontAtlas: Added ImFontAtlasFlags_NoMouseCursors flag to disable baking software mouse cursors, mostly to save texture memory on very low end hardware. (#1613) - ImDrawList: Fixed AddRect() with antialiasing disabled (lower-right corner pixel was often missing, rounding looks a little better.) (#1646) +- Fonts: Updated stb_truetype from 1.14 to stb_truetype 1.19. (w/ include fix from some platforms #1622) +- Fonts: Added optional FreeType rasterizer in misc/freetype. Moved from imgui_club repo. (#618) [@Vuhdo, @mikesart, @ocornut] +- Fonts: Moved extra_fonts/ to misc/fonts/. - Misc: Functions passed to libc qsort are explicitely marked cdecl to support compiling with vectorcall as the default calling convention. (#1230, #1611) [@RandyGaul] - Misc: ImVec2: added [] operator. This is becoming desirable for some types of code, better added sooner than later. - Misc: Exposed IM_OFFSETOF() helper in imgui.h. @@ -134,18 +139,17 @@ Other Changes: - Misc: Updated stb_rect_pack from 0.10 to 0.11 (minor changes). - Misc: Added ImGuiConfigFlags_IsSRGB and ImGuiConfigFlags_IsTouchScreen user flags (for io.ConfigFlags). (Those flags are not used by ImGui itself, they only exists to make it easy for the engine/back-end to pass information to the application in a standard manner.) -- Fonts: Updated stb_truetype from 1.14 to stb_truetype 1.19. (w/ include fix from some platforms #1622) -- Fonts: Added optional FreeType rasterizer in misc/freetype. Moved from imgui_club repo. (#618) [@Vuhdo, @mikesart, @ocornut] -- Fonts: Moved extra_fonts/ to misc/fonts/. +- Metrics: Added display of Columns state. - Demo: Improved Selectable() examples. (#1528) - Demo: Tweaked the Child demos, added a menu bar to the second child to test some navigation functions. - Demo: Console: Using ImGuiCol_Text to be more friendly to color changes. - Demo: Using IM_COL32() instead of ImColor() in ImDrawList centric contexts. Trying to phase out use of the ImColor helper whenever possible. - Examples: Files in examples/ now include their own changelog so it is easier to occasionally update your bindings if needed. - Examples: Using Dark theme by default. (#707). Tweaked demo code. -- Examples: Added support for horizontal mouse wheel for API that allows it. (#1463) +- Examples: Added support for horizontal mouse wheel for API that allows it. (#1463) [@tseeker] - Examples: DirectX12: Added DirectX 12 example. (#301) [@jdm3] -- Examples: OpenGL3+GLFW,SDL: Changed GLSL shader version to 150 (#1466, #1504). +- Examples: OpenGL3+GLFW,SDL: Changed GLSL shader version from 330 to 150. (#1466, #1504) +- Examples: OpenGL3+GLFW,SDL: Added a way to override the GLSL version string in the Init function. (#1466, #1504). - Examples: OpenGL3+GLFW,SDL: Creating VAO in the render function so it can be more easily used by multiple shared OpenGL contexts. (#1217) - Examples: OpenGL3+GLFW: Using 3.2 context instead of 3.3. (#1466) - Examples: OpenGL: Setting up glPixelStorei() explicitly before uploading texture. diff --git a/imgui.cpp b/imgui.cpp index 775d61e31216..3d8ef3df0275 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -19,7 +19,7 @@ - Read first - How to update to a newer version of Dear ImGui - Getting started with integrating Dear ImGui in your code/engine - - Using gamepad/keyboard navigation [BETA] + - Using gamepad/keyboard navigation controls [BETA] - API BREAKING CHANGES (read me when you update!) - ISSUES & TODO LIST - FREQUENTLY ASKED QUESTIONS (FAQ), TIPS @@ -76,7 +76,8 @@ - ESCAPE to revert text to its original value. - You can apply arithmetic operators +,*,/ on numerical values. Use +- to subtract (because - would set a negative value!) - Controls are automatically adjusted for OSX to match standard OSX text editing operations. - - Gamepad navigation: see suggested mappings in imgui.h ImGuiNavInput_ + download PNG/PSD at goo.gl/9LgVZW. + - General Keyboard controls: enable with ImGuiConfigFlags_NavEnableKeyboard. + - General Gamepad controls: enable with ImGuiConfigFlags_NavEnableGamepad. See suggested mappings in imgui.h ImGuiNavInput_ + download PNG/PSD at goo.gl/9LgVZW. PROGRAMMER GUIDE @@ -210,9 +211,9 @@ They tell you if ImGui intends to use your inputs. So for example, if 'io.WantCaptureMouse' is set you would typically want to hide mouse inputs from the rest of your application. Read the FAQ below for more information about those flags. - USING GAMEPAD/KEYBOARD NAVIGATION [BETA] + USING GAMEPAD/KEYBOARD NAVIGATION CONTROLS [BETA] - - Ask questions and report issues at https://github.com/ocornut/imgui/issues/787 + - The gamepad/keyboard navigation is in Beta. Ask questions and report issues at https://github.com/ocornut/imgui/issues/787 - The initial focus was to support game controllers, but keyboard is becoming increasingly and decently usable. - Keyboard: - Set io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard to enable. NewFrame() will automatically fill io.NavInputs[] based on your io.KeyDown[] + io.KeyMap[] arrays. @@ -227,13 +228,13 @@ - See 'enum ImGuiNavInput_' in imgui.h for a description of inputs. For each entry of io.NavInputs[], set the following values: 0.0f= not held. 1.0f= fully held. Pass intermediate 0.0f..1.0f values for analog triggers/sticks. - We uses a simple >0.0f test for activation testing, and won't attempt to test for a dead-zone. - Your code will probably need to transform your raw inputs (such as e.g. remapping your 0.2..0.9 raw input range to 0.0..1.0 imgui range, maybe a power curve, etc.). + Your code will probably need to transform your raw inputs (such as e.g. remapping your 0.2..0.9 raw input range to 0.0..1.0 imgui range, etc.). - You can download PNG/PSD files depicting the gamepad controls for common controllers at: goo.gl/9LgVZW. - If you need to share inputs between your game and the imgui parts, the easiest approach is to go all-or-nothing, with a buttons combo to toggle the target. Please reach out if you think the game vs navigation input sharing could be improved. - Mouse: - PS4 users: Consider emulating a mouse cursor with DualShock4 touch pad or a spare analog stick as a mouse-emulation fallback. - - Consoles/Tablet/Phone users: Consider using a Synergy 1.x server (on your PC) + uSynergy.c (in your console/tablet/phone app) to share your PC mouse/keyboard. + - Consoles/Tablet/Phone users: Consider using a Synergy 1.x server (on your PC) + uSynergy.c (on your console/tablet/phone app) to share your PC mouse/keyboard. - On a TV/console system where readability may be lower or mouse inputs may be awkward, you may want to set the ImGuiConfigFlags_NavMoveMouse flag. Enabling ImGuiConfigFlags_NavMoveMouse instructs dear imgui to move your mouse cursor along with navigation movements. When enabled, the NewFrame() function may alter 'io.MousePos' and set 'io.WantMoveMouse' to notify you that it wants the mouse cursor to be moved. diff --git a/imgui.h b/imgui.h index d1934ae8c45f..1273e0a2462d 100644 --- a/imgui.h +++ b/imgui.h @@ -753,7 +753,7 @@ enum ImGuiNavInput_ ImGuiNavInput_TweakFast, // faster tweaks // e.g. R1 or R2 (PS4), RB or RT (Xbox), R or ZL (Switch) // [Internal] Don't use directly! This is used internally to differentiate keyboard from gamepad inputs for behaviors that require to differentiate them. - // Keyboard behavior that have no corresponding gamepad mapping (e.g. CTRL+TAB) may be directly reading from io.KeyDown[] instead of io.NavInputs[]. + // Keyboard behavior that have no corresponding gamepad mapping (e.g. CTRL+TAB) will be directly reading from io.KeyDown[] instead of io.NavInputs[]. ImGuiNavInput_KeyMenu_, // toggle menu // = io.KeyAlt ImGuiNavInput_KeyLeft_, // move left // = Arrow keys ImGuiNavInput_KeyRight_, // move right From 3dfac93ebe0fc4d63fb46f676263b9da64226100 Mon Sep 17 00:00:00 2001 From: omar Date: Thu, 8 Mar 2018 15:58:56 +0100 Subject: [PATCH 755/823] Fonts: Fixed debug name not being zero-terminated if longer than storage buffer + made buffer slightly longer as well. --- imgui.h | 2 +- imgui_draw.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/imgui.h b/imgui.h index 1273e0a2462d..282365e41424 100644 --- a/imgui.h +++ b/imgui.h @@ -1628,7 +1628,7 @@ struct ImFontConfig float RasterizerMultiply; // 1.0f // Brighten (>1.0f) or darken (<1.0f) font output. Brightening small fonts may be a good workaround to make them more readable. // [Internal] - char Name[32]; // Name (strictly to ease debugging) + char Name[40]; // Name (strictly to ease debugging) ImFont* DstFont; IMGUI_API ImFontConfig(); diff --git a/imgui_draw.cpp b/imgui_draw.cpp index 53f8160b1f7a..8d8d90f55c0c 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -1543,7 +1543,7 @@ ImFont* ImFontAtlas::AddFontFromFileTTF(const char* filename, float size_pixels, // Store a short copy of filename into into the font name for convenience const char* p; for (p = filename + strlen(filename); p > filename && p[-1] != '/' && p[-1] != '\\'; p--) {} - snprintf(font_cfg.Name, IM_ARRAYSIZE(font_cfg.Name), "%s, %.0fpx", p, size_pixels); + ImFormatString(font_cfg.Name, IM_ARRAYSIZE(font_cfg.Name), "%s, %.0fpx", p, size_pixels); } return AddFontFromMemoryTTF(data, data_size, size_pixels, &font_cfg, glyph_ranges); } From 1ef1acbd8d7d46ac6fe083b331dadf9324dc7e07 Mon Sep 17 00:00:00 2001 From: omar Date: Thu, 8 Mar 2018 16:47:41 +0100 Subject: [PATCH 756/823] Font: Fixed MergeMode adding duplicate glyphs data instead of reusing existing (broken by 072d6d8cb5a8bb66318ae5db7d23b3be74bf5ffe) --- CHANGELOG.txt | 3 ++- TODO.txt | 5 ++++- imgui.h | 1 + imgui_draw.cpp | 8 +++++++- misc/freetype/imgui_freetype.cpp | 2 ++ 5 files changed, 16 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.txt b/CHANGELOG.txt index a33696e38fbd..b492255c3ae2 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -268,8 +268,9 @@ Other Changes: - NewFrame(): using literal strings in the most-frequently firing IM_ASSERT expressions to increase the odd of programmers seeing them (especially those who don't use a debugger). - NewFrame() now asserts if neither Render or EndFrame have been called. Exposed EndFrame(). Made it legal to call EndFrame() more than one. (#1423) - ImGuiStorage: Added BuildSortByKey() helper to rebuild storage from stratch. -- ImFont: Added GetDebugName() helper. +- ImFont: Added GetDebugName() helper. - ImFontAtlas: Added missing Thai punctuation in the GetGlyphRangesThai() ranges. (#1396) [@nProtect] +- ImFontAtlas: Fixed cfg.MergeMode not reusing existing glyphs if available (always overwrote). - ImDrawList: Removed 'bool anti_aliased = true' final parameter of ImDrawList::AddPolyline() and ImDrawList::AddConvexPolyFilled(). Anti-aliasing is controlled via the regular style.AntiAliased flags. - ImDrawList: Added ImDrawList::AddImageRounded() helper. (#845) [@thedmd] - ImDrawList: Refactored to make ImDrawList independant of ImGui. Removed static variable in PathArcToFast() which caused linking issues to some. diff --git a/TODO.txt b/TODO.txt index 939393ba6d13..5c58f63f84b8 100644 --- a/TODO.txt +++ b/TODO.txt @@ -212,7 +212,10 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i - pie menus patterns (#434) - markup: simple markup language for color change? (#902) - - font: better vertical centering (based e.g on height of lowercase 'x'?). currently Roboto-Medium size 16 px isn't currently centered. +!- font: need handling of missing glyphs by not packing/rasterizing glyph 0 of a given font. + - font: MergeMode: flags to select overwriting or not. + - font: MergeMode: duplicate glyphs are stored in the atlas texture which is suboptimal. + - font: better vertical centering (based e.g on height of lowercase 'x'?). currently Roboto-Medium size 16 px isn't currently centered. (#1619) - font: free the Alpha buffer if user only requested RGBA. !- font: better CalcTextSizeA() API, at least for simple use cases. current one is horrible (perhaps have simple vs extended versions). - font: enforce monospace through ImFontConfig (for icons?) + create dual ImFont output from same input, reusing rasterized data but with different glyphs/AdvanceX diff --git a/imgui.h b/imgui.h index 282365e41424..4302de937fb2 100644 --- a/imgui.h +++ b/imgui.h @@ -1775,6 +1775,7 @@ struct ImFont ImFontConfig* ConfigData; // // Pointer within ContainerAtlas->ConfigData ImFontAtlas* ContainerAtlas; // // What we has been loaded into float Ascent, Descent; // // Ascent: distance from top to bottom of e.g. 'A' [0..FontSize] + bool DirtyLookupTables; int MetricsTotalSurface;// // Total surface in pixels to get an idea of the font rasterization/texture cost (not exact, we approximate the cost of padding between glyphs) // Methods diff --git a/imgui_draw.cpp b/imgui_draw.cpp index 8d8d90f55c0c..072533174e1c 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -1817,6 +1817,8 @@ bool ImFontAtlasBuildWithStbTruetype(ImFontAtlas* atlas) ImFontConfig& cfg = atlas->ConfigData[input_i]; ImFontTempBuildData& tmp = tmp_array[input_i]; ImFont* dst_font = cfg.DstFont; // We can have multiple input fonts writing into a same destination font (when using MergeMode=true) + if (cfg.MergeMode) + dst_font->BuildLookupTable(); const float font_scale = stbtt_ScaleForPixelHeight(&tmp.FontInfo, cfg.SizePixels); int unscaled_ascent, unscaled_descent, unscaled_line_gap; @@ -1960,7 +1962,8 @@ void ImFontAtlasBuildFinish(ImFontAtlas* atlas) // Build all fonts lookup tables for (int i = 0; i < atlas->Fonts.Size; i++) - atlas->Fonts[i]->BuildLookupTable(); + if (atlas->Fonts[i]->DirtyLookupTables) + atlas->Fonts[i]->BuildLookupTable(); } // Retrieve list of range (2 int per range, values are inclusive) @@ -2165,6 +2168,7 @@ void ImFont::ClearOutputData() ConfigData = NULL; ContainerAtlas = NULL; Ascent = Descent = 0.0f; + DirtyLookupTables = true; MetricsTotalSurface = 0; } @@ -2177,6 +2181,7 @@ void ImFont::BuildLookupTable() IM_ASSERT(Glyphs.Size < 0xFFFF); // -1 is reserved IndexAdvanceX.clear(); IndexLookup.clear(); + DirtyLookupTables = false; GrowIndex(max_codepoint + 1); for (int i = 0; i < Glyphs.Size; i++) { @@ -2241,6 +2246,7 @@ void ImFont::AddGlyph(ImWchar codepoint, float x0, float y0, float x1, float y1, glyph.AdvanceX = (float)(int)(glyph.AdvanceX + 0.5f); // Compute rough surface usage metrics (+1 to account for average padding, +0.99 to round) + DirtyLookupTables = true; MetricsTotalSurface += (int)((glyph.U1 - glyph.U0) * ContainerAtlas->TexWidth + 1.99f) * (int)((glyph.V1 - glyph.V0) * ContainerAtlas->TexHeight + 1.99f); } diff --git a/misc/freetype/imgui_freetype.cpp b/misc/freetype/imgui_freetype.cpp index 0a80bbdfb7d7..54957112a0cf 100644 --- a/misc/freetype/imgui_freetype.cpp +++ b/misc/freetype/imgui_freetype.cpp @@ -315,6 +315,8 @@ bool ImGuiFreeType::BuildFontAtlas(ImFontAtlas* atlas, unsigned int extra_flags) ImFontConfig& cfg = atlas->ConfigData[input_i]; FreeTypeFont& font_face = fonts[input_i]; ImFont* dst_font = cfg.DstFont; + if (cfg.MergeMode) + dst_font->BuildLookupTable(); const float ascent = font_face.Info.Ascender; const float descent = font_face.Info.Descender; From 351b3fa7b07f1e94e9cf83ae41b5b7529e9c0141 Mon Sep 17 00:00:00 2001 From: omar Date: Thu, 8 Mar 2018 16:59:38 +0100 Subject: [PATCH 757/823] Updated Changelog following merge of #1619 + fixed entry added to wrong version Changelog in 1ef1acbd8d7d46ac6fe083b331dadf9324dc7e07 --- CHANGELOG.txt | 12 ++++++++---- imgui.cpp | 2 +- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.txt b/CHANGELOG.txt index b492255c3ae2..2d7039596f15 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -46,6 +46,8 @@ Various internal refactors have also been done, as part of the navigation work a Breaking Changes: (IN PROGRESS, WILL ADD TO THIS LIST AS WE WORK ON 1.60) + - Fonts: changed ImFont::DisplayOffset.y to defaults to 0 instead of +1. Fixed vertical rounding of Ascent/Descent to match TrueType renderer. + If you were adding or subtracting to ImFont::DisplayOffset check if your fonts are correctly aligned vertically. (#1619) - BeginDragDropSource(): temporarily removed the optional mouse_button=0 parameter because it is not really usable in many situations at the moment. - Obsoleted the io.RenderDrawListsFn callback, you can call your graphics engine render function after ImGui::Render(). Use ImGui::GetDrawData() to retrieve the ImDrawData* to display. - Reorganized context handling to be more explicit, @@ -121,14 +123,17 @@ Other Changes: - Combo: BeginCombo(): Added ImGuiComboFlags_NoPreview to disable the preview and only display a square arrow button. - Combo: Arrow button isn't displayed over frame background so its blended color matches other buttons. Left side of the button isn't rounded. - PlotLines: plot a flat line if scale_min==scale_max. (#1621) +- Fonts: Changed DisplayOffset.y to defaults to 0 instead of +1. Fixed rounding of Ascent/Descent to match TrueType renderer. + If you were adding or subtracting to ImFont::DisplayOffset check if your fonts are correctly aligned vertically. (#1619) +- Fonts: Updated stb_truetype from 1.14 to stb_truetype 1.19. (w/ include fix from some platforms #1622) +- Fonts: Added optional FreeType rasterizer in misc/freetype. Moved from imgui_club repo. (#618) [@Vuhdo, @mikesart, @ocornut] +- Fonts: Moved extra_fonts/ to misc/fonts/. +- ImFontAtlas: Fixed cfg.MergeMode not reusing existing glyphs if available (always overwrote). - ImFontAtlas: Handle stb_truetype stbtt_InitFont() and stbtt_PackBegin() possible failures more gracefully, GetTexDataAsRGBA32() won't crash during conversion. (#1527) - ImFontAtlas: Moved mouse cursor data out of ImGuiContext, fix drawing them with multiple contexts. Also remove the last remaining undesirable dependency on ImGui in imgui_draw.cpp. (#939) - ImFontAtlas: Added ImFontAtlasFlags_NoPowerOfTwoHeight flag to disable padding font height to nearest power of two. (#1613) - ImFontAtlas: Added ImFontAtlasFlags_NoMouseCursors flag to disable baking software mouse cursors, mostly to save texture memory on very low end hardware. (#1613) - ImDrawList: Fixed AddRect() with antialiasing disabled (lower-right corner pixel was often missing, rounding looks a little better.) (#1646) -- Fonts: Updated stb_truetype from 1.14 to stb_truetype 1.19. (w/ include fix from some platforms #1622) -- Fonts: Added optional FreeType rasterizer in misc/freetype. Moved from imgui_club repo. (#618) [@Vuhdo, @mikesart, @ocornut] -- Fonts: Moved extra_fonts/ to misc/fonts/. - Misc: Functions passed to libc qsort are explicitely marked cdecl to support compiling with vectorcall as the default calling convention. (#1230, #1611) [@RandyGaul] - Misc: ImVec2: added [] operator. This is becoming desirable for some types of code, better added sooner than later. - Misc: Exposed IM_OFFSETOF() helper in imgui.h. @@ -270,7 +275,6 @@ Other Changes: - ImGuiStorage: Added BuildSortByKey() helper to rebuild storage from stratch. - ImFont: Added GetDebugName() helper. - ImFontAtlas: Added missing Thai punctuation in the GetGlyphRangesThai() ranges. (#1396) [@nProtect] -- ImFontAtlas: Fixed cfg.MergeMode not reusing existing glyphs if available (always overwrote). - ImDrawList: Removed 'bool anti_aliased = true' final parameter of ImDrawList::AddPolyline() and ImDrawList::AddConvexPolyFilled(). Anti-aliasing is controlled via the regular style.AntiAliased flags. - ImDrawList: Added ImDrawList::AddImageRounded() helper. (#845) [@thedmd] - ImDrawList: Refactored to make ImDrawList independant of ImGui. Removed static variable in PathArcToFast() which caused linking issues to some. diff --git a/imgui.cpp b/imgui.cpp index ee35145b4150..6890fac3814a 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -251,7 +251,7 @@ Here is a change-log of API breaking changes, if you are using one of the functions listed, expect to have to fix some code. Also read releases logs https://github.com/ocornut/imgui/releases for more details. - - 2018/XX/XX (1.XX) - ImFont::DisplayOffset.y field defaults to 0 instead of +1. + - 2018/03/08 (1.60) - Changed ImFont::DisplayOffset.y to default to 0 instead of +1. Fixed rounding of Ascent/Descent to match TrueType renderer. If you were adding or subtracting to ImFont::DisplayOffset check if your fonts are correctly aligned vertically. - 2018/03/03 (1.60) - Renamed ImGuiStyleVar_Count_ to ImGuiStyleVar_COUNT and ImGuiMouseCursor_Count_ to ImGuiMouseCursor_COUNT for consistency with other public enums. - 2018/02/18 (1.60) - BeginDragDropSource(): temporarily removed the optional mouse_button=0 parameter because it is not really usable in many situations at the moment. - 2018/02/16 (1.60) - obsoleted the io.RenderDrawListsFn callback, you can call your graphics engine render function after ImGui::Render(). Use ImGui::GetDrawData() to retrieve the ImDrawData* to display. From 1f6ad7a894d11c2956c1cd0ade978efb15cba1c8 Mon Sep 17 00:00:00 2001 From: omar Date: Sat, 10 Mar 2018 10:33:12 +0100 Subject: [PATCH 758/823] ImFont: Added FindGlyphNoFallback. Fixed MergeMode broken by 1ef1acbd8d7d46ac6fe083b331dadf9324dc7e07 --- imgui.h | 1 + imgui_demo.cpp | 7 ++----- imgui_draw.cpp | 28 ++++++++++++++++++---------- misc/freetype/imgui_freetype.cpp | 2 +- 4 files changed, 22 insertions(+), 16 deletions(-) diff --git a/imgui.h b/imgui.h index 708e62969cdb..9b4cf2c9c184 100644 --- a/imgui.h +++ b/imgui.h @@ -1784,6 +1784,7 @@ struct ImFont IMGUI_API void ClearOutputData(); IMGUI_API void BuildLookupTable(); IMGUI_API const ImFontGlyph*FindGlyph(ImWchar c) const; + IMGUI_API const ImFontGlyph*FindGlyphNoFallback(ImWchar c) const; IMGUI_API void SetFallbackChar(ImWchar c); float GetCharAdvance(ImWchar c) const { return ((int)c < IndexAdvanceX.Size) ? IndexAdvanceX[(int)c] : FallbackAdvanceX; } bool IsLoaded() const { return ContainerAtlas != NULL; } diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 713a929d89f7..2a94de4e0d19 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -2222,13 +2222,11 @@ void ImGui::ShowStyleEditor(ImGuiStyle* ref) if (ImGui::TreeNode("Glyphs", "Glyphs (%d)", font->Glyphs.Size)) { // Display all glyphs of the fonts in separate pages of 256 characters - const ImFontGlyph* glyph_fallback = font->FallbackGlyph; // Forcefully/dodgily make FindGlyph() return NULL on fallback, which isn't the default behavior. - font->FallbackGlyph = NULL; for (int base = 0; base < 0x10000; base += 256) { int count = 0; for (int n = 0; n < 256; n++) - count += font->FindGlyph((ImWchar)(base + n)) ? 1 : 0; + count += font->FindGlyphNoFallback((ImWchar)(base + n)) ? 1 : 0; if (count > 0 && ImGui::TreeNode((void*)(intptr_t)base, "U+%04X..U+%04X (%d %s)", base, base+255, count, count > 1 ? "glyphs" : "glyph")) { float cell_spacing = style.ItemSpacing.y; @@ -2239,7 +2237,7 @@ void ImGui::ShowStyleEditor(ImGuiStyle* ref) { ImVec2 cell_p1(base_pos.x + (n % 16) * (cell_size.x + cell_spacing), base_pos.y + (n / 16) * (cell_size.y + cell_spacing)); ImVec2 cell_p2(cell_p1.x + cell_size.x, cell_p1.y + cell_size.y); - const ImFontGlyph* glyph = font->FindGlyph((ImWchar)(base+n)); + const ImFontGlyph* glyph = font->FindGlyphNoFallback((ImWchar)(base+n)); draw_list->AddRect(cell_p1, cell_p2, glyph ? IM_COL32(255,255,255,100) : IM_COL32(255,255,255,50)); font->RenderChar(draw_list, cell_size.x, cell_p1, ImGui::GetColorU32(ImGuiCol_Text), (ImWchar)(base+n)); // We use ImFont::RenderChar as a shortcut because we don't have UTF-8 conversion functions available to generate a string. if (glyph && ImGui::IsMouseHoveringRect(cell_p1, cell_p2)) @@ -2257,7 +2255,6 @@ void ImGui::ShowStyleEditor(ImGuiStyle* ref) ImGui::TreePop(); } } - font->FallbackGlyph = glyph_fallback; ImGui::TreePop(); } ImGui::TreePop(); diff --git a/imgui_draw.cpp b/imgui_draw.cpp index 027283dd4681..dd44578166b0 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -1841,7 +1841,7 @@ bool ImFontAtlasBuildWithStbTruetype(ImFontAtlas* atlas) continue; const int codepoint = range.first_unicode_codepoint_in_range + char_idx; - if (cfg.MergeMode && dst_font->FindGlyph((unsigned short)codepoint)) + if (cfg.MergeMode && dst_font->FindGlyphNoFallback((unsigned short)codepoint)) continue; stbtt_aligned_quad q; @@ -2205,8 +2205,7 @@ void ImFont::BuildLookupTable() IndexLookup[(int)tab_glyph.Codepoint] = (unsigned short)(Glyphs.Size-1); } - FallbackGlyph = NULL; - FallbackGlyph = FindGlyph(FallbackChar); + FallbackGlyph = FindGlyphNoFallback(FallbackChar); FallbackAdvanceX = FallbackGlyph ? FallbackGlyph->AdvanceX : 0.0f; for (int i = 0; i < max_codepoint + 1; i++) if (IndexAdvanceX[i] < 0.0f) @@ -2268,13 +2267,22 @@ void ImFont::AddRemapChar(ImWchar dst, ImWchar src, bool overwrite_dst) const ImFontGlyph* ImFont::FindGlyph(ImWchar c) const { - if (c < IndexLookup.Size) - { - const unsigned short i = IndexLookup[c]; - if (i != (unsigned short)-1) - return &Glyphs.Data[i]; - } - return FallbackGlyph; + if (c >= IndexLookup.Size) + return FallbackGlyph; + const unsigned short i = IndexLookup[c]; + if (i == (unsigned short)-1) + return FallbackGlyph; + return &Glyphs.Data[i]; +} + +const ImFontGlyph* ImFont::FindGlyphNoFallback(ImWchar c) const +{ + if (c >= IndexLookup.Size) + return NULL; + const unsigned short i = IndexLookup[c]; + if (i == (unsigned short)-1) + return NULL; + return &Glyphs.Data[i]; } const char* ImFont::CalcWordWrapPositionA(float scale, const char* text, const char* text_end, float wrap_width) const diff --git a/misc/freetype/imgui_freetype.cpp b/misc/freetype/imgui_freetype.cpp index 54957112a0cf..37526d78ce75 100644 --- a/misc/freetype/imgui_freetype.cpp +++ b/misc/freetype/imgui_freetype.cpp @@ -333,7 +333,7 @@ bool ImGuiFreeType::BuildFontAtlas(ImFontAtlas* atlas, unsigned int extra_flags) { for (uint32_t codepoint = in_range[0]; codepoint <= in_range[1]; ++codepoint) { - if (cfg.MergeMode && dst_font->FindGlyph((unsigned short)codepoint)) + if (cfg.MergeMode && dst_font->FindGlyphNoFallback((unsigned short)codepoint)) continue; FT_Glyph ft_glyph = NULL; From b9ac127b0b272147f2e63b61ecb479bae8acab0b Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 12 Mar 2018 11:03:27 +0100 Subject: [PATCH 759/823] Internals: Columns renaming fields --- imgui.cpp | 19 ++++++++++--------- imgui_internal.h | 8 ++++---- 2 files changed, 14 insertions(+), 13 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 6890fac3814a..0913819ce43c 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1807,13 +1807,14 @@ float ImGuiMenuColumns::CalcExtraSpace(float avail_w) static void SetCursorPosYAndSetupDummyPrevLine(float pos_y, float line_height) { // Set cursor position and a few other things so that SetScrollHere() and Columns() can work when seeking cursor. - // FIXME: It is problematic that we have to do that here, because custom/equivalent end-user code would stumble on the same issue. Consider moving within SetCursorXXX functions? + // FIXME: It is problematic that we have to do that here, because custom/equivalent end-user code would stumble on the same issue. + // The clipper should probably have a 4th step to display the last item in a regular manner. ImGui::SetCursorPosY(pos_y); ImGuiWindow* window = ImGui::GetCurrentWindow(); window->DC.CursorPosPrevLine.y = window->DC.CursorPos.y - line_height; // Setting those fields so that SetScrollHere() can properly function after the end of our clipper usage. window->DC.PrevLineHeight = (line_height - GImGui->Style.ItemSpacing.y); // If we end up needing more accurate data (to e.g. use SameLine) we may as well make the clipper have a fourth step to let user process and display the last item in their list. if (window->DC.ColumnsSet) - window->DC.ColumnsSet->CellMinY = window->DC.CursorPos.y; // Setting this so that cell Y position are set properly + window->DC.ColumnsSet->LineMinY = window->DC.CursorPos.y; // Setting this so that cell Y position are set properly } // Use case A: Begin() called from constructor with items_height<0, then called again from Sync() in StepNo 1 @@ -12103,7 +12104,7 @@ void ImGui::Separator() if (window->DC.ColumnsSet) { PushColumnClipRect(); - window->DC.ColumnsSet->CellMinY = window->DC.CursorPos.y; + window->DC.ColumnsSet->LineMinY = window->DC.CursorPos.y; } } @@ -12322,7 +12323,7 @@ void ImGui::NextColumn() PopClipRect(); ImGuiColumnsSet* columns = window->DC.ColumnsSet; - columns->CellMaxY = ImMax(columns->CellMaxY, window->DC.CursorPos.y); + columns->LineMaxY = ImMax(columns->LineMaxY, window->DC.CursorPos.y); if (++columns->Current < columns->Count) { // Columns 1+ cancel out IndentX @@ -12334,10 +12335,10 @@ void ImGui::NextColumn() window->DC.ColumnsOffsetX = 0.0f; window->DrawList->ChannelsSetCurrent(0); columns->Current = 0; - columns->CellMinY = columns->CellMaxY; + columns->LineMinY = columns->LineMaxY; } window->DC.CursorPos.x = (float)(int)(window->Pos.x + window->DC.IndentX + window->DC.ColumnsOffsetX); - window->DC.CursorPos.y = columns->CellMinY; + window->DC.CursorPos.y = columns->LineMinY; window->DC.CurrentLineHeight = 0.0f; window->DC.CurrentLineTextBaseOffset = 0.0f; @@ -12508,7 +12509,7 @@ void ImGui::BeginColumns(const char* str_id, int columns_count, ImGuiColumnsFlag columns->MaxX = ImMax(content_region_width - window->Scroll.x, columns->MinX + 1.0f); columns->StartPosY = window->DC.CursorPos.y; columns->StartMaxPosX = window->DC.CursorMaxPos.x; - columns->CellMinY = columns->CellMaxY = window->DC.CursorPos.y; + columns->LineMinY = columns->LineMaxY = window->DC.CursorPos.y; window->DC.ColumnsOffsetX = 0.0f; window->DC.CursorPos.x = (float)(int)(window->Pos.x + window->DC.IndentX + window->DC.ColumnsOffsetX); @@ -12555,8 +12556,8 @@ void ImGui::EndColumns() PopClipRect(); window->DrawList->ChannelsMerge(); - columns->CellMaxY = ImMax(columns->CellMaxY, window->DC.CursorPos.y); - window->DC.CursorPos.y = columns->CellMaxY; + columns->LineMaxY = ImMax(columns->LineMaxY, window->DC.CursorPos.y); + window->DC.CursorPos.y = columns->LineMaxY; if (!(columns->Flags & ImGuiColumnsFlags_GrowParentContentsSize)) window->DC.CursorMaxPos.x = ImMax(columns->StartMaxPosX, columns->MaxX); // Restore cursor max pos, as columns don't grow parent diff --git a/imgui_internal.h b/imgui_internal.h index 1ffa16006123..d924736751ce 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -462,9 +462,9 @@ struct ImGuiColumnsSet int Current; int Count; float MinX, MaxX; - float StartPosY; - float StartMaxPosX; // Backup of CursorMaxPos - float CellMinY, CellMaxY; + float LineMinY, LineMaxY; + float StartPosY; // Copy of CursorPos + float StartMaxPosX; // Copy of CursorMaxPos ImVector Columns; ImGuiColumnsSet() { Clear(); } @@ -477,9 +477,9 @@ struct ImGuiColumnsSet Current = 0; Count = 1; MinX = MaxX = 0.0f; + LineMinY = LineMaxY = 0.0f; StartPosY = 0.0f; StartMaxPosX = 0.0f; - CellMinY = CellMaxY = 0.0f; Columns.clear(); } }; From e7670c0bcc447392b56f6648fc3df50e9726b40c Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 12 Mar 2018 11:48:04 +0100 Subject: [PATCH 760/823] Style: CloseButton() now display a proper cross. Using Button colors for background. Removed ImGuiCol_CloseButton, ImGuiCol_CloseButtonActive, ImGuiCol_CloseButtonHovered as the closing cross uses regular button colors now. (#707) --- CHANGELOG.txt | 2 ++ imgui.cpp | 27 ++++++++++++--------------- imgui.h | 3 --- imgui_draw.cpp | 9 --------- 4 files changed, 14 insertions(+), 27 deletions(-) diff --git a/CHANGELOG.txt b/CHANGELOG.txt index 2d7039596f15..ac672e74e0b8 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -60,6 +60,7 @@ Breaking Changes: - Renamed ImGuiStyleVar_Count_ to ImGuiStyleVar_COUNT and ImGuiMouseCursor_Count_ to ImGuiMouseCursor_COUNT for consistency with other public enums. - Obsoleted IsAnyWindowHovered() in favor of IsWindowHovered(ImGuiHoveredFlags_AnyWindow). Kept redirection function (will obsolete). - Obsoleted IsAnyWindowFocused() in favor of IsWindowFocused(ImGuiFocusedFlags_AnyWindow). Kept redirection function (will obsolete). + - Removed ImGuiCol_CloseButton, ImGuiCol_CloseButtonActive, ImGuiCol_CloseButtonHovered style colors as the closing cross uses regular button colors now. - Renamed ImGuiSizeConstraintCallback to ImGuiSizeCallback, ImGuiSizeConstraintCallbackData to ImGuiSizeCallbackData. - Removed CalcItemRectClosestPoint() which was weird and not really used by anyone except demo code. If you need it it's easy to replicate on your side. @@ -101,6 +102,7 @@ Other Changes: - Style: Enable window border by default. (#707) - Style: Exposed ImGuiStyleVar_WindowTitleAlign, ImGuiStyleVar_ScrollbarSize, ImGuiStyleVar_ScrollbarRounding, ImGuiStyleVar_GrabRounding + added an assert to reduce accidental breakage. (#1181) - Style: Added style.MouseCursorScale help when using the software mouse cursor facility. (#939). +- Style: Close button nows display a cross before hovering. Uses button colors for highlight when hovering. (#707) - Popup: OpenPopup() Always reopen existing popup. (Removed imgui_internal.h's OpenPopupEx() which was used for this.) (#1497, #1533). - Popup: BeginPopupContextItem(), BeginPopupContextWindow(), BeginPopupContextVoid(), OpenPopupOnItemClick() all react on mouse release instead of mouse press. (~#439) - Popup: Better handling of user mistakenly calling OpenPopup() every frame (with reopen_existing option). The error will now be more visible and easier to understand. (#1497) diff --git a/imgui.cpp b/imgui.cpp index 0913819ce43c..a0bd747835bb 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -251,6 +251,7 @@ Here is a change-log of API breaking changes, if you are using one of the functions listed, expect to have to fix some code. Also read releases logs https://github.com/ocornut/imgui/releases for more details. + - 2018/03/12 (1.60) - Removed ImGuiCol_CloseButton, ImGuiCol_CloseButtonActive, ImGuiCol_CloseButtonHovered as the closing cross uses regular button colors now. - 2018/03/08 (1.60) - Changed ImFont::DisplayOffset.y to default to 0 instead of +1. Fixed rounding of Ascent/Descent to match TrueType renderer. If you were adding or subtracting to ImFont::DisplayOffset check if your fonts are correctly aligned vertically. - 2018/03/03 (1.60) - Renamed ImGuiStyleVar_Count_ to ImGuiStyleVar_COUNT and ImGuiMouseCursor_Count_ to ImGuiMouseCursor_COUNT for consistency with other public enums. - 2018/02/18 (1.60) - BeginDragDropSource(): temporarily removed the optional mouse_button=0 parameter because it is not really usable in many situations at the moment. @@ -6079,9 +6080,9 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) // Close button if (p_open != NULL) { - const float PAD = 2.0f; - const float rad = (window->TitleBarHeight() - PAD*2.0f) * 0.5f; - if (CloseButton(window->GetID("#CLOSE"), window->Rect().GetTR() + ImVec2(-PAD - rad, PAD + rad), rad)) + const float pad = style.FramePadding.y; + const float rad = g.FontSize * 0.5f; + if (CloseButton(window->GetID("#CLOSE"), window->Rect().GetTR() + ImVec2(-pad - rad, pad + rad), rad + 1)) *p_open = false; } @@ -6676,9 +6677,6 @@ const char* ImGui::GetStyleColorName(ImGuiCol idx) case ImGuiCol_ResizeGrip: return "ResizeGrip"; case ImGuiCol_ResizeGripHovered: return "ResizeGripHovered"; case ImGuiCol_ResizeGripActive: return "ResizeGripActive"; - case ImGuiCol_CloseButton: return "CloseButton"; - case ImGuiCol_CloseButtonHovered: return "CloseButtonHovered"; - case ImGuiCol_CloseButtonActive: return "CloseButtonActive"; case ImGuiCol_PlotLines: return "PlotLines"; case ImGuiCol_PlotLinesHovered: return "PlotLinesHovered"; case ImGuiCol_PlotHistogram: return "PlotHistogram"; @@ -7720,17 +7718,16 @@ bool ImGui::CloseButton(ImGuiID id, const ImVec2& pos, float radius) return pressed; // Render - const ImU32 col = GetColorU32((held && hovered) ? ImGuiCol_CloseButtonActive : hovered ? ImGuiCol_CloseButtonHovered : ImGuiCol_CloseButton); ImVec2 center = bb.GetCenter(); - window->DrawList->AddCircleFilled(center, ImMax(2.0f, radius), col, 12); - - const float cross_extent = (radius * 0.7071f) - 1.0f; if (hovered) - { - center -= ImVec2(0.5f, 0.5f); - window->DrawList->AddLine(center + ImVec2(+cross_extent,+cross_extent), center + ImVec2(-cross_extent,-cross_extent), GetColorU32(ImGuiCol_Text)); - window->DrawList->AddLine(center + ImVec2(+cross_extent,-cross_extent), center + ImVec2(-cross_extent,+cross_extent), GetColorU32(ImGuiCol_Text)); - } + window->DrawList->AddCircleFilled(center, ImMax(2.0f, radius), GetColorU32((held && hovered) ? ImGuiCol_ButtonActive : ImGuiCol_ButtonHovered), 9); + + float cross_extent = (radius * 0.7071f) - 1.0f; + ImU32 cross_col = GetColorU32(ImGuiCol_Text); + center -= ImVec2(0.5f, 0.5f); + window->DrawList->AddLine(center + ImVec2(+cross_extent,+cross_extent), center + ImVec2(-cross_extent,-cross_extent), cross_col, 1.0f); + window->DrawList->AddLine(center + ImVec2(+cross_extent,-cross_extent), center + ImVec2(-cross_extent,+cross_extent), cross_col, 1.0f); + return pressed; } diff --git a/imgui.h b/imgui.h index 9b4cf2c9c184..f84002337325 100644 --- a/imgui.h +++ b/imgui.h @@ -812,9 +812,6 @@ enum ImGuiCol_ ImGuiCol_ResizeGrip, ImGuiCol_ResizeGripHovered, ImGuiCol_ResizeGripActive, - ImGuiCol_CloseButton, - ImGuiCol_CloseButtonHovered, - ImGuiCol_CloseButtonActive, ImGuiCol_PlotLines, ImGuiCol_PlotLinesHovered, ImGuiCol_PlotHistogram, diff --git a/imgui_draw.cpp b/imgui_draw.cpp index dd44578166b0..b86ee86958f1 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -165,9 +165,6 @@ void ImGui::StyleColorsDark(ImGuiStyle* dst) colors[ImGuiCol_ResizeGrip] = ImVec4(0.26f, 0.59f, 0.98f, 0.25f); colors[ImGuiCol_ResizeGripHovered] = ImVec4(0.26f, 0.59f, 0.98f, 0.67f); colors[ImGuiCol_ResizeGripActive] = ImVec4(0.26f, 0.59f, 0.98f, 0.95f); - colors[ImGuiCol_CloseButton] = ImVec4(0.41f, 0.41f, 0.41f, 0.50f); - colors[ImGuiCol_CloseButtonHovered] = ImVec4(0.98f, 0.39f, 0.36f, 1.00f); - colors[ImGuiCol_CloseButtonActive] = ImVec4(0.98f, 0.39f, 0.36f, 1.00f); colors[ImGuiCol_PlotLines] = ImVec4(0.61f, 0.61f, 0.61f, 1.00f); colors[ImGuiCol_PlotLinesHovered] = ImVec4(1.00f, 0.43f, 0.35f, 1.00f); colors[ImGuiCol_PlotHistogram] = ImVec4(0.90f, 0.70f, 0.00f, 1.00f); @@ -217,9 +214,6 @@ void ImGui::StyleColorsClassic(ImGuiStyle* dst) colors[ImGuiCol_ResizeGrip] = ImVec4(1.00f, 1.00f, 1.00f, 0.16f); colors[ImGuiCol_ResizeGripHovered] = ImVec4(0.78f, 0.82f, 1.00f, 0.60f); colors[ImGuiCol_ResizeGripActive] = ImVec4(0.78f, 0.82f, 1.00f, 0.90f); - colors[ImGuiCol_CloseButton] = ImVec4(0.50f, 0.50f, 0.90f, 0.50f); - colors[ImGuiCol_CloseButtonHovered] = ImVec4(0.70f, 0.70f, 0.90f, 0.60f); - colors[ImGuiCol_CloseButtonActive] = ImVec4(0.70f, 0.70f, 0.70f, 1.00f); colors[ImGuiCol_PlotLines] = ImVec4(1.00f, 1.00f, 1.00f, 1.00f); colors[ImGuiCol_PlotLinesHovered] = ImVec4(0.90f, 0.70f, 0.00f, 1.00f); colors[ImGuiCol_PlotHistogram] = ImVec4(0.90f, 0.70f, 0.00f, 1.00f); @@ -272,9 +266,6 @@ void ImGui::StyleColorsLight(ImGuiStyle* dst) colors[ImGuiCol_ResizeGrip] = ImVec4(0.80f, 0.80f, 0.80f, 0.56f); colors[ImGuiCol_ResizeGripHovered] = ImVec4(0.26f, 0.59f, 0.98f, 0.67f); colors[ImGuiCol_ResizeGripActive] = ImVec4(0.26f, 0.59f, 0.98f, 0.95f); - colors[ImGuiCol_CloseButton] = ImVec4(0.59f, 0.59f, 0.59f, 0.50f); - colors[ImGuiCol_CloseButtonHovered] = ImVec4(0.98f, 0.39f, 0.36f, 1.00f); - colors[ImGuiCol_CloseButtonActive] = ImVec4(0.98f, 0.39f, 0.36f, 1.00f); colors[ImGuiCol_PlotLines] = ImVec4(0.39f, 0.39f, 0.39f, 1.00f); colors[ImGuiCol_PlotLinesHovered] = ImVec4(1.00f, 0.43f, 0.35f, 1.00f); colors[ImGuiCol_PlotHistogram] = ImVec4(0.90f, 0.70f, 0.00f, 1.00f); From 887712a6f14140808b877f7e60b5d1a901959e86 Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 12 Mar 2018 14:20:39 +0100 Subject: [PATCH 761/823] Updated templates, added pull request template. --- .github/CONTRIBUTING.md | 4 ++++ .github/issue_template.md | 9 +++++++-- .github/pull_request_template.md | 5 +++++ 3 files changed, 16 insertions(+), 2 deletions(-) create mode 100644 .github/pull_request_template.md diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index 984ea521dc4b..b4079e0a92d4 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -22,3 +22,7 @@ You may use the Issue tracker to submit bug reports, feature requests or suggest If you have been using dear imgui for a while and/or have been using C/C++ for several years and/or have demonstrated good behavior here, it is ok to not fullfill every item to the letter. Those are guidelines and experienced users of dear imgui will know what information are useful in a given context. +## How to create an Pull Request + +- If you are adding a feature, please explain the context of the change: what do you need the feature for? +- Make sure you create a branch for the pull request. In Git, 1 PR is associated to 1 branch. If you keep pushing to the same branch after you submitted the PR, your new commits will appear in the PR. diff --git a/.github/issue_template.md b/.github/issue_template.md index e47ef9e892dd..958aa1653aa0 100644 --- a/.github/issue_template.md +++ b/.github/issue_template.md @@ -1,7 +1,12 @@ -(Please carefully read guidelines in [CONTRIBUTING.md](https://github.com/ocornut/imgui/blob/master/.github/CONTRIBUTING.md) then delete this line) +You may use the Issue tracker to ask for help, submit bug reports, feature requests or suggestions. +Please carefully read this document before doing so: +[CONTRIBUTING.md](https://github.com/ocornut/imgui/blob/master/.github/CONTRIBUTING.md). -You can include code this way: +You can include code snippets using `Begin()` for short in-line snippets, or: ```cpp ImGui::Begin("Hello"); ImGui::ThisIsMoreCode(); ``` +For multiline snippets. + +(Clear this form before submitting your issue) diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md new file mode 100644 index 000000000000..66308e480e67 --- /dev/null +++ b/.github/pull_request_template.md @@ -0,0 +1,5 @@ +- If you are adding a feature, please explain the context of the change: what do you need the feature for? +- Make sure you create a branch for the pull request. In Git, 1 PR is associated to 1 branch. If you keep pushing to the same branch after you submitted the PR, your new commits will appear in the PR. +- You can read [CONTRIBUTING.md](https://github.com/ocornut/imgui/blob/master/.github/CONTRIBUTING.md) for more details. + +(Clear this form before submitting your PR) From b2453d7e8f790b2a74cb7fc6b0e46ce26c425c3a Mon Sep 17 00:00:00 2001 From: Peter Particle Date: Sat, 10 Mar 2018 20:49:06 +0100 Subject: [PATCH 762/823] Fixed resize window validation errors with removing frame prerender once and present last but one frame functionality. Frame rate is still similar. --- examples/vulkan_example/main.cpp | 27 +++++---------------------- 1 file changed, 5 insertions(+), 22 deletions(-) diff --git a/examples/vulkan_example/main.cpp b/examples/vulkan_example/main.cpp index ca6479269f7e..1631c8df7ddd 100644 --- a/examples/vulkan_example/main.cpp +++ b/examples/vulkan_example/main.cpp @@ -12,9 +12,9 @@ #define IMGUI_MAX_POSSIBLE_BACK_BUFFERS 16 #define IMGUI_UNLIMITED_FRAME_RATE -//#ifdef _DEBUG -//#define IMGUI_VULKAN_DEBUG_REPORT -//#endif +#ifdef _DEBUG +#define IMGUI_VULKAN_DEBUG_REPORT +#endif static VkAllocationCallbacks* g_Allocator = NULL; static VkInstance g_Instance = VK_NULL_HANDLE; @@ -568,19 +568,12 @@ static void frame_end() static void frame_present() { VkResult err; - // If IMGUI_UNLIMITED_FRAME_RATE is defined we present the latest but one frame. Otherwise we present the latest rendered frame -#ifdef IMGUI_UNLIMITED_FRAME_RATE - uint32_t PresentIndex = (g_FrameIndex + IMGUI_VK_QUEUED_FRAMES - 1) % IMGUI_VK_QUEUED_FRAMES; -#else - uint32_t PresentIndex = g_FrameIndex; -#endif // IMGUI_UNLIMITED_FRAME_RATE - VkSwapchainKHR swapchains[1] = {g_Swapchain}; - uint32_t indices[1] = {g_BackbufferIndices[PresentIndex]}; + uint32_t indices[1] = {g_BackbufferIndices[g_FrameIndex]}; VkPresentInfoKHR info = {}; info.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR; info.waitSemaphoreCount = 1; - info.pWaitSemaphores = &g_RenderCompleteSemaphore[PresentIndex]; + info.pWaitSemaphores = &g_RenderCompleteSemaphore[g_FrameIndex]; info.swapchainCount = 1; info.pSwapchains = swapchains; info.pImageIndices = indices; @@ -678,16 +671,6 @@ int main(int, char**) bool show_another_window = false; ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f); - // When IMGUI_UNLIMITED_FRAME_RATE is defined we render into latest image acquired from the swapchain but we display the image which was rendered before. - // Hence we must render once and increase the g_FrameIndex without presenting, which we do before entering the render loop. - // This is also the reason why frame_end() is split into frame_end() and frame_present(), the later one not being called here. -#ifdef IMGUI_UNLIMITED_FRAME_RATE - ImGui_ImplGlfwVulkan_NewFrame(); - frame_begin(); - ImGui_ImplGlfwVulkan_Render(g_CommandBuffer[g_FrameIndex]); - frame_end(); - g_FrameIndex = (g_FrameIndex + 1) % IMGUI_VK_QUEUED_FRAMES; -#endif // IMGUI_UNLIMITED_FRAME_RATE // Main loop while (!glfwWindowShouldClose(window)) From 1c18d653134e1eb7e3e039d8b055334dba25f2cf Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 12 Mar 2018 14:43:37 +0100 Subject: [PATCH 763/823] Examples: Renamed glfw error callback for clarity. --- examples/opengl2_example/main.cpp | 4 ++-- examples/opengl3_example/main.cpp | 4 ++-- examples/vulkan_example/main.cpp | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/examples/opengl2_example/main.cpp b/examples/opengl2_example/main.cpp index 370606888e3c..6728347ccfae 100644 --- a/examples/opengl2_example/main.cpp +++ b/examples/opengl2_example/main.cpp @@ -11,7 +11,7 @@ #include #include -static void error_callback(int error, const char* description) +static void glfw_error_callback(int error, const char* description) { fprintf(stderr, "Error %d: %s\n", error, description); } @@ -19,7 +19,7 @@ static void error_callback(int error, const char* description) int main(int, char**) { // Setup window - glfwSetErrorCallback(error_callback); + glfwSetErrorCallback(glfw_error_callback); if (!glfwInit()) return 1; GLFWwindow* window = glfwCreateWindow(1280, 720, "ImGui OpenGL2 example", NULL, NULL); diff --git a/examples/opengl3_example/main.cpp b/examples/opengl3_example/main.cpp index 143dcc596967..ce2f1156dd76 100644 --- a/examples/opengl3_example/main.cpp +++ b/examples/opengl3_example/main.cpp @@ -9,7 +9,7 @@ #include // This example is using gl3w to access OpenGL functions (because it is small). You may use glew/glad/glLoadGen/etc. whatever already works for you. #include -static void error_callback(int error, const char* description) +static void glfw_error_callback(int error, const char* description) { fprintf(stderr, "Error %d: %s\n", error, description); } @@ -17,7 +17,7 @@ static void error_callback(int error, const char* description) int main(int, char**) { // Setup window - glfwSetErrorCallback(error_callback); + glfwSetErrorCallback(glfw_error_callback); if (!glfwInit()) return 1; glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); diff --git a/examples/vulkan_example/main.cpp b/examples/vulkan_example/main.cpp index 1631c8df7ddd..79ceb8b2d00c 100644 --- a/examples/vulkan_example/main.cpp +++ b/examples/vulkan_example/main.cpp @@ -583,7 +583,7 @@ static void frame_present() g_FrameIndex = (g_FrameIndex + 1) % IMGUI_VK_QUEUED_FRAMES; } -static void error_callback(int error, const char* description) +static void glfw_error_callback(int error, const char* description) { fprintf(stderr, "Error %d: %s\n", error, description); } @@ -591,7 +591,7 @@ static void error_callback(int error, const char* description) int main(int, char**) { // Setup window - glfwSetErrorCallback(error_callback); + glfwSetErrorCallback(glfw_error_callback); if (!glfwInit()) return 1; From 37cb177745daa9b19c102a86958d514beae8eacb Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 12 Mar 2018 14:46:24 +0100 Subject: [PATCH 764/823] Examples: Vulkan: Only resize swap chain and framebuffer once. (#1042) --- examples/vulkan_example/main.cpp | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/examples/vulkan_example/main.cpp b/examples/vulkan_example/main.cpp index 79ceb8b2d00c..a197515f1472 100644 --- a/examples/vulkan_example/main.cpp +++ b/examples/vulkan_example/main.cpp @@ -34,7 +34,9 @@ static VkPresentModeKHR g_PresentMode; static VkPipelineCache g_PipelineCache = VK_NULL_HANDLE; static VkDescriptorPool g_DescriptorPool = VK_NULL_HANDLE; -static int fb_width, fb_height; +static int fb_width = 0, fb_height = 0; +static bool g_ResizeWanted = false; +static int g_ResizeWidth = 0, g_ResizeHeight = 0; static uint32_t g_BackbufferIndices[IMGUI_VK_QUEUED_FRAMES]; // keep track of recently rendered swapchain frame indices static uint32_t g_BackBufferCount = 0; static VkImage g_BackBuffer[IMGUI_MAX_POSSIBLE_BACK_BUFFERS] = {}; @@ -58,7 +60,7 @@ static void check_vk_result(VkResult err) abort(); } -static void resize_vulkan(GLFWwindow* /*window*/, int w, int h) +static void resize_vulkan(int w, int h) { VkResult err; VkSwapchainKHR old_swapchain = g_Swapchain; @@ -355,7 +357,7 @@ static void setup_vulkan(GLFWwindow* window) // Get Present Mode { - // Requst a certain mode and confirm that it is available. If not use VK_PRESENT_MODE_FIFO_KHR which is mandatory + // Request a certain mode and confirm that it is available. If not use VK_PRESENT_MODE_FIFO_KHR which is mandatory #ifdef IMGUI_UNLIMITED_FRAME_RATE g_PresentMode = VK_PRESENT_MODE_IMMEDIATE_KHR; #else @@ -406,8 +408,7 @@ static void setup_vulkan(GLFWwindow* window) { int w, h; glfwGetFramebufferSize(window, &w, &h); - resize_vulkan(window, w, h); - glfwSetFramebufferSizeCallback(window, resize_vulkan); + resize_vulkan(w, h); } // Create Command Buffers @@ -588,6 +589,13 @@ static void glfw_error_callback(int error, const char* description) fprintf(stderr, "Error %d: %s\n", error, description); } +static void glfw_resize_callback(GLFWwindow*, int w, int h) +{ + g_ResizeWanted = true; + g_ResizeWidth = w; + g_ResizeHeight = h; +} + int main(int, char**) { // Setup window @@ -605,6 +613,7 @@ int main(int, char**) return 1; } setup_vulkan(window); + glfwSetFramebufferSizeCallback(window, glfw_resize_callback); // Setup ImGui binding ImGui::CreateContext(); @@ -680,6 +689,11 @@ int main(int, char**) // - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application. // Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags. glfwPollEvents(); + + if (g_ResizeWanted) + resize_vulkan(g_ResizeWidth, g_ResizeHeight); + g_ResizeWanted = false; + ImGui_ImplGlfwVulkan_NewFrame(); // 1. Show a simple window. From 111ea7af77bf82ccfb2d014593d8760013a44974 Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 12 Mar 2018 17:24:15 +0100 Subject: [PATCH 765/823] Misc comments, todos + reintroduced removed ImGuiCol defines under !IMGUI_DISABLE_OBSOLETE_FUNCTIONS wrap. --- TODO.txt | 1 + imgui.h | 9 ++++++--- imgui_demo.cpp | 10 +++++----- misc/freetype/README.md | 3 ++- misc/freetype/imgui_freetype.cpp | 3 ++- 5 files changed, 16 insertions(+), 10 deletions(-) diff --git a/TODO.txt b/TODO.txt index 5c58f63f84b8..6da01e735640 100644 --- a/TODO.txt +++ b/TODO.txt @@ -30,6 +30,7 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i !- scrolling: allow immediately effective change of scroll after Begin() if we haven't appended items yet. - scrolling/clipping: separator on the initial position of a window is not visible (cursorpos.y <= clippos.y). (2017-08-20: can't repro) + - drawdata: make it easy to clone (or swap?) a ImDrawData so user can easily save that data if they use threaded renderering. - drawlist: end-user probably can't call Clear() directly because we expect a texture to be pushed in the stack. - drawlist: maintaining bounding box per command would allow to merge draw command when clipping isn't relied on (typical non-scrolling window or non-overflowing column would merge with previous command). - drawlist: primtiives/helpers to manipulate vertices post submission, so e.g. a quad/rect can be resized to fit later submitted content, _without_ using the ChannelSplit api diff --git a/imgui.h b/imgui.h index f84002337325..715f5415d612 100644 --- a/imgui.h +++ b/imgui.h @@ -821,12 +821,15 @@ enum ImGuiCol_ ImGuiCol_DragDropTarget, ImGuiCol_NavHighlight, // gamepad/keyboard: current highlighted item ImGuiCol_NavWindowingHighlight, // gamepad/keyboard: when holding NavMenu to focus/move/resize windows - ImGuiCol_COUNT // Obsolete names (will be removed) #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS - //, ImGuiCol_ComboBg = ImGuiCol_PopupBg // ComboBg has been merged with PopupBg, so a redirect isn't accurate. - , ImGuiCol_ChildWindowBg = ImGuiCol_ChildBg, ImGuiCol_Column = ImGuiCol_Separator, ImGuiCol_ColumnHovered = ImGuiCol_SeparatorHovered, ImGuiCol_ColumnActive = ImGuiCol_SeparatorActive + ImGuiCol_CloseButton, ImGuiCol_CloseButtonActive, ImGuiCol_CloseButtonHovered, // [unused since 1.60+] the close button now uses regular button colors. + ImGuiCol_ComboBg, // [unused since 1.53+] ComboBg has been merged with PopupBg, so a redirect isn't accurate. + ImGuiCol_COUNT, + ImGuiCol_ChildWindowBg = ImGuiCol_ChildBg, ImGuiCol_Column = ImGuiCol_Separator, ImGuiCol_ColumnHovered = ImGuiCol_SeparatorHovered, ImGuiCol_ColumnActive = ImGuiCol_SeparatorActive +#else + ImGuiCol_COUNT #endif }; diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 2a94de4e0d19..b36205b14ac0 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -2229,17 +2229,17 @@ void ImGui::ShowStyleEditor(ImGuiStyle* ref) count += font->FindGlyphNoFallback((ImWchar)(base + n)) ? 1 : 0; if (count > 0 && ImGui::TreeNode((void*)(intptr_t)base, "U+%04X..U+%04X (%d %s)", base, base+255, count, count > 1 ? "glyphs" : "glyph")) { + float cell_size = font->FontSize * 1; float cell_spacing = style.ItemSpacing.y; - ImVec2 cell_size(font->FontSize * 1, font->FontSize * 1); ImVec2 base_pos = ImGui::GetCursorScreenPos(); ImDrawList* draw_list = ImGui::GetWindowDrawList(); for (int n = 0; n < 256; n++) { - ImVec2 cell_p1(base_pos.x + (n % 16) * (cell_size.x + cell_spacing), base_pos.y + (n / 16) * (cell_size.y + cell_spacing)); - ImVec2 cell_p2(cell_p1.x + cell_size.x, cell_p1.y + cell_size.y); + ImVec2 cell_p1(base_pos.x + (n % 16) * (cell_size + cell_spacing), base_pos.y + (n / 16) * (cell_size + cell_spacing)); + ImVec2 cell_p2(cell_p1.x + cell_size, cell_p1.y + cell_size); const ImFontGlyph* glyph = font->FindGlyphNoFallback((ImWchar)(base+n)); draw_list->AddRect(cell_p1, cell_p2, glyph ? IM_COL32(255,255,255,100) : IM_COL32(255,255,255,50)); - font->RenderChar(draw_list, cell_size.x, cell_p1, ImGui::GetColorU32(ImGuiCol_Text), (ImWchar)(base+n)); // We use ImFont::RenderChar as a shortcut because we don't have UTF-8 conversion functions available to generate a string. + font->RenderChar(draw_list, cell_size, cell_p1, ImGui::GetColorU32(ImGuiCol_Text), (ImWchar)(base+n)); // We use ImFont::RenderChar as a shortcut because we don't have UTF-8 conversion functions available to generate a string. if (glyph && ImGui::IsMouseHoveringRect(cell_p1, cell_p2)) { ImGui::BeginTooltip(); @@ -2251,7 +2251,7 @@ void ImGui::ShowStyleEditor(ImGuiStyle* ref) ImGui::EndTooltip(); } } - ImGui::Dummy(ImVec2((cell_size.x + cell_spacing) * 16, (cell_size.y + cell_spacing) * 16)); + ImGui::Dummy(ImVec2((cell_size + cell_spacing) * 16, (cell_size + cell_spacing) * 16)); ImGui::TreePop(); } } diff --git a/misc/freetype/README.md b/misc/freetype/README.md index ad0e4d3b3bd3..4038dbcdf7eb 100644 --- a/misc/freetype/README.md +++ b/misc/freetype/README.md @@ -121,8 +121,9 @@ struct FreeTypeTest ``` **Known issues** -- Output texture has excessive resolution (lots of vertical waste) +- Output texture has excessive resolution (lots of vertical waste). - FreeType's memory allocator is not overridden. +- `cfg.OversampleH`, `OversampleV` are ignored (but perhaps not so necessary with this rasterizer). **Obligatory comparison screenshots** diff --git a/misc/freetype/imgui_freetype.cpp b/misc/freetype/imgui_freetype.cpp index 37526d78ce75..8235ac5f6c6f 100644 --- a/misc/freetype/imgui_freetype.cpp +++ b/misc/freetype/imgui_freetype.cpp @@ -17,8 +17,9 @@ // The default imgui styles will be impacted by this change (alpha values will need tweaking). // TODO: -// - Output texture has excessive resolution (lots of vertical waste) +// - Output texture has excessive resolution (lots of vertical waste). // - FreeType's memory allocator is not overridden. +// - cfg.OversampleH, OversampleV are ignored (but perhaps not so necessary with this rasterizer). #include "imgui_freetype.h" #include "imgui_internal.h" // ImMin,ImMax,ImFontAtlasBuild*, From f93a22ae6e7860c4aa928a1e4bbb0d916a9aa69b Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 13 Mar 2018 11:47:57 +0100 Subject: [PATCH 766/823] Contributing: tweaks, mention screenshots more prominently. --- .github/CONTRIBUTING.md | 1 + .github/issue_template.md | 2 +- .github/pull_request_template.md | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index b4079e0a92d4..05bf73fd444d 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -25,4 +25,5 @@ If you have been using dear imgui for a while and/or have been using C/C++ for s ## How to create an Pull Request - If you are adding a feature, please explain the context of the change: what do you need the feature for? +- Try to attach screenshots to clarify the context and demonstrate the feature at a glance. - Make sure you create a branch for the pull request. In Git, 1 PR is associated to 1 branch. If you keep pushing to the same branch after you submitted the PR, your new commits will appear in the PR. diff --git a/.github/issue_template.md b/.github/issue_template.md index 958aa1653aa0..ae4eb7b5d9b9 100644 --- a/.github/issue_template.md +++ b/.github/issue_template.md @@ -9,4 +9,4 @@ ImGui::ThisIsMoreCode(); ``` For multiline snippets. -(Clear this form before submitting your issue) +(Clear this form before submitting your issue. Please read the CONTRIBUTING.md file!) diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index 66308e480e67..1a6418d5a6f8 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -1,4 +1,5 @@ - If you are adding a feature, please explain the context of the change: what do you need the feature for? +- Try to attach screenshots to clarify the context and demonstrate the feature at a glance. - Make sure you create a branch for the pull request. In Git, 1 PR is associated to 1 branch. If you keep pushing to the same branch after you submitted the PR, your new commits will appear in the PR. - You can read [CONTRIBUTING.md](https://github.com/ocornut/imgui/blob/master/.github/CONTRIBUTING.md) for more details. From 26296bb4c1c4d474fe6aa9b7deb0ec53b2a48e14 Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 13 Mar 2018 11:53:12 +0100 Subject: [PATCH 767/823] Misc: Fix 111ea7af77bf82ccfb2d014593d8760013a44974, GetStyleColorName() would assert, removed removed ImGuiCol defines (too much risk/complexity trying to silently ignore it). --- imgui.h | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/imgui.h b/imgui.h index 715f5415d612..99645440d874 100644 --- a/imgui.h +++ b/imgui.h @@ -821,15 +821,13 @@ enum ImGuiCol_ ImGuiCol_DragDropTarget, ImGuiCol_NavHighlight, // gamepad/keyboard: current highlighted item ImGuiCol_NavWindowingHighlight, // gamepad/keyboard: when holding NavMenu to focus/move/resize windows + ImGuiCol_COUNT // Obsolete names (will be removed) #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS - ImGuiCol_CloseButton, ImGuiCol_CloseButtonActive, ImGuiCol_CloseButtonHovered, // [unused since 1.60+] the close button now uses regular button colors. - ImGuiCol_ComboBg, // [unused since 1.53+] ComboBg has been merged with PopupBg, so a redirect isn't accurate. - ImGuiCol_COUNT, - ImGuiCol_ChildWindowBg = ImGuiCol_ChildBg, ImGuiCol_Column = ImGuiCol_Separator, ImGuiCol_ColumnHovered = ImGuiCol_SeparatorHovered, ImGuiCol_ColumnActive = ImGuiCol_SeparatorActive -#else - ImGuiCol_COUNT + , ImGuiCol_ChildWindowBg = ImGuiCol_ChildBg, ImGuiCol_Column = ImGuiCol_Separator, ImGuiCol_ColumnHovered = ImGuiCol_SeparatorHovered, ImGuiCol_ColumnActive = ImGuiCol_SeparatorActive + //ImGuiCol_CloseButton, ImGuiCol_CloseButtonActive, ImGuiCol_CloseButtonHovered, // [unused since 1.60+] the close button now uses regular button colors. + //ImGuiCol_ComboBg, // [unused since 1.53+] ComboBg has been merged with PopupBg, so a redirect isn't accurate. #endif }; From 7b833dabc89f54bfed6262093b3aad8fda63c6bf Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 13 Mar 2018 15:04:47 +0100 Subject: [PATCH 768/823] ImVector: Spacing, assert tweaks --- imgui.h | 91 ++++++++++++++++++++++++++------------------------------- 1 file changed, 42 insertions(+), 49 deletions(-) diff --git a/imgui.h b/imgui.h index 99645440d874..fc3e917f1abf 100644 --- a/imgui.h +++ b/imgui.h @@ -111,16 +111,12 @@ typedef unsigned __int64 ImU64; // 64-bit unsigned integer typedef unsigned long long ImU64; // 64-bit unsigned integer #endif -// Others helpers at bottom of the file: -// class ImVector<> // Lightweight std::vector like class. -// 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 ImVec2 { float x, y; ImVec2() { x = y = 0.0f; } ImVec2(float _x, float _y) { x = _x; y = _y; } - float operator[] (size_t idx) const { IM_ASSERT(idx == 0 || idx == 1); return (&x)[idx]; } // We very rarely use this [] operator, thus an assert is fine. + float operator[] (size_t idx) const { IM_ASSERT(idx <= 1); return (&x)[idx]; } // We very rarely use this [] operator, thus an assert is fine. #ifdef IM_VEC2_CLASS_EXTRA // Define constructor and implicit cast operators in imconfig.h to convert back<>forth from your math types and ImVec2. IM_VEC2_CLASS_EXTRA #endif @@ -675,22 +671,22 @@ enum ImGuiHoveredFlags_ enum ImGuiDragDropFlags_ { // BeginDragDropSource() flags - ImGuiDragDropFlags_SourceNoPreviewTooltip = 1 << 0, // By default, a successful call to BeginDragDropSource opens a tooltip so you can display a preview or description of the source contents. This flag disable this behavior. - ImGuiDragDropFlags_SourceNoDisableHover = 1 << 1, // By default, when dragging we clear data so that IsItemHovered() will return true, to avoid subsequent user code submitting tooltips. This flag disable this behavior so you can still call IsItemHovered() on the source item. - ImGuiDragDropFlags_SourceNoHoldToOpenOthers = 1 << 2, // Disable the behavior that allows to open tree nodes and collapsing header by holding over them while dragging a source item. - ImGuiDragDropFlags_SourceAllowNullID = 1 << 3, // Allow items such as Text(), Image() that have no unique identifier to be used as drag source, by manufacturing a temporary identifier based on their window-relative position. This is extremely unusual within the dear imgui ecosystem and so we made it explicit. - ImGuiDragDropFlags_SourceExtern = 1 << 4, // External source (from outside of imgui), won't attempt to read current item/window info. Will always return true. Only one Extern source can be active simultaneously. + ImGuiDragDropFlags_SourceNoPreviewTooltip = 1 << 0, // By default, a successful call to BeginDragDropSource opens a tooltip so you can display a preview or description of the source contents. This flag disable this behavior. + ImGuiDragDropFlags_SourceNoDisableHover = 1 << 1, // By default, when dragging we clear data so that IsItemHovered() will return true, to avoid subsequent user code submitting tooltips. This flag disable this behavior so you can still call IsItemHovered() on the source item. + ImGuiDragDropFlags_SourceNoHoldToOpenOthers = 1 << 2, // Disable the behavior that allows to open tree nodes and collapsing header by holding over them while dragging a source item. + ImGuiDragDropFlags_SourceAllowNullID = 1 << 3, // Allow items such as Text(), Image() that have no unique identifier to be used as drag source, by manufacturing a temporary identifier based on their window-relative position. This is extremely unusual within the dear imgui ecosystem and so we made it explicit. + ImGuiDragDropFlags_SourceExtern = 1 << 4, // External source (from outside of imgui), won't attempt to read current item/window info. Will always return true. Only one Extern source can be active simultaneously. // AcceptDragDropPayload() flags - ImGuiDragDropFlags_AcceptBeforeDelivery = 1 << 10, // AcceptDragDropPayload() will returns true even before the mouse button is released. You can then call IsDelivery() to test if the payload needs to be delivered. - ImGuiDragDropFlags_AcceptNoDrawDefaultRect = 1 << 11, // Do not draw the default highlight rectangle when hovering over target. + ImGuiDragDropFlags_AcceptBeforeDelivery = 1 << 10, // AcceptDragDropPayload() will returns true even before the mouse button is released. You can then call IsDelivery() to test if the payload needs to be delivered. + ImGuiDragDropFlags_AcceptNoDrawDefaultRect = 1 << 11, // Do not draw the default highlight rectangle when hovering over target. ImGuiDragDropFlags_AcceptPeekOnly = ImGuiDragDropFlags_AcceptBeforeDelivery | ImGuiDragDropFlags_AcceptNoDrawDefaultRect // For peeking ahead and inspecting the payload before delivery. }; // Standard Drag and Drop payload types. You can define you own payload types using 12-characters long strings. Types starting with '_' are defined by Dear ImGui. -#define IMGUI_PAYLOAD_TYPE_COLOR_3F "_COL3F" // float[3] // Standard type for colors, without alpha. User code may use this type. -#define IMGUI_PAYLOAD_TYPE_COLOR_4F "_COL4F" // float[4] // Standard type for colors. User code may use this type. +#define IMGUI_PAYLOAD_TYPE_COLOR_3F "_COL3F" // float[3]: Standard type for colors, without alpha. User code may use this type. +#define IMGUI_PAYLOAD_TYPE_COLOR_4F "_COL4F" // float[4]: Standard type for colors. User code may use this type. -// A direction +// A cardinal direction enum ImGuiDir_ { ImGuiDir_None = -1, @@ -877,6 +873,7 @@ enum ImGuiColorEditFlags_ ImGuiColorEditFlags_NoTooltip = 1 << 6, // // ColorEdit, ColorPicker, ColorButton: disable tooltip when hovering the preview. ImGuiColorEditFlags_NoLabel = 1 << 7, // // ColorEdit, ColorPicker: disable display of inline text label (the label is still forwarded to the tooltip and picker). ImGuiColorEditFlags_NoSidePreview = 1 << 8, // // ColorPicker: disable bigger color preview on right side of the picker, use small colored square preview instead. + // User Options (right-click on widget to change some of them). You can set application defaults using SetColorEditOptions(). The idea is that you probably don't want to override them in most of your calls, let the user choose and/or call SetColorEditOptions() during startup. ImGuiColorEditFlags_AlphaBar = 1 << 9, // // ColorEdit, ColorPicker: show vertical alpha bar/gradient in picker. ImGuiColorEditFlags_AlphaPreview = 1 << 10, // // ColorEdit, ColorPicker, ColorButton: display preview as a transparent color over a checkerboard, instead of opaque. @@ -889,7 +886,8 @@ enum ImGuiColorEditFlags_ ImGuiColorEditFlags_Float = 1 << 17, // [DataType] // ColorEdit, ColorPicker, ColorButton: _display_ values formatted as 0.0f..1.0f floats instead of 0..255 integers. No round-trip of value via integers. ImGuiColorEditFlags_PickerHueBar = 1 << 18, // [PickerMode] // ColorPicker: bar for Hue, rectangle for Sat/Value. ImGuiColorEditFlags_PickerHueWheel = 1 << 19, // [PickerMode] // ColorPicker: wheel for Hue, triangle for Sat/Value. - // Internals/Masks + + // [Internal] Masks ImGuiColorEditFlags__InputsMask = ImGuiColorEditFlags_RGB|ImGuiColorEditFlags_HSV|ImGuiColorEditFlags_HEX, ImGuiColorEditFlags__DataTypeMask = ImGuiColorEditFlags_Uint8|ImGuiColorEditFlags_Float, ImGuiColorEditFlags__PickerMask = ImGuiColorEditFlags_PickerHueWheel|ImGuiColorEditFlags_PickerHueBar, @@ -1121,7 +1119,7 @@ namespace ImGui // 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). +// 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). // Our implementation does NOT call C++ constructors/destructors. This is intentional and we do not require it. Do not use this class as a straight std::vector replacement in your code! template class ImVector @@ -1141,7 +1139,6 @@ class ImVector inline bool empty() const { return Size == 0; } inline int size() const { return Size; } inline int capacity() const { return Capacity; } - inline value_type& operator[](int i) { IM_ASSERT(i < Size); return Data[i]; } inline const value_type& operator[](int i) const { IM_ASSERT(i < Size); return Data[i]; } @@ -1156,11 +1153,10 @@ class ImVector inline const value_type& back() const { IM_ASSERT(Size > 0); return Data[Size - 1]; } inline void swap(ImVector& rhs) { int rhs_size = rhs.Size; rhs.Size = Size; Size = rhs_size; int rhs_cap = rhs.Capacity; rhs.Capacity = Capacity; Capacity = rhs_cap; value_type* rhs_data = rhs.Data; rhs.Data = Data; Data = rhs_data; } - inline int _grow_capacity(int sz) const { int new_capacity = Capacity ? (Capacity + Capacity/2) : 8; return new_capacity > sz ? new_capacity : sz; } - - inline void resize(int new_size) { if (new_size > Capacity) reserve(_grow_capacity(new_size)); Size = new_size; } - inline void resize(int new_size, const T& v){ if (new_size > Capacity) reserve(_grow_capacity(new_size)); if (new_size > Size) for (int n = Size; n < new_size; n++) Data[n] = v; Size = new_size; } - inline void reserve(int new_capacity) + inline int _grow_capacity(int sz) const { int new_capacity = Capacity ? (Capacity + Capacity/2) : 8; return new_capacity > sz ? new_capacity : sz; } + inline void resize(int new_size) { if (new_size > Capacity) reserve(_grow_capacity(new_size)); Size = new_size; } + inline void resize(int new_size, const T& v) { if (new_size > Capacity) reserve(_grow_capacity(new_size)); if (new_size > Size) for (int n = Size; n < new_size; n++) Data[n] = v; Size = new_size; } + inline void reserve(int new_capacity) { if (new_capacity <= Capacity) return; @@ -1173,20 +1169,16 @@ class ImVector } // NB: &v cannot be pointing inside the ImVector Data itself! e.g. v.push_back(v[10]) is forbidden. - 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 void push_front(const value_type& v) { if (Size == 0) push_back(v); else insert(Data, v); } - - inline iterator erase(const_iterator it) { IM_ASSERT(it >= Data && it < Data+Size); const ptrdiff_t off = it - Data; memmove(Data + off, Data + off + 1, ((size_t)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 >= Data && it <= Data+Size); const ptrdiff_t off = it - Data; if (Size == Capacity) reserve(_grow_capacity(Size + 1)); if (off < (int)Size) memmove(Data + off + 1, Data + off, ((size_t)Size - (size_t)off) * sizeof(value_type)); Data[off] = v; Size++; return Data + off; } - inline bool contains(const value_type& v) const { const T* data = Data; const T* data_end = Data + Size; while (data < data_end) if (*data++ == v) return true; return false; } + 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 void push_front(const value_type& v) { if (Size == 0) push_back(v); else insert(Data, v); } + inline iterator erase(const_iterator it) { IM_ASSERT(it >= Data && it < Data+Size); const ptrdiff_t off = it - Data; memmove(Data + off, Data + off + 1, ((size_t)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 >= Data && it <= Data+Size); const ptrdiff_t off = it - Data; if (Size == Capacity) reserve(_grow_capacity(Size + 1)); if (off < (int)Size) memmove(Data + off + 1, Data + off, ((size_t)Size - (size_t)off) * sizeof(value_type)); Data[off] = v; Size++; return Data + off; } + inline bool contains(const value_type& v) const { const T* data = Data; const T* data_end = Data + Size; while (data < data_end) if (*data++ == v) return true; return false; } }; // Helper: execute a block of code at maximum once a frame. Convenient if you want to quickly create an UI within deep-nested code that runs multiple times every frame. -// Usage: -// static ImGuiOnceUponAFrame oaf; -// if (oaf) -// ImGui::Text("This will be called only once per frame"); +// Usage: static ImGuiOnceUponAFrame oaf; if (oaf) ImGui::Text("This will be called only once per frame"); struct ImGuiOnceUponAFrame { ImGuiOnceUponAFrame() { RefFrame = -1; } @@ -1611,22 +1603,23 @@ struct ImDrawData struct ImFontConfig { - void* FontData; // // TTF/OTF data - int FontDataSize; // // TTF/OTF data size - bool FontDataOwnedByAtlas; // true // TTF/OTF data ownership taken by the container ImFontAtlas (will delete memory itself). - int FontNo; // 0 // Index of font within TTF/OTF file - float SizePixels; // // Size in pixels for rasterizer. - int OversampleH, OversampleV; // 3, 1 // Rasterize at higher quality for sub-pixel positioning. We don't use sub-pixel positions on the Y axis. - bool PixelSnapH; // false // Align every glyph to pixel boundary. Useful e.g. if you are merging a non-pixel aligned font with the default font. If enabled, you can set OversampleH/V to 1. - ImVec2 GlyphExtraSpacing; // 0, 0 // Extra spacing (in pixels) between glyphs. Only X axis is supported for now. - ImVec2 GlyphOffset; // 0, 0 // Offset all glyphs from this font input. - const ImWchar* GlyphRanges; // NULL // Pointer to a user-provided list of Unicode range (2 value per range, values are inclusive, zero-terminated list). THE ARRAY DATA NEEDS TO PERSIST AS LONG AS THE FONT IS ALIVE. - bool MergeMode; // false // Merge into previous ImFont, so you can combine multiple inputs font into one ImFont (e.g. ASCII font + icons + Japanese glyphs). You may want to use GlyphOffset.y when merge font of different heights. - unsigned int RasterizerFlags; // 0x00 // Settings for custom font rasterizer (e.g. ImGuiFreeType). Leave as zero if you aren't using one. - float RasterizerMultiply; // 1.0f // Brighten (>1.0f) or darken (<1.0f) font output. Brightening small fonts may be a good workaround to make them more readable. + void* FontData; // // TTF/OTF data + int FontDataSize; // // TTF/OTF data size + bool FontDataOwnedByAtlas; // true // TTF/OTF data ownership taken by the container ImFontAtlas (will delete memory itself). + int FontNo; // 0 // Index of font within TTF/OTF file + float SizePixels; // // Size in pixels for rasterizer. + int OversampleH; // 3 // Rasterize at higher quality for sub-pixel positioning. We don't use sub-pixel positions on the Y axis. + int OversampleV; // 1 // Rasterize at higher quality for sub-pixel positioning. We don't use sub-pixel positions on the Y axis. + bool PixelSnapH; // false // Align every glyph to pixel boundary. Useful e.g. if you are merging a non-pixel aligned font with the default font. If enabled, you can set OversampleH/V to 1. + ImVec2 GlyphExtraSpacing; // 0, 0 // Extra spacing (in pixels) between glyphs. Only X axis is supported for now. + ImVec2 GlyphOffset; // 0, 0 // Offset all glyphs from this font input. + const ImWchar* GlyphRanges; // NULL // Pointer to a user-provided list of Unicode range (2 value per range, values are inclusive, zero-terminated list). THE ARRAY DATA NEEDS TO PERSIST AS LONG AS THE FONT IS ALIVE. + bool MergeMode; // false // Merge into previous ImFont, so you can combine multiple inputs font into one ImFont (e.g. ASCII font + icons + Japanese glyphs). You may want to use GlyphOffset.y when merge font of different heights. + unsigned int RasterizerFlags; // 0x00 // Settings for custom font rasterizer (e.g. ImGuiFreeType). Leave as zero if you aren't using one. + float RasterizerMultiply; // 1.0f // Brighten (>1.0f) or darken (<1.0f) font output. Brightening small fonts may be a good workaround to make them more readable. // [Internal] - char Name[40]; // Name (strictly to ease debugging) + char Name[40]; // Name (strictly to ease debugging) ImFont* DstFont; IMGUI_API ImFontConfig(); @@ -1726,7 +1719,7 @@ struct ImFontAtlas IMGUI_API int AddCustomRectFontGlyph(ImFont* font, ImWchar id, int width, int height, float advance_x, const ImVec2& offset = ImVec2(0,0)); // Id needs to be < 0x10000 to register a rectangle to map into a specific font. const CustomRect* GetCustomRectByIndex(int index) const { if (index < 0) return NULL; return &CustomRects[index]; } - // Internals + // [Internal] IMGUI_API void CalcCustomRectUV(const CustomRect* rect, ImVec2* out_uv_min, ImVec2* out_uv_max); IMGUI_API bool GetMouseCursorTexData(ImGuiMouseCursor cursor, ImVec2* out_offset, ImVec2* out_size, ImVec2 out_uv_border[2], ImVec2 out_uv_fill[2]); From 0e3a6ef4f78f6009b7781610256d7146eb6fa9dc Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 13 Mar 2018 16:14:50 +0100 Subject: [PATCH 769/823] Moved IM_NEW, IM_DELETE helpers to imgui.h for convenient use by back-ends and user code. --- imgui.h | 10 ++++++++++ imgui_internal.h | 9 --------- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/imgui.h b/imgui.h index fc3e917f1abf..d6a6aaa540ff 100644 --- a/imgui.h +++ b/imgui.h @@ -1177,6 +1177,16 @@ class ImVector inline bool contains(const value_type& v) const { const T* data = Data; const T* data_end = Data + Size; while (data < data_end) if (*data++ == v) return true; return false; } }; +// Helper: IM_NEW(), IM_PLACEMENT_NEW(), IM_DELETE() macros to call MemAlloc + Placement New, Placement Delete + MemFree +// We call C++ constructor on own allocated memory via the placement "new(ptr) Type()" syntax. +// Defining a custom placement new() with a dummy parameter allows us to bypass including which on some platforms complains when user has disabled exceptions. +struct ImNewDummy {}; +inline void* operator new(size_t, ImNewDummy, void* ptr) { return ptr; } +inline void operator delete(void*, ImNewDummy, void*) {} // This is only required so we can use the symetrical new() +#define IM_PLACEMENT_NEW(_PTR) new(ImNewDummy(), _PTR) +#define IM_NEW(_TYPE) new(ImNewDummy(), ImGui::MemAlloc(sizeof(_TYPE))) _TYPE +template void IM_DELETE(T*& p) { if (p) { p->~T(); ImGui::MemFree(p); p = NULL; } } + // Helper: execute a block of code at maximum once a frame. Convenient if you want to quickly create an UI within deep-nested code that runs multiple times every frame. // Usage: static ImGuiOnceUponAFrame oaf; if (oaf) ImGui::Text("This will be called only once per frame"); struct ImGuiOnceUponAFrame diff --git a/imgui_internal.h b/imgui_internal.h index d924736751ce..b6e2355740e5 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -165,15 +165,6 @@ static inline ImVec2 ImRotate(const ImVec2& v, float cos_a, float sin_a) static inline float ImLinearSweep(float current, float target, float speed) { if (current < target) return ImMin(current + speed, target); if (current > target) return ImMax(current - speed, target); return current; } static inline ImVec2 ImMul(const ImVec2& lhs, const ImVec2& rhs) { return ImVec2(lhs.x * rhs.x, lhs.y * rhs.y); } -// We call C++ constructor on own allocated memory via the placement "new(ptr) Type()" syntax. -// Defining a custom placement new() with a dummy parameter allows us to bypass including which on some platforms complains when user has disabled exceptions. -struct ImNewPlacementDummy {}; -inline void* operator new(size_t, ImNewPlacementDummy, void* ptr) { return ptr; } -inline void operator delete(void*, ImNewPlacementDummy, void*) {} // This is only required so we can use the symetrical new() -#define IM_PLACEMENT_NEW(_PTR) new(ImNewPlacementDummy(), _PTR) -#define IM_NEW(_TYPE) new(ImNewPlacementDummy(), ImGui::MemAlloc(sizeof(_TYPE))) _TYPE -template void IM_DELETE(T*& p) { if (p) { p->~T(); ImGui::MemFree(p); p = NULL; } } - //----------------------------------------------------------------------------- // Types //----------------------------------------------------------------------------- From 533c86a7a33d954494715b8c7b67156297914662 Mon Sep 17 00:00:00 2001 From: omar Date: Sat, 17 Mar 2018 17:29:58 +0100 Subject: [PATCH 770/823] Update TODO list, minor fix in Readme, comments, Clang -Weverything warning fix in imgui_draw.cpp under Windows. --- README.md | 2 +- TODO.txt | 7 ++++++- imgui.h | 1 + imgui_draw.cpp | 1 - 4 files changed, 8 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 5773278aa25d..080ae31dbec3 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ Monthly donations via Patreon: One-off donations via PayPal:
[![PayPal](https://www.paypalobjects.com/en_US/i/btn/btn_donate_LG.gif)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=5Q73FPZ9C526U) -Dear ImGui is a bloat-free graphical user interface library for C++. It outputs optimized vertex buffers that you can render anytime in your 3D-pipeline enabled application. It is fast, portable, renderer agnostic and self-contained (no external dependencies).** +Dear ImGui is a bloat-free graphical user interface library for C++. It outputs optimized vertex buffers that you can render anytime in your 3D-pipeline enabled application. It is fast, portable, renderer agnostic and self-contained (no external dependencies). Dear ImGui is designed to enable fast iterations and to empower programmers to create content creation tools and visualization / debug tools (as opposed to UI for the average end-user). It favors simplicity and productivity toward this goal, and lacks certain features normally found in more high-level libraries. diff --git a/TODO.txt b/TODO.txt index 6da01e735640..9276e67e8636 100644 --- a/TODO.txt +++ b/TODO.txt @@ -137,8 +137,10 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i - drag float: added leeway on edge (e.g. a few invisible steps past the clamp limits) - combo: use clipper: make it easier to disable clipper with a single flag. - - combo: option for BeginCombo to not return true when unchanged (#1182) + - combo: flag for BeginCombo to not return true when unchanged (#1182) + - combo: a way/helper to customize the combo preview (#1658) - combo/listbox: keyboard control. need InputText-like non-active focus + key handling. considering keyboard for custom listbox (pr #203) + - listbox: refactor and clean the begin/end api - listbox: multiple selection. - listbox: unselect option (#1208) - listbox: make it easier/more natural to implement range-select (need some sort of info/ref about the last clicked/focused item that user can translate to an index?) (wip stash) @@ -207,6 +209,7 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i - filters: fuzzy matches (may use code at blog.forrestthewoods.com/4cffeed33fdb) - drag and drop: add demo. (#143, #479) + - drag and drop: allow using with other mouse buttons (where activeid won't be set). (#1637) - drag and drop: test with reordering nodes (in a list, or a tree node). (#143) - drag and drop: test integrating with os drag and drop. - node/graph editor (#306) @@ -258,6 +261,8 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i - misc: make the ImGuiCond values linear (non-power-of-two). internal storage for ImGuiWindow can use integers to combine into flags (Why?) - misc: provide a way to compile out the entire implementation while providing a dummy API (e.g. #define IMGUI_DUMMY_IMPL) - misc: fix for compilation settings where stdcall isn't the default (e.g. vectorcall) (#1230) + - misc: PushItemFlag(): add a flag to disable keyboard capture when used with mouse? (#1682) + - remote: make a system like RemoteImGui first-class citizen/project (#75) - demo: add vertical separator demo diff --git a/imgui.h b/imgui.h index d6a6aaa540ff..04041acbcbc4 100644 --- a/imgui.h +++ b/imgui.h @@ -1596,6 +1596,7 @@ struct ImDrawList }; // All draw data to render an ImGui frame +// (NB: the style and the naming convention here is a little inconsistent but we preserve them for backward compatibility purpose) struct ImDrawData { bool Valid; // Only valid after Render() is called and before the next NewFrame() is called. diff --git a/imgui_draw.cpp b/imgui_draw.cpp index b86ee86958f1..ae268d60381a 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -34,7 +34,6 @@ #ifdef _MSC_VER #pragma warning (disable: 4505) // unreferenced local function has been removed (stb stuff) #pragma warning (disable: 4996) // 'This function or variable may be unsafe': strcpy, strdup, sprintf, vsnprintf, sscanf, fopen -#define snprintf _snprintf #endif #ifdef __clang__ From d68be086b27e6b7807e73b65c17042000f720bd0 Mon Sep 17 00:00:00 2001 From: omar Date: Sat, 17 Mar 2018 17:34:57 +0100 Subject: [PATCH 771/823] ImVector: Using value_type consistently. Spacing. --- imgui.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/imgui.h b/imgui.h index 04041acbcbc4..eeca3b75c01e 100644 --- a/imgui.h +++ b/imgui.h @@ -1120,7 +1120,7 @@ namespace ImGui //----------------------------------------------------------------------------- // 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). -// Our implementation does NOT call C++ constructors/destructors. This is intentional and we do not require it. Do not use this class as a straight std::vector replacement in your code! +// Important: Our implementation does NOT call C++ constructors/destructors. This is intentional, we do not require it but you have to be mindful of that. Do not use this class as a straight std::vector replacement in your code! template class ImVector { @@ -1151,18 +1151,18 @@ class ImVector 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) { int rhs_size = rhs.Size; rhs.Size = Size; Size = rhs_size; int rhs_cap = rhs.Capacity; rhs.Capacity = Capacity; Capacity = rhs_cap; value_type* rhs_data = rhs.Data; rhs.Data = Data; Data = rhs_data; } + inline void swap(ImVector& rhs) { int rhs_size = rhs.Size; rhs.Size = Size; Size = rhs_size; int rhs_cap = rhs.Capacity; rhs.Capacity = Capacity; Capacity = rhs_cap; value_type* rhs_data = rhs.Data; rhs.Data = Data; Data = rhs_data; } inline int _grow_capacity(int sz) const { int new_capacity = Capacity ? (Capacity + Capacity/2) : 8; return new_capacity > sz ? new_capacity : sz; } inline void resize(int new_size) { if (new_size > Capacity) reserve(_grow_capacity(new_size)); Size = new_size; } - inline void resize(int new_size, const T& v) { if (new_size > Capacity) reserve(_grow_capacity(new_size)); if (new_size > Size) for (int n = Size; n < new_size; n++) Data[n] = v; Size = new_size; } + inline void resize(int new_size,const value_type& v){ if (new_size > Capacity) reserve(_grow_capacity(new_size)); if (new_size > Size) for (int n = Size; n < new_size; n++) Data[n] = v; Size = new_size; } inline void reserve(int new_capacity) { if (new_capacity <= Capacity) return; - T* new_data = (value_type*)ImGui::MemAlloc((size_t)new_capacity * sizeof(T)); + value_type* new_data = (value_type*)ImGui::MemAlloc((size_t)new_capacity * sizeof(value_type)); if (Data) - memcpy(new_data, Data, (size_t)Size * sizeof(T)); + memcpy(new_data, Data, (size_t)Size * sizeof(value_type)); ImGui::MemFree(Data); Data = new_data; Capacity = new_capacity; From 4186c2c2b110a1f156171926b41f4564ea9580ab Mon Sep 17 00:00:00 2001 From: omar Date: Sat, 17 Mar 2018 20:42:56 +0100 Subject: [PATCH 772/823] ImVector: resize() / push_back() use memcpy() as we are not supposed to be constructor/destructor/operator aware at all. (If we do need to rework ImVector). In turn this will allow us to define assign/copy operators. --- imgui.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/imgui.h b/imgui.h index eeca3b75c01e..ff92752eddf3 100644 --- a/imgui.h +++ b/imgui.h @@ -1155,7 +1155,7 @@ class ImVector inline int _grow_capacity(int sz) const { int new_capacity = Capacity ? (Capacity + Capacity/2) : 8; return new_capacity > sz ? new_capacity : sz; } inline void resize(int new_size) { if (new_size > Capacity) reserve(_grow_capacity(new_size)); Size = new_size; } - inline void resize(int new_size,const value_type& v){ if (new_size > Capacity) reserve(_grow_capacity(new_size)); if (new_size > Size) for (int n = Size; n < new_size; n++) Data[n] = v; Size = new_size; } + inline void resize(int new_size,const value_type& v){ if (new_size > Capacity) reserve(_grow_capacity(new_size)); if (new_size > Size) for (int n = Size; n < new_size; n++) memcpy(&Data[n], &v, sizeof(v)); Size = new_size; } inline void reserve(int new_capacity) { if (new_capacity <= Capacity) @@ -1169,7 +1169,7 @@ class ImVector } // NB: &v cannot be pointing inside the ImVector Data itself! e.g. v.push_back(v[10]) is forbidden. - inline void push_back(const value_type& v) { if (Size == Capacity) reserve(_grow_capacity(Size + 1)); Data[Size++] = v; } + inline void push_back(const value_type& v) { if (Size == Capacity) reserve(_grow_capacity(Size + 1)); memcpy(&Data[Size], &v, sizeof(v)); Size++; } inline void pop_back() { IM_ASSERT(Size > 0); Size--; } inline void push_front(const value_type& v) { if (Size == 0) push_back(v); else insert(Data, v); } inline iterator erase(const_iterator it) { IM_ASSERT(it >= Data && it < Data+Size); const ptrdiff_t off = it - Data; memmove(Data + off, Data + off + 1, ((size_t)Size - (size_t)off - 1) * sizeof(value_type)); Size--; return Data + off; } From 1e296453efb65002d302b77ab1ead35ddc26406f Mon Sep 17 00:00:00 2001 From: omar Date: Sat, 17 Mar 2018 21:10:40 +0100 Subject: [PATCH 773/823] ImDrawList: Added Clone() helper function. --- CHANGELOG.txt | 1 + imgui.h | 18 ++++++++++-------- imgui_draw.cpp | 10 ++++++++++ 3 files changed, 21 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.txt b/CHANGELOG.txt index ac672e74e0b8..999a40666e2d 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -136,6 +136,7 @@ Other Changes: - ImFontAtlas: Added ImFontAtlasFlags_NoPowerOfTwoHeight flag to disable padding font height to nearest power of two. (#1613) - ImFontAtlas: Added ImFontAtlasFlags_NoMouseCursors flag to disable baking software mouse cursors, mostly to save texture memory on very low end hardware. (#1613) - ImDrawList: Fixed AddRect() with antialiasing disabled (lower-right corner pixel was often missing, rounding looks a little better.) (#1646) +- ImDrawList: Added CloneOutput() helper to facilitate the cloning of ImDrawData or ImDrawList for multi-threaded rendering. - Misc: Functions passed to libc qsort are explicitely marked cdecl to support compiling with vectorcall as the default calling convention. (#1230, #1611) [@RandyGaul] - Misc: ImVec2: added [] operator. This is becoming desirable for some types of code, better added sooner than later. - Misc: Exposed IM_OFFSETOF() helper in imgui.h. diff --git a/imgui.h b/imgui.h index ff92752eddf3..24bdb0312e6b 100644 --- a/imgui.h +++ b/imgui.h @@ -1579,6 +1579,7 @@ struct ImDrawList // Advanced IMGUI_API void AddCallback(ImDrawCallback callback, void* callback_data); // Your rendering function must check for 'UserCallback' in ImDrawCmd and call the function instead of rendering triangles. IMGUI_API void AddDrawCmd(); // This is useful if you need to forcefully create a new draw call (to allow for dependent rendering / blending). Otherwise primitives are merged into the same draw-call as much as possible + IMGUI_API ImDrawList* CloneOutput() const; // Create a clone of the CmdBuffer/IdxBuffer/VtxBuffer. // Internal helpers // NB: all primitives needs to be reserved via PrimReserve() beforehand! @@ -1600,16 +1601,17 @@ struct ImDrawList struct ImDrawData { bool Valid; // Only valid after Render() is called and before the next NewFrame() is called. - ImDrawList** CmdLists; - int CmdListsCount; - int TotalVtxCount; // For convenience, sum of all cmd_lists vtx_buffer.Size - int TotalIdxCount; // For convenience, sum of all cmd_lists idx_buffer.Size + ImDrawList** CmdLists; // Array of ImDrawList* to render. The ImDrawList are owned by ImGuiContext and only pointed to from here. + int CmdListsCount; // Number of ImDrawList* to render + int TotalIdxCount; // For convenience, sum of all ImDrawList's IdxBuffer.Size + int TotalVtxCount; // For convenience, sum of all ImDrawList's VtxBuffer.Size // Functions - ImDrawData() { Clear(); } - void Clear() { Valid = false; CmdLists = NULL; CmdListsCount = TotalVtxCount = TotalIdxCount = 0; } // Draw lists are owned by the ImGuiContext and only pointed to here. - IMGUI_API void DeIndexAllBuffers(); // For backward compatibility or convenience: convert all buffers from indexed to de-indexed, in case you cannot render indexed. Note: this is slow and most likely a waste of resources. Always prefer indexed rendering! - IMGUI_API void ScaleClipRects(const ImVec2& sc); // Helper to scale the ClipRect field of each ImDrawCmd. Use if your final output buffer is at a different scale than ImGui expects, or if there is a difference between your window resolution and framebuffer resolution. + ImDrawData() { Valid = false; Clear(); } + ~ImDrawData() { Clear(); } + void Clear() { Valid = false; CmdLists = NULL; CmdListsCount = TotalVtxCount = TotalIdxCount = 0; } // The ImDrawList are owned by ImGuiContext! + IMGUI_API void DeIndexAllBuffers(); // Helper to convert all buffers from indexed to non-indexed, in case you cannot render indexed. Note: this is slow and most likely a waste of resources. Always prefer indexed rendering! + IMGUI_API void ScaleClipRects(const ImVec2& sc); // Helper to scale the ClipRect field of each ImDrawCmd. Use if your final output buffer is at a different scale than ImGui expects, or if there is a difference between your window resolution and framebuffer resolution. }; struct ImFontConfig diff --git a/imgui_draw.cpp b/imgui_draw.cpp index ae268d60381a..a6bda8a501a7 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -338,6 +338,16 @@ void ImDrawList::ClearFreeMemory() _Channels.clear(); } +ImDrawList* ImDrawList::CloneOutput() const +{ + ImDrawList* dst = IM_NEW(ImDrawList(NULL)); + dst->CmdBuffer = CmdBuffer; + dst->IdxBuffer = IdxBuffer; + dst->VtxBuffer = VtxBuffer; + dst->Flags = Flags; + return dst; +} + // Using macros because C++ is a terrible language, we want guaranteed inline, no code in header, and no overhead in Debug builds #define GetCurrentClipRect() (_ClipRectStack.Size ? _ClipRectStack.Data[_ClipRectStack.Size-1] : _Data->ClipRectFullscreen) #define GetCurrentTextureId() (_TextureIdStack.Size ? _TextureIdStack.Data[_TextureIdStack.Size-1] : NULL) From 6bda816ffeff47b0bc38ff76a220e4b776724774 Mon Sep 17 00:00:00 2001 From: omar Date: Sat, 17 Mar 2018 21:00:56 +0100 Subject: [PATCH 774/823] ImVector: Added copy/assign operators as helpers to ease cloning of data. --- imgui.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/imgui.h b/imgui.h index 24bdb0312e6b..ec664a175db5 100644 --- a/imgui.h +++ b/imgui.h @@ -1120,7 +1120,7 @@ namespace ImGui //----------------------------------------------------------------------------- // 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). -// Important: Our implementation does NOT call C++ constructors/destructors. This is intentional, we do not require it but you have to be mindful of that. Do not use this class as a straight std::vector replacement in your code! +// *Important* Our implementation does NOT call C++ constructors/destructors. This is intentional, we do not require it but you have to be mindful of that. Do not use this class as a straight std::vector replacement in your code! template class ImVector { @@ -1135,6 +1135,8 @@ class ImVector inline ImVector() { Size = Capacity = 0; Data = NULL; } inline ~ImVector() { if (Data) ImGui::MemFree(Data); } + inline ImVector(const ImVector& src) { Size = Capacity = 0; Data = NULL; operator=(src); } + inline ImVector& operator=(const ImVector& src) { clear(); resize(src.Size); memcpy(Data, src.Data, (size_t)Size * sizeof(value_type)); return *this; } inline bool empty() const { return Size == 0; } inline int size() const { return Size; } From 6fe22e629742628eb84c1d1c98e7b951de1b9afd Mon Sep 17 00:00:00 2001 From: omar Date: Sun, 18 Mar 2018 12:23:33 +0100 Subject: [PATCH 775/823] imgui.h: Moved columns lower in the file. Various spacing changes and minor comments. --- imgui.h | 135 ++++++++++++++++++++++++++++---------------------------- 1 file changed, 67 insertions(+), 68 deletions(-) diff --git a/imgui.h b/imgui.h index ec664a175db5..88edbe93dad1 100644 --- a/imgui.h +++ b/imgui.h @@ -188,16 +188,16 @@ namespace ImGui IMGUI_API void SetWindowFontScale(float scale); // per-window font scale. Adjust IO.FontGlobalScale if you want to scale all windows IMGUI_API void SetNextWindowPos(const ImVec2& pos, ImGuiCond cond = 0, const ImVec2& pivot = ImVec2(0,0)); // set next window position. call before Begin(). use pivot=(0.5f,0.5f) to center on given point, etc. - IMGUI_API void SetNextWindowSize(const ImVec2& size, ImGuiCond cond = 0); // set next window size. set axis to 0.0f to force an auto-fit on this axis. call before Begin() + IMGUI_API void SetNextWindowSize(const ImVec2& size, ImGuiCond cond = 0); // set next window size. set axis to 0.0f to force an auto-fit on this axis. call before Begin() IMGUI_API void SetNextWindowSizeConstraints(const ImVec2& size_min, const ImVec2& size_max, ImGuiSizeCallback custom_callback = NULL, void* custom_callback_data = NULL); // set next window size limits. use -1,-1 on either X/Y axis to preserve the current size. Use callback to apply non-trivial programmatic constraints. - IMGUI_API void SetNextWindowContentSize(const ImVec2& size); // set next window content size (~ enforce the range of scrollbars). not including window decorations (title bar, menu bar, etc.). set an axis to 0.0f to leave it automatic. call before Begin() - IMGUI_API void SetNextWindowCollapsed(bool collapsed, ImGuiCond cond = 0); // set next window collapsed state. call before Begin() - IMGUI_API void SetNextWindowFocus(); // set next window to be focused / front-most. call before Begin() - IMGUI_API void SetNextWindowBgAlpha(float alpha); // set next window background color alpha. helper to easily modify ImGuiCol_WindowBg/ChildBg/PopupBg. - IMGUI_API void SetWindowPos(const ImVec2& pos, ImGuiCond cond = 0); // (not recommended) set current window position - call within Begin()/End(). prefer using SetNextWindowPos(), as this may incur tearing and side-effects. - IMGUI_API void SetWindowSize(const ImVec2& size, ImGuiCond cond = 0); // (not recommended) set current window size - call within Begin()/End(). set to ImVec2(0,0) to force an auto-fit. prefer using SetNextWindowSize(), as this may incur tearing and minor side-effects. - IMGUI_API void SetWindowCollapsed(bool collapsed, ImGuiCond cond = 0); // (not recommended) set current window collapsed state. prefer using SetNextWindowCollapsed(). - IMGUI_API void SetWindowFocus(); // (not recommended) set current window to be focused / front-most. prefer using SetNextWindowFocus(). + IMGUI_API void SetNextWindowContentSize(const ImVec2& size); // set next window content size (~ enforce the range of scrollbars). not including window decorations (title bar, menu bar, etc.). set an axis to 0.0f to leave it automatic. call before Begin() + IMGUI_API void SetNextWindowCollapsed(bool collapsed, ImGuiCond cond = 0); // set next window collapsed state. call before Begin() + IMGUI_API void SetNextWindowFocus(); // set next window to be focused / front-most. call before Begin() + IMGUI_API void SetNextWindowBgAlpha(float alpha); // set next window background color alpha. helper to easily modify ImGuiCol_WindowBg/ChildBg/PopupBg. + IMGUI_API void SetWindowPos(const ImVec2& pos, ImGuiCond cond = 0); // (not recommended) set current window position - call within Begin()/End(). prefer using SetNextWindowPos(), as this may incur tearing and side-effects. + IMGUI_API void SetWindowSize(const ImVec2& size, ImGuiCond cond = 0); // (not recommended) set current window size - call within Begin()/End(). set to ImVec2(0,0) to force an auto-fit. prefer using SetNextWindowSize(), as this may incur tearing and minor side-effects. + IMGUI_API void SetWindowCollapsed(bool collapsed, ImGuiCond cond = 0); // (not recommended) set current window collapsed state. prefer using SetNextWindowCollapsed(). + IMGUI_API void SetWindowFocus(); // (not recommended) set current window to be focused / front-most. prefer using SetNextWindowFocus(). IMGUI_API void SetWindowPos(const char* name, const ImVec2& pos, ImGuiCond cond = 0); // set named window position. IMGUI_API void SetWindowSize(const char* name, const ImVec2& size, ImGuiCond cond = 0); // set named window size. set axis to 0.0f to force an auto-fit on this axis. IMGUI_API void SetWindowCollapsed(const char* name, bool collapsed, ImGuiCond cond = 0); // set named window collapsed state @@ -223,60 +223,49 @@ namespace ImGui IMGUI_API void PushStyleVar(ImGuiStyleVar idx, float val); IMGUI_API void PushStyleVar(ImGuiStyleVar idx, const ImVec2& val); IMGUI_API void PopStyleVar(int count = 1); - IMGUI_API const ImVec4& GetStyleColorVec4(ImGuiCol idx); // retrieve style color as stored in ImGuiStyle structure. use to feed back into PushStyleColor(), otherwhise use GetColorU32() to get style color + style alpha. - IMGUI_API ImFont* GetFont(); // get current font - IMGUI_API float GetFontSize(); // get current font size (= height in pixels) of current font with current scale applied - IMGUI_API ImVec2 GetFontTexUvWhitePixel(); // get UV coordinate for a while pixel, useful to draw custom shapes via the ImDrawList API - IMGUI_API ImU32 GetColorU32(ImGuiCol idx, float alpha_mul = 1.0f); // retrieve given style color with style alpha applied and optional extra alpha multiplier - IMGUI_API ImU32 GetColorU32(const ImVec4& col); // retrieve given color with style alpha applied - IMGUI_API ImU32 GetColorU32(ImU32 col); // retrieve given color with style alpha applied + IMGUI_API const ImVec4& GetStyleColorVec4(ImGuiCol idx); // retrieve style color as stored in ImGuiStyle structure. use to feed back into PushStyleColor(), otherwhise use GetColorU32() to get style color with style alpha baked in. + IMGUI_API ImFont* GetFont(); // get current font + IMGUI_API float GetFontSize(); // get current font size (= height in pixels) of current font with current scale applied + IMGUI_API ImVec2 GetFontTexUvWhitePixel(); // get UV coordinate for a while pixel, useful to draw custom shapes via the ImDrawList API + IMGUI_API ImU32 GetColorU32(ImGuiCol idx, float alpha_mul = 1.0f); // retrieve given style color with style alpha applied and optional extra alpha multiplier + IMGUI_API ImU32 GetColorU32(const ImVec4& col); // retrieve given color with style alpha applied + IMGUI_API ImU32 GetColorU32(ImU32 col); // retrieve given color with style alpha applied // Parameters stacks (current window) - IMGUI_API void PushItemWidth(float item_width); // width of items for the common item+label case, pixels. 0.0f = default to ~2/3 of windows width, >0.0f: width in pixels, <0.0f align xx pixels to the right of window (so -1.0f always align width to the right side) + IMGUI_API void PushItemWidth(float item_width); // width of items for the common item+label case, pixels. 0.0f = default to ~2/3 of windows width, >0.0f: width in pixels, <0.0f align xx pixels to the right of window (so -1.0f always align width to the right side) IMGUI_API void PopItemWidth(); - IMGUI_API float CalcItemWidth(); // width of item given pushed settings and current cursor position - IMGUI_API void PushTextWrapPos(float wrap_pos_x = 0.0f); // word-wrapping for Text*() commands. < 0.0f: no wrapping; 0.0f: wrap to end of window (or column); > 0.0f: wrap at 'wrap_pos_x' position in window local space + IMGUI_API float CalcItemWidth(); // width of item given pushed settings and current cursor position + IMGUI_API void PushTextWrapPos(float wrap_pos_x = 0.0f); // word-wrapping for Text*() commands. < 0.0f: no wrapping; 0.0f: wrap to end of window (or column); > 0.0f: wrap at 'wrap_pos_x' position in window local space IMGUI_API void PopTextWrapPos(); - IMGUI_API void PushAllowKeyboardFocus(bool allow_keyboard_focus); // allow focusing using TAB/Shift-TAB, enabled by default but you can disable it for certain widgets + IMGUI_API void PushAllowKeyboardFocus(bool allow_keyboard_focus); // allow focusing using TAB/Shift-TAB, enabled by default but you can disable it for certain widgets IMGUI_API void PopAllowKeyboardFocus(); - IMGUI_API void PushButtonRepeat(bool repeat); // in 'repeat' mode, Button*() functions return repeated true in a typematic manner (using io.KeyRepeatDelay/io.KeyRepeatRate setting). Note that you can call IsItemActive() after any Button() to tell if the button is held in the current frame. + IMGUI_API void PushButtonRepeat(bool repeat); // in 'repeat' mode, Button*() functions return repeated true in a typematic manner (using io.KeyRepeatDelay/io.KeyRepeatRate setting). Note that you can call IsItemActive() after any Button() to tell if the button is held in the current frame. IMGUI_API void PopButtonRepeat(); // Cursor / Layout - IMGUI_API void Separator(); // separator, generally horizontal. inside a menu bar or in horizontal layout mode, this becomes a vertical separator. - IMGUI_API void SameLine(float pos_x = 0.0f, float spacing_w = -1.0f); // call between widgets or groups to layout them horizontally - IMGUI_API void NewLine(); // undo a SameLine() - IMGUI_API void Spacing(); // add vertical spacing - IMGUI_API void Dummy(const ImVec2& size); // add a dummy item of given size - IMGUI_API void Indent(float indent_w = 0.0f); // move content position toward the right, by style.IndentSpacing or indent_w if != 0 - IMGUI_API void Unindent(float indent_w = 0.0f); // move content position back to the left, by style.IndentSpacing or indent_w if != 0 - IMGUI_API void BeginGroup(); // lock horizontal starting position + capture group bounding box into one "item" (so you can use IsItemHovered() or layout primitives such as SameLine() on whole group, etc.) + IMGUI_API void Separator(); // separator, generally horizontal. inside a menu bar or in horizontal layout mode, this becomes a vertical separator. + IMGUI_API void SameLine(float pos_x = 0.0f, float spacing_w = -1.0f); // call between widgets or groups to layout them horizontally + IMGUI_API void NewLine(); // undo a SameLine() + IMGUI_API void Spacing(); // add vertical spacing + IMGUI_API void Dummy(const ImVec2& size); // add a dummy item of given size + IMGUI_API void Indent(float indent_w = 0.0f); // move content position toward the right, by style.IndentSpacing or indent_w if != 0 + IMGUI_API void Unindent(float indent_w = 0.0f); // move content position back to the left, by style.IndentSpacing or indent_w if != 0 + IMGUI_API void BeginGroup(); // lock horizontal starting position + capture group bounding box into one "item" (so you can use IsItemHovered() or layout primitives such as SameLine() on whole group, etc.) IMGUI_API void EndGroup(); - IMGUI_API ImVec2 GetCursorPos(); // cursor position is relative to window position - IMGUI_API float GetCursorPosX(); // " - IMGUI_API float GetCursorPosY(); // " - IMGUI_API void SetCursorPos(const ImVec2& local_pos); // " - IMGUI_API void SetCursorPosX(float x); // " - IMGUI_API void SetCursorPosY(float y); // " - IMGUI_API ImVec2 GetCursorStartPos(); // initial cursor position - IMGUI_API ImVec2 GetCursorScreenPos(); // cursor position in absolute screen coordinates [0..io.DisplaySize] (useful to work with ImDrawList API) - IMGUI_API void SetCursorScreenPos(const ImVec2& pos); // cursor position in absolute screen coordinates [0..io.DisplaySize] - IMGUI_API void AlignTextToFramePadding(); // vertically align/lower upcoming text to FramePadding.y so that it will aligns to upcoming widgets (call if you have text on a line before regular widgets) - IMGUI_API float GetTextLineHeight(); // ~ FontSize - IMGUI_API float GetTextLineHeightWithSpacing(); // ~ FontSize + style.ItemSpacing.y (distance in pixels between 2 consecutive lines of text) - IMGUI_API float GetFrameHeight(); // ~ FontSize + style.FramePadding.y * 2 - IMGUI_API float GetFrameHeightWithSpacing(); // ~ FontSize + style.FramePadding.y * 2 + style.ItemSpacing.y (distance in pixels between 2 consecutive lines of framed widgets) - - // Columns - // You can also use SameLine(pos_x) for simplified columns. The columns API is still work-in-progress and rather lacking. - IMGUI_API void Columns(int count = 1, const char* id = NULL, bool border = true); - IMGUI_API void NextColumn(); // next column, defaults to current row or next row if the current row is finished - IMGUI_API int GetColumnIndex(); // get current column index - IMGUI_API float GetColumnWidth(int column_index = -1); // get column width (in pixels). pass -1 to use current column - IMGUI_API void SetColumnWidth(int column_index, float width); // set column width (in pixels). pass -1 to use current column - IMGUI_API float GetColumnOffset(int column_index = -1); // get position of column line (in pixels, from the left side of the contents region). pass -1 to use current column, otherwise 0..GetColumnsCount() inclusive. column 0 is typically 0.0f - IMGUI_API void SetColumnOffset(int column_index, float offset_x); // set position of column line (in pixels, from the left side of the contents region). pass -1 to use current column - IMGUI_API int GetColumnsCount(); + IMGUI_API ImVec2 GetCursorPos(); // cursor position is relative to window position + IMGUI_API float GetCursorPosX(); // " + IMGUI_API float GetCursorPosY(); // " + IMGUI_API void SetCursorPos(const ImVec2& local_pos); // " + IMGUI_API void SetCursorPosX(float x); // " + IMGUI_API void SetCursorPosY(float y); // " + IMGUI_API ImVec2 GetCursorStartPos(); // initial cursor position + IMGUI_API ImVec2 GetCursorScreenPos(); // cursor position in absolute screen coordinates [0..io.DisplaySize] (useful to work with ImDrawList API) + IMGUI_API void SetCursorScreenPos(const ImVec2& screen_pos); // cursor position in absolute screen coordinates [0..io.DisplaySize] + IMGUI_API void AlignTextToFramePadding(); // vertically align upcoming text baseline to FramePadding.y so that it will align properly to regularly framed items (call if you have text on a line before a framed item) + IMGUI_API float GetTextLineHeight(); // ~ FontSize + IMGUI_API float GetTextLineHeightWithSpacing(); // ~ FontSize + style.ItemSpacing.y (distance in pixels between 2 consecutive lines of text) + IMGUI_API float GetFrameHeight(); // ~ FontSize + style.FramePadding.y * 2 + IMGUI_API float GetFrameHeightWithSpacing(); // ~ FontSize + style.FramePadding.y * 2 + style.ItemSpacing.y (distance in pixels between 2 consecutive lines of framed widgets) // ID scopes // If you are creating widgets in a loop you most likely want to push a unique identifier (e.g. object pointer, loop index) so ImGui can differentiate them. @@ -291,20 +280,19 @@ namespace ImGui IMGUI_API ImGuiID GetID(const void* ptr_id); // Widgets: Text - IMGUI_API void TextUnformatted(const char* text, const char* text_end = NULL); // raw text without formatting. Roughly equivalent to Text("%s", text) but: A) doesn't require null terminated string if 'text_end' is specified, B) it's faster, no memory copy is done, no buffer size limits, recommended for long chunks of text. - IMGUI_API void Text(const char* fmt, ...) IM_FMTARGS(1); // simple formatted text - IMGUI_API void TextV(const char* fmt, va_list args) IM_FMTLIST(1); - IMGUI_API void TextColored(const ImVec4& col, const char* fmt, ...) IM_FMTARGS(2); // shortcut for PushStyleColor(ImGuiCol_Text, col); Text(fmt, ...); PopStyleColor(); - IMGUI_API void TextColoredV(const ImVec4& col, const char* fmt, va_list args) IM_FMTLIST(2); - IMGUI_API void TextDisabled(const char* fmt, ...) IM_FMTARGS(1); // shortcut for PushStyleColor(ImGuiCol_Text, style.Colors[ImGuiCol_TextDisabled]); Text(fmt, ...); PopStyleColor(); - IMGUI_API void TextDisabledV(const char* fmt, va_list args) IM_FMTLIST(1); - IMGUI_API void TextWrapped(const char* fmt, ...) IM_FMTARGS(1); // shortcut for PushTextWrapPos(0.0f); Text(fmt, ...); PopTextWrapPos();. Note that this won't work on an auto-resizing window if there's no other widgets to extend the window width, yoy may need to set a size using SetNextWindowSize(). - IMGUI_API void TextWrappedV(const char* fmt, va_list args) IM_FMTLIST(1); - IMGUI_API void LabelText(const char* label, const char* fmt, ...) IM_FMTARGS(2); // display text+label aligned the same way as value+label widgets - IMGUI_API void LabelTextV(const char* label, const char* fmt, va_list args) IM_FMTLIST(2); - IMGUI_API void BulletText(const char* fmt, ...) IM_FMTARGS(1); // shortcut for Bullet()+Text() - IMGUI_API void BulletTextV(const char* fmt, va_list args) IM_FMTLIST(1); - IMGUI_API void Bullet(); // draw a small circle and keep the cursor on the same line. advance cursor x position by GetTreeNodeToLabelSpacing(), same distance that TreeNode() uses + IMGUI_API void TextUnformatted(const char* text, const char* text_end = NULL); // raw text without formatting. Roughly equivalent to Text("%s", text) but: A) doesn't require null terminated string if 'text_end' is specified, B) it's faster, no memory copy is done, no buffer size limits, recommended for long chunks of text. + IMGUI_API void Text(const char* fmt, ...) IM_FMTARGS(1); // simple formatted text + IMGUI_API void TextV(const char* fmt, va_list args) IM_FMTLIST(1); + IMGUI_API void TextColored(const ImVec4& col, const char* fmt, ...) IM_FMTARGS(2); // shortcut for PushStyleColor(ImGuiCol_Text, col); Text(fmt, ...); PopStyleColor(); + IMGUI_API void TextColoredV(const ImVec4& col, const char* fmt, va_list args) IM_FMTLIST(2); + IMGUI_API void TextDisabled(const char* fmt, ...) IM_FMTARGS(1); // shortcut for PushStyleColor(ImGuiCol_Text, style.Colors[ImGuiCol_TextDisabled]); Text(fmt, ...); PopStyleColor(); + IMGUI_API void TextDisabledV(const char* fmt, va_list args) IM_FMTLIST(1); + IMGUI_API void TextWrapped(const char* fmt, ...) IM_FMTARGS(1); // shortcut for PushTextWrapPos(0.0f); Text(fmt, ...); PopTextWrapPos();. Note that this won't work on an auto-resizing window if there's no other widgets to extend the window width, yoy may need to set a size using SetNextWindowSize(). + IMGUI_API void TextWrappedV(const char* fmt, va_list args) IM_FMTLIST(1); + IMGUI_API void LabelText(const char* label, const char* fmt, ...) IM_FMTARGS(2); // display text+label aligned the same way as value+label widgets + IMGUI_API void LabelTextV(const char* label, const char* fmt, va_list args) IM_FMTLIST(2); + IMGUI_API void BulletText(const char* fmt, ...) IM_FMTARGS(1); // shortcut for Bullet()+Text() + IMGUI_API void BulletTextV(const char* fmt, va_list args) IM_FMTLIST(1); // Widgets: Main IMGUI_API bool Button(const char* label, const ImVec2& size = ImVec2(0,0)); // button @@ -443,6 +431,17 @@ namespace ImGui IMGUI_API bool IsPopupOpen(const char* str_id); // return true if the popup is open IMGUI_API void CloseCurrentPopup(); // close the popup we have begin-ed into. clicking on a MenuItem or Selectable automatically close the current popup. + // Columns + // You can also use SameLine(pos_x) for simplified columns. The columns API is still work-in-progress and rather lacking. + IMGUI_API void Columns(int count = 1, const char* id = NULL, bool border = true); + IMGUI_API void NextColumn(); // next column, defaults to current row or next row if the current row is finished + IMGUI_API int GetColumnIndex(); // get current column index + IMGUI_API float GetColumnWidth(int column_index = -1); // get column width (in pixels). pass -1 to use current column + IMGUI_API void SetColumnWidth(int column_index, float width); // set column width (in pixels). pass -1 to use current column + IMGUI_API float GetColumnOffset(int column_index = -1); // get position of column line (in pixels, from the left side of the contents region). pass -1 to use current column, otherwise 0..GetColumnsCount() inclusive. column 0 is typically 0.0f + IMGUI_API void SetColumnOffset(int column_index, float offset_x); // set position of column line (in pixels, from the left side of the contents region). pass -1 to use current column + IMGUI_API int GetColumnsCount(); + // Logging/Capture: all text output from interface is captured to tty/file/clipboard. By default, tree nodes are automatically opened during logging. IMGUI_API void LogToTTY(int max_depth = -1); // start logging to tty IMGUI_API void LogToFile(int max_depth = -1, const char* filename = NULL); // start logging to file From d8d93f6360efb184e342a221b71018a2a2709778 Mon Sep 17 00:00:00 2001 From: omar Date: Sun, 18 Mar 2018 12:24:28 +0100 Subject: [PATCH 776/823] imgui.h: Various comments and tweaks. --- imconfig.h | 9 +-- imgui.h | 186 ++++++++++++++++++++++++++++------------------------- 2 files changed, 104 insertions(+), 91 deletions(-) diff --git a/imconfig.h b/imconfig.h index afa54914c751..75e7e44ef353 100644 --- a/imconfig.h +++ b/imconfig.h @@ -1,6 +1,7 @@ //----------------------------------------------------------------------------- // COMPILE-TIME OPTIONS FOR DEAR IMGUI -// Most options (memory allocation, clipboard callbacks, etc.) can be set at runtime via the ImGuiIO structure - ImGui::GetIO(). +// Runtime options (clipboard callbacks, enabling various features, etc.) can generally be set via the ImGuiIO structure. +// You can use ImGui::SetAllocatorFunctions() before calling ImGui::CreateContext() to rewire memory allocation functions. //----------------------------------------------------------------------------- // A) You may edit imconfig.h (and not overwrite it when updating imgui, or maintain a patch/branch with your modifications to imconfig.h) // B) or add configuration directives in your own file and compile with #define IMGUI_USER_CONFIG "myfilename.h" @@ -16,7 +17,7 @@ //#define IMGUI_API __declspec( dllexport ) //#define IMGUI_API __declspec( dllimport ) -//---- Don't define obsolete functions names. Consider enabling from time to time or when updating to reduce likelihood of using already obsolete function/names +//---- Don't define obsolete functions/enums names. Consider enabling from time to time after updating to avoid using soon-to-be obsolete function/names //#define IMGUI_DISABLE_OBSOLETE_FUNCTIONS //---- Don't implement default handlers for Windows (so as not to link with certain functions) @@ -24,7 +25,7 @@ //#define IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS // Don't use and link with ImmGetContext/ImmSetCompositionWindow. //---- Don't implement demo windows functionality (ShowDemoWindow()/ShowStyleEditor()/ShowUserGuide() methods will be empty) -//---- It is very strongly recommended to NOT disable the demo windows. Please read the comment at the top of imgui_demo.cpp. +//---- It is very strongly recommended to NOT disable the demo windows during development. Please read the comments in imgui_demo.cpp. //#define IMGUI_DISABLE_DEMO_WINDOWS //---- Don't implement ImFormatString(), ImFormatStringV() so you can reimplement them yourself. @@ -51,7 +52,7 @@ operator MyVec4() const { return MyVec4(x,y,z,w); } */ -//---- Use 32-bit vertex indices (instead of default 16-bit) to allow meshes with more than 64K vertices. Render function needs to support it. +//---- Use 32-bit vertex indices (default is 16-bit) to allow meshes with more than 64K vertices. Render function needs to support it. //#define ImDrawIdx unsigned int //---- Tip: You can add extra functions within the ImGui:: namespace, here or in your own headers files. diff --git a/imgui.h b/imgui.h index 88edbe93dad1..90eef826b728 100644 --- a/imgui.h +++ b/imgui.h @@ -8,7 +8,7 @@ #pragma once -// User-editable configuration files (edit stock imconfig.h or define IMGUI_USER_CONFIG to your own filename) +// Configuration file (edit imconfig.h or define IMGUI_USER_CONFIG to set your own filename) #ifdef IMGUI_USER_CONFIG #include IMGUI_USER_CONFIG #endif @@ -35,16 +35,15 @@ #endif // Helpers -// Some compilers support applying printf-style warnings to user functions. #if defined(__clang__) || defined(__GNUC__) -#define IM_FMTARGS(FMT) __attribute__((format(printf, FMT, FMT+1))) +#define IM_FMTARGS(FMT) __attribute__((format(printf, FMT, FMT+1))) // Apply printf-style warnings to user functions. #define IM_FMTLIST(FMT) __attribute__((format(printf, FMT, 0))) #else #define IM_FMTARGS(FMT) #define IM_FMTLIST(FMT) #endif -#define IM_ARRAYSIZE(_ARR) ((int)(sizeof(_ARR)/sizeof(*_ARR))) -#define IM_OFFSETOF(_TYPE,_MEMBER) ((size_t)&(((_TYPE*)0)->_MEMBER)) // Offset of _MEMBER within _TYPE. Standardized as offsetof() in modern C++. +#define IM_ARRAYSIZE(_ARR) ((int)(sizeof(_ARR)/sizeof(*_ARR))) // Size of a static C-style array. Don't use on pointers! +#define IM_OFFSETOF(_TYPE,_MEMBER) ((size_t)&(((_TYPE*)0)->_MEMBER)) // Offset of _MEMBER within _TYPE. Standardized as offsetof() in modern C++. #if defined(__clang__) #pragma clang diagnostic push @@ -75,13 +74,13 @@ struct ImGuiPayload; // User data payload for drag and drop opera struct ImGuiContext; // ImGui context (opaque) #ifndef ImTextureID -typedef void* ImTextureID; // user data to identify a texture (this is whatever to you want it to be! read the FAQ about ImTextureID in imgui.cpp) +typedef void* ImTextureID; // User data to identify a texture (this is whatever to you want it to be! read the FAQ about ImTextureID in imgui.cpp) #endif // Typedefs and Enumerations (declared as int for compatibility with old C++ and to not pollute the top of this file) typedef unsigned int ImU32; // 32-bit unsigned integer (typically used to store packed colors) -typedef unsigned int ImGuiID; // unique ID used by widgets (typically hashed from a stack of string) -typedef unsigned short ImWchar; // character for keyboard input/display +typedef unsigned int ImGuiID; // Unique ID used by widgets (typically hashed from a stack of string) +typedef unsigned short ImWchar; // Character for keyboard input/display typedef int ImGuiCol; // enum: a color identifier for styling // enum ImGuiCol_ typedef int ImGuiDir; // enum: a cardinal direction // enum ImGuiDir_ typedef int ImGuiCond; // enum: a condition for Set*() // enum ImGuiCond_ @@ -116,7 +115,7 @@ struct ImVec2 float x, y; ImVec2() { x = y = 0.0f; } ImVec2(float _x, float _y) { x = _x; y = _y; } - float operator[] (size_t idx) const { IM_ASSERT(idx <= 1); return (&x)[idx]; } // We very rarely use this [] operator, thus an assert is fine. + float operator[] (size_t idx) const { IM_ASSERT(idx <= 1); return (&x)[idx]; } // We very rarely use this [] operator, the assert overhead is fine. #ifdef IM_VEC2_CLASS_EXTRA // Define constructor and implicit cast operators in imconfig.h to convert back<>forth from your math types and ImVec2. IM_VEC2_CLASS_EXTRA #endif @@ -136,11 +135,11 @@ struct ImVec4 // In a namespace so that user can add extra functions in a separate file (e.g. Value() helpers for your vector or common types) namespace ImGui { - // Context creation and access, if you want to use multiple context, share context between modules (e.g. DLL). + // Context creation and access // All contexts share a same ImFontAtlas by default. If you want different font atlas, you can new() them and overwrite the GetIO().Fonts variable of an ImGui context. // All those functions are not reliant on the current context. IMGUI_API ImGuiContext* CreateContext(ImFontAtlas* shared_font_atlas = NULL); - IMGUI_API void DestroyContext(ImGuiContext* ctx = NULL); // NULL = Destroy current context + IMGUI_API void DestroyContext(ImGuiContext* ctx = NULL); // NULL = destroy current context IMGUI_API ImGuiContext* GetCurrentContext(); IMGUI_API void SetCurrentContext(ImGuiContext* ctx); @@ -152,40 +151,48 @@ namespace ImGui IMGUI_API ImDrawData* GetDrawData(); // valid after Render() and until the next call to NewFrame(). this is what you have to render. (Obsolete: this used to be passed to your io.RenderDrawListsFn() function.) IMGUI_API void EndFrame(); // ends the ImGui frame. automatically called by Render(), so most likely don't need to ever call that yourself directly. If you don't need to render you may call EndFrame() but you'll have wasted CPU already. If you don't need to render, better to not create any imgui windows instead! - // Demo, Debug, Informations + // Demo, Debug, Information IMGUI_API void ShowDemoWindow(bool* p_open = NULL); // create demo/test window (previously called ShowTestWindow). demonstrate most ImGui features. call this to learn about the library! try to make it always available in your application! IMGUI_API void ShowMetricsWindow(bool* p_open = NULL); // create metrics window. display ImGui internals: draw commands (with individual draw calls and vertices), window list, basic internal state, etc. IMGUI_API void ShowStyleEditor(ImGuiStyle* ref = NULL); // add style editor block (not a window). you can pass in a reference ImGuiStyle structure to compare to, revert to and save to (else it uses the default style) - IMGUI_API bool ShowStyleSelector(const char* label); - IMGUI_API void ShowFontSelector(const char* label); + IMGUI_API bool ShowStyleSelector(const char* label); // add style selector block (not a window), essentially a combo listing the default styles. + IMGUI_API void ShowFontSelector(const char* label); // add font selector block (not a window), essentially a combo listing the loaded fonts. IMGUI_API void ShowUserGuide(); // add basic help/info block (not a window): how to manipulate ImGui as a end-user (mouse/keyboard controls). - IMGUI_API const char* GetVersion(); + IMGUI_API const char* GetVersion(); // get a version string e.g. "1.23" // Styles - IMGUI_API void StyleColorsDark(ImGuiStyle* dst = NULL); // New, recommended style - IMGUI_API void StyleColorsClassic(ImGuiStyle* dst = NULL); // Classic imgui style (default) - IMGUI_API void StyleColorsLight(ImGuiStyle* dst = NULL); // Best used with borders and a custom, thicker font - - // Window - IMGUI_API bool Begin(const char* name, bool* p_open = NULL, ImGuiWindowFlags flags = 0); // push window to the stack and start appending to it. see .cpp for details. return false when window is collapsed (so you can early out in your code) but you always need to call End() regardless. 'bool* p_open' creates a widget on the upper-right to close the window (which sets your bool to false). - IMGUI_API void End(); // always call even if Begin() return false (which indicates a collapsed window)! finish appending to current window, pop it off the window stack. - IMGUI_API bool BeginChild(const char* str_id, const ImVec2& size = ImVec2(0,0), bool border = false, ImGuiWindowFlags flags = 0); // begin a scrolling region. size==0.0f: use remaining window size, size<0.0f: use remaining window size minus abs(size). size>0.0f: fixed size. each axis can use a different mode, e.g. ImVec2(0,400). - IMGUI_API bool BeginChild(ImGuiID id, const ImVec2& size = ImVec2(0,0), bool border = false, ImGuiWindowFlags flags = 0); // " - IMGUI_API void EndChild(); // always call even if BeginChild() return false (which indicates a collapsed or clipping child window) - IMGUI_API ImVec2 GetContentRegionMax(); // current content boundaries (typically window boundaries including scrolling, or current column boundaries), in windows coordinates - IMGUI_API ImVec2 GetContentRegionAvail(); // == GetContentRegionMax() - GetCursorPos() - IMGUI_API float GetContentRegionAvailWidth(); // - IMGUI_API ImVec2 GetWindowContentRegionMin(); // content boundaries min (roughly (0,0)-Scroll), in window coordinates - IMGUI_API ImVec2 GetWindowContentRegionMax(); // content boundaries max (roughly (0,0)+Size-Scroll) where Size can be override with SetNextWindowContentSize(), in window coordinates - IMGUI_API float GetWindowContentRegionWidth(); // - IMGUI_API ImDrawList* GetWindowDrawList(); // get rendering command-list if you want to append your own draw primitives - IMGUI_API ImVec2 GetWindowPos(); // get current window position in screen space (useful if you want to do your own drawing via the DrawList api) - IMGUI_API ImVec2 GetWindowSize(); // get current window size - IMGUI_API float GetWindowWidth(); - IMGUI_API float GetWindowHeight(); - IMGUI_API bool IsWindowCollapsed(); + IMGUI_API void StyleColorsDark(ImGuiStyle* dst = NULL); // new, recommended style + IMGUI_API void StyleColorsClassic(ImGuiStyle* dst = NULL); // old, classic imgui style (default) + IMGUI_API void StyleColorsLight(ImGuiStyle* dst = NULL); // best used with borders and a custom, thicker font + + // Windows + // (Begin = push window to the stack and start appending to it. End = pop window from the stack. You may append multiple times to the same window during the same frame) + // Begin()/BeginChild() return false to indicate the window being collapsed or fully clipped, so you may early out and omit submitting anything to the window. + // However you need to always call a matching End()/EndChild() for a Begin()/BeginChild() call, regardless of its return value (this is due to legacy reason and is inconsistent with BeginMenu/EndMenu, BeginPopup/EndPopup and other functions where the End call should only be called if the corresponding Begin function returned true.) + // Passing 'bool* p_open != NULL' shows a close widget in the upper-right corner of the window, which when clicking will set the boolean to false. + // Use child windows to introduce independent scrolling/clipping regions within a host window. Child windows can embed their own child. + IMGUI_API bool Begin(const char* name, bool* p_open = NULL, ImGuiWindowFlags flags = 0); + IMGUI_API void End(); + IMGUI_API bool BeginChild(const char* str_id, const ImVec2& size = ImVec2(0,0), bool border = false, ImGuiWindowFlags flags = 0); // Begin a scrolling region. size==0.0f: use remaining window size, size<0.0f: use remaining window size minus abs(size). size>0.0f: fixed size. each axis can use a different mode, e.g. ImVec2(0,400). + IMGUI_API bool BeginChild(ImGuiID id, const ImVec2& size = ImVec2(0,0), bool border = false, ImGuiWindowFlags flags = 0); + IMGUI_API void EndChild(); + + // Windows Utilities IMGUI_API bool IsWindowAppearing(); - IMGUI_API void SetWindowFontScale(float scale); // per-window font scale. Adjust IO.FontGlobalScale if you want to scale all windows + IMGUI_API bool IsWindowCollapsed(); + IMGUI_API bool IsWindowFocused(ImGuiFocusedFlags flags=0); // is current window focused? or its root/child, depending on flags. see flags for options. + IMGUI_API bool IsWindowHovered(ImGuiHoveredFlags flags=0); // is current window hovered (and typically: not blocked by a popup/modal)? see flags for options. NB: If you are trying to check whether your mouse should be dispatched to imgui or to your app, you should use the 'io.WantCaptureMouse' boolean for that! Please read the FAQ! + IMGUI_API ImDrawList* GetWindowDrawList(); // get draw list associated to the window, to append your own drawing primitives + IMGUI_API ImVec2 GetWindowPos(); // get current window position in screen space (useful if you want to do your own drawing via the DrawList API) + IMGUI_API ImVec2 GetWindowSize(); // get current window size + IMGUI_API float GetWindowWidth(); // get current window width (shortcut for GetWindowSize().x) + IMGUI_API float GetWindowHeight(); // get current window height (shortcut for GetWindowSize().y) + IMGUI_API ImVec2 GetContentRegionMax(); // current content boundaries (typically window boundaries including scrolling, or current column boundaries), in windows coordinates + IMGUI_API ImVec2 GetContentRegionAvail(); // == GetContentRegionMax() - GetCursorPos() + IMGUI_API float GetContentRegionAvailWidth(); // + IMGUI_API ImVec2 GetWindowContentRegionMin(); // content boundaries min (roughly (0,0)-Scroll), in window coordinates + IMGUI_API ImVec2 GetWindowContentRegionMax(); // content boundaries max (roughly (0,0)+Size-Scroll) where Size can be override with SetNextWindowContentSize(), in window coordinates + IMGUI_API float GetWindowContentRegionWidth(); // IMGUI_API void SetNextWindowPos(const ImVec2& pos, ImGuiCond cond = 0, const ImVec2& pivot = ImVec2(0,0)); // set next window position. call before Begin(). use pivot=(0.5f,0.5f) to center on given point, etc. IMGUI_API void SetNextWindowSize(const ImVec2& size, ImGuiCond cond = 0); // set next window size. set axis to 0.0f to force an auto-fit on this axis. call before Begin() @@ -198,24 +205,24 @@ namespace ImGui IMGUI_API void SetWindowSize(const ImVec2& size, ImGuiCond cond = 0); // (not recommended) set current window size - call within Begin()/End(). set to ImVec2(0,0) to force an auto-fit. prefer using SetNextWindowSize(), as this may incur tearing and minor side-effects. IMGUI_API void SetWindowCollapsed(bool collapsed, ImGuiCond cond = 0); // (not recommended) set current window collapsed state. prefer using SetNextWindowCollapsed(). IMGUI_API void SetWindowFocus(); // (not recommended) set current window to be focused / front-most. prefer using SetNextWindowFocus(). + IMGUI_API void SetWindowFontScale(float scale); // set font scale. Adjust IO.FontGlobalScale if you want to scale all windows IMGUI_API void SetWindowPos(const char* name, const ImVec2& pos, ImGuiCond cond = 0); // set named window position. IMGUI_API void SetWindowSize(const char* name, const ImVec2& size, ImGuiCond cond = 0); // set named window size. set axis to 0.0f to force an auto-fit on this axis. IMGUI_API void SetWindowCollapsed(const char* name, bool collapsed, ImGuiCond cond = 0); // set named window collapsed state IMGUI_API void SetWindowFocus(const char* name); // set named window to be focused / front-most. use NULL to remove focus. - IMGUI_API float GetScrollX(); // get scrolling amount [0..GetScrollMaxX()] - IMGUI_API float GetScrollY(); // get scrolling amount [0..GetScrollMaxY()] - IMGUI_API float GetScrollMaxX(); // get maximum scrolling amount ~~ ContentSize.X - WindowSize.X - IMGUI_API float GetScrollMaxY(); // get maximum scrolling amount ~~ ContentSize.Y - WindowSize.Y - IMGUI_API void SetScrollX(float scroll_x); // set scrolling amount [0..GetScrollMaxX()] - IMGUI_API void SetScrollY(float scroll_y); // set scrolling amount [0..GetScrollMaxY()] - IMGUI_API void SetScrollHere(float center_y_ratio = 0.5f); // adjust scrolling amount to make current cursor position visible. center_y_ratio=0.0: top, 0.5: center, 1.0: bottom. When using to make a "default/current item" visible, consider using SetItemDefaultFocus() instead. - IMGUI_API void SetScrollFromPosY(float pos_y, float center_y_ratio = 0.5f); // adjust scrolling amount to make given position valid. use GetCursorPos() or GetCursorStartPos()+offset to get valid positions. - IMGUI_API void SetStateStorage(ImGuiStorage* tree); // replace tree state storage with our own (if you want to manipulate it yourself, typically clear subsection of it) - IMGUI_API ImGuiStorage* GetStateStorage(); + // Windows Scrolling + IMGUI_API float GetScrollX(); // get scrolling amount [0..GetScrollMaxX()] + IMGUI_API float GetScrollY(); // get scrolling amount [0..GetScrollMaxY()] + IMGUI_API float GetScrollMaxX(); // get maximum scrolling amount ~~ ContentSize.X - WindowSize.X + IMGUI_API float GetScrollMaxY(); // get maximum scrolling amount ~~ ContentSize.Y - WindowSize.Y + IMGUI_API void SetScrollX(float scroll_x); // set scrolling amount [0..GetScrollMaxX()] + IMGUI_API void SetScrollY(float scroll_y); // set scrolling amount [0..GetScrollMaxY()] + IMGUI_API void SetScrollHere(float center_y_ratio = 0.5f); // adjust scrolling amount to make current cursor position visible. center_y_ratio=0.0: top, 0.5: center, 1.0: bottom. When using to make a "default/current item" visible, consider using SetItemDefaultFocus() instead. + IMGUI_API void SetScrollFromPosY(float pos_y, float center_y_ratio = 0.5f); // adjust scrolling amount to make given position valid. use GetCursorPos() or GetCursorStartPos()+offset to get valid positions. // Parameters stacks (shared) - IMGUI_API void PushFont(ImFont* font); // use NULL as a shortcut to push default font + IMGUI_API void PushFont(ImFont* font); // use NULL as a shortcut to push default font IMGUI_API void PopFont(); IMGUI_API void PushStyleColor(ImGuiCol idx, ImU32 col); IMGUI_API void PushStyleColor(ImGuiCol idx, const ImVec4& col); @@ -267,15 +274,18 @@ namespace ImGui IMGUI_API float GetFrameHeight(); // ~ FontSize + style.FramePadding.y * 2 IMGUI_API float GetFrameHeightWithSpacing(); // ~ FontSize + style.FramePadding.y * 2 + style.ItemSpacing.y (distance in pixels between 2 consecutive lines of framed widgets) - // ID scopes - // If you are creating widgets in a loop you most likely want to push a unique identifier (e.g. object pointer, loop index) so ImGui can differentiate them. - // You can also use the "##foobar" syntax within widget label to distinguish them from each others. Read "A primer on the use of labels/IDs" in the FAQ for more details. - IMGUI_API void PushID(const char* str_id); // push identifier into the ID stack. IDs are hash of the entire stack! + // ID stack/scopes + // Read the FAQ for more details about how ID are handled in dear imgui. If you are creating widgets in a loop you most + // likely want to push a unique identifier (e.g. object pointer, loop index) to uniquely differentiate them. + // You can also use the "##foobar" syntax within widget label to distinguish them from each others. + // In this header file we use the "label"/"name" terminology to denote a string that will be displayed and used as an ID, + // whereas "str_id" denote a string that is only used as an ID and not aimed to be displayed. + IMGUI_API void PushID(const char* str_id); // push identifier into the ID stack. IDs are hash of the entire stack! IMGUI_API void PushID(const char* str_id_begin, const char* str_id_end); IMGUI_API void PushID(const void* ptr_id); IMGUI_API void PushID(int int_id); IMGUI_API void PopID(); - IMGUI_API ImGuiID GetID(const char* str_id); // calculate unique ID (hash of whole ID stack + given parameter). e.g. if you want to query into ImGuiStorage yourself + IMGUI_API ImGuiID GetID(const char* str_id); // calculate unique ID (hash of whole ID stack + given parameter). e.g. if you want to query into ImGuiStorage yourself IMGUI_API ImGuiID GetID(const char* str_id_begin, const char* str_id_end); IMGUI_API ImGuiID GetID(const void* ptr_id); @@ -295,10 +305,10 @@ namespace ImGui IMGUI_API void BulletTextV(const char* fmt, va_list args) IM_FMTLIST(1); // Widgets: Main - IMGUI_API bool Button(const char* label, const ImVec2& size = ImVec2(0,0)); // button - IMGUI_API bool SmallButton(const char* label); // button with FramePadding=(0,0) to easily embed within text + IMGUI_API bool Button(const char* label, const ImVec2& size = ImVec2(0,0)); // button + IMGUI_API bool SmallButton(const char* label); // button with FramePadding=(0,0) to easily embed within text IMGUI_API bool ArrowButton(const char* str_id, ImGuiDir dir); - IMGUI_API bool InvisibleButton(const char* str_id, const ImVec2& size); // button behavior without the visuals, useful to build custom behaviors using the public api (along with IsItemActive, IsItemHovered, etc.) + IMGUI_API bool InvisibleButton(const char* str_id, const ImVec2& size); // button behavior without the visuals, useful to build custom behaviors using the public api (along with IsItemActive, IsItemHovered, etc.) IMGUI_API void Image(ImTextureID user_texture_id, const ImVec2& size, const ImVec2& uv0 = ImVec2(0,0), const ImVec2& uv1 = ImVec2(1,1), const ImVec4& tint_col = ImVec4(1,1,1,1), const ImVec4& border_col = ImVec4(0,0,0,0)); IMGUI_API bool ImageButton(ImTextureID user_texture_id, const ImVec2& size, const ImVec2& uv0 = ImVec2(0,0), const ImVec2& uv1 = ImVec2(1,1), int frame_padding = -1, const ImVec4& bg_col = ImVec4(0,0,0,0), const ImVec4& tint_col = ImVec4(1,1,1,1)); // <0 frame_padding uses default frame padding settings. 0 for no padding IMGUI_API bool Checkbox(const char* label, bool* v); @@ -310,6 +320,7 @@ namespace ImGui IMGUI_API void PlotHistogram(const char* label, const float* values, int values_count, int values_offset = 0, const char* overlay_text = NULL, float scale_min = FLT_MAX, float scale_max = FLT_MAX, ImVec2 graph_size = ImVec2(0,0), int stride = sizeof(float)); IMGUI_API void PlotHistogram(const char* label, float (*values_getter)(void* data, int idx), void* data, int values_count, int values_offset = 0, const char* overlay_text = NULL, float scale_min = FLT_MAX, float scale_max = FLT_MAX, ImVec2 graph_size = ImVec2(0,0)); IMGUI_API void ProgressBar(float fraction, const ImVec2& size_arg = ImVec2(-1,0), const char* overlay = NULL); + IMGUI_API void Bullet(); // draw a small circle and keep the cursor on the same line. advance cursor x position by GetTreeNodeToLabelSpacing(), same distance that TreeNode() uses // Widgets: Combo Box // The new BeginCombo()/EndCombo() api allows you to manage your contents and selection state however you want it. @@ -366,12 +377,12 @@ namespace ImGui IMGUI_API bool ColorPicker3(const char* label, float col[3], ImGuiColorEditFlags flags = 0); IMGUI_API bool ColorPicker4(const char* label, float col[4], ImGuiColorEditFlags flags = 0, const float* ref_col = NULL); IMGUI_API bool ColorButton(const char* desc_id, const ImVec4& col, ImGuiColorEditFlags flags = 0, ImVec2 size = ImVec2(0,0)); // display a colored square/button, hover for details, return true when pressed. - IMGUI_API void SetColorEditOptions(ImGuiColorEditFlags flags); // initialize current options (generally on application startup) if you want to select a default format, picker type, etc. User will be able to change many settings, unless you pass the _NoOptions flag to your calls. + IMGUI_API void SetColorEditOptions(ImGuiColorEditFlags flags); // initialize current options (generally on application startup) if you want to select a default format, picker type, etc. User will be able to change many settings, unless you pass the _NoOptions flag to your calls. // Widgets: Trees - IMGUI_API bool TreeNode(const char* label); // if returning 'true' the node is open and the tree id is pushed into the id stack. user is responsible for calling TreePop(). - IMGUI_API bool TreeNode(const char* str_id, const char* fmt, ...) IM_FMTARGS(2); // read the FAQ about why and how to use ID. to align arbitrary text at the same level as a TreeNode() you can use Bullet(). - IMGUI_API bool TreeNode(const void* ptr_id, const char* fmt, ...) IM_FMTARGS(2); // " + IMGUI_API bool TreeNode(const char* label); // if returning 'true' the node is open and the tree id is pushed into the id stack. user is responsible for calling TreePop(). + IMGUI_API bool TreeNode(const char* str_id, const char* fmt, ...) IM_FMTARGS(2); // read the FAQ about why and how to use ID. to align arbitrary text at the same level as a TreeNode() you can use Bullet(). + IMGUI_API bool TreeNode(const void* ptr_id, const char* fmt, ...) IM_FMTARGS(2); // " IMGUI_API bool TreeNodeV(const char* str_id, const char* fmt, va_list args) IM_FMTLIST(2); IMGUI_API bool TreeNodeV(const void* ptr_id, const char* fmt, va_list args) IM_FMTLIST(2); IMGUI_API bool TreeNodeEx(const char* label, ImGuiTreeNodeFlags flags = 0); @@ -379,13 +390,13 @@ namespace ImGui IMGUI_API bool TreeNodeEx(const void* ptr_id, ImGuiTreeNodeFlags flags, const char* fmt, ...) IM_FMTARGS(3); IMGUI_API bool TreeNodeExV(const char* str_id, ImGuiTreeNodeFlags flags, const char* fmt, va_list args) IM_FMTLIST(3); IMGUI_API bool TreeNodeExV(const void* ptr_id, ImGuiTreeNodeFlags flags, const char* fmt, va_list args) IM_FMTLIST(3); - IMGUI_API void TreePush(const char* str_id); // ~ Indent()+PushId(). Already called by TreeNode() when returning true, but you can call Push/Pop yourself for layout purpose - IMGUI_API void TreePush(const void* ptr_id = NULL); // " - IMGUI_API void TreePop(); // ~ Unindent()+PopId() - IMGUI_API void TreeAdvanceToLabelPos(); // advance cursor x position by GetTreeNodeToLabelSpacing() - IMGUI_API float GetTreeNodeToLabelSpacing(); // horizontal distance preceding label when using TreeNode*() or Bullet() == (g.FontSize + style.FramePadding.x*2) for a regular unframed TreeNode - IMGUI_API void SetNextTreeNodeOpen(bool is_open, ImGuiCond cond = 0); // set next TreeNode/CollapsingHeader open state. - IMGUI_API bool CollapsingHeader(const char* label, ImGuiTreeNodeFlags flags = 0); // if returning 'true' the header is open. doesn't indent nor push on ID stack. user doesn't have to call TreePop(). + IMGUI_API void TreePush(const char* str_id); // ~ Indent()+PushId(). Already called by TreeNode() when returning true, but you can call Push/Pop yourself for layout purpose + IMGUI_API void TreePush(const void* ptr_id = NULL); // " + IMGUI_API void TreePop(); // ~ Unindent()+PopId() + IMGUI_API void TreeAdvanceToLabelPos(); // advance cursor x position by GetTreeNodeToLabelSpacing() + IMGUI_API float GetTreeNodeToLabelSpacing(); // horizontal distance preceding label when using TreeNode*() or Bullet() == (g.FontSize + style.FramePadding.x*2) for a regular unframed TreeNode + IMGUI_API void SetNextTreeNodeOpen(bool is_open, ImGuiCond cond = 0); // set next TreeNode/CollapsingHeader open state. + IMGUI_API bool CollapsingHeader(const char* label, ImGuiTreeNodeFlags flags = 0); // if returning 'true' the header is open. doesn't indent nor push on ID stack. user doesn't have to call TreePop(). IMGUI_API bool CollapsingHeader(const char* label, bool* p_open, ImGuiTreeNodeFlags flags = 0); // when 'p_open' isn't NULL, display an additional small close button on upper right of the header // Widgets: Selectable / Lists @@ -393,9 +404,9 @@ namespace ImGui IMGUI_API bool Selectable(const char* label, bool* p_selected, ImGuiSelectableFlags flags = 0, const ImVec2& size = ImVec2(0,0)); // "bool* p_selected" point to the selection state (read-write), as a convenient helper. IMGUI_API bool ListBox(const char* label, int* current_item, const char* const items[], int items_count, int height_in_items = -1); IMGUI_API bool ListBox(const char* label, int* current_item, bool (*items_getter)(void* data, int idx, const char** out_text), void* data, int items_count, int height_in_items = -1); - IMGUI_API bool ListBoxHeader(const char* label, const ImVec2& size = ImVec2(0,0)); // use if you want to reimplement ListBox() will custom data or interactions. make sure to call ListBoxFooter() afterwards. + IMGUI_API bool ListBoxHeader(const char* label, const ImVec2& size = ImVec2(0,0)); // use if you want to reimplement ListBox() will custom data or interactions. make sure to call ListBoxFooter() afterwards. IMGUI_API bool ListBoxHeader(const char* label, int items_count, int height_in_items = -1); // " - IMGUI_API void ListBoxFooter(); // terminate the scrolling region + IMGUI_API void ListBoxFooter(); // terminate the scrolling region // Widgets: Value() Helpers. Output single value in "name: value" format (tip: freely declare more in your code to handle your types. you can add functions to the ImGui namespace) IMGUI_API void Value(const char* prefix, bool b); @@ -415,7 +426,7 @@ namespace ImGui IMGUI_API bool BeginMenuBar(); // append to menu-bar of current window (requires ImGuiWindowFlags_MenuBar flag set on parent window). IMGUI_API void EndMenuBar(); // only call EndMenuBar() if BeginMenuBar() returns true! IMGUI_API bool BeginMenu(const char* label, bool enabled = true); // create a sub-menu entry. only call EndMenu() if this returns true! - IMGUI_API void EndMenu(); // only call EndBegin() if BeginMenu() returns true! + IMGUI_API void EndMenu(); // only call EndMenu() if BeginMenu() returns true! IMGUI_API bool MenuItem(const char* label, const char* shortcut = NULL, bool selected = false, bool enabled = true); // return true when activated. shortcuts are displayed for convenience but not processed by ImGui at the moment IMGUI_API bool MenuItem(const char* label, const char* shortcut, bool* p_selected, bool enabled = true); // return true when activated + toggle (*p_selected) if p_selected != NULL @@ -481,15 +492,15 @@ namespace ImGui IMGUI_API ImVec2 GetItemRectMax(); // " IMGUI_API ImVec2 GetItemRectSize(); // get size of last item, in screen space IMGUI_API void SetItemAllowOverlap(); // allow last item to be overlapped by a subsequent item. sometimes useful with invisible buttons, selectables, etc. to catch unused area. - IMGUI_API bool IsWindowFocused(ImGuiFocusedFlags flags = 0); // is current window focused? or its root/child, depending on flags. see flags for options. - IMGUI_API bool IsWindowHovered(ImGuiHoveredFlags flags = 0); // is current window hovered (and typically: not blocked by a popup/modal)? see flags for options. NB: If you are trying to check whether your mouse should be dispatched to imgui or to your app, you should use the 'io.WantCaptureMouse' boolean for that! Please read the FAQ! IMGUI_API bool IsRectVisible(const ImVec2& size); // test if rectangle (of given size, starting from cursor position) is visible / not clipped. IMGUI_API bool IsRectVisible(const ImVec2& rect_min, const ImVec2& rect_max); // test if rectangle (in screen space) is visible / not clipped. to perform coarse clipping on user's side. IMGUI_API float GetTime(); IMGUI_API int GetFrameCount(); IMGUI_API ImDrawList* GetOverlayDrawList(); // this draw list will be the last rendered one, useful to quickly draw overlays shapes/text - IMGUI_API ImDrawListSharedData* GetDrawListSharedData(); + IMGUI_API ImDrawListSharedData* GetDrawListSharedData(); // you may use this when creating your own ImDrawList instances IMGUI_API const char* GetStyleColorName(ImGuiCol idx); + IMGUI_API void SetStateStorage(ImGuiStorage* storage); // replace current window storage with our own (if you want to manipulate it yourself, typically clear subsection of it) + IMGUI_API ImGuiStorage* GetStateStorage(); IMGUI_API ImVec2 CalcTextSize(const char* text, const char* text_end = NULL, bool hide_text_after_double_hash = false, float wrap_width = -1.0f); IMGUI_API void CalcListClipping(int items_count, float items_height, int* out_items_display_start, int* out_items_display_end); // calculate coarse clipping for large list of evenly sized items. Prefer using the ImGuiListClipper higher-level helper if you can. @@ -516,7 +527,7 @@ namespace ImGui IMGUI_API bool IsMouseHoveringRect(const ImVec2& r_min, const ImVec2& r_max, bool clip = true); // is mouse hovering given bounding rect (in screen space). clipped by current clipping settings. disregarding of consideration of focus/window ordering/blocked by a popup. IMGUI_API bool IsMousePosValid(const ImVec2* mouse_pos = NULL); // IMGUI_API ImVec2 GetMousePos(); // shortcut to ImGui::GetIO().MousePos provided by user, to be consistent with other calls - IMGUI_API ImVec2 GetMousePosOnOpeningCurrentPopup(); // retrieve backup of mouse positioning at the time of opening popup we have BeginPopup() into + IMGUI_API ImVec2 GetMousePosOnOpeningCurrentPopup(); // retrieve backup of mouse position at the time of opening popup we have BeginPopup() into IMGUI_API ImVec2 GetMouseDragDelta(int button = 0, float lock_threshold = -1.0f); // dragging amount since clicking. if lock_threshold < -1.0f uses io.MouseDraggingThreshold IMGUI_API void ResetMouseDragDelta(int button = 0); // IMGUI_API ImGuiMouseCursor GetMouseCursor(); // get desired cursor type, reset in ImGui::NewFrame(), this is updated during the frame. valid before Render(). If you use software rendering by setting io.MouseDrawCursor ImGui will render those for you @@ -812,7 +823,7 @@ enum ImGuiCol_ ImGuiCol_PlotHistogram, ImGuiCol_PlotHistogramHovered, ImGuiCol_TextSelectedBg, - ImGuiCol_ModalWindowDarkening, // darken entire screen when a modal window is active + ImGuiCol_ModalWindowDarkening, // darken/colorize entire screen behind a modal window, when one is active ImGuiCol_DragDropTarget, ImGuiCol_NavHighlight, // gamepad/keyboard: current highlighted item ImGuiCol_NavWindowingHighlight, // gamepad/keyboard: when holding NavMenu to focus/move/resize windows @@ -894,12 +905,13 @@ enum ImGuiColorEditFlags_ }; // Enumeration for GetMouseCursor() +// User code may request binding to display given cursor by calling SetMouseCursor(), which is why we have some cursors that are marked unused here enum ImGuiMouseCursor_ { ImGuiMouseCursor_None = -1, ImGuiMouseCursor_Arrow = 0, ImGuiMouseCursor_TextInput, // When hovering over InputText, etc. - ImGuiMouseCursor_ResizeAll, // Unused + ImGuiMouseCursor_ResizeAll, // Unused by imgui functions ImGuiMouseCursor_ResizeNS, // When hovering over an horizontal border ImGuiMouseCursor_ResizeEW, // When hovering over a vertical border or a column ImGuiMouseCursor_ResizeNESW, // When hovering over the bottom-left corner of a window @@ -918,8 +930,8 @@ enum ImGuiCond_ { ImGuiCond_Always = 1 << 0, // Set the variable ImGuiCond_Once = 1 << 1, // Set the variable once per runtime session (only the first call with succeed) - ImGuiCond_FirstUseEver = 1 << 2, // Set the variable if the window has no saved data (if doesn't exist in the .ini file) - ImGuiCond_Appearing = 1 << 3 // Set the variable if the window is appearing after being hidden/inactive (or the first time) + ImGuiCond_FirstUseEver = 1 << 2, // Set the variable if the object/window has no persistently saved data (no entry in .ini file) + ImGuiCond_Appearing = 1 << 3 // Set the variable if the object/window is appearing after being hidden/inactive (or the first time) // Obsolete names (will be removed) #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS @@ -928,7 +940,7 @@ enum ImGuiCond_ }; // You may modify the ImGui::GetStyle() main instance during initialization and before NewFrame(). -// During the frame, prefer using ImGui::PushStyleVar(ImGuiStyleVar_XXXX)/PopStyleVar() to alter the main style values, and ImGui::PushStyleColor(ImGuiCol_XXX)/PopStyleColor() for colors. +// During the frame, use ImGui::PushStyleVar(ImGuiStyleVar_XXXX)/PopStyleVar() to alter the main style values, and ImGui::PushStyleColor(ImGuiCol_XXX)/PopStyleColor() for colors. struct ImGuiStyle { float Alpha; // Global alpha applies to everything in ImGui. @@ -1118,7 +1130,7 @@ namespace ImGui // 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). +// Helper: 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). // *Important* Our implementation does NOT call C++ constructors/destructors. This is intentional, we do not require it but you have to be mindful of that. Do not use this class as a straight std::vector replacement in your code! template class ImVector @@ -1188,7 +1200,7 @@ inline void operator delete(void*, ImNewDummy, void*) {} // This is only requ #define IM_NEW(_TYPE) new(ImNewDummy(), ImGui::MemAlloc(sizeof(_TYPE))) _TYPE template void IM_DELETE(T*& p) { if (p) { p->~T(); ImGui::MemFree(p); p = NULL; } } -// Helper: execute a block of code at maximum once a frame. Convenient if you want to quickly create an UI within deep-nested code that runs multiple times every frame. +// Helper: Execute a block of code at maximum once a frame. Convenient if you want to quickly create an UI within deep-nested code that runs multiple times every frame. // Usage: static ImGuiOnceUponAFrame oaf; if (oaf) ImGui::Text("This will be called only once per frame"); struct ImGuiOnceUponAFrame { @@ -1197,7 +1209,7 @@ struct ImGuiOnceUponAFrame operator bool() const { int current_frame = ImGui::GetFrameCount(); if (RefFrame == current_frame) return false; RefFrame = current_frame; return true; } }; -// Helper macro for ImGuiOnceUponAFrame. Attention: The macro expands into 2 statement so make sure you don't use it within e.g. an if() statement without curly braces. +// Helper: Macro for ImGuiOnceUponAFrame. Attention: The macro expands into 2 statement so make sure you don't use it within e.g. an if() statement without curly braces. #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS // Will obsolete #define IMGUI_ONCE_UPON_A_FRAME static ImGuiOnceUponAFrame imgui_oaf; if (imgui_oaf) #endif @@ -1253,8 +1265,8 @@ struct ImGuiTextBuffer // Helper: Simple Key->value storage // Typically you don't have to worry about this since a storage is held within each Window. -// We use it to e.g. store collapse state for a tree (Int 0/1), store color edit options. -// This is optimized for efficient reading (dichotomy into a contiguous buffer), rare writing (typically tied to user interactions) +// We use it to e.g. store collapse state for a tree (Int 0/1) +// This is optimized for efficient lookup (dichotomy into a contiguous buffer) and rare insertion (typically tied to user interactions aka max once a frame) // You can use it as custom user storage for temporary values. Declare your own storage if, for example: // - You want to manipulate the open/close state of a particular sub-tree in your interface (tree node uses Int 0/1 to store their state). // - You want to store custom debug data easily without adding or editing structures in your code (probably not efficient, but convenient) @@ -1379,7 +1391,7 @@ struct ImGuiPayload #define IM_COL32_BLACK IM_COL32(0,0,0,255) // Opaque black #define IM_COL32_BLACK_TRANS IM_COL32(0,0,0,0) // Transparent black = 0x00000000 -// ImColor() helper to implicity converts colors to either ImU32 (packed 4x1 byte) or ImVec4 (4x1 float) +// Helper: ImColor() implicity converts colors to either ImU32 (packed 4x1 byte) or ImVec4 (4x1 float) // Prefer using IM_COL32() macros if you want a guaranteed compile-time ImU32 for usage with ImDrawList API. // **Avoid storing ImColor! Store either u32 of ImVec4. This is not a full-featured color class. MAY OBSOLETE. // **None of the ImGui API are using ImColor directly but you can use it as a convenience to pass colors in either ImU32 or ImVec4 formats. Explicitly cast to ImU32 or ImVec4 if needed. @@ -1513,9 +1525,9 @@ struct ImDrawList ImVector CmdBuffer; // Draw commands. Typically 1 command = 1 GPU draw call, unless the command is a callback. ImVector IdxBuffer; // Index buffer. Each command consume ImDrawCmd::ElemCount of those ImVector VtxBuffer; // Vertex buffer. + ImDrawListFlags Flags; // Flags, you may poke into these to adjust anti-aliasing settings per-primitive. // [Internal, used while building lists] - ImDrawListFlags Flags; // Flags, you may poke into these to adjust anti-aliasing settings per-primitive. const ImDrawListSharedData* _Data; // Pointer to shared draw data (you can use ImGui::GetDrawListSharedData() to get the one from current ImGui context) const char* _OwnerName; // Pointer to owner window's name for debugging unsigned int _VtxCurrentIdx; // [Internal] == VtxBuffer.Size From 33ad8b2f0c6d8fe3fe156bf6cbea17079e9bfa48 Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 19 Mar 2018 12:13:22 +0100 Subject: [PATCH 777/823] Nav: Track nav input source more generally (gamepad vs keyboard) (#787) + update todos and demo tweaks --- TODO.txt | 7 +++---- imgui.cpp | 28 ++++++++++++++++------------ imgui.h | 2 +- imgui_demo.cpp | 19 ++++++++++--------- imgui_internal.h | 6 +++--- 5 files changed, 33 insertions(+), 29 deletions(-) diff --git a/TODO.txt b/TODO.txt index 9276e67e8636..5876b9279dc5 100644 --- a/TODO.txt +++ b/TODO.txt @@ -237,12 +237,11 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i - font: fix AddRemapChar() to work before font has been built. - font: (api breaking) removed "TTF" from symbol names. also because it now supports OTF. - - nav: integrate navigation branch into master. (#787) - nav: allow input system to be be more tolerant of io.DeltaTime=0.0f - - nav: Left within a tree node block as a fallback. - - nav: Esc on a flattened child + - nav: ESC on a flattened child + - nav: Left within a tree node block as a fallback (ImGuiTreeNodeFlags_NavLeftJumpsBackHere by default?) + - nav: menus: pressing left-right on a vertically clipped menu bar tends to jump to the collapse/close buttons. - nav: menus: allow pressing Menu to leave a sub-menu. - - nav: integrate/design keyboard controls. - nav: simulate right-click or context activation? (SHIFT+F10) - nav: tabs should go through most/all widgets (in submission order?). - nav: when CTRL-Tab/windowing is active, the HoveredWindow detection doesn't take account of the window display re-ordering. diff --git a/imgui.cpp b/imgui.cpp index a0bd747835bb..cc2d56a7c76d 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2811,12 +2811,12 @@ static void ImGui::NavUpdateWindowing() g.NavWindowingTarget = window->RootWindowForTabbing; g.NavWindowingHighlightTimer = g.NavWindowingHighlightAlpha = 0.0f; g.NavWindowingToggleLayer = start_windowing_with_keyboard ? false : true; - g.NavWindowingInputSource = start_windowing_with_keyboard ? ImGuiInputSource_NavKeyboard : ImGuiInputSource_NavGamepad; + g.NavInputSource = start_windowing_with_keyboard ? ImGuiInputSource_NavKeyboard : ImGuiInputSource_NavGamepad; } // Gamepad update g.NavWindowingHighlightTimer += g.IO.DeltaTime; - if (g.NavWindowingTarget && g.NavWindowingInputSource == ImGuiInputSource_NavGamepad) + if (g.NavWindowingTarget && g.NavInputSource == ImGuiInputSource_NavGamepad) { // Highlight only appears after a brief time holding the button, so that a fast tap on PadMenu (to toggle NavLayer) doesn't add visual noise g.NavWindowingHighlightAlpha = ImMax(g.NavWindowingHighlightAlpha, ImSaturate((g.NavWindowingHighlightTimer - 0.20f) / 0.05f)); @@ -2842,7 +2842,7 @@ static void ImGui::NavUpdateWindowing() } // Keyboard: Focus - if (g.NavWindowingTarget && g.NavWindowingInputSource == ImGuiInputSource_NavKeyboard) + if (g.NavWindowingTarget && g.NavInputSource == ImGuiInputSource_NavKeyboard) { // Visuals only appears after a brief time after pressing TAB the first time, so that a fast CTRL+TAB doesn't add visual noise g.NavWindowingHighlightAlpha = ImMax(g.NavWindowingHighlightAlpha, ImSaturate((g.NavWindowingHighlightTimer - 0.15f) / 0.04f)); // 1.0f @@ -2862,9 +2862,9 @@ static void ImGui::NavUpdateWindowing() if (g.NavWindowingTarget && !(g.NavWindowingTarget->Flags & ImGuiWindowFlags_NoMove)) { ImVec2 move_delta; - if (g.NavWindowingInputSource == ImGuiInputSource_NavKeyboard && !g.IO.KeyShift) + if (g.NavInputSource == ImGuiInputSource_NavKeyboard && !g.IO.KeyShift) move_delta = GetNavInputAmount2d(ImGuiNavDirSourceFlags_Keyboard, ImGuiInputReadMode_Down); - if (g.NavWindowingInputSource == ImGuiInputSource_NavGamepad) + if (g.NavInputSource == ImGuiInputSource_NavGamepad) move_delta = GetNavInputAmount2d(ImGuiNavDirSourceFlags_PadLStick, ImGuiInputReadMode_Down); if (move_delta.x != 0.0f || move_delta.y != 0.0f) { @@ -2957,11 +2957,14 @@ static void ImGui::NavUpdate() if (g.NavScoringCount > 0) printf("[%05d] NavScoringCount %d for '%s' layer %d (Init:%d, Move:%d)\n", g.FrameCount, g.NavScoringCount, g.NavWindow ? g.NavWindow->Name : "NULL", g.NavLayer, g.NavInitRequest || g.NavInitResultId != 0, g.NavMoveRequest); #endif + if (g.IO.ConfigFlags & ImGuiConfigFlags_NavEnableGamepad) + if (g.IO.NavInputs[ImGuiNavInput_Activate] > 0.0f || g.IO.NavInputs[ImGuiNavInput_Input] > 0.0f || g.IO.NavInputs[ImGuiNavInput_Cancel] > 0.0f || g.IO.NavInputs[ImGuiNavInput_Menu] > 0.0f) + g.NavInputSource = ImGuiInputSource_NavGamepad; + // Update Keyboard->Nav inputs mapping - memset(g.IO.NavInputs + ImGuiNavInput_InternalStart_, 0, (ImGuiNavInput_COUNT - ImGuiNavInput_InternalStart_) * sizeof(g.IO.NavInputs[0])); if (g.IO.ConfigFlags & ImGuiConfigFlags_NavEnableKeyboard) { - #define NAV_MAP_KEY(_KEY, _NAV_INPUT) if (g.IO.KeyMap[_KEY] != -1 && IsKeyDown(g.IO.KeyMap[_KEY])) g.IO.NavInputs[_NAV_INPUT] = 1.0f; + #define NAV_MAP_KEY(_KEY, _NAV_INPUT) if (IsKeyDown(g.IO.KeyMap[_KEY])) { g.IO.NavInputs[_NAV_INPUT] = 1.0f; g.NavInputSource = ImGuiInputSource_NavKeyboard; } NAV_MAP_KEY(ImGuiKey_Space, ImGuiNavInput_Activate ); NAV_MAP_KEY(ImGuiKey_Enter, ImGuiNavInput_Input ); NAV_MAP_KEY(ImGuiKey_Escape, ImGuiNavInput_Cancel ); @@ -2972,7 +2975,7 @@ static void ImGui::NavUpdate() if (g.IO.KeyCtrl) g.IO.NavInputs[ImGuiNavInput_TweakSlow] = 1.0f; if (g.IO.KeyShift) g.IO.NavInputs[ImGuiNavInput_TweakFast] = 1.0f; if (g.IO.KeyAlt) g.IO.NavInputs[ImGuiNavInput_KeyMenu_] = 1.0f; -#undef NAV_MAP_KEY + #undef NAV_MAP_KEY } memcpy(g.IO.NavInputsDownDurationPrev, g.IO.NavInputsDownDuration, sizeof(g.IO.NavInputsDownDuration)); @@ -5513,13 +5516,13 @@ static void ImGui::UpdateManualResize(ImGuiWindow* window, const ImVec2& size_au } PopID(); - // Navigation/gamepad resize + // Navigation resize (keyboard/gamepad) if (g.NavWindowingTarget == window) { ImVec2 nav_resize_delta; - if (g.NavWindowingInputSource == ImGuiInputSource_NavKeyboard && g.IO.KeyShift) + if (g.NavInputSource == ImGuiInputSource_NavKeyboard && g.IO.KeyShift) nav_resize_delta = GetNavInputAmount2d(ImGuiNavDirSourceFlags_Keyboard, ImGuiInputReadMode_Down); - if (g.NavWindowingInputSource == ImGuiInputSource_NavGamepad) + if (g.NavInputSource == ImGuiInputSource_NavGamepad) nav_resize_delta = GetNavInputAmount2d(ImGuiNavDirSourceFlags_PadDPad, ImGuiInputReadMode_Down); if (nav_resize_delta.x != 0.0f || nav_resize_delta.y != 0.0f) { @@ -13246,7 +13249,7 @@ void ImGui::ShowMetricsWindow(bool* p_open) } if (ImGui::TreeNode("Internal state")) { - const char* input_source_names[] = { "None", "Mouse", "Nav", "NavGamepad", "NavKeyboard" }; IM_ASSERT(IM_ARRAYSIZE(input_source_names) == ImGuiInputSource_COUNT); + const char* input_source_names[] = { "None", "Mouse", "Nav", "NavKeyboard", "NavGamepad" }; IM_ASSERT(IM_ARRAYSIZE(input_source_names) == ImGuiInputSource_COUNT); ImGui::Text("HoveredWindow: '%s'", g.HoveredWindow ? g.HoveredWindow->Name : "NULL"); ImGui::Text("HoveredRootWindow: '%s'", g.HoveredRootWindow ? g.HoveredRootWindow->Name : "NULL"); ImGui::Text("HoveredId: 0x%08X/0x%08X (%.2f sec)", g.HoveredId, g.HoveredIdPreviousFrame, g.HoveredIdTimer); // Data is "in-flight" so depending on when the Metrics window is called we may see current frame information or not @@ -13254,6 +13257,7 @@ void ImGui::ShowMetricsWindow(bool* p_open) ImGui::Text("ActiveIdWindow: '%s'", g.ActiveIdWindow ? g.ActiveIdWindow->Name : "NULL"); ImGui::Text("NavWindow: '%s'", g.NavWindow ? g.NavWindow->Name : "NULL"); ImGui::Text("NavId: 0x%08X, NavLayer: %d", g.NavId, g.NavLayer); + ImGui::Text("NavInputSource: %s", input_source_names[g.NavInputSource]); ImGui::Text("NavActive: %d, NavVisible: %d", g.IO.NavActive, g.IO.NavVisible); ImGui::Text("NavActivateId: 0x%08X, NavInputId: 0x%08X", g.NavActivateId, g.NavInputId); ImGui::Text("NavDisableHighlight: %d, NavDisableMouseHover: %d", g.NavDisableHighlight, g.NavDisableMouseHover); diff --git a/imgui.h b/imgui.h index 90eef826b728..c70e8b2af980 100644 --- a/imgui.h +++ b/imgui.h @@ -1048,7 +1048,7 @@ struct ImGuiIO bool KeySuper; // Keyboard modifier pressed: Cmd/Super/Windows bool KeysDown[512]; // Keyboard keys that are pressed (ideally left in the "native" order your engine has access to keyboard keys, so you can use your own defines/enums for keys). ImWchar InputCharacters[16+1]; // List of characters input (translated by user from keypress+keyboard state). Fill using AddInputCharacter() helper. - float NavInputs[ImGuiNavInput_COUNT]; // Gamepad inputs (keyboard keys will be auto-mapped and be written here by ImGui::NewFrame) + float NavInputs[ImGuiNavInput_COUNT]; // Gamepad inputs (keyboard keys will be auto-mapped and be written here by ImGui::NewFrame, all values will be cleared back to zero in ImGui::EndFrame) // Functions IMGUI_API void AddInputCharacter(ImWchar c); // Add new character into InputCharacters[] diff --git a/imgui_demo.cpp b/imgui_demo.cpp index b36205b14ac0..fb7cd1904636 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -570,8 +570,8 @@ void ImGui::ShowDemoWindow(bool* p_open) if (ImGui::TreeNode("Images")) { - ImGui::TextWrapped("Below we are displaying the font texture (which is the only texture we have access to in this demo). Use the 'ImTextureID' type as storage to pass pointers or identifier to your own texture data. Hover the texture for a zoomed view!"); ImGuiIO& io = ImGui::GetIO(); + ImGui::TextWrapped("Below we are displaying the font texture (which is the only texture we have access to in this demo). Use the 'ImTextureID' type as storage to pass pointers or identifier to your own texture data. Hover the texture for a zoomed view!"); // Here we are grabbing the font texture because that's the only one we have access to inside the demo code. // Remember that ImTextureID is just storage for whatever you want it to be, it is essentially a value that will be passed to the render function inside the ImDrawCmd structure. @@ -590,14 +590,15 @@ void ImGui::ShowDemoWindow(bool* p_open) if (ImGui::IsItemHovered()) { ImGui::BeginTooltip(); - float focus_sz = 32.0f; - float focus_x = io.MousePos.x - pos.x - focus_sz * 0.5f; if (focus_x < 0.0f) focus_x = 0.0f; else if (focus_x > my_tex_w - focus_sz) focus_x = my_tex_w - focus_sz; - float focus_y = io.MousePos.y - pos.y - focus_sz * 0.5f; if (focus_y < 0.0f) focus_y = 0.0f; else if (focus_y > my_tex_h - focus_sz) focus_y = my_tex_h - focus_sz; - ImGui::Text("Min: (%.2f, %.2f)", focus_x, focus_y); - ImGui::Text("Max: (%.2f, %.2f)", focus_x + focus_sz, focus_y + focus_sz); - ImVec2 uv0 = ImVec2((focus_x) / my_tex_w, (focus_y) / my_tex_h); - ImVec2 uv1 = ImVec2((focus_x + focus_sz) / my_tex_w, (focus_y + focus_sz) / my_tex_h); - ImGui::Image(my_tex_id, ImVec2(128,128), uv0, uv1, ImColor(255,255,255,255), ImColor(255,255,255,128)); + float region_sz = 32.0f; + float region_x = io.MousePos.x - pos.x - region_sz * 0.5f; if (region_x < 0.0f) region_x = 0.0f; else if (region_x > my_tex_w - region_sz) region_x = my_tex_w - region_sz; + float region_y = io.MousePos.y - pos.y - region_sz * 0.5f; if (region_y < 0.0f) region_y = 0.0f; else if (region_y > my_tex_h - region_sz) region_y = my_tex_h - region_sz; + float zoom = 4.0f; + ImGui::Text("Min: (%.2f, %.2f)", region_x, region_y); + ImGui::Text("Max: (%.2f, %.2f)", region_x + region_sz, region_y + region_sz); + ImVec2 uv0 = ImVec2((region_x) / my_tex_w, (region_y) / my_tex_h); + ImVec2 uv1 = ImVec2((region_x + region_sz) / my_tex_w, (region_y + region_sz) / my_tex_h); + ImGui::Image(my_tex_id, ImVec2(region_sz * zoom, region_sz * zoom), uv0, uv1, ImColor(255,255,255,255), ImColor(255,255,255,128)); ImGui::EndTooltip(); } ImGui::TextWrapped("And now some textured buttons.."); diff --git a/imgui_internal.h b/imgui_internal.h index b6e2355740e5..1f169ccb236f 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -607,15 +607,15 @@ struct ImGuiContext ImGuiID NavActivatePressedId; // ~~ IsNavInputPressed(ImGuiNavInput_Activate) ? NavId : 0 ImGuiID NavInputId; // ~~ IsNavInputPressed(ImGuiNavInput_Input) ? NavId : 0 ImGuiID NavJustTabbedId; // Just tabbed to this id. - ImGuiID NavNextActivateId; // Set by ActivateItem(), queued until next frame ImGuiID NavJustMovedToId; // Just navigated to this id (result of a successfully MoveRequest) + ImGuiID NavNextActivateId; // Set by ActivateItem(), queued until next frame + ImGuiInputSource NavInputSource; // Keyboard or Gamepad mode? ImRect NavScoringRectScreen; // Rectangle used for scoring, in screen space. Based of window->DC.NavRefRectRel[], modified for directional navigation scoring. int NavScoringCount; // Metrics for debugging ImGuiWindow* NavWindowingTarget; // When selecting a window (holding Menu+FocusPrev/Next, or equivalent of CTRL-TAB) this window is temporarily displayed front-most. float NavWindowingHighlightTimer; float NavWindowingHighlightAlpha; bool NavWindowingToggleLayer; - ImGuiInputSource NavWindowingInputSource; // Gamepad or keyboard mode int NavLayer; // Layer we are navigating on. For now the system is hard-coded for 0=main contents and 1=menu/title bar, may expose layers later. int NavIdTabCounter; // == NavWindow->DC.FocusIdxTabCounter at time of NavId processing bool NavIdIsAlive; // Nav widget has been seen this frame ~~ NavRefRectRel is valid @@ -729,12 +729,12 @@ struct ImGuiContext NavWindow = NULL; NavId = NavActivateId = NavActivateDownId = NavActivatePressedId = NavInputId = 0; NavJustTabbedId = NavJustMovedToId = NavNextActivateId = 0; + NavInputSource = ImGuiInputSource_None; NavScoringRectScreen = ImRect(); NavScoringCount = 0; NavWindowingTarget = NULL; NavWindowingHighlightTimer = NavWindowingHighlightAlpha = 0.0f; NavWindowingToggleLayer = false; - NavWindowingInputSource = ImGuiInputSource_None; NavLayer = 0; NavIdTabCounter = INT_MAX; NavIdIsAlive = false; From 62e94717eb0acd20e4ff7835dac22c8ea2a88722 Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 19 Mar 2018 13:20:25 +0100 Subject: [PATCH 778/823] Nav: InputText: Allow editing text input fields with NavActivate (space). Not sure about that, on one hand it feels more consistent but you can't finish the editing with space to double space (activate + input space) could feel inconsistent. (#787) --- imgui.cpp | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index cc2d56a7c76d..ce8c2b8b3ec5 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -9887,11 +9887,12 @@ bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2 const bool user_clicked = hovered && io.MouseClicked[0]; const bool user_scrolled = is_multiline && g.ActiveId == 0 && edit_state.Id == id && g.ActiveIdPreviousFrame == draw_window->GetIDNoKeepAlive("#SCROLLY"); + const bool user_nav_input_start = (g.ActiveId != id) && ((g.NavInputId == id) || (g.NavActivateId == id && g.NavInputSource == ImGuiInputSource_NavKeyboard)); bool clear_active_id = false; - bool select_all = (g.ActiveId != id) && (((flags & ImGuiInputTextFlags_AutoSelectAll) != 0) || (g.NavInputId == id)) && (!is_multiline); - if (focus_requested || user_clicked || user_scrolled || g.NavInputId == id) + bool select_all = (g.ActiveId != id) && ((flags & ImGuiInputTextFlags_AutoSelectAll) != 0 || user_nav_input_start) && (!is_multiline); + if (focus_requested || user_clicked || user_scrolled || user_nav_input_start) { if (g.ActiveId != id) { @@ -9999,18 +10000,15 @@ bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2 if (io.InputCharacters[0]) { // Process text input (before we check for Return because using some IME will effectively send a Return?) - // We ignore CTRL inputs, but need to allow CTRL+ALT as some keyboards (e.g. German) use AltGR - which is Alt+Ctrl - to input certain characters. - if (!(io.KeyCtrl && !io.KeyAlt) && is_editable) - { + // We ignore CTRL inputs, but need to allow ALT+CTRL as some keyboards (e.g. German) use AltGR (which _is_ Alt+Ctrl) to input certain characters. + if (!(io.KeyCtrl && !io.KeyAlt) && is_editable && !user_nav_input_start) for (int n = 0; n < IM_ARRAYSIZE(io.InputCharacters) && io.InputCharacters[n]; n++) - if (unsigned int c = (unsigned int)io.InputCharacters[n]) - { - // Insert character if they pass filtering - if (!InputTextFilterCharacter(&c, flags, callback, user_data)) - continue; + { + // Insert character if they pass filtering + unsigned int c = (unsigned int)io.InputCharacters[n]; + if (InputTextFilterCharacter(&c, flags, callback, user_data)) edit_state.OnKeyPressed((int)c); - } - } + } // Consume characters memset(g.IO.InputCharacters, 0, sizeof(g.IO.InputCharacters)); From 166411287faa6ff219de5314bb69d99473982cfa Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 19 Mar 2018 14:44:37 +0100 Subject: [PATCH 779/823] Demo: Added more complete Combo demo. (#1658) --- TODO.txt | 1 + imgui_demo.cpp | 109 ++++++++++++++++++++++++++++++++----------------- 2 files changed, 72 insertions(+), 38 deletions(-) diff --git a/TODO.txt b/TODO.txt index 5876b9279dc5..0c54dad3e9b9 100644 --- a/TODO.txt +++ b/TODO.txt @@ -237,6 +237,7 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i - font: fix AddRemapChar() to work before font has been built. - font: (api breaking) removed "TTF" from symbol names. also because it now supports OTF. + - nav: SetItemDefaultFocus() level of priority, so widget like Selectable when inside a popup could claim a low-priority default focus on the first selected iem - nav: allow input system to be be more tolerant of io.DeltaTime=0.0f - nav: ESC on a flattened child - nav: Left within a tree node block as a fallback (ImGuiTreeNodeFlags_NavLeftJumpsBackHere by default?) diff --git a/imgui_demo.cpp b/imgui_demo.cpp index fb7cd1904636..31319ef250da 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -321,37 +321,16 @@ void ImGui::ShowDemoWindow(bool* p_open) ImGui::EndTooltip(); } - // Testing ImGuiOnceUponAFrame helper. - //static ImGuiOnceUponAFrame once; - //for (int i = 0; i < 5; i++) - // if (once) - // ImGui::Text("This will be displayed only once."); - ImGui::Separator(); ImGui::LabelText("label", "Value"); { - // Simplified one-liner Combo() API, using values packed in a single constant string - static int current_item_1 = 1; - ImGui::Combo("combo", ¤t_item_1, "aaaa\0bbbb\0cccc\0dddd\0eeee\0\0"); - //ImGui::Combo("combo w/ array of char*", ¤t_item_2_idx, items, IM_ARRAYSIZE(items)); // Combo using proper array. You can also pass a callback to retrieve array value, no need to create/copy an array just for that. - - // General BeginCombo() API, you have full control over your selection data and display type - const char* items[] = { "AAAA", "BBBB", "CCCC", "DDDD", "EEEE", "FFFF", "GGGG", "HHHH", "IIII", "JJJJ", "KKKK", "LLLLLLL", "MMMM", "OOOOOOO", "PPPP", "QQQQQQQQQQ", "RRR", "SSSS" }; - static const char* current_item_2 = NULL; - if (ImGui::BeginCombo("combo 2", current_item_2)) // The second parameter is the label previewed before opening the combo. - { - for (int n = 0; n < IM_ARRAYSIZE(items); n++) - { - bool is_selected = (current_item_2 == items[n]); // You can store your selection however you want, outside or inside your objects - if (ImGui::Selectable(items[n], is_selected)) - current_item_2 = items[n]; - if (is_selected) - ImGui::SetItemDefaultFocus(); // Set the initial focus when opening the combo (scrolling + for keyboard navigation support in the upcoming navigation branch) - } - ImGui::EndCombo(); - } + // Using the _simplified_ one-liner Combo() api here + const char* items[] = { "AAAA", "BBBB", "CCCC", "DDDD", "EEEE", "FFFF", "GGGG", "HHHH", "IIII", "JJJJ", "KKKK", "LLLLLLL", "MMMM", "OOOOOOO" }; + static int item_current = 0; + ImGui::Combo("combo", &item_current, items, IM_ARRAYSIZE(items)); + ImGui::SameLine(); ShowHelpMarker("Refer to the \"Combo\" section below for an explanation of the full BeginCombo/EndCombo API, and demonstration of various flags.\n"); } { @@ -394,25 +373,36 @@ void ImGui::ShowDemoWindow(bool* p_open) ImGui::SliderAngle("slider angle", &angle); } - static float col1[3] = { 1.0f,0.0f,0.2f }; - static float col2[4] = { 0.4f,0.7f,0.0f,0.5f }; - ImGui::ColorEdit3("color 1", col1); - ImGui::SameLine(); ShowHelpMarker("Click on the colored square to open a color picker.\nRight-click on the colored square to show options.\nCTRL+click on individual component to input value.\n"); + { + static float col1[3] = { 1.0f,0.0f,0.2f }; + static float col2[4] = { 0.4f,0.7f,0.0f,0.5f }; + ImGui::ColorEdit3("color 1", col1); + ImGui::SameLine(); ShowHelpMarker("Click on the colored square to open a color picker.\nRight-click on the colored square to show options.\nCTRL+click on individual component to input value.\n"); - ImGui::ColorEdit4("color 2", col2); + ImGui::ColorEdit4("color 2", col2); + } - const char* listbox_items[] = { "Apple", "Banana", "Cherry", "Kiwi", "Mango", "Orange", "Pineapple", "Strawberry", "Watermelon" }; - static int listbox_item_current = 1; - ImGui::ListBox("listbox\n(single select)", &listbox_item_current, listbox_items, IM_ARRAYSIZE(listbox_items), 4); + { + // List box + const char* listbox_items[] = { "Apple", "Banana", "Cherry", "Kiwi", "Mango", "Orange", "Pineapple", "Strawberry", "Watermelon" }; + static int listbox_item_current = 1; + ImGui::ListBox("listbox\n(single select)", &listbox_item_current, listbox_items, IM_ARRAYSIZE(listbox_items), 4); - //static int listbox_item_current2 = 2; - //ImGui::PushItemWidth(-1); - //ImGui::ListBox("##listbox2", &listbox_item_current2, listbox_items, IM_ARRAYSIZE(listbox_items), 4); - //ImGui::PopItemWidth(); + //static int listbox_item_current2 = 2; + //ImGui::PushItemWidth(-1); + //ImGui::ListBox("##listbox2", &listbox_item_current2, listbox_items, IM_ARRAYSIZE(listbox_items), 4); + //ImGui::PopItemWidth(); + } ImGui::TreePop(); } + // Testing ImGuiOnceUponAFrame helper. + //static ImGuiOnceUponAFrame once; + //for (int i = 0; i < 5; i++) + // if (once) + // ImGui::Text("This will be displayed only once."); + if (ImGui::TreeNode("Trees")) { if (ImGui::TreeNode("Basic trees")) @@ -617,6 +607,49 @@ void ImGui::ShowDemoWindow(bool* p_open) ImGui::TreePop(); } + if (ImGui::TreeNode("Combo")) + { + // Expose flags as checkbox for the demo + static ImGuiComboFlags flags = 0; + ImGui::CheckboxFlags("ImGuiComboFlags_PopupAlignLeft", (unsigned int*)&flags, ImGuiComboFlags_PopupAlignLeft); + if (ImGui::CheckboxFlags("ImGuiComboFlags_NoArrowButton", (unsigned int*)&flags, ImGuiComboFlags_NoArrowButton)) + flags &= ~ImGuiComboFlags_NoPreview; // Clear the other flag, as we cannot combine both + if (ImGui::CheckboxFlags("ImGuiComboFlags_NoPreview", (unsigned int*)&flags, ImGuiComboFlags_NoPreview)) + flags &= ~ImGuiComboFlags_NoArrowButton; // Clear the other flag, as we cannot combine both + + // General BeginCombo() API, you have full control over your selection data and display type. + // (your selection data could be an index, a pointer to the object, an id for the object, a flag stored in the object itself, etc.) + const char* items[] = { "AAAA", "BBBB", "CCCC", "DDDD", "EEEE", "FFFF", "GGGG", "HHHH", "IIII", "JJJJ", "KKKK", "LLLLLLL", "MMMM", "OOOOOOO" }; + static const char* item_current = items[0]; // Here our selection is a single pointer stored outside the object. + if (ImGui::BeginCombo("combo 1", item_current, flags)) // The second parameter is the label previewed before opening the combo. + { + for (int n = 0; n < IM_ARRAYSIZE(items); n++) + { + bool is_selected = (item_current == items[n]); + if (ImGui::Selectable(items[n], is_selected)) + item_current = items[n]; + if (is_selected) + ImGui::SetItemDefaultFocus(); // Set the initial focus when opening the combo (scrolling + for keyboard navigation support in the upcoming navigation branch) + } + ImGui::EndCombo(); + } + + // Simplified one-liner Combo() API, using values packed in a single constant string + static int item_current_2 = 0; + ImGui::Combo("combo 2 (one-liner)", &item_current_2, "aaaa\0bbbb\0cccc\0dddd\0eeee\0\0"); + + // Simplified one-liner Combo() using an array of const char* + static int item_current_3 = -1; // If the selection isn't within 0..count, Combo won't display a preview + ImGui::Combo("combo 3 (array)", &item_current_3, items, IM_ARRAYSIZE(items)); + + // Simplified one-liner Combo() using an accessor function + struct FuncHolder { static bool ItemGetter(void* data, int idx, const char** out_str) { *out_str = ((const char**)data)[idx]; return true; } }; + static int item_current_4 = 0; + ImGui::Combo("combo 4 (function)", &item_current_4, &FuncHolder::ItemGetter, items, IM_ARRAYSIZE(items)); + + ImGui::TreePop(); + } + if (ImGui::TreeNode("Selectables")) { // Selectable() has 2 overloads: From a73f6d06e036b914de5020041357812d18477517 Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 19 Mar 2018 16:47:28 +0100 Subject: [PATCH 780/823] Examples: Vulkan: Using VK_PRESENT_MODE_MAILBOX_KHR. Disable IMGUI_UNLIMITED_FRAME_RATE by default. Fixed warnings. (#1042) --- examples/vulkan_example/main.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/examples/vulkan_example/main.cpp b/examples/vulkan_example/main.cpp index a197515f1472..2732a218ab9b 100644 --- a/examples/vulkan_example/main.cpp +++ b/examples/vulkan_example/main.cpp @@ -11,7 +11,7 @@ #include #define IMGUI_MAX_POSSIBLE_BACK_BUFFERS 16 -#define IMGUI_UNLIMITED_FRAME_RATE +//#define IMGUI_UNLIMITED_FRAME_RATE #ifdef _DEBUG #define IMGUI_VULKAN_DEBUG_REPORT #endif @@ -195,6 +195,7 @@ static void resize_vulkan(int w, int h) static VKAPI_ATTR VkBool32 VKAPI_CALL debug_report( VkDebugReportFlagsEXT flags, VkDebugReportObjectTypeEXT objectType, uint64_t object, size_t location, int32_t messageCode, const char* pLayerPrefix, const char* pMessage, void* pUserData) { + (void)flags; (void)object; (void)pUserData; (void)pLayerPrefix; (void)messageCode; (void)location; printf("[vulkan] ObjectType: %i\nMessage: %s\n\n", objectType, pMessage ); return VK_FALSE; } @@ -359,7 +360,7 @@ static void setup_vulkan(GLFWwindow* window) { // Request a certain mode and confirm that it is available. If not use VK_PRESENT_MODE_FIFO_KHR which is mandatory #ifdef IMGUI_UNLIMITED_FRAME_RATE - g_PresentMode = VK_PRESENT_MODE_IMMEDIATE_KHR; + g_PresentMode = VK_PRESENT_MODE_MAILBOX_KHR; //VK_PRESENT_MODE_IMMEDIATE_KHR; #else g_PresentMode = VK_PRESENT_MODE_FIFO_KHR; #endif @@ -376,7 +377,7 @@ static void setup_vulkan(GLFWwindow* window) break; } } - if( !presentModeAvailable ) + if (!presentModeAvailable) g_PresentMode = VK_PRESENT_MODE_FIFO_KHR; // always available } From 4485e56e02ee46469e2521937358b435377fde63 Mon Sep 17 00:00:00 2001 From: Christian Forfang Date: Mon, 19 Mar 2018 15:01:00 +0100 Subject: [PATCH 781/823] Examples: Vulkan: Fix missing subpass dependency Without a dependency between pWaitDstStageMask (COLOR_ATTACHMENT_OUTPUT) and the render-pass, the UNDEFINED -> COLOR_ATTACHMENT_OPTIMAL transition might happen before the image is ready to be used. --- examples/vulkan_example/main.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/examples/vulkan_example/main.cpp b/examples/vulkan_example/main.cpp index 2732a218ab9b..40d0a233201a 100644 --- a/examples/vulkan_example/main.cpp +++ b/examples/vulkan_example/main.cpp @@ -142,12 +142,21 @@ static void resize_vulkan(int w, int h) subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; subpass.colorAttachmentCount = 1; subpass.pColorAttachments = &color_attachment; + VkSubpassDependency dependency = {}; + dependency.srcSubpass = VK_SUBPASS_EXTERNAL; + dependency.dstSubpass = 0; + dependency.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; + dependency.dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; + dependency.srcAccessMask = 0; + dependency.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; VkRenderPassCreateInfo info = {}; info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO; info.attachmentCount = 1; info.pAttachments = &attachment; info.subpassCount = 1; info.pSubpasses = &subpass; + info.dependencyCount = 1; + info.pDependencies = &dependency; err = vkCreateRenderPass(g_Device, &info, g_Allocator, &g_RenderPass); check_vk_result(err); } From d1c45db9e8cb972843fb028929d4a412313e0c14 Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 19 Mar 2018 22:47:10 +0100 Subject: [PATCH 782/823] Fixed enum typo. --- imgui.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/imgui.cpp b/imgui.cpp index ce8c2b8b3ec5..91f5346da491 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -12066,7 +12066,7 @@ void ImGui::Separator() return; ImGuiContext& g = *GImGui; - ImGuiWindowFlags flags = 0; + ImGuiSeparatorFlags flags = 0; if ((flags & (ImGuiSeparatorFlags_Horizontal | ImGuiSeparatorFlags_Vertical)) == 0) flags |= (window->DC.LayoutType == ImGuiLayoutType_Horizontal) ? ImGuiSeparatorFlags_Vertical : ImGuiSeparatorFlags_Horizontal; IM_ASSERT(ImIsPowerOfTwo((int)(flags & (ImGuiSeparatorFlags_Horizontal | ImGuiSeparatorFlags_Vertical)))); // Check that only 1 option is selected From 70d500502a024186bcc09fc05eca2b546f1344f0 Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 20 Mar 2018 11:35:10 +0100 Subject: [PATCH 783/823] ImVector: Fixed insert() helper using the = operator (followup to be consistent with 4186c2c2b110a1f156171926b41f4564ea9580ab) --- imgui.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/imgui.h b/imgui.h index c70e8b2af980..4563eb2c0847 100644 --- a/imgui.h +++ b/imgui.h @@ -1186,7 +1186,7 @@ class ImVector inline void pop_back() { IM_ASSERT(Size > 0); Size--; } inline void push_front(const value_type& v) { if (Size == 0) push_back(v); else insert(Data, v); } inline iterator erase(const_iterator it) { IM_ASSERT(it >= Data && it < Data+Size); const ptrdiff_t off = it - Data; memmove(Data + off, Data + off + 1, ((size_t)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 >= Data && it <= Data+Size); const ptrdiff_t off = it - Data; if (Size == Capacity) reserve(_grow_capacity(Size + 1)); if (off < (int)Size) memmove(Data + off + 1, Data + off, ((size_t)Size - (size_t)off) * sizeof(value_type)); Data[off] = v; Size++; return Data + off; } + inline iterator insert(const_iterator it, const value_type& v) { IM_ASSERT(it >= Data && it <= Data+Size); const ptrdiff_t off = it - Data; if (Size == Capacity) reserve(_grow_capacity(Size + 1)); if (off < (int)Size) memmove(Data + off + 1, Data + off, ((size_t)Size - (size_t)off) * sizeof(value_type)); memcpy(&Data[off], &v, sizeof(v)); Size++; return Data + off; } inline bool contains(const value_type& v) const { const T* data = Data; const T* data_end = Data + Size; while (data < data_end) if (*data++ == v) return true; return false; } }; From 74b7dce3945d63ff05dbc48c4d77f3111afd71b8 Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 20 Mar 2018 15:57:54 +0100 Subject: [PATCH 784/823] Examples: Renamed applications to emphasis on use of GLFW as a platform framework + minor local tweaks --- examples/opengl2_example/main.cpp | 2 +- examples/opengl3_example/main.cpp | 2 +- examples/sdl_opengl2_example/main.cpp | 6 +++--- examples/sdl_opengl3_example/main.cpp | 6 +++--- examples/vulkan_example/main.cpp | 2 +- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/examples/opengl2_example/main.cpp b/examples/opengl2_example/main.cpp index 6728347ccfae..8ee95cadc33e 100644 --- a/examples/opengl2_example/main.cpp +++ b/examples/opengl2_example/main.cpp @@ -22,7 +22,7 @@ int main(int, char**) glfwSetErrorCallback(glfw_error_callback); if (!glfwInit()) return 1; - GLFWwindow* window = glfwCreateWindow(1280, 720, "ImGui OpenGL2 example", NULL, NULL); + GLFWwindow* window = glfwCreateWindow(1280, 720, "ImGui GLFW+OpenGL2 example", NULL, NULL); glfwMakeContextCurrent(window); glfwSwapInterval(1); // Enable vsync diff --git a/examples/opengl3_example/main.cpp b/examples/opengl3_example/main.cpp index ce2f1156dd76..06a9231a69ea 100644 --- a/examples/opengl3_example/main.cpp +++ b/examples/opengl3_example/main.cpp @@ -26,7 +26,7 @@ int main(int, char**) #if __APPLE__ glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); #endif - GLFWwindow* window = glfwCreateWindow(1280, 720, "ImGui OpenGL3 example", NULL, NULL); + GLFWwindow* window = glfwCreateWindow(1280, 720, "ImGui GLFW+OpenGL3 example", NULL, NULL); glfwMakeContextCurrent(window); glfwSwapInterval(1); // Enable vsync gl3wInit(); diff --git a/examples/sdl_opengl2_example/main.cpp b/examples/sdl_opengl2_example/main.cpp index 2dfdd72bc8ba..797650377f37 100644 --- a/examples/sdl_opengl2_example/main.cpp +++ b/examples/sdl_opengl2_example/main.cpp @@ -29,8 +29,8 @@ int main(int, char**) SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2); SDL_DisplayMode current; SDL_GetCurrentDisplayMode(0, ¤t); - SDL_Window *window = SDL_CreateWindow("ImGui SDL2+OpenGL example", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 1280, 720, SDL_WINDOW_OPENGL|SDL_WINDOW_RESIZABLE); - SDL_GLContext glcontext = SDL_GL_CreateContext(window); + SDL_Window* window = SDL_CreateWindow("ImGui SDL2+OpenGL example", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 1280, 720, SDL_WINDOW_OPENGL|SDL_WINDOW_RESIZABLE); + SDL_GLContext gl_context = SDL_GL_CreateContext(window); SDL_GL_SetSwapInterval(1); // Enable vsync // Setup ImGui binding @@ -130,7 +130,7 @@ int main(int, char**) ImGui_ImplSdlGL2_Shutdown(); ImGui::DestroyContext(); - SDL_GL_DeleteContext(glcontext); + SDL_GL_DeleteContext(gl_context); SDL_DestroyWindow(window); SDL_Quit(); diff --git a/examples/sdl_opengl3_example/main.cpp b/examples/sdl_opengl3_example/main.cpp index 4426fcdebf46..1cac6b16a309 100644 --- a/examples/sdl_opengl3_example/main.cpp +++ b/examples/sdl_opengl3_example/main.cpp @@ -28,8 +28,8 @@ int main(int, char**) SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2); SDL_DisplayMode current; SDL_GetCurrentDisplayMode(0, ¤t); - SDL_Window *window = SDL_CreateWindow("ImGui SDL2+OpenGL3 example", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 1280, 720, SDL_WINDOW_OPENGL|SDL_WINDOW_RESIZABLE); - SDL_GLContext glcontext = SDL_GL_CreateContext(window); + SDL_Window* window = SDL_CreateWindow("ImGui SDL2+OpenGL3 example", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 1280, 720, SDL_WINDOW_OPENGL|SDL_WINDOW_RESIZABLE); + SDL_GLContext gl_context = SDL_GL_CreateContext(window); SDL_GL_SetSwapInterval(1); // Enable vsync gl3wInit(); @@ -129,7 +129,7 @@ int main(int, char**) ImGui_ImplSdlGL3_Shutdown(); ImGui::DestroyContext(); - SDL_GL_DeleteContext(glcontext); + SDL_GL_DeleteContext(gl_context); SDL_DestroyWindow(window); SDL_Quit(); diff --git a/examples/vulkan_example/main.cpp b/examples/vulkan_example/main.cpp index 40d0a233201a..a708b6db9461 100644 --- a/examples/vulkan_example/main.cpp +++ b/examples/vulkan_example/main.cpp @@ -614,7 +614,7 @@ int main(int, char**) return 1; glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API); - GLFWwindow* window = glfwCreateWindow(1280, 720, "ImGui Vulkan example", NULL, NULL); + GLFWwindow* window = glfwCreateWindow(1280, 720, "ImGui GLFW+Vulkan example", NULL, NULL); // Setup Vulkan if (!glfwVulkanSupported()) From fe5347ef94d7dc648c237323cc9e257aff6ab917 Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 20 Mar 2018 18:25:37 +0100 Subject: [PATCH 785/823] imconfig: Added IMGUI_STB_TRUETYPE_FILENAME, IMGUI_STB_RECT_PACK_FILENAME + documenting IMGUI_DISABLE_STB_XXX flags and hiding IMGUI_STB_NAMESPACE which is misleading. Fixed typos in todo list. --- CHANGELOG.txt | 8 +++++--- imconfig.h | 8 ++++++-- imgui_draw.cpp | 19 +++++++++++++++---- 3 files changed, 26 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.txt b/CHANGELOG.txt index 999a40666e2d..51e669c2c258 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -67,6 +67,7 @@ Breaking Changes: Other Changes: (IN PROGRESS, WILL ADD TO THIS LIST AS WE WORK ON 1.60) +- Doc: Added a Changelog file in the repository to ease comparing versions (it goes back to dear imgui 1.48), until now it was only on GitHub. - Navigation: merged in the gamepad/keyboard navigation (about one million changes!). (#787, #323) The initial focus was to support game controllers, but keyboard is becoming increasingly and decently usable. - To use Keyboard Navigation: @@ -138,12 +139,13 @@ Other Changes: - ImDrawList: Fixed AddRect() with antialiasing disabled (lower-right corner pixel was often missing, rounding looks a little better.) (#1646) - ImDrawList: Added CloneOutput() helper to facilitate the cloning of ImDrawData or ImDrawList for multi-threaded rendering. - Misc: Functions passed to libc qsort are explicitely marked cdecl to support compiling with vectorcall as the default calling convention. (#1230, #1611) [@RandyGaul] -- Misc: ImVec2: added [] operator. This is becoming desirable for some types of code, better added sooner than later. -- Misc: Exposed IM_OFFSETOF() helper in imgui.h. +- Misc: ImVec2: added [] operator. This is becoming desirable for some code working of either axes independently. Better adding it sooner than later. - Misc: NewFrame(): Added an assert to detect incorrect filling of the io.KeyMap[] array earlier. (#1555) +- Misc: Added IM_OFFSETOF() helper in imgui.h (previously was in imgui_internal.h) - Misc: Added obsolete redirection function GetItemsLineHeightWithSpacing() (which redirects to GetFrameHeightWithSpacing()), as intended and stated in docs of 1.53. -- Misc: Added misc/natvis/imgui.natvis for visual studio debugger users to easily visualizer imgui internal types. Added to examples projects. +- Misc: Added misc/natvis/imgui.natvis for visual studio debugger users to easily visualize imgui internal types. Added to examples projects. - Misc: Added IMGUI_USER_CONFIG to define a custom configuration filename. (#255, #1573, #1144, #41) +- Misc: Added IMGUI_STB_TRUETYPE_FILENAME and IMGUI_STB_RECT_PACK_FILENAME compile time directives to use another version of the stb_ files. - Misc: Updated stb_rect_pack from 0.10 to 0.11 (minor changes). - Misc: Added ImGuiConfigFlags_IsSRGB and ImGuiConfigFlags_IsTouchScreen user flags (for io.ConfigFlags). (Those flags are not used by ImGui itself, they only exists to make it easy for the engine/back-end to pass information to the application in a standard manner.) diff --git a/imconfig.h b/imconfig.h index 75e7e44ef353..4ba731341d84 100644 --- a/imconfig.h +++ b/imconfig.h @@ -37,8 +37,12 @@ //---- Pack colors to BGRA8 instead of RGBA8 (if you needed to convert from one to another anyway) //#define IMGUI_USE_BGRA_PACKED_COLOR -//---- Implement STB libraries in a namespace to avoid linkage conflicts (defaults to global namespace) -//#define IMGUI_STB_NAMESPACE ImGuiStb +//---- Avoid multiple STB libraries implementations, or redefine path/filenames to prioritize another version +// By default the embedded implementations are declared static and not available outside of imgui cpp files. +//#define IMGUI_STB_TRUETYPE_FILENAME "my_folder/stb_truetype.h" +//#define IMGUI_STB_RECT_PACK_FILENAME "my_folder/stb_rect_pack.h" +//#define IMGUI_DISABLE_STB_TRUETYPE_IMPLEMENTATION +//#define IMGUI_DISABLE_STB_RECT_PACK_IMPLEMENTATION //---- Define constructor and implicit cast operators to convert back<>forth from your math types and ImVec2/ImVec4. // This will be inlined as part of ImVec2 and ImVec4 class declarations. diff --git a/imgui_draw.cpp b/imgui_draw.cpp index a6bda8a501a7..a2d0215f411f 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -61,9 +61,12 @@ // STB libraries implementation //------------------------------------------------------------------------- -//#define IMGUI_STB_NAMESPACE ImGuiStb -//#define IMGUI_DISABLE_STB_RECT_PACK_IMPLEMENTATION +// Compile time options: +//#define IMGUI_STB_NAMESPACE ImGuiStb +//#define IMGUI_STB_TRUETYPE_FILENAME "my_folder/stb_truetype.h" +//#define IMGUI_STB_RECT_PACK_FILENAME "my_folder/stb_rect_pack.h" //#define IMGUI_DISABLE_STB_TRUETYPE_IMPLEMENTATION +//#define IMGUI_DISABLE_STB_RECT_PACK_IMPLEMENTATION #ifdef IMGUI_STB_NAMESPACE namespace IMGUI_STB_NAMESPACE @@ -87,23 +90,31 @@ namespace IMGUI_STB_NAMESPACE #pragma GCC diagnostic ignored "-Wtype-limits" // warning: comparison is always true due to limited range of data type [-Wtype-limits] #endif -#define STBRP_ASSERT(x) IM_ASSERT(x) #ifndef IMGUI_DISABLE_STB_RECT_PACK_IMPLEMENTATION #define STBRP_STATIC +#define STBRP_ASSERT(x) IM_ASSERT(x) #define STB_RECT_PACK_IMPLEMENTATION #endif +#ifdef IMGUI_STB_RECT_PACK_FILENAME +#include IMGUI_STB_RECT_PACK_FILENAME +#else #include "stb_rect_pack.h" +#endif +#ifndef IMGUI_DISABLE_STB_TRUETYPE_IMPLEMENTATION #define STBTT_malloc(x,u) ((void)(u), ImGui::MemAlloc(x)) #define STBTT_free(x,u) ((void)(u), ImGui::MemFree(x)) #define STBTT_assert(x) IM_ASSERT(x) -#ifndef IMGUI_DISABLE_STB_TRUETYPE_IMPLEMENTATION #define STBTT_STATIC #define STB_TRUETYPE_IMPLEMENTATION #else #define STBTT_DEF extern #endif +#ifdef IMGUI_STB_TRUETYPE_FILENAME +#include IMGUI_STB_TRUETYPE_FILENAME +#else #include "stb_truetype.h" +#endif #ifdef __GNUC__ #pragma GCC diagnostic pop From 170f44e6f085f98e06d1e41c561a9271af4761fc Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 20 Mar 2018 20:12:34 +0100 Subject: [PATCH 786/823] IO: Renamed io.WantMoveMouse to io.WantSetMousePos (was added in 1.52, _not_ used by core and only honored by some binding ahead of merging the Nav branch) + internal renaming (#787) --- CHANGELOG.txt | 1 + .../directx10_example/imgui_impl_dx10.cpp | 6 ++--- .../directx11_example/imgui_impl_dx11.cpp | 6 ++--- .../directx12_example/imgui_impl_dx12.cpp | 4 +-- examples/directx9_example/imgui_impl_dx9.cpp | 5 ++-- .../opengl2_example/imgui_impl_glfw_gl2.cpp | 7 ++--- .../opengl3_example/imgui_impl_glfw_gl3.cpp | 7 ++--- imgui.cpp | 27 ++++++++++--------- imgui.h | 4 +-- imgui_demo.cpp | 6 ++--- imgui_internal.h | 2 +- 11 files changed, 40 insertions(+), 35 deletions(-) diff --git a/CHANGELOG.txt b/CHANGELOG.txt index 51e669c2c258..4f11c40c4b09 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -60,6 +60,7 @@ Breaking Changes: - Renamed ImGuiStyleVar_Count_ to ImGuiStyleVar_COUNT and ImGuiMouseCursor_Count_ to ImGuiMouseCursor_COUNT for consistency with other public enums. - Obsoleted IsAnyWindowHovered() in favor of IsWindowHovered(ImGuiHoveredFlags_AnyWindow). Kept redirection function (will obsolete). - Obsoleted IsAnyWindowFocused() in favor of IsWindowFocused(ImGuiFocusedFlags_AnyWindow). Kept redirection function (will obsolete). + - Renamed io.WantMoveMouse to io.WantSetMousePos for consistency and ease of understanding (was added in 1.52, _not_ used by core, and honored by some binding ahead of merging the Nav branch). - Removed ImGuiCol_CloseButton, ImGuiCol_CloseButtonActive, ImGuiCol_CloseButtonHovered style colors as the closing cross uses regular button colors now. - Renamed ImGuiSizeConstraintCallback to ImGuiSizeCallback, ImGuiSizeConstraintCallbackData to ImGuiSizeCallbackData. - Removed CalcItemRectClosestPoint() which was weird and not really used by anyone except demo code. If you need it it's easy to replicate on your side. diff --git a/examples/directx10_example/imgui_impl_dx10.cpp b/examples/directx10_example/imgui_impl_dx10.cpp index cbf791be9cbe..241f46983a70 100644 --- a/examples/directx10_example/imgui_impl_dx10.cpp +++ b/examples/directx10_example/imgui_impl_dx10.cpp @@ -14,7 +14,7 @@ // 2018-02-16: Misc: Obsoleted the io.RenderDrawListsFn callback and exposed ImGui_ImplDX10_RenderDrawData() in the .h file so you can call it yourself. // 2018-02-06: Misc: Removed call to ImGui::Shutdown() which is not available from 1.60 WIP, user needs to call CreateContext/DestroyContext themselves. // 2018-02-06: Inputs: Added mapping for ImGuiKey_Space. -// 2018-02-06: Inputs: Honoring the io.WantMoveMouse by repositioning the mouse (when using navigation and ImGuiConfigFlags_NavMoveMouse is set). +// 2018-02-06: Inputs: Honoring the io.WantSetMousePos by repositioning the mouse (when using navigation and ImGuiConfigFlags_NavEnableSetMousePos is set). // 2018-01-20: Inputs: Added Horizontal Mouse Wheel support. // 2018-01-08: Inputs: Added mapping for ImGuiKey_Insert. // 2018-01-05: Inputs: Added WM_LBUTTONDBLCLK double-click handlers for window classes with the CS_DBLCLKS flag. @@ -647,8 +647,8 @@ void ImGui_ImplDX10_NewFrame() // io.MouseDown : filled by WM_*BUTTON* events // io.MouseWheel : filled by WM_MOUSEWHEEL events - // Set OS mouse position if requested last frame by io.WantMoveMouse flag (used when io.NavMovesTrue is enabled by user and using directional navigation) - if (io.WantMoveMouse) + // Set OS mouse position if requested (only used when ImGuiConfigFlags_NavEnableSetMousePos is enabled by user) + if (io.WantSetMousePos) { POINT pos = { (int)io.MousePos.x, (int)io.MousePos.y }; ClientToScreen(g_hWnd, &pos); diff --git a/examples/directx11_example/imgui_impl_dx11.cpp b/examples/directx11_example/imgui_impl_dx11.cpp index b100cf96f0d1..f9596af3113e 100644 --- a/examples/directx11_example/imgui_impl_dx11.cpp +++ b/examples/directx11_example/imgui_impl_dx11.cpp @@ -14,7 +14,7 @@ // 2018-02-16: Misc: Obsoleted the io.RenderDrawListsFn callback and exposed ImGui_ImplDX11_RenderDrawData() in the .h file so you can call it yourself. // 2018-02-06: Misc: Removed call to ImGui::Shutdown() which is not available from 1.60 WIP, user needs to call CreateContext/DestroyContext themselves. // 2018-02-06: Inputs: Added mapping for ImGuiKey_Space. -// 2018-02-06: Inputs: Honoring the io.WantMoveMouse by repositioning the mouse (when using navigation and ImGuiConfigFlags_NavMoveMouse is set). +// 2018-02-06: Inputs: Honoring the io.WantSetMousePos by repositioning the mouse (when using navigation and ImGuiConfigFlags_NavEnableSetMousePos is set). // 2018-01-20: Inputs: Added Horizontal Mouse Wheel support. // 2018-01-08: Inputs: Added mapping for ImGuiKey_Insert. // 2018-01-05: Inputs: Added WM_LBUTTONDBLCLK double-click handlers for window classes with the CS_DBLCLKS flag. @@ -650,8 +650,8 @@ void ImGui_ImplDX11_NewFrame() // io.MouseDown : filled by WM_*BUTTON* events // io.MouseWheel : filled by WM_MOUSEWHEEL events - // Set OS mouse position if requested last frame by io.WantMoveMouse flag (used when io.NavMovesTrue is enabled by user and using directional navigation) - if (io.WantMoveMouse) + // Set OS mouse position if requested (only used when ImGuiConfigFlags_NavEnableSetMousePos is enabled by user) + if (io.WantSetMousePos) { POINT pos = { (int)io.MousePos.x, (int)io.MousePos.y }; ClientToScreen(g_hWnd, &pos); diff --git a/examples/directx12_example/imgui_impl_dx12.cpp b/examples/directx12_example/imgui_impl_dx12.cpp index 6c74dadf8532..86184e22814a 100644 --- a/examples/directx12_example/imgui_impl_dx12.cpp +++ b/examples/directx12_example/imgui_impl_dx12.cpp @@ -790,8 +790,8 @@ void ImGui_ImplDX12_NewFrame(ID3D12GraphicsCommandList* command_list) // io.MouseDown : filled by WM_*BUTTON* events // io.MouseWheel : filled by WM_MOUSEWHEEL events - // Set OS mouse position if requested last frame by io.WantMoveMouse flag (used when io.NavMovesTrue is enabled by user and using directional navigation) - if (io.WantMoveMouse) + // Set OS mouse position if requested (only used when ImGuiConfigFlags_NavEnableSetMousePos is enabled by user) + if (io.WantSetMousePos) { POINT pos = { (int)io.MousePos.x, (int)io.MousePos.y }; ClientToScreen(g_hWnd, &pos); diff --git a/examples/directx9_example/imgui_impl_dx9.cpp b/examples/directx9_example/imgui_impl_dx9.cpp index 157c27d51f17..464fc39147da 100644 --- a/examples/directx9_example/imgui_impl_dx9.cpp +++ b/examples/directx9_example/imgui_impl_dx9.cpp @@ -13,6 +13,7 @@ // 2018-02-20: Inputs: Added support for mouse cursors (ImGui::GetMouseCursor() value and WM_SETCURSOR message handling). // 2018-02-16: Misc: Obsoleted the io.RenderDrawListsFn callback and exposed ImGui_ImplDX9_RenderDrawData() in the .h file so you can call it yourself. // 2018-02-06: Misc: Removed call to ImGui::Shutdown() which is not available from 1.60 WIP, user needs to call CreateContext/DestroyContext themselves. +// 2018-02-06: Inputs: Honoring the io.WantSetMousePos by repositioning the mouse (when using navigation and ImGuiConfigFlags_NavEnableSetMousePos is set). // 2018-02-06: Inputs: Added mapping for ImGuiKey_Space. #include "imgui.h" @@ -417,8 +418,8 @@ void ImGui_ImplDX9_NewFrame() // io.MouseDown : filled by WM_*BUTTON* events // io.MouseWheel : filled by WM_MOUSEWHEEL events - // Set OS mouse position if requested last frame by io.WantMoveMouse flag (used when io.NavMovesTrue is enabled by user and using directional navigation) - if (io.WantMoveMouse) + // Set OS mouse position if requested (only used when ImGuiConfigFlags_NavEnableSetMousePos is enabled by user) + if (io.WantSetMousePos) { POINT pos = { (int)io.MousePos.x, (int)io.MousePos.y }; ClientToScreen(g_hWnd, &pos); diff --git a/examples/opengl2_example/imgui_impl_glfw_gl2.cpp b/examples/opengl2_example/imgui_impl_glfw_gl2.cpp index 89d2509f3ad1..0b4ba6843e99 100644 --- a/examples/opengl2_example/imgui_impl_glfw_gl2.cpp +++ b/examples/opengl2_example/imgui_impl_glfw_gl2.cpp @@ -24,7 +24,7 @@ // 2018-02-16: Misc: Obsoleted the io.RenderDrawListsFn callback and exposed ImGui_ImplGlfwGL2_RenderDrawData() in the .h file so you can call it yourself. // 2018-02-06: Misc: Removed call to ImGui::Shutdown() which is not available from 1.60 WIP, user needs to call CreateContext/DestroyContext themselves. // 2018-02-06: Inputs: Added mapping for ImGuiKey_Space. -// 2018-02-06: Inputs: Honoring the io.WantMoveMouse by repositioning the mouse (when using navigation and ImGuiConfigFlags_NavMoveMouse is set). +// 2018-02-06: Inputs: Honoring the io.WantSetMousePos flag by repositioning the mouse (ImGuiConfigFlags_NavEnableSetMousePos is set). // 2018-01-20: Inputs: Added Horizontal Mouse Wheel support. // 2018-01-18: Inputs: Added mapping for ImGuiKey_Insert. // 2018-01-09: Misc: Renamed imgui_impl_glfw.* to imgui_impl_glfw_gl2.*. @@ -314,9 +314,10 @@ void ImGui_ImplGlfwGL2_NewFrame() // (we already got mouse wheel, keyboard keys & characters from glfw callbacks polled in glfwPollEvents()) if (glfwGetWindowAttrib(g_Window, GLFW_FOCUSED)) { - if (io.WantMoveMouse) + // Set OS mouse position if requested (only used when ImGuiConfigFlags_NavEnableSetMousePos is enabled by user) + if (io.WantSetMousePos) { - glfwSetCursorPos(g_Window, (double)io.MousePos.x, (double)io.MousePos.y); // Set mouse position if requested by io.WantMoveMouse flag (used when io.NavMovesTrue is enabled by user and using directional navigation) + glfwSetCursorPos(g_Window, (double)io.MousePos.x, (double)io.MousePos.y); } else { diff --git a/examples/opengl3_example/imgui_impl_glfw_gl3.cpp b/examples/opengl3_example/imgui_impl_glfw_gl3.cpp index 8a8b8ed96072..cbec000f7954 100644 --- a/examples/opengl3_example/imgui_impl_glfw_gl3.cpp +++ b/examples/opengl3_example/imgui_impl_glfw_gl3.cpp @@ -21,7 +21,7 @@ // 2018-02-06: Misc: Removed call to ImGui::Shutdown() which is not available from 1.60 WIP, user needs to call CreateContext/DestroyContext themselves. // 2018-02-06: Inputs: Added mapping for ImGuiKey_Space. // 2018-01-25: Inputs: Added gamepad support if ImGuiConfigFlags_NavEnableGamepad is set. -// 2018-01-25: Inputs: Honoring the io.WantMoveMouse by repositioning the mouse (when using navigation and ImGuiConfigFlags_NavMoveMouse is set). +// 2018-01-25: Inputs: Honoring the io.WantSetMousePos flag by repositioning the mouse (ImGuiConfigFlags_NavEnableSetMousePos is set). // 2018-01-20: Inputs: Added Horizontal Mouse Wheel support. // 2018-01-18: Inputs: Added mapping for ImGuiKey_Insert. // 2018-01-07: OpenGL: Changed GLSL shader version from 330 to 150. (Also changed GL context from 3.3 to 3.2 in example's main.cpp) @@ -447,9 +447,10 @@ void ImGui_ImplGlfwGL3_NewFrame() // (we already got mouse wheel, keyboard keys & characters from glfw callbacks polled in glfwPollEvents()) if (glfwGetWindowAttrib(g_Window, GLFW_FOCUSED)) { - if (io.WantMoveMouse) + // Set OS mouse position if requested (only used when ImGuiConfigFlags_NavEnableSetMousePos is enabled by user) + if (io.WantSetMousePos) { - glfwSetCursorPos(g_Window, (double)io.MousePos.x, (double)io.MousePos.y); // Set mouse position if requested by io.WantMoveMouse flag (used when io.NavMovesTrue is enabled by user and using directional navigation) + glfwSetCursorPos(g_Window, (double)io.MousePos.x, (double)io.MousePos.y); } else { diff --git a/imgui.cpp b/imgui.cpp index 91f5346da491..740a1f00725e 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -235,11 +235,11 @@ - Mouse: - PS4 users: Consider emulating a mouse cursor with DualShock4 touch pad or a spare analog stick as a mouse-emulation fallback. - Consoles/Tablet/Phone users: Consider using a Synergy 1.x server (on your PC) + uSynergy.c (on your console/tablet/phone app) to share your PC mouse/keyboard. - - On a TV/console system where readability may be lower or mouse inputs may be awkward, you may want to set the ImGuiConfigFlags_NavMoveMouse flag. - Enabling ImGuiConfigFlags_NavMoveMouse instructs dear imgui to move your mouse cursor along with navigation movements. - When enabled, the NewFrame() function may alter 'io.MousePos' and set 'io.WantMoveMouse' to notify you that it wants the mouse cursor to be moved. + - On a TV/console system where readability may be lower or mouse inputs may be awkward, you may want to set the ImGuiConfigFlags_NavEnableSetMousePos flag. + Enabling ImGuiConfigFlags_NavEnableSetMousePos instructs dear imgui to move your mouse cursor along with navigation movements. + When enabled, the NewFrame() function may alter 'io.MousePos' and set 'io.WantSetMousePos' to notify you that it wants the mouse cursor to be moved. When that happens your back-end NEEDS to move the OS or underlying mouse cursor on the next frame. Some of the binding in examples/ do that. - (If you set the NavMoveMouse flag but don't honor 'io.WantMoveMouse' properly, imgui will misbehave as it will see your mouse as moving back and forth!) + (If you set the NavEnableSetMousePos flag but don't honor 'io.WantSetMousePos' properly, imgui will misbehave as it will see your mouse as moving back and forth!) (In a setup when you may not have easy control over the mouse cursor, e.g. uSynergy.c doesn't expose moving remote mouse cursor, you may want to set a boolean to ignore your other external mouse positions until the external source is moved again.) @@ -251,6 +251,7 @@ Here is a change-log of API breaking changes, if you are using one of the functions listed, expect to have to fix some code. Also read releases logs https://github.com/ocornut/imgui/releases for more details. + - 2018/03/20 (1.60) - Renamed io.WantMoveMouse to io.WantSetMousePos for consistency and ease of understanding (was added in 1.52, _not_ used by core and only honored by some binding ahead of merging the Nav branch). - 2018/03/12 (1.60) - Removed ImGuiCol_CloseButton, ImGuiCol_CloseButtonActive, ImGuiCol_CloseButtonHovered as the closing cross uses regular button colors now. - 2018/03/08 (1.60) - Changed ImFont::DisplayOffset.y to default to 0 instead of +1. Fixed rounding of Ascent/Descent to match TrueType renderer. If you were adding or subtracting to ImFont::DisplayOffset check if your fonts are correctly aligned vertically. - 2018/03/03 (1.60) - Renamed ImGuiStyleVar_Count_ to ImGuiStyleVar_COUNT and ImGuiMouseCursor_Count_ to ImGuiMouseCursor_COUNT for consistency with other public enums. @@ -2009,7 +2010,7 @@ static void SetNavID(ImGuiID id, int nav_layer) g.NavWindow->NavLastIds[nav_layer] = id; } -static void SetNavIDAndMoveMouse(ImGuiID id, int nav_layer, const ImRect& rect_rel) +static void SetNavIDWithRectRel(ImGuiID id, int nav_layer, const ImRect& rect_rel) { ImGuiContext& g = *GImGui; SetNavID(id, nav_layer); @@ -2309,7 +2310,7 @@ static void NavRestoreLayer(int layer) if (layer == 0) g.NavWindow = NavRestoreLastChildNavWindow(g.NavWindow); if (layer == 0 && g.NavWindow->NavLastIds[0] != 0) - SetNavIDAndMoveMouse(g.NavWindow->NavLastIds[0], layer, g.NavWindow->NavRectRel[0]); + SetNavIDWithRectRel(g.NavWindow->NavLastIds[0], layer, g.NavWindow->NavRectRel[0]); else ImGui::NavInitWindow(g.NavWindow, true); } @@ -2951,7 +2952,7 @@ static void NavScrollToBringItemIntoView(ImGuiWindow* window, ImRect& item_rect_ static void ImGui::NavUpdate() { ImGuiContext& g = *GImGui; - g.IO.WantMoveMouse = false; + g.IO.WantSetMousePos = false; #if 0 if (g.NavScoringCount > 0) printf("[%05d] NavScoringCount %d for '%s' layer %d (Init:%d, Move:%d)\n", g.FrameCount, g.NavScoringCount, g.NavWindow ? g.NavWindow->Name : "NULL", g.NavLayer, g.NavInitRequest || g.NavInitResultId != 0, g.NavMoveRequest); @@ -2988,7 +2989,7 @@ static void ImGui::NavUpdate() // Apply result from previous navigation init request (will typically select the first item, unless SetItemDefaultFocus() has been called) IM_ASSERT(g.NavWindow); if (g.NavInitRequestFromMove) - SetNavIDAndMoveMouse(g.NavInitResultId, g.NavLayer, g.NavInitResultRectRel); + SetNavIDWithRectRel(g.NavInitResultId, g.NavLayer, g.NavInitResultRectRel); else SetNavID(g.NavInitResultId, g.NavLayer); g.NavWindow->NavRectRel[g.NavLayer] = g.NavInitResultRectRel; @@ -3016,7 +3017,7 @@ static void ImGui::NavUpdate() // Apply result from previous frame navigation directional move request ClearActiveID(); g.NavWindow = result->Window; - SetNavIDAndMoveMouse(result->ID, g.NavLayer, result->RectRel); + SetNavIDWithRectRel(result->ID, g.NavLayer, result->RectRel); g.NavJustMovedToId = result->ID; g.NavMoveFromClampedRefRect = false; } @@ -3034,10 +3035,10 @@ static void ImGui::NavUpdate() if (g.NavMousePosDirty && g.NavIdIsAlive) { // Set mouse position given our knowledge of the nav widget position from last frame - if (g.IO.ConfigFlags & ImGuiConfigFlags_NavMoveMouse) + if (g.IO.ConfigFlags & ImGuiConfigFlags_NavEnableSetMousePos) { g.IO.MousePos = g.IO.MousePosPrev = NavCalcPreferredMousePos(); - g.IO.WantMoveMouse = true; + g.IO.WantSetMousePos = true; } g.NavMousePosDirty = false; } @@ -5836,7 +5837,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) float sc = g.Style.MouseCursorScale; ImVec2 ref_pos = (!g.NavDisableHighlight && g.NavDisableMouseHover) ? NavCalcPreferredMousePos() : g.IO.MousePos; ImRect rect_to_avoid; - if (!g.NavDisableHighlight && g.NavDisableMouseHover && !(g.IO.ConfigFlags & ImGuiConfigFlags_NavMoveMouse)) + if (!g.NavDisableHighlight && g.NavDisableMouseHover && !(g.IO.ConfigFlags & ImGuiConfigFlags_NavEnableSetMousePos)) rect_to_avoid = ImRect(ref_pos.x - 16, ref_pos.y - 8, ref_pos.x + 16, ref_pos.y + 8); else rect_to_avoid = ImRect(ref_pos.x - 16, ref_pos.y - 8, ref_pos.x + 24 * sc, ref_pos.y + 24 * sc); // FIXME: Hard-coded based on mouse cursor shape expectation. Exact dimension not very important. @@ -11112,7 +11113,7 @@ void ImGui::EndMenuBar() // This involve a one-frame delay which isn't very problematic in this situation. We could remove it by scoring in advance for multiple window (probably not worth the hassle/cost) IM_ASSERT(window->DC.NavLayerActiveMaskNext & 0x02); // Sanity check FocusWindow(window); - SetNavIDAndMoveMouse(window->NavLastIds[1], 1, window->NavRectRel[1]); + SetNavIDWithRectRel(window->NavLastIds[1], 1, window->NavRectRel[1]); g.NavLayer = 1; g.NavDisableHighlight = true; // Hide highlight for the current frame so we don't see the intermediary selection. g.NavMoveRequestForward = ImGuiNavForward_ForwardQueued; diff --git a/imgui.h b/imgui.h index 4563eb2c0847..4c16f170eb95 100644 --- a/imgui.h +++ b/imgui.h @@ -774,7 +774,7 @@ enum ImGuiConfigFlags_ { ImGuiConfigFlags_NavEnableKeyboard = 1 << 0, // Master keyboard navigation enable flag. NewFrame() will automatically fill io.NavInputs[] based on io.KeyDown[]. ImGuiConfigFlags_NavEnableGamepad = 1 << 1, // Master gamepad navigation enable flag. This is mostly to instruct your imgui back-end to fill io.NavInputs[]. - ImGuiConfigFlags_NavMoveMouse = 1 << 2, // Request navigation to allow moving the mouse cursor. May be useful on TV/console systems where moving a virtual mouse is awkward. Will update io.MousePos and set io.WantMoveMouse=true. If enabled you MUST honor io.WantMoveMouse requests in your binding, otherwise ImGui will react as if the mouse is jumping around back and forth. + ImGuiConfigFlags_NavEnableSetMousePos = 1 << 2, // Request navigation to allow moving the mouse cursor. May be useful on TV/console systems where moving a virtual mouse is awkward. Will update io.MousePos and set io.WantSetMousePos=true. If enabled you MUST honor io.WantSetMousePos requests in your binding, otherwise ImGui will react as if the mouse is jumping around back and forth. ImGuiConfigFlags_NavNoCaptureKeyboard = 1 << 3, // Do not set the io.WantCaptureKeyboard flag with io.NavActive is set. // User storage (to allow your back-end/engine to communicate to code that may be shared between multiple projects. Those flags are not used by core ImGui) @@ -1062,7 +1062,7 @@ struct ImGuiIO bool WantCaptureMouse; // When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application. This is set by ImGui when it wants to use your mouse (e.g. unclicked mouse is hovering a window, or a widget is active). bool WantCaptureKeyboard; // When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application. This is set by ImGui when it wants to use your keyboard inputs. bool WantTextInput; // Mobile/console: when io.WantTextInput is true, you may display an on-screen keyboard. This is set by ImGui when it wants textual keyboard input to happen (e.g. when a InputText widget is active). - bool WantMoveMouse; // MousePos has been altered, back-end should reposition mouse on next frame. Set only when ImGuiConfigFlags_NavMoveMouse flag is enabled. + bool WantSetMousePos; // MousePos has been altered, back-end should reposition mouse on next frame. Set only when ImGuiConfigFlags_NavEnableSetMousePos flag is enabled. bool NavActive; // Directional navigation is currently allowed (will handle ImGuiKey_NavXXX events) = a window is focused and it doesn't use the ImGuiWindowFlags_NoNavInputs flag. bool NavVisible; // Directional navigation is visible and allowed (will handle ImGuiKey_NavXXX events). float Framerate; // Application framerate estimation, in frame per second. Solely for convenience. Rolling average estimation based on IO.DeltaTime over 120 frames diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 31319ef250da..8ff62a9b54d2 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -1841,15 +1841,15 @@ void ImGui::ShowDemoWindow(bool* p_open) ImGui::Text("WantCaptureMouse: %d", io.WantCaptureMouse); ImGui::Text("WantCaptureKeyboard: %d", io.WantCaptureKeyboard); ImGui::Text("WantTextInput: %d", io.WantTextInput); - ImGui::Text("WantMoveMouse: %d", io.WantMoveMouse); + ImGui::Text("WantSetMousePos: %d", io.WantSetMousePos); ImGui::Text("NavActive: %d, NavVisible: %d", io.NavActive, io.NavVisible); ImGui::Checkbox("io.MouseDrawCursor", &io.MouseDrawCursor); ImGui::SameLine(); ShowHelpMarker("Request ImGui to render a mouse cursor for you in software. Note that a mouse cursor rendered via your application GPU rendering path will feel more laggy than hardware cursor, but will be more in sync with your other visuals.\n\nSome desktop applications may use both kinds of cursors (e.g. enable software cursor only when resizing/dragging something)."); ImGui::CheckboxFlags("io.ConfigFlags: NavEnableGamepad", (unsigned int *)&io.ConfigFlags, ImGuiConfigFlags_NavEnableGamepad); ImGui::CheckboxFlags("io.ConfigFlags: NavEnableKeyboard", (unsigned int *)&io.ConfigFlags, ImGuiConfigFlags_NavEnableKeyboard); - ImGui::CheckboxFlags("io.ConfigFlags: NavMoveMouse", (unsigned int *)&io.ConfigFlags, ImGuiConfigFlags_NavMoveMouse); - ImGui::SameLine(); ShowHelpMarker("Request ImGui to move your move cursor when using gamepad/keyboard navigation. NewFrame() will change io.MousePos and set the io.WantMoveMouse flag, your backend will need to apply the new mouse position."); + ImGui::CheckboxFlags("io.ConfigFlags: NavEnableSetMousePos", (unsigned int *)&io.ConfigFlags, ImGuiConfigFlags_NavEnableSetMousePos); + ImGui::SameLine(); ShowHelpMarker("Request ImGui to move your move cursor when using gamepad/keyboard navigation. NewFrame() will change io.MousePos and set the io.WantSetMousePos flag, your backend will need to apply the new mouse position."); if (ImGui::TreeNode("Keyboard, Mouse & Navigation State")) { diff --git a/imgui_internal.h b/imgui_internal.h index 1f169ccb236f..8114faae2e33 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -619,7 +619,7 @@ struct ImGuiContext int NavLayer; // Layer we are navigating on. For now the system is hard-coded for 0=main contents and 1=menu/title bar, may expose layers later. int NavIdTabCounter; // == NavWindow->DC.FocusIdxTabCounter at time of NavId processing bool NavIdIsAlive; // Nav widget has been seen this frame ~~ NavRefRectRel is valid - bool NavMousePosDirty; // When set we will update mouse position if (io.ConfigFlags & ImGuiConfigFlags_NavMoveMouse) if set (NB: this not enabled by default) + bool NavMousePosDirty; // When set we will update mouse position if (io.ConfigFlags & ImGuiConfigFlags_NavEnableSetMousePos) if set (NB: this not enabled by default) bool NavDisableHighlight; // When user starts using mouse, we hide gamepad/keyboard highlight (NB: but they are still available, which is why NavDisableHighlight isn't always != NavDisableMouseHover) bool NavDisableMouseHover; // When user starts using gamepad/keyboard, we hide mouse hovering highlight until mouse is touched again. bool NavAnyRequest; // ~~ NavMoveRequest || NavInitRequest From dcf7c3d188c83bf7689c0561ca1b6d6da8a04b6d Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 20 Mar 2018 20:39:44 +0100 Subject: [PATCH 787/823] Added ImGuiBackendFlags for backend to expose its capabilities. Added ImGuiBackendFlags_HasGamepad. (#787, #1542) --- CHANGELOG.txt | 3 ++- .../opengl3_example/imgui_impl_glfw_gl3.cpp | 4 +++ imgui.cpp | 12 ++++++--- imgui.h | 26 ++++++++++++------- 4 files changed, 31 insertions(+), 14 deletions(-) diff --git a/CHANGELOG.txt b/CHANGELOG.txt index 4f11c40c4b09..f63f6b34b466 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -76,7 +76,8 @@ Other Changes: - When keyboard navigation is active (io.NavActive + ImGuiConfigFlags_NavEnableKeyboard), the io.WantCaptureKeyboard flag will be set. For more advanced uses, you may want to read from io.NavActive or io.NavVisible. Read imgui.cpp for more details. - To use Gamepad Navigation: - - Set io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad to enable. Fill the io.NavInputs[] fields before calling NewFrame(). Note that io.NavInputs[] is cleared by EndFrame(). + - Set io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad to enable. + - Backend: Set io.BackendFlags |= ImGuiBackendFlags_HasGamepad + fill the io.NavInputs[] fields before calling NewFrame(). Note that io.NavInputs[] is cleared by EndFrame(). - See https://github.com/ocornut/imgui/issues/1599 for recommended gamepad mapping. - See 'enum ImGuiNavInput_' in imgui.h for a description of inputs. Read imgui.cpp for more details. - Navigation: SetItemDefaultFocus() sets the navigation position in addition to scrolling. (#787) diff --git a/examples/opengl3_example/imgui_impl_glfw_gl3.cpp b/examples/opengl3_example/imgui_impl_glfw_gl3.cpp index cbec000f7954..3fc32f9324e4 100644 --- a/examples/opengl3_example/imgui_impl_glfw_gl3.cpp +++ b/examples/opengl3_example/imgui_impl_glfw_gl3.cpp @@ -511,6 +511,10 @@ void ImGui_ImplGlfwGL3_NewFrame() MAP_ANALOG(ImGuiNavInput_LStickDown, 1, -0.3f, -0.9f); #undef MAP_BUTTON #undef MAP_ANALOG + if (axes_count > 0 && buttons_count > 0) + io.BackendFlags |= ImGuiBackendFlags_HasGamepad; + else + io.BackendFlags &= ~ImGuiBackendFlags_HasGamepad; } // Start the frame. This call will update the io.WantCaptureMouse, io.WantCaptureKeyboard flag that you can use to dispatch inputs (or not) to your application. diff --git a/imgui.cpp b/imgui.cpp index 740a1f00725e..462ac4c66457 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -224,7 +224,8 @@ - or query focus information with e.g. IsWindowFocused(), IsItemFocused() etc. functions. Please reach out if you think the game vs navigation input sharing could be improved. - Gamepad: - - Set io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad to enable. Fill the io.NavInputs[] fields before calling NewFrame(). Note that io.NavInputs[] is cleared by EndFrame(). + - Set io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad to enable. + - Backend: Set io.BackendFlags |= ImGuiBackendFlags_HasGamepad + fill the io.NavInputs[] fields before calling NewFrame(). Note that io.NavInputs[] is cleared by EndFrame(). - See 'enum ImGuiNavInput_' in imgui.h for a description of inputs. For each entry of io.NavInputs[], set the following values: 0.0f= not held. 1.0f= fully held. Pass intermediate 0.0f..1.0f values for analog triggers/sticks. - We uses a simple >0.0f test for activation testing, and won't attempt to test for a dead-zone. @@ -846,9 +847,10 @@ ImGuiIO::ImGuiIO() memset(this, 0, sizeof(*this)); // Settings + ConfigFlags = 0x00; + BackendFlags = 0x00; DisplaySize = ImVec2(-1.0f, -1.0f); DeltaTime = 1.0f/60.0f; - ConfigFlags = 0x00; IniSavingRate = 5.0f; IniFilename = "imgui.ini"; LogFilename = "imgui_log.txt"; @@ -2958,7 +2960,7 @@ static void ImGui::NavUpdate() if (g.NavScoringCount > 0) printf("[%05d] NavScoringCount %d for '%s' layer %d (Init:%d, Move:%d)\n", g.FrameCount, g.NavScoringCount, g.NavWindow ? g.NavWindow->Name : "NULL", g.NavLayer, g.NavInitRequest || g.NavInitResultId != 0, g.NavMoveRequest); #endif - if (g.IO.ConfigFlags & ImGuiConfigFlags_NavEnableGamepad) + if ((g.IO.ConfigFlags & ImGuiConfigFlags_NavEnableGamepad) && (g.IO.BackendFlags & ImGuiBackendFlags_HasGamepad)) if (g.IO.NavInputs[ImGuiNavInput_Activate] > 0.0f || g.IO.NavInputs[ImGuiNavInput_Input] > 0.0f || g.IO.NavInputs[ImGuiNavInput_Cancel] > 0.0f || g.IO.NavInputs[ImGuiNavInput_Menu] > 0.0f) g.NavInputSource = ImGuiInputSource_NavGamepad; @@ -3055,7 +3057,9 @@ static void ImGui::NavUpdate() NavUpdateWindowing(); // Set output flags for user application - g.IO.NavActive = (g.IO.ConfigFlags & (ImGuiConfigFlags_NavEnableGamepad | ImGuiConfigFlags_NavEnableKeyboard)) && g.NavWindow && !(g.NavWindow->Flags & ImGuiWindowFlags_NoNavInputs); + bool nav_keyboard_active = (g.IO.ConfigFlags & ImGuiConfigFlags_NavEnableKeyboard) != 0; + bool nav_gamepad_active = (g.IO.ConfigFlags & ImGuiConfigFlags_NavEnableGamepad) != 0 && (g.IO.BackendFlags & ImGuiBackendFlags_HasGamepad) != 0; + g.IO.NavActive = (nav_keyboard_active || nav_gamepad_active) && g.NavWindow && !(g.NavWindow->Flags & ImGuiWindowFlags_NoNavInputs); g.IO.NavVisible = (g.IO.NavActive && g.NavId != 0 && !g.NavDisableHighlight) || (g.NavWindowingTarget != NULL) || g.NavInitRequest; // Process NavCancel input (to close a popup, get back to parent, clear focus) diff --git a/imgui.h b/imgui.h index 4c16f170eb95..20077604d82b 100644 --- a/imgui.h +++ b/imgui.h @@ -91,6 +91,7 @@ typedef int ImGuiStyleVar; // enum: a variable identifier for styling typedef int ImDrawCornerFlags; // flags: for ImDrawList::AddRect*() etc. // enum ImDrawCornerFlags_ typedef int ImDrawListFlags; // flags: for ImDrawList // enum ImDrawListFlags_ typedef int ImFontAtlasFlags; // flags: for ImFontAtlas // enum ImFontAtlasFlags_ +typedef int ImGuiBackendFlags; // flags: for io.BackendFlags // enum ImGuiBackendFlags_ typedef int ImGuiColorEditFlags; // flags: for ColorEdit*(), ColorPicker*() // enum ImGuiColorEditFlags_ typedef int ImGuiColumnsFlags; // flags: for *Columns*() // enum ImGuiColumnsFlags_ typedef int ImGuiConfigFlags; // flags: for io.ConfigFlags // enum ImGuiConfigFlags_ @@ -736,7 +737,7 @@ enum ImGuiKey_ // [BETA] Gamepad/Keyboard directional navigation // Keyboard: Set io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard to enable. NewFrame() will automatically fill io.NavInputs[] based on your io.KeyDown[] + io.KeyMap[] arrays. -// Gamepad: Set io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad to enable. Fill the io.NavInputs[] fields before calling NewFrame(). Note that io.NavInputs[] is cleared by EndFrame(). +// Gamepad: Set io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad to enable. Back-end: set ImGuiBackendFlags_HasGamepad and fill the io.NavInputs[] fields before calling NewFrame(). Note that io.NavInputs[] is cleared by EndFrame(). // Read instructions in imgui.cpp for more details. Download PNG/PSD at goo.gl/9LgVZW. enum ImGuiNavInput_ { @@ -769,17 +770,23 @@ enum ImGuiNavInput_ ImGuiNavInput_InternalStart_ = ImGuiNavInput_KeyMenu_ }; -// Configuration flags stored in io.ConfigFlags +// Configuration flags stored in io.ConfigFlags. Set by user/application. enum ImGuiConfigFlags_ { - ImGuiConfigFlags_NavEnableKeyboard = 1 << 0, // Master keyboard navigation enable flag. NewFrame() will automatically fill io.NavInputs[] based on io.KeyDown[]. - ImGuiConfigFlags_NavEnableGamepad = 1 << 1, // Master gamepad navigation enable flag. This is mostly to instruct your imgui back-end to fill io.NavInputs[]. - ImGuiConfigFlags_NavEnableSetMousePos = 1 << 2, // Request navigation to allow moving the mouse cursor. May be useful on TV/console systems where moving a virtual mouse is awkward. Will update io.MousePos and set io.WantSetMousePos=true. If enabled you MUST honor io.WantSetMousePos requests in your binding, otherwise ImGui will react as if the mouse is jumping around back and forth. - ImGuiConfigFlags_NavNoCaptureKeyboard = 1 << 3, // Do not set the io.WantCaptureKeyboard flag with io.NavActive is set. + ImGuiConfigFlags_NavEnableKeyboard = 1 << 0, // Master keyboard navigation enable flag. NewFrame() will automatically fill io.NavInputs[] based on io.KeyDown[]. + ImGuiConfigFlags_NavEnableGamepad = 1 << 1, // Master gamepad navigation enable flag. This is mostly to instruct your imgui back-end to fill io.NavInputs[]. Back-end also needs to set ImGuiBackendFlags_HasGamepad. + ImGuiConfigFlags_NavEnableSetMousePos = 1 << 2, // Request navigation to allow moving the mouse cursor. May be useful on TV/console systems where moving a virtual mouse is awkward. Will update io.MousePos and set io.WantSetMousePos=true. If enabled you MUST honor io.WantSetMousePos requests in your binding, otherwise ImGui will react as if the mouse is jumping around back and forth. + ImGuiConfigFlags_NavNoCaptureKeyboard = 1 << 3, // Do not set the io.WantCaptureKeyboard flag with io.NavActive is set. // User storage (to allow your back-end/engine to communicate to code that may be shared between multiple projects. Those flags are not used by core ImGui) - ImGuiConfigFlags_IsSRGB = 1 << 20, // Back-end is SRGB-aware. - ImGuiConfigFlags_IsTouchScreen = 1 << 21 // Back-end is using a touch screen instead of a mouse. + ImGuiConfigFlags_IsSRGB = 1 << 20, // Application is SRGB-aware. + ImGuiConfigFlags_IsTouchScreen = 1 << 21 // Application is using a touch screen instead of a mouse. +}; + +// Back-end capabilities flags stored in io.BackendFlags. Set by imgui_impl_xxx or custom back-end. +enum ImGuiBackendFlags_ +{ + ImGuiBackendFlags_HasGamepad = 1 << 0 // Back-end has a connected gamepad }; // Enumeration for PushStyleColor() / PopStyleColor() @@ -986,9 +993,10 @@ struct ImGuiIO // Settings (fill once) // Default value: //------------------------------------------------------------------ + ImGuiConfigFlags ConfigFlags; // = 0 // See ImGuiConfigFlags_ enum. Set by user/application. Gamepad/keyboard navigation options, etc. + ImGuiBackendFlags BackendFlags; // = 0 // Set ImGuiBackendFlags_ enum. Set by imgui_impl_xxx files or custom back-end. ImVec2 DisplaySize; // // Display size, in pixels. For clamping windows positions. float DeltaTime; // = 1.0f/60.0f // Time elapsed since last frame, in seconds. - ImGuiConfigFlags ConfigFlags; // = 0 // See ImGuiConfigFlags_ enum. Gamepad/keyboard navigation options, etc. float IniSavingRate; // = 5.0f // Maximum time between saving positions/sizes to .ini file, in seconds. const char* IniFilename; // = "imgui.ini" // Path to .ini file. NULL to disable .ini saving. const char* LogFilename; // = "imgui_log.txt" // Path to .log file (default parameter to ImGui::LogToFile when no file is specified). From 75c3793db5316626de94cb77c4529093e987ba15 Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 20 Mar 2018 21:19:23 +0100 Subject: [PATCH 788/823] IO: Added ImGuiConfigFlags_NoSetMouseCursors. Added ImGuiBackendFlags_HasMouseCursors, ImGuiBackendFlags_HasSetMousePos. (#787, #1495, #1202) --- CHANGELOG.txt | 3 +++ .../directx10_example/imgui_impl_dx10.cpp | 19 ++++++++----- .../directx11_example/imgui_impl_dx11.cpp | 19 ++++++++----- .../directx12_example/imgui_impl_dx12.cpp | 19 ++++++++----- examples/directx9_example/imgui_impl_dx9.cpp | 19 ++++++++----- .../opengl2_example/imgui_impl_glfw_gl2.cpp | 27 ++++++++++++------- .../opengl3_example/imgui_impl_glfw_gl3.cpp | 26 +++++++++++------- .../imgui_impl_sdl_gl2.cpp | 25 ++++++++++------- .../imgui_impl_sdl_gl3.cpp | 25 ++++++++++------- .../vulkan_example/imgui_impl_glfw_vulkan.cpp | 26 +++++++++++------- imgui.cpp | 4 +-- imgui.h | 5 +++- imgui_demo.cpp | 1 + 13 files changed, 146 insertions(+), 72 deletions(-) diff --git a/CHANGELOG.txt b/CHANGELOG.txt index f63f6b34b466..d345c19d09d6 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -91,6 +91,8 @@ Other Changes: - Context: Removed allocator parameters from CreateContext(), they are now setup with SetAllocatorFunctions() and shared by all contexts. (#1565, #586, #992, #1007, #1558) - Context: You may pass a ImFontAtlas to CreateContext() to specify a font atlas to share. Shared font atlas are not owned by the context and not destroyed along with it. - Context: Added IMGUI_DISABLE_DEFAULT_ALLOCATORS to disable linking with malloc/free. (#1565, #586, #992, #1007, #1558) +- IO: Added io.ConfigFlags for user application to store settings for imgui and for the back-end (currently: _NavEnableKeyboard, _NavEnableGamepad, _NavEnableSetMousePos, _NoSetMouseCursor). +- IO: Added io.BackendFlags for back-end to store its capabilities (currently: _HasGamepad, _HasMouseCursors, _HasSetMousePos). This will be used more in the next version. - IO: Added ImGuiKey_Insert, ImGuiKey_Space keys. Setup in all example bindings. (#1541) - IO: Added Horizontal Mouse Wheel support for horizontal scrolling. (#1463) [@tseeker] - IO: Added IsAnyMouseDown() helper which is helpful for bindings to handle mouse capturing. @@ -159,6 +161,7 @@ Other Changes: - Examples: Files in examples/ now include their own changelog so it is easier to occasionally update your bindings if needed. - Examples: Using Dark theme by default. (#707). Tweaked demo code. - Examples: Added support for horizontal mouse wheel for API that allows it. (#1463) [@tseeker] +- Examples: All examples now setup the io.BackendFlags to signify they can honor mouse cursors, gamepad, etc. - Examples: DirectX12: Added DirectX 12 example. (#301) [@jdm3] - Examples: OpenGL3+GLFW,SDL: Changed GLSL shader version from 330 to 150. (#1466, #1504) - Examples: OpenGL3+GLFW,SDL: Added a way to override the GLSL version string in the Init function. (#1466, #1504). diff --git a/examples/directx10_example/imgui_impl_dx10.cpp b/examples/directx10_example/imgui_impl_dx10.cpp index 241f46983a70..cc2ebddba493 100644 --- a/examples/directx10_example/imgui_impl_dx10.cpp +++ b/examples/directx10_example/imgui_impl_dx10.cpp @@ -10,6 +10,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2018-03-20: Misc: Setup io.BackendFlags ImGuiBackendFlags_HasMouseCursors and ImGuiBackendFlags_HasSetMousePos flags + honor ImGuiConfigFlags_NoSetMouseCursor flag. // 2018-02-20: Inputs: Added support for mouse cursors (ImGui::GetMouseCursor() value and WM_SETCURSOR message handling). // 2018-02-16: Misc: Obsoleted the io.RenderDrawListsFn callback and exposed ImGui_ImplDX10_RenderDrawData() in the .h file so you can call it yourself. // 2018-02-06: Misc: Removed call to ImGui::Shutdown() which is not available from 1.60 WIP, user needs to call CreateContext/DestroyContext themselves. @@ -243,9 +244,12 @@ void ImGui_ImplDX10_RenderDrawData(ImDrawData* draw_data) ctx->IASetInputLayout(old.InputLayout); if (old.InputLayout) old.InputLayout->Release(); } -static void ImGui_ImplWin32_UpdateMouseCursor() +static bool ImGui_ImplWin32_UpdateMouseCursor() { ImGuiIO& io = ImGui::GetIO(); + if (io.ConfigFlags & ImGuiConfigFlags_NoSetMouseCursor) + return false; + ImGuiMouseCursor imgui_cursor = io.MouseDrawCursor ? ImGuiMouseCursor_None : ImGui::GetMouseCursor(); if (imgui_cursor == ImGuiMouseCursor_None) { @@ -268,6 +272,7 @@ static void ImGui_ImplWin32_UpdateMouseCursor() } ::SetCursor(::LoadCursor(NULL, win32_cursor)); } + return true; } // Process Win32 mouse/keyboard inputs. @@ -337,11 +342,8 @@ IMGUI_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hwnd, UINT msg, WPARAM wPa io.AddInputCharacter((unsigned short)wParam); return 0; case WM_SETCURSOR: - if (LOWORD(lParam) == HTCLIENT) - { - ImGui_ImplWin32_UpdateMouseCursor(); + if (LOWORD(lParam) == HTCLIENT && ImGui_ImplWin32_UpdateMouseCursor()) return 1; - } return 0; } return 0; @@ -584,8 +586,13 @@ bool ImGui_ImplDX10_Init(void* hwnd, ID3D10Device* device) if (!QueryPerformanceCounter((LARGE_INTEGER *)&g_Time)) return false; + // Setup back-end capabilities flags ImGuiIO& io = ImGui::GetIO(); - 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.BackendFlags |= ImGuiBackendFlags_HasMouseCursors; // We can honor GetMouseCursor() values + io.BackendFlags |= ImGuiBackendFlags_HasSetMousePos; // We can honor io.WantSetMousePos requests (optional, rarely used) + + // 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_Tab] = VK_TAB; io.KeyMap[ImGuiKey_LeftArrow] = VK_LEFT; io.KeyMap[ImGuiKey_RightArrow] = VK_RIGHT; io.KeyMap[ImGuiKey_UpArrow] = VK_UP; diff --git a/examples/directx11_example/imgui_impl_dx11.cpp b/examples/directx11_example/imgui_impl_dx11.cpp index f9596af3113e..a9748eeaa178 100644 --- a/examples/directx11_example/imgui_impl_dx11.cpp +++ b/examples/directx11_example/imgui_impl_dx11.cpp @@ -10,6 +10,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2018-03-20: Misc: Setup io.BackendFlags ImGuiBackendFlags_HasMouseCursors and ImGuiBackendFlags_HasSetMousePos flags + honor ImGuiConfigFlags_NoSetMouseCursor flag. // 2018-02-20: Inputs: Added support for mouse cursors (ImGui::GetMouseCursor() value and WM_SETCURSOR message handling). // 2018-02-16: Misc: Obsoleted the io.RenderDrawListsFn callback and exposed ImGui_ImplDX11_RenderDrawData() in the .h file so you can call it yourself. // 2018-02-06: Misc: Removed call to ImGui::Shutdown() which is not available from 1.60 WIP, user needs to call CreateContext/DestroyContext themselves. @@ -250,9 +251,12 @@ void ImGui_ImplDX11_RenderDrawData(ImDrawData* draw_data) ctx->IASetInputLayout(old.InputLayout); if (old.InputLayout) old.InputLayout->Release(); } -static void ImGui_ImplWin32_UpdateMouseCursor() +static bool ImGui_ImplWin32_UpdateMouseCursor() { ImGuiIO& io = ImGui::GetIO(); + if (io.ConfigFlags & ImGuiConfigFlags_NoSetMouseCursor) + return false; + ImGuiMouseCursor imgui_cursor = io.MouseDrawCursor ? ImGuiMouseCursor_None : ImGui::GetMouseCursor(); if (imgui_cursor == ImGuiMouseCursor_None) { @@ -275,6 +279,7 @@ static void ImGui_ImplWin32_UpdateMouseCursor() } ::SetCursor(::LoadCursor(NULL, win32_cursor)); } + return true; } // Process Win32 mouse/keyboard inputs. @@ -344,11 +349,8 @@ IMGUI_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hwnd, UINT msg, WPARAM wPa io.AddInputCharacter((unsigned short)wParam); return 0; case WM_SETCURSOR: - if (LOWORD(lParam) == HTCLIENT) - { - ImGui_ImplWin32_UpdateMouseCursor(); + if (LOWORD(lParam) == HTCLIENT && ImGui_ImplWin32_UpdateMouseCursor()) return 1; - } return 0; } return 0; @@ -586,8 +588,13 @@ bool ImGui_ImplDX11_Init(void* hwnd, ID3D11Device* device, ID3D11DeviceContex if (!QueryPerformanceCounter((LARGE_INTEGER *)&g_Time)) return false; + // Setup back-end capabilities flags ImGuiIO& io = ImGui::GetIO(); - 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.BackendFlags |= ImGuiBackendFlags_HasMouseCursors; // We can honor GetMouseCursor() values (optional) + io.BackendFlags |= ImGuiBackendFlags_HasSetMousePos; // We can honor io.WantSetMousePos requests (optional, rarely used) + + // 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_Tab] = VK_TAB; io.KeyMap[ImGuiKey_LeftArrow] = VK_LEFT; io.KeyMap[ImGuiKey_RightArrow] = VK_RIGHT; io.KeyMap[ImGuiKey_UpArrow] = VK_UP; diff --git a/examples/directx12_example/imgui_impl_dx12.cpp b/examples/directx12_example/imgui_impl_dx12.cpp index 86184e22814a..a6f36f6fe47f 100644 --- a/examples/directx12_example/imgui_impl_dx12.cpp +++ b/examples/directx12_example/imgui_impl_dx12.cpp @@ -11,6 +11,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2018-03-20: Misc: Setup io.BackendFlags ImGuiBackendFlags_HasMouseCursors and ImGuiBackendFlags_HasSetMousePos flags + honor ImGuiConfigFlags_NoSetMouseCursor flag. // 2018-02-22: Merged into master with all Win32 code synchronized to other examples. #include "imgui.h" @@ -221,9 +222,12 @@ void ImGui_ImplDX12_RenderDrawData(ImDrawData* draw_data) } } -static void ImGui_ImplWin32_UpdateMouseCursor() +static bool ImGui_ImplWin32_UpdateMouseCursor() { ImGuiIO& io = ImGui::GetIO(); + if (io.ConfigFlags & ImGuiConfigFlags_NoSetMouseCursor) + return false; + ImGuiMouseCursor imgui_cursor = io.MouseDrawCursor ? ImGuiMouseCursor_None : ImGui::GetMouseCursor(); if (imgui_cursor == ImGuiMouseCursor_None) { @@ -246,6 +250,7 @@ static void ImGui_ImplWin32_UpdateMouseCursor() } ::SetCursor(::LoadCursor(NULL, win32_cursor)); } + return true; } // Process Win32 mouse/keyboard inputs. @@ -315,11 +320,8 @@ IMGUI_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hwnd, UINT msg, WPARAM wPa io.AddInputCharacter((unsigned short)wParam); return 0; case WM_SETCURSOR: - if (LOWORD(lParam) == HTCLIENT) - { - ImGui_ImplWin32_UpdateMouseCursor(); + if (LOWORD(lParam) == HTCLIENT && ImGui_ImplWin32_UpdateMouseCursor()) return 1; - } return 0; } return 0; @@ -718,8 +720,13 @@ bool ImGui_ImplDX12_Init(void* hwnd, int num_frames_in_flight, if (!QueryPerformanceCounter((LARGE_INTEGER *)&g_Time)) return false; + // Setup back-end capabilities flags ImGuiIO& io = ImGui::GetIO(); - 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.BackendFlags |= ImGuiBackendFlags_HasMouseCursors; // We can honor GetMouseCursor() values (optional) + io.BackendFlags |= ImGuiBackendFlags_HasSetMousePos; // We can honor io.WantSetMousePos requests (optional, rarely used) + + // 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_Tab] = VK_TAB; io.KeyMap[ImGuiKey_LeftArrow] = VK_LEFT; io.KeyMap[ImGuiKey_RightArrow] = VK_RIGHT; io.KeyMap[ImGuiKey_UpArrow] = VK_UP; diff --git a/examples/directx9_example/imgui_impl_dx9.cpp b/examples/directx9_example/imgui_impl_dx9.cpp index 464fc39147da..1c1bb1c0e36e 100644 --- a/examples/directx9_example/imgui_impl_dx9.cpp +++ b/examples/directx9_example/imgui_impl_dx9.cpp @@ -10,6 +10,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2018-03-20: Misc: Setup io.BackendFlags ImGuiBackendFlags_HasMouseCursors and ImGuiBackendFlags_HasSetMousePos flags + honor ImGuiConfigFlags_NoSetMouseCursor flag. // 2018-02-20: Inputs: Added support for mouse cursors (ImGui::GetMouseCursor() value and WM_SETCURSOR message handling). // 2018-02-16: Misc: Obsoleted the io.RenderDrawListsFn callback and exposed ImGui_ImplDX9_RenderDrawData() in the .h file so you can call it yourself. // 2018-02-06: Misc: Removed call to ImGui::Shutdown() which is not available from 1.60 WIP, user needs to call CreateContext/DestroyContext themselves. @@ -183,9 +184,12 @@ void ImGui_ImplDX9_RenderDrawData(ImDrawData* draw_data) d3d9_state_block->Release(); } -static void ImGui_ImplWin32_UpdateMouseCursor() +static bool ImGui_ImplWin32_UpdateMouseCursor() { ImGuiIO& io = ImGui::GetIO(); + if (io.ConfigFlags & ImGuiConfigFlags_NoSetMouseCursor) + return false; + ImGuiMouseCursor imgui_cursor = io.MouseDrawCursor ? ImGuiMouseCursor_None : ImGui::GetMouseCursor(); if (imgui_cursor == ImGuiMouseCursor_None) { @@ -208,6 +212,7 @@ static void ImGui_ImplWin32_UpdateMouseCursor() } ::SetCursor(::LoadCursor(NULL, win32_cursor)); } + return true; } // Process Win32 mouse/keyboard inputs. @@ -277,11 +282,8 @@ IMGUI_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hwnd, UINT msg, WPARAM wPa io.AddInputCharacter((unsigned short)wParam); return 0; case WM_SETCURSOR: - if (LOWORD(lParam) == HTCLIENT) - { - ImGui_ImplWin32_UpdateMouseCursor(); + if (LOWORD(lParam) == HTCLIENT && ImGui_ImplWin32_UpdateMouseCursor()) return 1; - } return 0; } return 0; @@ -297,8 +299,13 @@ bool ImGui_ImplDX9_Init(void* hwnd, IDirect3DDevice9* device) if (!QueryPerformanceCounter((LARGE_INTEGER *)&g_Time)) return false; + // Setup back-end capabilities flags ImGuiIO& io = ImGui::GetIO(); - 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.BackendFlags |= ImGuiBackendFlags_HasMouseCursors; // We can honor GetMouseCursor() values (optional) + io.BackendFlags |= ImGuiBackendFlags_HasSetMousePos; // We can honor io.WantSetMousePos requests (optional, rarely used) + + // 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_Tab] = VK_TAB; io.KeyMap[ImGuiKey_LeftArrow] = VK_LEFT; io.KeyMap[ImGuiKey_RightArrow] = VK_RIGHT; io.KeyMap[ImGuiKey_UpArrow] = VK_UP; diff --git a/examples/opengl2_example/imgui_impl_glfw_gl2.cpp b/examples/opengl2_example/imgui_impl_glfw_gl2.cpp index 0b4ba6843e99..149051bab6cc 100644 --- a/examples/opengl2_example/imgui_impl_glfw_gl2.cpp +++ b/examples/opengl2_example/imgui_impl_glfw_gl2.cpp @@ -19,6 +19,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2018-03-20: Misc: Setup io.BackendFlags ImGuiBackendFlags_HasMouseCursors and ImGuiBackendFlags_HasSetMousePos flags + honor ImGuiConfigFlags_NoSetMouseCursor flag. // 2018-02-20: Inputs: Added support for mouse cursors (ImGui::GetMouseCursor() value and WM_SETCURSOR message handling). // 2018-02-20: Inputs: Renamed GLFW callbacks exposed in .h to not include GL2 in their name. // 2018-02-16: Misc: Obsoleted the io.RenderDrawListsFn callback and exposed ImGui_ImplGlfwGL2_RenderDrawData() in the .h file so you can call it yourself. @@ -233,8 +234,13 @@ bool ImGui_ImplGlfwGL2_Init(GLFWwindow* window, bool install_callbacks) { g_Window = window; + // Setup back-end capabilities flags ImGuiIO& io = ImGui::GetIO(); - io.KeyMap[ImGuiKey_Tab] = GLFW_KEY_TAB; // Keyboard mapping. ImGui will use those indices to peek into the io.KeyDown[] array. + io.BackendFlags |= ImGuiBackendFlags_HasMouseCursors; // We can honor GetMouseCursor() values (optional) + io.BackendFlags |= ImGuiBackendFlags_HasSetMousePos; // We can honor io.WantSetMousePos requests (optional, rarely used) + + // Keyboard mapping. ImGui will use those indices to peek into the io.KeyDown[] array. + io.KeyMap[ImGuiKey_Tab] = GLFW_KEY_TAB; io.KeyMap[ImGuiKey_LeftArrow] = GLFW_KEY_LEFT; io.KeyMap[ImGuiKey_RightArrow] = GLFW_KEY_RIGHT; io.KeyMap[ImGuiKey_UpArrow] = GLFW_KEY_UP; @@ -339,15 +345,18 @@ void ImGui_ImplGlfwGL2_NewFrame() } // Update OS/hardware mouse cursor if imgui isn't drawing a software cursor - ImGuiMouseCursor cursor = ImGui::GetMouseCursor(); - if (io.MouseDrawCursor || cursor == ImGuiMouseCursor_None) + if ((io.ConfigFlags & ImGuiConfigFlags_NoSetMouseCursor) == 0) { - glfwSetInputMode(g_Window, GLFW_CURSOR, GLFW_CURSOR_HIDDEN); - } - else - { - glfwSetCursor(g_Window, g_MouseCursors[cursor] ? g_MouseCursors[cursor] : g_MouseCursors[ImGuiMouseCursor_Arrow]); - glfwSetInputMode(g_Window, GLFW_CURSOR, GLFW_CURSOR_NORMAL); + ImGuiMouseCursor cursor = ImGui::GetMouseCursor(); + if (io.MouseDrawCursor || cursor == ImGuiMouseCursor_None) + { + glfwSetInputMode(g_Window, GLFW_CURSOR, GLFW_CURSOR_HIDDEN); + } + else + { + glfwSetCursor(g_Window, g_MouseCursors[cursor] ? g_MouseCursors[cursor] : g_MouseCursors[ImGuiMouseCursor_Arrow]); + glfwSetInputMode(g_Window, GLFW_CURSOR, GLFW_CURSOR_NORMAL); + } } // Start the frame. This call will update the io.WantCaptureMouse, io.WantCaptureKeyboard flag that you can use to dispatch inputs (or not) to your application. diff --git a/examples/opengl3_example/imgui_impl_glfw_gl3.cpp b/examples/opengl3_example/imgui_impl_glfw_gl3.cpp index 3fc32f9324e4..a0f631c1d25b 100644 --- a/examples/opengl3_example/imgui_impl_glfw_gl3.cpp +++ b/examples/opengl3_example/imgui_impl_glfw_gl3.cpp @@ -13,6 +13,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2018-03-20: Misc: Setup io.BackendFlags ImGuiBackendFlags_HasMouseCursors and ImGuiBackendFlags_HasSetMousePos flags + honor ImGuiConfigFlags_NoSetMouseCursor flag. // 2018-03-06: OpenGL: Added const char* glsl_version parameter to ImGui_ImplGlfwGL3_Init() so user can override the GLSL version e.g. "#version 150". // 2018-02-23: OpenGL: Create the VAO in the render function so the setup can more easily be used with multiple shared GL context. // 2018-02-20: Inputs: Added support for mouse cursors (ImGui::GetMouseCursor() value and WM_SETCURSOR message handling). @@ -365,8 +366,12 @@ bool ImGui_ImplGlfwGL3_Init(GLFWwindow* window, bool install_callbacks, const strcpy(g_GlslVersion, glsl_version); strcat(g_GlslVersion, "\n"); - // Keyboard mapping. ImGui will use those indices to peek into the io.KeyDown[] array. + // Setup back-end capabilities flags ImGuiIO& io = ImGui::GetIO(); + io.BackendFlags |= ImGuiBackendFlags_HasMouseCursors; // We can honor GetMouseCursor() values (optional) + io.BackendFlags |= ImGuiBackendFlags_HasSetMousePos; // We can honor io.WantSetMousePos requests (optional, rarely used) + + // Keyboard mapping. ImGui will use those indices to peek into the io.KeyDown[] array. io.KeyMap[ImGuiKey_Tab] = GLFW_KEY_TAB; io.KeyMap[ImGuiKey_LeftArrow] = GLFW_KEY_LEFT; io.KeyMap[ImGuiKey_RightArrow] = GLFW_KEY_RIGHT; @@ -472,15 +477,18 @@ void ImGui_ImplGlfwGL3_NewFrame() } // Update OS/hardware mouse cursor if imgui isn't drawing a software cursor - ImGuiMouseCursor cursor = ImGui::GetMouseCursor(); - if (io.MouseDrawCursor || cursor == ImGuiMouseCursor_None) - { - glfwSetInputMode(g_Window, GLFW_CURSOR, GLFW_CURSOR_HIDDEN); - } - else + if ((io.ConfigFlags & ImGuiConfigFlags_NoSetMouseCursor) == 0) { - glfwSetCursor(g_Window, g_MouseCursors[cursor] ? g_MouseCursors[cursor] : g_MouseCursors[ImGuiMouseCursor_Arrow]); - glfwSetInputMode(g_Window, GLFW_CURSOR, GLFW_CURSOR_NORMAL); + ImGuiMouseCursor cursor = ImGui::GetMouseCursor(); + if (io.MouseDrawCursor || cursor == ImGuiMouseCursor_None) + { + glfwSetInputMode(g_Window, GLFW_CURSOR, GLFW_CURSOR_HIDDEN); + } + else + { + glfwSetCursor(g_Window, g_MouseCursors[cursor] ? g_MouseCursors[cursor] : g_MouseCursors[ImGuiMouseCursor_Arrow]); + glfwSetInputMode(g_Window, GLFW_CURSOR, GLFW_CURSOR_NORMAL); + } } // Gamepad navigation mapping [BETA] diff --git a/examples/sdl_opengl2_example/imgui_impl_sdl_gl2.cpp b/examples/sdl_opengl2_example/imgui_impl_sdl_gl2.cpp index ca224744ee14..117a073ae48c 100644 --- a/examples/sdl_opengl2_example/imgui_impl_sdl_gl2.cpp +++ b/examples/sdl_opengl2_example/imgui_impl_sdl_gl2.cpp @@ -19,6 +19,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2018-03-20: Misc: Setup io.BackendFlags ImGuiBackendFlags_HasMouseCursors flag + honor ImGuiConfigFlags_NoSetMouseCursor flag. // 2018-02-16: Inputs: Added support for mouse cursors, honoring ImGui::GetMouseCursor() value. // 2018-02-16: Misc: Obsoleted the io.RenderDrawListsFn callback and exposed ImGui_ImplSdlGL2_RenderDrawData() in the .h file so you can call it yourself. // 2018-02-06: Misc: Removed call to ImGui::Shutdown() which is not available from 1.60 WIP, user needs to call CreateContext/DestroyContext themselves. @@ -224,8 +225,11 @@ void ImGui_ImplSdlGL2_InvalidateDeviceObjects() bool ImGui_ImplSdlGL2_Init(SDL_Window* window) { - // Keyboard mapping. ImGui will use those indices to peek into the io.KeyDown[] array. + // Setup back-end capabilities flags ImGuiIO& io = ImGui::GetIO(); + io.BackendFlags |= ImGuiBackendFlags_HasMouseCursors; // We can honor GetMouseCursor() values (optional) + + // Keyboard mapping. ImGui will use those indices to peek into the io.KeyDown[] array. io.KeyMap[ImGuiKey_Tab] = SDL_SCANCODE_TAB; io.KeyMap[ImGuiKey_LeftArrow] = SDL_SCANCODE_LEFT; io.KeyMap[ImGuiKey_RightArrow] = SDL_SCANCODE_RIGHT; @@ -330,15 +334,18 @@ void ImGui_ImplSdlGL2_NewFrame(SDL_Window *window) #endif // Update OS/hardware mouse cursor if imgui isn't drawing a software cursor - ImGuiMouseCursor cursor = ImGui::GetMouseCursor(); - if (io.MouseDrawCursor || cursor == ImGuiMouseCursor_None) - { - SDL_ShowCursor(0); - } - else + if ((io.ConfigFlags & ImGuiConfigFlags_NoSetMouseCursor) == 0) { - SDL_SetCursor(g_MouseCursors[cursor] ? g_MouseCursors[cursor] : g_MouseCursors[ImGuiMouseCursor_Arrow]); - SDL_ShowCursor(1); + ImGuiMouseCursor cursor = ImGui::GetMouseCursor(); + if (io.MouseDrawCursor || cursor == ImGuiMouseCursor_None) + { + SDL_ShowCursor(0); + } + else + { + SDL_SetCursor(g_MouseCursors[cursor] ? g_MouseCursors[cursor] : g_MouseCursors[ImGuiMouseCursor_Arrow]); + SDL_ShowCursor(1); + } } // Start the frame. This call will update the io.WantCaptureMouse, io.WantCaptureKeyboard flag that you can use to dispatch inputs (or not) to your application. diff --git a/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.cpp b/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.cpp index 995948d0c765..16c1d44007bc 100644 --- a/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.cpp +++ b/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.cpp @@ -12,6 +12,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2018-03-20: Misc: Setup io.BackendFlags ImGuiBackendFlags_HasMouseCursors flag + honor ImGuiConfigFlags_NoSetMouseCursor flag. // 2018-03-06: OpenGL: Added const char* glsl_version parameter to ImGui_ImplSdlGL3_Init() so user can override the GLSL version e.g. "#version 150". // 2018-02-23: OpenGL: Create the VAO in the render function so the setup can more easily be used with multiple shared GL context. // 2018-02-16: Inputs: Added support for mouse cursors, honoring ImGui::GetMouseCursor() value. @@ -357,8 +358,11 @@ bool ImGui_ImplSdlGL3_Init(SDL_Window* window, const char* glsl_version) strcpy(g_GlslVersion, glsl_version); strcat(g_GlslVersion, "\n"); - // Keyboard mapping. ImGui will use those indices to peek into the io.KeyDown[] array. + // Setup back-end capabilities flags ImGuiIO& io = ImGui::GetIO(); + io.BackendFlags |= ImGuiBackendFlags_HasMouseCursors; // We can honor GetMouseCursor() values (optional) + + // Keyboard mapping. ImGui will use those indices to peek into the io.KeyDown[] array. io.KeyMap[ImGuiKey_Tab] = SDL_SCANCODE_TAB; io.KeyMap[ImGuiKey_LeftArrow] = SDL_SCANCODE_LEFT; io.KeyMap[ImGuiKey_RightArrow] = SDL_SCANCODE_RIGHT; @@ -463,15 +467,18 @@ void ImGui_ImplSdlGL3_NewFrame(SDL_Window* window) #endif // Update OS/hardware mouse cursor if imgui isn't drawing a software cursor - ImGuiMouseCursor cursor = ImGui::GetMouseCursor(); - if (io.MouseDrawCursor || cursor == ImGuiMouseCursor_None) - { - SDL_ShowCursor(0); - } - else + if ((io.ConfigFlags & ImGuiConfigFlags_NoSetMouseCursor) == 0) { - SDL_SetCursor(g_MouseCursors[cursor] ? g_MouseCursors[cursor] : g_MouseCursors[ImGuiMouseCursor_Arrow]); - SDL_ShowCursor(1); + ImGuiMouseCursor cursor = ImGui::GetMouseCursor(); + if (io.MouseDrawCursor || cursor == ImGuiMouseCursor_None) + { + SDL_ShowCursor(0); + } + else + { + SDL_SetCursor(g_MouseCursors[cursor] ? g_MouseCursors[cursor] : g_MouseCursors[ImGuiMouseCursor_Arrow]); + SDL_ShowCursor(1); + } } // Start the frame. This call will update the io.WantCaptureMouse, io.WantCaptureKeyboard flag that you can use to dispatch inputs (or not) to your application. diff --git a/examples/vulkan_example/imgui_impl_glfw_vulkan.cpp b/examples/vulkan_example/imgui_impl_glfw_vulkan.cpp index f982d643fc9a..44e7296360d6 100644 --- a/examples/vulkan_example/imgui_impl_glfw_vulkan.cpp +++ b/examples/vulkan_example/imgui_impl_glfw_vulkan.cpp @@ -10,6 +10,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2018-03-20: Misc: Setup io.BackendFlags ImGuiBackendFlags_HasMouseCursors flag + honor ImGuiConfigFlags_NoSetMouseCursor flag. // 2018-02-20: Inputs: Added support for mouse cursors (ImGui::GetMouseCursor() value and WM_SETCURSOR message handling). // 2018-02-20: Inputs: Renamed GLFW callbacks exposed in .h to not include Vulkan in their name. // 2018-02-16: Misc: Obsoleted the io.RenderDrawListsFn callback, ImGui_ImplGlfwVulkan_Render() calls ImGui_ImplGlfwVulkan_RenderDrawData() itself. @@ -769,8 +770,12 @@ bool ImGui_ImplGlfwVulkan_Init(GLFWwindow* window, bool install_callbacks, Im g_Window = window; + // Setup back-end capabilities flags ImGuiIO& io = ImGui::GetIO(); - io.KeyMap[ImGuiKey_Tab] = GLFW_KEY_TAB; // Keyboard mapping. ImGui will use those indices to peek into the io.KeyDown[] array. + io.BackendFlags |= ImGuiBackendFlags_HasMouseCursors; // We can honor GetMouseCursor() values (optional) + + // Keyboard mapping. ImGui will use those indices to peek into the io.KeyDown[] array. + io.KeyMap[ImGuiKey_Tab] = GLFW_KEY_TAB; io.KeyMap[ImGuiKey_LeftArrow] = GLFW_KEY_LEFT; io.KeyMap[ImGuiKey_RightArrow] = GLFW_KEY_RIGHT; io.KeyMap[ImGuiKey_UpArrow] = GLFW_KEY_UP; @@ -865,15 +870,18 @@ void ImGui_ImplGlfwVulkan_NewFrame() } // Update OS/hardware mouse cursor if imgui isn't drawing a software cursor - ImGuiMouseCursor cursor = ImGui::GetMouseCursor(); - if (io.MouseDrawCursor || cursor == ImGuiMouseCursor_None) - { - glfwSetInputMode(g_Window, GLFW_CURSOR, GLFW_CURSOR_HIDDEN); - } - else + if ((io.ConfigFlags & ImGuiConfigFlags_NoSetMouseCursor) == 0) { - glfwSetCursor(g_Window, g_MouseCursors[cursor] ? g_MouseCursors[cursor] : g_MouseCursors[ImGuiMouseCursor_Arrow]); - glfwSetInputMode(g_Window, GLFW_CURSOR, GLFW_CURSOR_NORMAL); + ImGuiMouseCursor cursor = ImGui::GetMouseCursor(); + if (io.MouseDrawCursor || cursor == ImGuiMouseCursor_None) + { + glfwSetInputMode(g_Window, GLFW_CURSOR, GLFW_CURSOR_HIDDEN); + } + else + { + glfwSetCursor(g_Window, g_MouseCursors[cursor] ? g_MouseCursors[cursor] : g_MouseCursors[ImGuiMouseCursor_Arrow]); + glfwSetInputMode(g_Window, GLFW_CURSOR, GLFW_CURSOR_NORMAL); + } } // Start the frame. This call will update the io.WantCaptureMouse, io.WantCaptureKeyboard flag that you can use to dispatch inputs (or not) to your application. diff --git a/imgui.cpp b/imgui.cpp index 462ac4c66457..41e25c2da898 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -237,7 +237,7 @@ - PS4 users: Consider emulating a mouse cursor with DualShock4 touch pad or a spare analog stick as a mouse-emulation fallback. - Consoles/Tablet/Phone users: Consider using a Synergy 1.x server (on your PC) + uSynergy.c (on your console/tablet/phone app) to share your PC mouse/keyboard. - On a TV/console system where readability may be lower or mouse inputs may be awkward, you may want to set the ImGuiConfigFlags_NavEnableSetMousePos flag. - Enabling ImGuiConfigFlags_NavEnableSetMousePos instructs dear imgui to move your mouse cursor along with navigation movements. + Enabling ImGuiConfigFlags_NavEnableSetMousePos + ImGuiBackendFlags_HasSetMousePos instructs dear imgui to move your mouse cursor along with navigation movements. When enabled, the NewFrame() function may alter 'io.MousePos' and set 'io.WantSetMousePos' to notify you that it wants the mouse cursor to be moved. When that happens your back-end NEEDS to move the OS or underlying mouse cursor on the next frame. Some of the binding in examples/ do that. (If you set the NavEnableSetMousePos flag but don't honor 'io.WantSetMousePos' properly, imgui will misbehave as it will see your mouse as moving back and forth!) @@ -3037,7 +3037,7 @@ static void ImGui::NavUpdate() if (g.NavMousePosDirty && g.NavIdIsAlive) { // Set mouse position given our knowledge of the nav widget position from last frame - if (g.IO.ConfigFlags & ImGuiConfigFlags_NavEnableSetMousePos) + if ((g.IO.ConfigFlags & ImGuiConfigFlags_NavEnableSetMousePos) && (g.IO.BackendFlags & ImGuiBackendFlags_HasSetMousePos)) { g.IO.MousePos = g.IO.MousePosPrev = NavCalcPreferredMousePos(); g.IO.WantSetMousePos = true; diff --git a/imgui.h b/imgui.h index 20077604d82b..f48681b94b1f 100644 --- a/imgui.h +++ b/imgui.h @@ -777,6 +777,7 @@ enum ImGuiConfigFlags_ ImGuiConfigFlags_NavEnableGamepad = 1 << 1, // Master gamepad navigation enable flag. This is mostly to instruct your imgui back-end to fill io.NavInputs[]. Back-end also needs to set ImGuiBackendFlags_HasGamepad. ImGuiConfigFlags_NavEnableSetMousePos = 1 << 2, // Request navigation to allow moving the mouse cursor. May be useful on TV/console systems where moving a virtual mouse is awkward. Will update io.MousePos and set io.WantSetMousePos=true. If enabled you MUST honor io.WantSetMousePos requests in your binding, otherwise ImGui will react as if the mouse is jumping around back and forth. ImGuiConfigFlags_NavNoCaptureKeyboard = 1 << 3, // Do not set the io.WantCaptureKeyboard flag with io.NavActive is set. + ImGuiConfigFlags_NoSetMouseCursor = 1 << 4, // Request back-end to not alter mouse cursor configuration. // User storage (to allow your back-end/engine to communicate to code that may be shared between multiple projects. Those flags are not used by core ImGui) ImGuiConfigFlags_IsSRGB = 1 << 20, // Application is SRGB-aware. @@ -786,7 +787,9 @@ enum ImGuiConfigFlags_ // Back-end capabilities flags stored in io.BackendFlags. Set by imgui_impl_xxx or custom back-end. enum ImGuiBackendFlags_ { - ImGuiBackendFlags_HasGamepad = 1 << 0 // Back-end has a connected gamepad + ImGuiBackendFlags_HasGamepad = 1 << 0, // Back-end has a connected gamepad. + ImGuiBackendFlags_HasMouseCursors = 1 << 1, // Back-end can honor GetMouseCursor() values and change the OS cursor shape. + ImGuiBackendFlags_HasSetMousePos = 1 << 2 // Back-end can honor io.WantSetMousePos and reposition the mouse (only used if ImGuiConfigFlags_NavEnableSetMousePos is set). }; // Enumeration for PushStyleColor() / PopStyleColor() diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 8ff62a9b54d2..9be5fef0b556 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -1849,6 +1849,7 @@ void ImGui::ShowDemoWindow(bool* p_open) ImGui::CheckboxFlags("io.ConfigFlags: NavEnableGamepad", (unsigned int *)&io.ConfigFlags, ImGuiConfigFlags_NavEnableGamepad); ImGui::CheckboxFlags("io.ConfigFlags: NavEnableKeyboard", (unsigned int *)&io.ConfigFlags, ImGuiConfigFlags_NavEnableKeyboard); ImGui::CheckboxFlags("io.ConfigFlags: NavEnableSetMousePos", (unsigned int *)&io.ConfigFlags, ImGuiConfigFlags_NavEnableSetMousePos); + ImGui::CheckboxFlags("io.ConfigFlags: NoSetMouseCursor", (unsigned int *)&io.ConfigFlags, ImGuiConfigFlags_NoSetMouseCursor); ImGui::SameLine(); ShowHelpMarker("Request ImGui to move your move cursor when using gamepad/keyboard navigation. NewFrame() will change io.MousePos and set the io.WantSetMousePos flag, your backend will need to apply the new mouse position."); if (ImGui::TreeNode("Keyboard, Mouse & Navigation State")) From 94116f1143a7bf552b759a913122e495dc4deee4 Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 20 Mar 2018 22:41:05 +0100 Subject: [PATCH 789/823] Examples: GLFW: Don't alter cursor mode if GLFW_CURSOR input mode is GLFW_CURSOR_DISABLED. (#1202) [@PhilCK] --- CHANGELOG.txt | 1 + examples/opengl2_example/imgui_impl_glfw_gl2.cpp | 2 +- examples/opengl3_example/imgui_impl_glfw_gl3.cpp | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.txt b/CHANGELOG.txt index d345c19d09d6..dbc6bd819669 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -173,6 +173,7 @@ Other Changes: - Examples: Win32 (DirectX9,10,11,12: Support for windows using the CS_DBLCLKS class flag by handling the double-click messages (WM_LBUTTONDBLCLK etc.). (#1538, #754) [@ndandoulakis] - Examples: Win32 (DirectX9,10,11,12): Made the Win32 proc handlers not assert if there is no active context yet, to be more flexible with creation order. (#1565) - Examples: GLFW: Added support for mouse cursor shapes (the diagonal resize cursors are unfortunately not supported by GLFW at the moment. (#1495) +- Examples: GLFW: Don't attempt to change the mouse cursor input mode if it is set to GLFW_CURSOR_DISABLED by the application. (#1202) [@PhilCK] - Examples: SDL: Added support for mouse cursor shapes. (#1626) [@olls] - Examples: SDL: Using SDL_CaptureMouse() to retrieve coordinates outside of client area when dragging (SDL 2.0.4+ only, otherwise using SDL_WINDOW_INPUT_FOCUS instead of previously SDL_WINDOW_MOUSE_FOCUS). (#1559) - Examples: SDL: Enabled vsync by default so people don't come at us with demoes running at 2000 FPS burning a cpu core. diff --git a/examples/opengl2_example/imgui_impl_glfw_gl2.cpp b/examples/opengl2_example/imgui_impl_glfw_gl2.cpp index 149051bab6cc..2789f0d1b893 100644 --- a/examples/opengl2_example/imgui_impl_glfw_gl2.cpp +++ b/examples/opengl2_example/imgui_impl_glfw_gl2.cpp @@ -345,7 +345,7 @@ void ImGui_ImplGlfwGL2_NewFrame() } // Update OS/hardware mouse cursor if imgui isn't drawing a software cursor - if ((io.ConfigFlags & ImGuiConfigFlags_NoSetMouseCursor) == 0) + if ((io.ConfigFlags & ImGuiConfigFlags_NoSetMouseCursor) == 0 && glfwGetInputMode(g_Window, GLFW_CURSOR) != GLFW_CURSOR_DISABLED) { ImGuiMouseCursor cursor = ImGui::GetMouseCursor(); if (io.MouseDrawCursor || cursor == ImGuiMouseCursor_None) diff --git a/examples/opengl3_example/imgui_impl_glfw_gl3.cpp b/examples/opengl3_example/imgui_impl_glfw_gl3.cpp index a0f631c1d25b..348a0b04730f 100644 --- a/examples/opengl3_example/imgui_impl_glfw_gl3.cpp +++ b/examples/opengl3_example/imgui_impl_glfw_gl3.cpp @@ -477,7 +477,7 @@ void ImGui_ImplGlfwGL3_NewFrame() } // Update OS/hardware mouse cursor if imgui isn't drawing a software cursor - if ((io.ConfigFlags & ImGuiConfigFlags_NoSetMouseCursor) == 0) + if ((io.ConfigFlags & ImGuiConfigFlags_NoSetMouseCursor) == 0 && glfwGetInputMode(g_Window, GLFW_CURSOR) != GLFW_CURSOR_DISABLED) { ImGuiMouseCursor cursor = ImGui::GetMouseCursor(); if (io.MouseDrawCursor || cursor == ImGuiMouseCursor_None) From 21ac470a8a5885ef9811b3c0738fd59bfa700cda Mon Sep 17 00:00:00 2001 From: omar Date: Wed, 21 Mar 2018 19:45:19 +0100 Subject: [PATCH 790/823] Nav: Fixed a crash with IMGUI_DEBUG_NAV_SCORING enabled + added info to Metrics. --- imgui.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/imgui.cpp b/imgui.cpp index 41e25c2da898..4e0417eee882 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -2320,7 +2320,9 @@ static void NavRestoreLayer(int layer) static inline void NavUpdateAnyRequestFlag() { ImGuiContext& g = *GImGui; - g.NavAnyRequest = g.NavMoveRequest || g.NavInitRequest || IMGUI_DEBUG_NAV_SCORING; + g.NavAnyRequest = g.NavMoveRequest || g.NavInitRequest || (IMGUI_DEBUG_NAV_SCORING && g.NavWindow != NULL); + if (g.NavAnyRequest) + IM_ASSERT(g.NavWindow != NULL); } static bool NavMoveRequestButNoResultYet() @@ -13258,6 +13260,7 @@ void ImGui::ShowMetricsWindow(bool* p_open) ImGui::Text("HoveredId: 0x%08X/0x%08X (%.2f sec)", g.HoveredId, g.HoveredIdPreviousFrame, g.HoveredIdTimer); // Data is "in-flight" so depending on when the Metrics window is called we may see current frame information or not ImGui::Text("ActiveId: 0x%08X/0x%08X (%.2f sec), ActiveIdSource: %s", g.ActiveId, g.ActiveIdPreviousFrame, g.ActiveIdTimer, input_source_names[g.ActiveIdSource]); ImGui::Text("ActiveIdWindow: '%s'", g.ActiveIdWindow ? g.ActiveIdWindow->Name : "NULL"); + ImGui::Text("MovingWindow: '%s'", g.MovingWindow ? g.MovingWindow->Name : "NULL"); ImGui::Text("NavWindow: '%s'", g.NavWindow ? g.NavWindow->Name : "NULL"); ImGui::Text("NavId: 0x%08X, NavLayer: %d", g.NavId, g.NavLayer); ImGui::Text("NavInputSource: %s", input_source_names[g.NavInputSource]); From c796960ff93c240c652960f98e361cdf141ef70d Mon Sep 17 00:00:00 2001 From: omar Date: Thu, 22 Mar 2018 17:49:53 +0100 Subject: [PATCH 791/823] InputFloat: Scientific input. InputText: Added ImGuiInputTextFlags_CharsScientific to add 'e' 'E' to list of characters that can be input. (later useful for #1011) --- CHANGELOG.txt | 1 + imgui.cpp | 11 ++++++++--- imgui.h | 1 + 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.txt b/CHANGELOG.txt index dbc6bd819669..801b483d60e2 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -104,6 +104,7 @@ Other Changes: - ArrowButton: Added ArrowButton() given a cardinal direction (e.g. ImGuiDir_Left). - InputText: Added alternative clipboard shortcuts: Shift+Delete (cut), Ctrl+Insert (copy), Shift+Insert (paste). (#1541) - InputText: Fixed losing Cursor X position when clicking outside on an item that's submitted after the InputText(). It was only noticeable when restoring focus programmatically. (#1418, #1554) +- InputText: Added ImGuiInputTextFlags_CharsScientific flag to also allow 'e'/'E' for input of values using scientific notation. Automatically used by InputFloat. - Style: Enable window border by default. (#707) - Style: Exposed ImGuiStyleVar_WindowTitleAlign, ImGuiStyleVar_ScrollbarSize, ImGuiStyleVar_ScrollbarRounding, ImGuiStyleVar_GrabRounding + added an assert to reduce accidental breakage. (#1181) - Style: Added style.MouseCursorScale help when using the software mouse cursor facility. (#939). diff --git a/imgui.cpp b/imgui.cpp index 4e0417eee882..03cf76b1d2df 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -9779,12 +9779,16 @@ static bool InputTextFilterCharacter(unsigned int* p_char, ImGuiInputTextFlags f if (c >= 0xE000 && c <= 0xF8FF) // Filter private Unicode range. I don't imagine anybody would want to input them. GLFW on OSX seems to send private characters for special keys like arrow keys. return false; - if (flags & (ImGuiInputTextFlags_CharsDecimal | ImGuiInputTextFlags_CharsHexadecimal | ImGuiInputTextFlags_CharsUppercase | ImGuiInputTextFlags_CharsNoBlank)) + if (flags & (ImGuiInputTextFlags_CharsDecimal | ImGuiInputTextFlags_CharsHexadecimal | ImGuiInputTextFlags_CharsUppercase | ImGuiInputTextFlags_CharsNoBlank | ImGuiInputTextFlags_CharsScientific)) { if (flags & ImGuiInputTextFlags_CharsDecimal) if (!(c >= '0' && c <= '9') && (c != '.') && (c != '-') && (c != '+') && (c != '*') && (c != '/')) return false; + if (flags & ImGuiInputTextFlags_CharsScientific) + if (!(c >= '0' && c <= '9') && (c != '.') && (c != '-') && (c != '+') && (c != '*') && (c != '/') && (c != 'e') && (c != 'E')) + return false; + if (flags & ImGuiInputTextFlags_CharsHexadecimal) if (!(c >= '0' && c <= '9') && !(c >= 'a' && c <= 'f') && !(c >= 'A' && c <= 'F')) return false; @@ -10446,7 +10450,7 @@ bool ImGui::InputScalarEx(const char* label, ImGuiDataType data_type, void* data DataTypeFormatString(data_type, data_ptr, scalar_format, buf, IM_ARRAYSIZE(buf)); bool value_changed = false; - if (!(extra_flags & ImGuiInputTextFlags_CharsHexadecimal)) + if ((extra_flags & (ImGuiInputTextFlags_CharsHexadecimal | ImGuiInputTextFlags_CharsScientific)) == 0) extra_flags |= ImGuiInputTextFlags_CharsDecimal; extra_flags |= ImGuiInputTextFlags_AutoSelectAll; if (InputText("", buf, IM_ARRAYSIZE(buf), extra_flags)) // PushId(label) + "" gives us the expected ID from outside point of view @@ -10489,6 +10493,7 @@ bool ImGui::InputFloat(const char* label, float* v, float step, float step_fast, strcpy(display_format, "%f"); // Ideally we'd have a minimum decimal precision of 1 to visually denote that this is a float, while hiding non-significant digits? %f doesn't have a minimum of 1 else ImFormatString(display_format, IM_ARRAYSIZE(display_format), "%%.%df", decimal_precision); + extra_flags |= ImGuiInputTextFlags_CharsScientific; return InputScalarEx(label, ImGuiDataType_Float, (void*)v, (void*)(step>0.0f ? &step : NULL), (void*)(step_fast>0.0f ? &step_fast : NULL), display_format, extra_flags); } @@ -10496,7 +10501,7 @@ bool ImGui::InputInt(const char* label, int* v, int step, int step_fast, ImGuiIn { // Hexadecimal input provided as a convenience but the flag name is awkward. Typically you'd use InputText() to parse your own data, if you want to handle prefixes. const char* scalar_format = (extra_flags & ImGuiInputTextFlags_CharsHexadecimal) ? "%08X" : "%d"; - return InputScalarEx(label, ImGuiDataType_Int, (void*)v, (void*)(step>0.0f ? &step : NULL), (void*)(step_fast>0.0f ? &step_fast : NULL), scalar_format, extra_flags); + return InputScalarEx(label, ImGuiDataType_Int, (void*)v, (void*)(step>0 ? &step : NULL), (void*)(step_fast>0 ? &step_fast : NULL), scalar_format, extra_flags); } bool ImGui::InputFloatN(const char* label, float* v, int components, int decimal_precision, ImGuiInputTextFlags extra_flags) diff --git a/imgui.h b/imgui.h index f48681b94b1f..a07e63449371 100644 --- a/imgui.h +++ b/imgui.h @@ -603,6 +603,7 @@ enum ImGuiInputTextFlags_ ImGuiInputTextFlags_ReadOnly = 1 << 14, // Read-only mode ImGuiInputTextFlags_Password = 1 << 15, // Password mode, display all characters as '*' ImGuiInputTextFlags_NoUndoRedo = 1 << 16, // Disable undo/redo. Note that input text owns the text data while active, if you want to provide your own undo/redo stack you need e.g. to call ClearActiveID(). + ImGuiInputTextFlags_CharsScientific = 1 << 17, // Allow 0123456789.+-*/eE (Scientific notation input) // [Internal] ImGuiInputTextFlags_Multiline = 1 << 20 // For internal use by InputTextMultiline() }; From c19b27813dad08c1bc26a5252a7c273e0645e74a Mon Sep 17 00:00:00 2001 From: omar Date: Thu, 22 Mar 2018 18:58:40 +0100 Subject: [PATCH 792/823] Added InputDouble() function. We use a format string instead of a decimal_precision parameter to also for "%e" and variants. (#1011) May transition the other InputXXX function to use format strings as well. --- CHANGELOG.txt | 2 ++ imgui.cpp | 94 ++++++++++++++++++++++++++++++++++-------------- imgui.h | 1 + imgui_demo.cpp | 11 ++++-- imgui_internal.h | 6 ++-- 5 files changed, 83 insertions(+), 31 deletions(-) diff --git a/CHANGELOG.txt b/CHANGELOG.txt index 801b483d60e2..266c7ff58925 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -126,6 +126,8 @@ Other Changes: - Drag and Drop: Increased payload type string to 32 characters instead of 8. (#143) - Drag and Drop: TreeNode as drop target displays rectangle over full frame. (#1597, #143) - DragFloat: Fix/workaround for backends which do not preserve a valid mouse position when dragged out of bounds. (#1559) +- InputFloat: Allow inputing value using scientific notation e.g. "1e+10". +- InputDouble: Added InputDouble() function. We use a format string instead of a decimal_precision parameter to also for "%e" and variants. (#1011) - Slider, Combo: Use ImGuiCol_FrameBgHovered color when hovered. (#1456) [@stfx] - Combo: BeginCombo(): Added ImGuiComboFlags_NoArrowButton to disable the arrow button and only display the wide value preview box. - Combo: BeginCombo(): Added ImGuiComboFlags_NoPreview to disable the preview and only display a square arrow button. diff --git a/imgui.cpp b/imgui.cpp index 03cf76b1d2df..a16cd5c253bb 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -725,7 +725,7 @@ static ImVec2 InputTextCalcTextSizeW(const ImWchar* text_begin, const static inline void DataTypeFormatString(ImGuiDataType data_type, void* data_ptr, const char* display_format, char* buf, int buf_size); static inline void DataTypeFormatString(ImGuiDataType data_type, void* data_ptr, int decimal_precision, char* buf, int buf_size); -static void DataTypeApplyOp(ImGuiDataType data_type, int op, void* value1, const void* value2); +static void DataTypeApplyOp(ImGuiDataType data_type, int op, void* output, void* arg_1, const void* arg_2); static bool DataTypeApplyOpFromText(const char* buf, const char* initial_value_buf, ImGuiDataType data_type, void* data_ptr, const char* scalar_format); namespace ImGui @@ -8380,6 +8380,8 @@ static inline void DataTypeFormatString(ImGuiDataType data_type, void* data_ptr, ImFormatString(buf, buf_size, display_format, *(int*)data_ptr); else if (data_type == ImGuiDataType_Float) ImFormatString(buf, buf_size, display_format, *(float*)data_ptr); + else if (data_type == ImGuiDataType_Double) + ImFormatString(buf, buf_size, display_format, *(double*)data_ptr); } static inline void DataTypeFormatString(ImGuiDataType data_type, void* data_ptr, int decimal_precision, char* buf, int buf_size) @@ -8398,27 +8400,45 @@ static inline void DataTypeFormatString(ImGuiDataType data_type, void* data_ptr, else ImFormatString(buf, buf_size, "%.*f", decimal_precision, *(float*)data_ptr); } + else if (data_type == ImGuiDataType_Double) + { + if (decimal_precision < 0) + ImFormatString(buf, buf_size, "%f", *(double*)data_ptr); + else + ImFormatString(buf, buf_size, "%.*f", decimal_precision, *(double*)data_ptr); + } } -static void DataTypeApplyOp(ImGuiDataType data_type, int op, void* value1, const void* value2)// Store into value1 +static void DataTypeApplyOp(ImGuiDataType data_type, int op, void* output, void* arg1, const void* arg2) { + IM_ASSERT(op == '+' || op == '-'); if (data_type == ImGuiDataType_Int) { - if (op == '+') - *(int*)value1 = *(int*)value1 + *(const int*)value2; - else if (op == '-') - *(int*)value1 = *(int*)value1 - *(const int*)value2; + if (op == '+') *(int*)output = *(int*)arg1 + *(const int*)arg2; + else if (op == '-') *(int*)output = *(int*)arg1 - *(const int*)arg2; } else if (data_type == ImGuiDataType_Float) { - if (op == '+') - *(float*)value1 = *(float*)value1 + *(const float*)value2; - else if (op == '-') - *(float*)value1 = *(float*)value1 - *(const float*)value2; + if (op == '+') *(float*)output = *(float*)arg1 + *(const float*)arg2; + else if (op == '-') *(float*)output = *(float*)arg1 - *(const float*)arg2; + } + else if (data_type == ImGuiDataType_Double) + { + if (op == '+') *(double*)output = *(double*)arg1 + *(const double*)arg2; + else if (op == '-') *(double*)output = *(double*)arg1 - *(const double*)arg2; } } +static size_t GDataTypeSize[ImGuiDataType_COUNT] = +{ + sizeof(int), + sizeof(float), + sizeof(double), + sizeof(float) * 2, +}; + // User can input math operators (e.g. +100) to edit a numerical values. +// NB: This is _not_ a full expression evaluator. We should probably add one though.. static bool DataTypeApplyOpFromText(const char* buf, const char* initial_value_buf, ImGuiDataType data_type, void* data_ptr, const char* scalar_format) { while (ImCharIsSpace(*buf)) @@ -8440,45 +8460,56 @@ static bool DataTypeApplyOpFromText(const char* buf, const char* initial_value_b if (!buf[0]) return false; + IM_ASSERT(data_type < ImGuiDataType_COUNT); + int data_backup[2]; + IM_ASSERT(GDataTypeSize[data_type] <= sizeof(data_backup)); + memcpy(data_backup, data_ptr, GDataTypeSize[data_type]); + if (data_type == ImGuiDataType_Int) { if (!scalar_format) scalar_format = "%d"; int* v = (int*)data_ptr; - const int old_v = *v; int arg0i = *v; if (op && sscanf(initial_value_buf, scalar_format, &arg0i) < 1) return false; - // Store operand in a float so we can use fractional value for multipliers (*1.1), but constant always parsed as integer so we can fit big integers (e.g. 2000000003) past float precision float arg1f = 0.0f; if (op == '+') { if (sscanf(buf, "%f", &arg1f) == 1) *v = (int)(arg0i + arg1f); } // Add (use "+-" to subtract) else if (op == '*') { if (sscanf(buf, "%f", &arg1f) == 1) *v = (int)(arg0i * arg1f); } // Multiply else if (op == '/') { if (sscanf(buf, "%f", &arg1f) == 1 && arg1f != 0.0f) *v = (int)(arg0i / arg1f); }// Divide - else { if (sscanf(buf, scalar_format, &arg0i) == 1) *v = arg0i; } // Assign constant (read as integer so big values are not lossy) - return (old_v != *v); + else { if (sscanf(buf, scalar_format, &arg0i) == 1) *v = arg0i; } // Assign integer constant } else if (data_type == ImGuiDataType_Float) { // For floats we have to ignore format with precision (e.g. "%.2f") because sscanf doesn't take them in scalar_format = "%f"; float* v = (float*)data_ptr; - const float old_v = *v; - float arg0f = *v; + float arg0f = *v, arg1f = 0.0f; if (op && sscanf(initial_value_buf, scalar_format, &arg0f) < 1) return false; - - float arg1f = 0.0f; if (sscanf(buf, scalar_format, &arg1f) < 1) return false; if (op == '+') { *v = arg0f + arg1f; } // Add (use "+-" to subtract) else if (op == '*') { *v = arg0f * arg1f; } // Multiply else if (op == '/') { if (arg1f != 0.0f) *v = arg0f / arg1f; } // Divide else { *v = arg1f; } // Assign constant - return (old_v != *v); } - - return false; + else if (data_type == ImGuiDataType_Double) + { + scalar_format = "%lf"; + double* v = (double*)data_ptr; + double arg0f = *v, arg1f = 0.0f; + if (op && sscanf(initial_value_buf, scalar_format, &arg0f) < 1) + return false; + if (sscanf(buf, scalar_format, &arg1f) < 1) + return false; + if (op == '+') { *v = arg0f + arg1f; } // Add (use "+-" to subtract) + else if (op == '*') { *v = arg0f * arg1f; } // Multiply + else if (op == '/') { if (arg1f != 0.0f) *v = arg0f / arg1f; } // Divide + else { *v = arg1f; } // Assign constant + } + return memcmp(data_backup, data_ptr, GDataTypeSize[data_type]) != 0; } // Create text input in place of a slider (when CTRL+Clicking on slider) @@ -10463,13 +10494,13 @@ bool ImGui::InputScalarEx(const char* label, ImGuiDataType data_type, void* data SameLine(0, style.ItemInnerSpacing.x); if (ButtonEx("-", button_sz, ImGuiButtonFlags_Repeat | ImGuiButtonFlags_DontClosePopups)) { - DataTypeApplyOp(data_type, '-', data_ptr, g.IO.KeyCtrl && step_fast_ptr ? step_fast_ptr : step_ptr); + DataTypeApplyOp(data_type, '-', data_ptr, data_ptr, g.IO.KeyCtrl && step_fast_ptr ? step_fast_ptr : step_ptr); value_changed = true; } SameLine(0, style.ItemInnerSpacing.x); if (ButtonEx("+", button_sz, ImGuiButtonFlags_Repeat | ImGuiButtonFlags_DontClosePopups)) { - DataTypeApplyOp(data_type, '+', data_ptr, g.IO.KeyCtrl && step_fast_ptr ? step_fast_ptr : step_ptr); + DataTypeApplyOp(data_type, '+', data_ptr, data_ptr, g.IO.KeyCtrl && step_fast_ptr ? step_fast_ptr : step_ptr); value_changed = true; } } @@ -10488,13 +10519,24 @@ bool ImGui::InputScalarEx(const char* label, ImGuiDataType data_type, void* data bool ImGui::InputFloat(const char* label, float* v, float step, float step_fast, int decimal_precision, ImGuiInputTextFlags extra_flags) { - char display_format[16]; + extra_flags |= ImGuiInputTextFlags_CharsScientific; if (decimal_precision < 0) - strcpy(display_format, "%f"); // Ideally we'd have a minimum decimal precision of 1 to visually denote that this is a float, while hiding non-significant digits? %f doesn't have a minimum of 1 + { + // Ideally we'd have a minimum decimal precision of 1 to visually denote that this is a float, while hiding non-significant digits? %f doesn't have a minimum of 1 + return InputScalarEx(label, ImGuiDataType_Float, (void*)v, (void*)(step>0.0f ? &step : NULL), (void*)(step_fast>0.0f ? &step_fast : NULL), "%f", extra_flags); + } else + { + char display_format[16]; ImFormatString(display_format, IM_ARRAYSIZE(display_format), "%%.%df", decimal_precision); + return InputScalarEx(label, ImGuiDataType_Float, (void*)v, (void*)(step>0.0f ? &step : NULL), (void*)(step_fast>0.0f ? &step_fast : NULL), display_format, extra_flags); + } +} + +bool ImGui::InputDouble(const char* label, double* v, double step, double step_fast, const char* display_format, ImGuiInputTextFlags extra_flags) +{ extra_flags |= ImGuiInputTextFlags_CharsScientific; - return InputScalarEx(label, ImGuiDataType_Float, (void*)v, (void*)(step>0.0f ? &step : NULL), (void*)(step_fast>0.0f ? &step_fast : NULL), display_format, extra_flags); + return InputScalarEx(label, ImGuiDataType_Double, (void*)v, (void*)(step>0.0 ? &step : NULL), (void*)(step_fast>0.0 ? &step_fast : NULL), display_format, extra_flags); } bool ImGui::InputInt(const char* label, int* v, int step, int step_fast, ImGuiInputTextFlags extra_flags) diff --git a/imgui.h b/imgui.h index a07e63449371..a79705bd0f83 100644 --- a/imgui.h +++ b/imgui.h @@ -357,6 +357,7 @@ namespace ImGui IMGUI_API bool InputInt2(const char* label, int v[2], ImGuiInputTextFlags extra_flags = 0); IMGUI_API bool InputInt3(const char* label, int v[3], ImGuiInputTextFlags extra_flags = 0); IMGUI_API bool InputInt4(const char* label, int v[4], ImGuiInputTextFlags extra_flags = 0); + IMGUI_API bool InputDouble(const char* label, double* v, double step = 0.0f, double step_fast = 0.0f, const char* display_format = "%.6f", ImGuiInputTextFlags extra_flags = 0); // Widgets: Sliders (tip: ctrl+click on a slider to input with keyboard. manually input values aren't clamped, can go off-bounds) IMGUI_API bool SliderFloat(const char* label, float* v, float v_min, float v_max, const char* display_format = "%.3f", float power = 1.0f); // adjust display_format to decorate the value with a prefix or a suffix for in-slider labels or unit display. Use power!=1.0 for logarithmic sliders diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 9be5fef0b556..b3d423919f19 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -335,8 +335,8 @@ void ImGui::ShowDemoWindow(bool* p_open) { static char str0[128] = "Hello, world!"; - static int i0=123; - static float f0=0.001f; + static int i0 = 123; + static float f0 = 0.001f; ImGui::InputText("input text", str0, IM_ARRAYSIZE(str0)); ImGui::SameLine(); ShowHelpMarker("Hold SHIFT or use mouse to select text.\n" "CTRL+Left/Right to word jump.\n" "CTRL+A or double-click to select all.\n" "CTRL+X,CTRL+C,CTRL+V clipboard.\n" "CTRL+Z,CTRL+Y undo/redo.\n" "ESCAPE to revert.\n"); @@ -345,12 +345,17 @@ void ImGui::ShowDemoWindow(bool* p_open) ImGui::InputFloat("input float", &f0, 0.01f, 1.0f); + // NB: You can use the %e notation as well. + static double d0 = 999999.000001; + ImGui::InputDouble("input double", &d0, 0.01f, 1.0f, "%.6f"); + ImGui::SameLine(); ShowHelpMarker("You can input value using the scientific notation,\n e.g. \"1e+8\" becomes \"100000000\".\n"); + static float vec4a[4] = { 0.10f, 0.20f, 0.30f, 0.44f }; ImGui::InputFloat3("input float3", vec4a); } { - static int i1=50, i2=42; + static int i1 = 50, i2 = 42; ImGui::DragInt("drag int", &i1, 1); ImGui::SameLine(); ShowHelpMarker("Click and drag to edit value.\nHold SHIFT/ALT for faster/slower edit.\nDouble-click or CTRL+click to input value."); diff --git a/imgui_internal.h b/imgui_internal.h index 8114faae2e33..479f25bec90a 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -248,7 +248,9 @@ enum ImGuiDataType { ImGuiDataType_Int, ImGuiDataType_Float, - ImGuiDataType_Float2 + ImGuiDataType_Double, + ImGuiDataType_Float2, + ImGuiDataType_COUNT }; enum ImGuiInputSource @@ -258,7 +260,7 @@ enum ImGuiInputSource ImGuiInputSource_Nav, ImGuiInputSource_NavKeyboard, // Only used occasionally for storage, not tested/handled by most code ImGuiInputSource_NavGamepad, // " - ImGuiInputSource_COUNT, + ImGuiInputSource_COUNT }; // FIXME-NAV: Clarify/expose various repeat delay/rate From b69dc45f6e94e931c38cc9e7101b7f4f97b4756d Mon Sep 17 00:00:00 2001 From: omar Date: Thu, 22 Mar 2018 20:14:31 +0100 Subject: [PATCH 793/823] Internals: Removed ImGuiDataType_Float2. --- imgui.cpp | 57 ++++++++++++++++++++++++------------------------ imgui_internal.h | 1 - 2 files changed, 29 insertions(+), 29 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index a16cd5c253bb..4699e6735fa8 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -6570,33 +6570,34 @@ void ImGui::PopStyleColor(int count) struct ImGuiStyleVarInfo { ImGuiDataType Type; + ImU32 Count; ImU32 Offset; void* GetVarPtr(ImGuiStyle* style) const { return (void*)((unsigned char*)style + Offset); } }; static const ImGuiStyleVarInfo GStyleVarInfo[] = { - { ImGuiDataType_Float, (ImU32)IM_OFFSETOF(ImGuiStyle, Alpha) }, // ImGuiStyleVar_Alpha - { ImGuiDataType_Float2, (ImU32)IM_OFFSETOF(ImGuiStyle, WindowPadding) }, // ImGuiStyleVar_WindowPadding - { ImGuiDataType_Float, (ImU32)IM_OFFSETOF(ImGuiStyle, WindowRounding) }, // ImGuiStyleVar_WindowRounding - { ImGuiDataType_Float, (ImU32)IM_OFFSETOF(ImGuiStyle, WindowBorderSize) }, // ImGuiStyleVar_WindowBorderSize - { ImGuiDataType_Float2, (ImU32)IM_OFFSETOF(ImGuiStyle, WindowMinSize) }, // ImGuiStyleVar_WindowMinSize - { ImGuiDataType_Float2, (ImU32)IM_OFFSETOF(ImGuiStyle, WindowTitleAlign) }, // ImGuiStyleVar_WindowTitleAlign - { ImGuiDataType_Float, (ImU32)IM_OFFSETOF(ImGuiStyle, ChildRounding) }, // ImGuiStyleVar_ChildRounding - { ImGuiDataType_Float, (ImU32)IM_OFFSETOF(ImGuiStyle, ChildBorderSize) }, // ImGuiStyleVar_ChildBorderSize - { ImGuiDataType_Float, (ImU32)IM_OFFSETOF(ImGuiStyle, PopupRounding) }, // ImGuiStyleVar_PopupRounding - { ImGuiDataType_Float, (ImU32)IM_OFFSETOF(ImGuiStyle, PopupBorderSize) }, // ImGuiStyleVar_PopupBorderSize - { ImGuiDataType_Float2, (ImU32)IM_OFFSETOF(ImGuiStyle, FramePadding) }, // ImGuiStyleVar_FramePadding - { ImGuiDataType_Float, (ImU32)IM_OFFSETOF(ImGuiStyle, FrameRounding) }, // ImGuiStyleVar_FrameRounding - { ImGuiDataType_Float, (ImU32)IM_OFFSETOF(ImGuiStyle, FrameBorderSize) }, // ImGuiStyleVar_FrameBorderSize - { ImGuiDataType_Float2, (ImU32)IM_OFFSETOF(ImGuiStyle, ItemSpacing) }, // ImGuiStyleVar_ItemSpacing - { ImGuiDataType_Float2, (ImU32)IM_OFFSETOF(ImGuiStyle, ItemInnerSpacing) }, // ImGuiStyleVar_ItemInnerSpacing - { ImGuiDataType_Float, (ImU32)IM_OFFSETOF(ImGuiStyle, IndentSpacing) }, // ImGuiStyleVar_IndentSpacing - { ImGuiDataType_Float, (ImU32)IM_OFFSETOF(ImGuiStyle, ScrollbarSize) }, // ImGuiStyleVar_ScrollbarSize - { ImGuiDataType_Float, (ImU32)IM_OFFSETOF(ImGuiStyle, ScrollbarRounding) }, // ImGuiStyleVar_ScrollbarRounding - { ImGuiDataType_Float, (ImU32)IM_OFFSETOF(ImGuiStyle, GrabMinSize) }, // ImGuiStyleVar_GrabMinSize - { ImGuiDataType_Float, (ImU32)IM_OFFSETOF(ImGuiStyle, GrabRounding) }, // ImGuiStyleVar_GrabRounding - { ImGuiDataType_Float2, (ImU32)IM_OFFSETOF(ImGuiStyle, ButtonTextAlign) }, // ImGuiStyleVar_ButtonTextAlign + { ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImGuiStyle, Alpha) }, // ImGuiStyleVar_Alpha + { ImGuiDataType_Float, 2, (ImU32)IM_OFFSETOF(ImGuiStyle, WindowPadding) }, // ImGuiStyleVar_WindowPadding + { ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImGuiStyle, WindowRounding) }, // ImGuiStyleVar_WindowRounding + { ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImGuiStyle, WindowBorderSize) }, // ImGuiStyleVar_WindowBorderSize + { ImGuiDataType_Float, 2, (ImU32)IM_OFFSETOF(ImGuiStyle, WindowMinSize) }, // ImGuiStyleVar_WindowMinSize + { ImGuiDataType_Float, 2, (ImU32)IM_OFFSETOF(ImGuiStyle, WindowTitleAlign) }, // ImGuiStyleVar_WindowTitleAlign + { ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImGuiStyle, ChildRounding) }, // ImGuiStyleVar_ChildRounding + { ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImGuiStyle, ChildBorderSize) }, // ImGuiStyleVar_ChildBorderSize + { ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImGuiStyle, PopupRounding) }, // ImGuiStyleVar_PopupRounding + { ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImGuiStyle, PopupBorderSize) }, // ImGuiStyleVar_PopupBorderSize + { ImGuiDataType_Float, 2, (ImU32)IM_OFFSETOF(ImGuiStyle, FramePadding) }, // ImGuiStyleVar_FramePadding + { ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImGuiStyle, FrameRounding) }, // ImGuiStyleVar_FrameRounding + { ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImGuiStyle, FrameBorderSize) }, // ImGuiStyleVar_FrameBorderSize + { ImGuiDataType_Float, 2, (ImU32)IM_OFFSETOF(ImGuiStyle, ItemSpacing) }, // ImGuiStyleVar_ItemSpacing + { ImGuiDataType_Float, 2, (ImU32)IM_OFFSETOF(ImGuiStyle, ItemInnerSpacing) }, // ImGuiStyleVar_ItemInnerSpacing + { ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImGuiStyle, IndentSpacing) }, // ImGuiStyleVar_IndentSpacing + { ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImGuiStyle, ScrollbarSize) }, // ImGuiStyleVar_ScrollbarSize + { ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImGuiStyle, ScrollbarRounding) }, // ImGuiStyleVar_ScrollbarRounding + { ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImGuiStyle, GrabMinSize) }, // ImGuiStyleVar_GrabMinSize + { ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImGuiStyle, GrabRounding) }, // ImGuiStyleVar_GrabRounding + { ImGuiDataType_Float, 2, (ImU32)IM_OFFSETOF(ImGuiStyle, ButtonTextAlign) }, // ImGuiStyleVar_ButtonTextAlign }; static const ImGuiStyleVarInfo* GetStyleVarInfo(ImGuiStyleVar idx) @@ -6609,7 +6610,7 @@ static const ImGuiStyleVarInfo* GetStyleVarInfo(ImGuiStyleVar idx) void ImGui::PushStyleVar(ImGuiStyleVar idx, float val) { const ImGuiStyleVarInfo* var_info = GetStyleVarInfo(idx); - if (var_info->Type == ImGuiDataType_Float) + if (var_info->Type == ImGuiDataType_Float && var_info->Count == 1) { ImGuiContext& g = *GImGui; float* pvar = (float*)var_info->GetVarPtr(&g.Style); @@ -6623,7 +6624,7 @@ void ImGui::PushStyleVar(ImGuiStyleVar idx, float val) void ImGui::PushStyleVar(ImGuiStyleVar idx, const ImVec2& val) { const ImGuiStyleVarInfo* var_info = GetStyleVarInfo(idx); - if (var_info->Type == ImGuiDataType_Float2) + if (var_info->Type == ImGuiDataType_Float && var_info->Count == 2) { ImGuiContext& g = *GImGui; ImVec2* pvar = (ImVec2*)var_info->GetVarPtr(&g.Style); @@ -6639,11 +6640,12 @@ void ImGui::PopStyleVar(int count) ImGuiContext& g = *GImGui; while (count > 0) { + // We avoid a generic memcpy(data, &backup.Backup.., GDataTypeSize[info->Type] * info->Count), the overhead in Debug is not worth it. ImGuiStyleMod& backup = g.StyleModifiers.back(); const ImGuiStyleVarInfo* info = GetStyleVarInfo(backup.VarIdx); - if (info->Type == ImGuiDataType_Float) (*(float*)info->GetVarPtr(&g.Style)) = backup.BackupFloat[0]; - else if (info->Type == ImGuiDataType_Float2) (*(ImVec2*)info->GetVarPtr(&g.Style)) = ImVec2(backup.BackupFloat[0], backup.BackupFloat[1]); - else if (info->Type == ImGuiDataType_Int) (*(int*)info->GetVarPtr(&g.Style)) = backup.BackupInt[0]; + void* data = info->GetVarPtr(&g.Style); + if (info->Type == ImGuiDataType_Float && info->Count == 1) { ((float*)data)[0] = backup.BackupFloat[0]; } + else if (info->Type == ImGuiDataType_Float && info->Count == 2) { ((float*)data)[0] = backup.BackupFloat[0]; ((float*)data)[1] = backup.BackupFloat[1]; } g.StyleModifiers.pop_back(); count--; } @@ -8433,8 +8435,7 @@ static size_t GDataTypeSize[ImGuiDataType_COUNT] = { sizeof(int), sizeof(float), - sizeof(double), - sizeof(float) * 2, + sizeof(double) }; // User can input math operators (e.g. +100) to edit a numerical values. diff --git a/imgui_internal.h b/imgui_internal.h index 479f25bec90a..b5c5b0e4e184 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -249,7 +249,6 @@ enum ImGuiDataType ImGuiDataType_Int, ImGuiDataType_Float, ImGuiDataType_Double, - ImGuiDataType_Float2, ImGuiDataType_COUNT }; From cd602b883271362256769dc6dbb265aef477a2e3 Mon Sep 17 00:00:00 2001 From: omar Date: Fri, 23 Mar 2018 12:03:57 +0100 Subject: [PATCH 794/823] Examples: SDL: Note about SDL breaking the IME under Windows (I can't seem a way SDL2 Windows IME implementation can possibly work, the functions are never called/referenced). --- examples/sdl_opengl2_example/imgui_impl_sdl_gl2.cpp | 2 ++ examples/sdl_opengl2_example/imgui_impl_sdl_gl2.h | 2 ++ examples/sdl_opengl3_example/imgui_impl_sdl_gl3.cpp | 2 ++ examples/sdl_opengl3_example/imgui_impl_sdl_gl3.h | 2 ++ 4 files changed, 8 insertions(+) diff --git a/examples/sdl_opengl2_example/imgui_impl_sdl_gl2.cpp b/examples/sdl_opengl2_example/imgui_impl_sdl_gl2.cpp index 117a073ae48c..0149864df562 100644 --- a/examples/sdl_opengl2_example/imgui_impl_sdl_gl2.cpp +++ b/examples/sdl_opengl2_example/imgui_impl_sdl_gl2.cpp @@ -3,6 +3,8 @@ // Implemented features: // [X] User texture binding. Cast 'GLuint' OpenGL texture identifier as void*/ImTextureID. Read the FAQ about ImTextureID in imgui.cpp. +// Missing features: +// [ ] SDL2 handling of IME under Windows appears to be broken and it explicitly disable the regular Windows IME. You can restore Windows IME by compiling SDL with SDL_DISABLE_WINDOWS_IME. // **DO NOT USE THIS CODE IF YOUR CODE/ENGINE IS USING MODERN OPENGL (SHADERS, VBO, VAO, etc.)** // **Prefer using the code in the sdl_opengl3_example/ folder** diff --git a/examples/sdl_opengl2_example/imgui_impl_sdl_gl2.h b/examples/sdl_opengl2_example/imgui_impl_sdl_gl2.h index 4df1c169c4ee..d3ef9168fc0f 100644 --- a/examples/sdl_opengl2_example/imgui_impl_sdl_gl2.h +++ b/examples/sdl_opengl2_example/imgui_impl_sdl_gl2.h @@ -3,6 +3,8 @@ // Implemented features: // [X] User texture binding. Cast 'GLuint' OpenGL texture identifier as void*/ImTextureID. Read the FAQ about ImTextureID in imgui.cpp. +// Missing features: +// [ ] SDL2 handling of IME under Windows appears to be broken and it explicitly disable the regular Windows IME. You can restore Windows IME by compiling SDL with SDL_DISABLE_WINDOWS_IME. // **DO NOT USE THIS CODE IF YOUR CODE/ENGINE IS USING MODERN OPENGL (SHADERS, VBO, VAO, etc.)** // **Prefer using the code in the sdl_opengl3_example/ folder** diff --git a/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.cpp b/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.cpp index 16c1d44007bc..8b04b933a78c 100644 --- a/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.cpp +++ b/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.cpp @@ -4,6 +4,8 @@ // Implemented features: // [X] User texture binding. Cast 'GLuint' OpenGL texture identifier as void*/ImTextureID. Read the FAQ about ImTextureID in imgui.cpp. +// Missing features: +// [ ] SDL2 handling of IME under Windows appears to be broken and it explicitly disable the regular Windows IME. You can restore Windows IME by compiling SDL with SDL_DISABLE_WINDOWS_IME. // You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this. // If you use this binding you'll need to call 4 functions: ImGui_ImplXXXX_Init(), ImGui_ImplXXXX_NewFrame(), ImGui::Render() and ImGui_ImplXXXX_Shutdown(). diff --git a/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.h b/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.h index 3aa00c3d1ac0..c694a481672d 100644 --- a/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.h +++ b/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.h @@ -4,6 +4,8 @@ // Implemented features: // [X] User texture binding. Cast 'GLuint' OpenGL texture identifier as void*/ImTextureID. Read the FAQ about ImTextureID in imgui.cpp. +// Missing features: +// [ ] SDL2 handling of IME under Windows appears to be broken and it explicitly disable the regular Windows IME. You can restore Windows IME by compiling SDL with SDL_DISABLE_WINDOWS_IME. // You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this. // If you use this binding you'll need to call 4 functions: ImGui_ImplXXXX_Init(), ImGui_ImplXXXX_NewFrame(), ImGui::Render() and ImGui_ImplXXXX_Shutdown(). From cc96477b1c6be28b116a0fe12ba6a11b7a1a565e Mon Sep 17 00:00:00 2001 From: omar Date: Sun, 25 Mar 2018 14:45:40 +0200 Subject: [PATCH 795/823] Comments (#1695) --- imconfig.h | 3 ++- imgui.cpp | 7 ++++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/imconfig.h b/imconfig.h index 4ba731341d84..47f4f54fe671 100644 --- a/imconfig.h +++ b/imconfig.h @@ -5,7 +5,8 @@ //----------------------------------------------------------------------------- // A) You may edit imconfig.h (and not overwrite it when updating imgui, or maintain a patch/branch with your modifications to imconfig.h) // B) or add configuration directives in your own file and compile with #define IMGUI_USER_CONFIG "myfilename.h" -// Note that options such as IMGUI_API, IM_VEC2_CLASS_EXTRA or ImDrawIdx needs to be defined consistently everywhere you include imgui.h, not only for the imgui*.cpp compilation units. +// C) Many compile-time options have an effect on data structures. They need defined consistently _everywhere_ imgui.h is included, +// not only for the imgui*.cpp compilation units. Defining those options in imconfig.h will ensure they correctly get used everywhere. //----------------------------------------------------------------------------- #pragma once diff --git a/imgui.cpp b/imgui.cpp index 4699e6735fa8..33574f66edb4 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -8,7 +8,12 @@ // Gallery (please post your screenshots/video there!): https://github.com/ocornut/imgui/issues/1269 // Developed by Omar Cornut and every direct or indirect contributors to the GitHub. // This library is free but I need your support to sustain development and maintenance. -// If you work for a company, please consider financial support, see Readme. For individuals: https://www.patreon.com/imgui +// If you work for a company, please consider financial support, see README. For individuals: https://www.patreon.com/imgui + +// It is recommended that you don't modify imgui.cpp! It will become difficult for you to update the library. +// Note that 'ImGui::' is a namespace and so you can add functions into it from your own source files without modifying imgui.h or imgui.cpp. +// You may include imgui_internal.h to access internal data structures, but it doesn't come with any guarantee of forward compatibility. +// Discussing your changes on the GitHub Issue Tracker may lead you to a better solution or official support for them. /* From ca39070ca0853128c1a718cc18b8d9cc7ecb9fa4 Mon Sep 17 00:00:00 2001 From: omar Date: Wed, 28 Mar 2018 23:32:02 +0200 Subject: [PATCH 796/823] Examples: Win32: Fixes for MingW which doesn't support a 2007 define? I have no idea why people still use MingW (#1704, #1463) --- examples/directx10_example/imgui_impl_dx10.cpp | 5 +++++ examples/directx11_example/imgui_impl_dx11.cpp | 5 +++++ examples/directx12_example/imgui_impl_dx12.cpp | 5 +++++ examples/directx9_example/imgui_impl_dx9.cpp | 5 +++++ 4 files changed, 20 insertions(+) diff --git a/examples/directx10_example/imgui_impl_dx10.cpp b/examples/directx10_example/imgui_impl_dx10.cpp index cc2ebddba493..60c79d52287f 100644 --- a/examples/directx10_example/imgui_impl_dx10.cpp +++ b/examples/directx10_example/imgui_impl_dx10.cpp @@ -275,6 +275,11 @@ static bool ImGui_ImplWin32_UpdateMouseCursor() return true; } +// MingW (which is stuck in the past) doesn't have this Vista-era define.. +#ifndef WM_MOUSEHWHEEL +#define WM_MOUSEHWHEEL 0x020E +#endif + // Process Win32 mouse/keyboard inputs. // You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs. // - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application. diff --git a/examples/directx11_example/imgui_impl_dx11.cpp b/examples/directx11_example/imgui_impl_dx11.cpp index a9748eeaa178..f319d2c4d676 100644 --- a/examples/directx11_example/imgui_impl_dx11.cpp +++ b/examples/directx11_example/imgui_impl_dx11.cpp @@ -282,6 +282,11 @@ static bool ImGui_ImplWin32_UpdateMouseCursor() return true; } +// MingW (which is stuck in the past) doesn't have this Vista-era define.. +#ifndef WM_MOUSEHWHEEL +#define WM_MOUSEHWHEEL 0x020E +#endif + // Process Win32 mouse/keyboard inputs. // You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs. // - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application. diff --git a/examples/directx12_example/imgui_impl_dx12.cpp b/examples/directx12_example/imgui_impl_dx12.cpp index a6f36f6fe47f..04df1dbcf215 100644 --- a/examples/directx12_example/imgui_impl_dx12.cpp +++ b/examples/directx12_example/imgui_impl_dx12.cpp @@ -253,6 +253,11 @@ static bool ImGui_ImplWin32_UpdateMouseCursor() return true; } +// MingW (which is stuck in the past) doesn't have this Vista-era define.. +#ifndef WM_MOUSEHWHEEL +#define WM_MOUSEHWHEEL 0x020E +#endif + // Process Win32 mouse/keyboard inputs. // You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs. // - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application. diff --git a/examples/directx9_example/imgui_impl_dx9.cpp b/examples/directx9_example/imgui_impl_dx9.cpp index 1c1bb1c0e36e..aa40d34a8e46 100644 --- a/examples/directx9_example/imgui_impl_dx9.cpp +++ b/examples/directx9_example/imgui_impl_dx9.cpp @@ -215,6 +215,11 @@ static bool ImGui_ImplWin32_UpdateMouseCursor() return true; } +// MingW (which is stuck in the past) doesn't have this Vista-era define.. +#ifndef WM_MOUSEHWHEEL +#define WM_MOUSEHWHEEL 0x020E +#endif + // Process Win32 mouse/keyboard inputs. // You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs. // - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application. From 664ab85f76d59023684e077ea5654bbaeea3abc0 Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 2 Apr 2018 17:31:51 +0200 Subject: [PATCH 797/823] Examples: Tweak comments. (#1704, #1708). --- examples/directx10_example/imgui_impl_dx10.cpp | 2 +- examples/directx11_example/imgui_impl_dx11.cpp | 2 +- examples/directx12_example/imgui_impl_dx12.cpp | 2 +- examples/directx9_example/imgui_impl_dx9.cpp | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/examples/directx10_example/imgui_impl_dx10.cpp b/examples/directx10_example/imgui_impl_dx10.cpp index 60c79d52287f..ae6dadc9406b 100644 --- a/examples/directx10_example/imgui_impl_dx10.cpp +++ b/examples/directx10_example/imgui_impl_dx10.cpp @@ -275,7 +275,7 @@ static bool ImGui_ImplWin32_UpdateMouseCursor() return true; } -// MingW (which is stuck in the past) doesn't have this Vista-era define.. +// Allow compilation with old Windows SDK. MinGW doesn't have default _WIN32_WINNT/WINVER versions. #ifndef WM_MOUSEHWHEEL #define WM_MOUSEHWHEEL 0x020E #endif diff --git a/examples/directx11_example/imgui_impl_dx11.cpp b/examples/directx11_example/imgui_impl_dx11.cpp index f319d2c4d676..6249120a078e 100644 --- a/examples/directx11_example/imgui_impl_dx11.cpp +++ b/examples/directx11_example/imgui_impl_dx11.cpp @@ -282,7 +282,7 @@ static bool ImGui_ImplWin32_UpdateMouseCursor() return true; } -// MingW (which is stuck in the past) doesn't have this Vista-era define.. +// Allow compilation with old Windows SDK. MinGW doesn't have default _WIN32_WINNT/WINVER versions. #ifndef WM_MOUSEHWHEEL #define WM_MOUSEHWHEEL 0x020E #endif diff --git a/examples/directx12_example/imgui_impl_dx12.cpp b/examples/directx12_example/imgui_impl_dx12.cpp index 04df1dbcf215..d327c36e9fd6 100644 --- a/examples/directx12_example/imgui_impl_dx12.cpp +++ b/examples/directx12_example/imgui_impl_dx12.cpp @@ -253,7 +253,7 @@ static bool ImGui_ImplWin32_UpdateMouseCursor() return true; } -// MingW (which is stuck in the past) doesn't have this Vista-era define.. +// Allow compilation with old Windows SDK. MinGW doesn't have default _WIN32_WINNT/WINVER versions. #ifndef WM_MOUSEHWHEEL #define WM_MOUSEHWHEEL 0x020E #endif diff --git a/examples/directx9_example/imgui_impl_dx9.cpp b/examples/directx9_example/imgui_impl_dx9.cpp index aa40d34a8e46..967e07e332bf 100644 --- a/examples/directx9_example/imgui_impl_dx9.cpp +++ b/examples/directx9_example/imgui_impl_dx9.cpp @@ -215,7 +215,7 @@ static bool ImGui_ImplWin32_UpdateMouseCursor() return true; } -// MingW (which is stuck in the past) doesn't have this Vista-era define.. +// Allow compilation with old Windows SDK. MinGW doesn't have default _WIN32_WINNT/WINVER versions. #ifndef WM_MOUSEHWHEEL #define WM_MOUSEHWHEEL 0x020E #endif From c461401b2123e4a22c12f63b613ef8b2cb124ccb Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 3 Apr 2018 20:05:59 +0200 Subject: [PATCH 798/823] Comments, FAQ --- README.md | 8 ++++---- imgui.cpp | 61 +++++++++++++++++++++++++++++-------------------------- 2 files changed, 36 insertions(+), 33 deletions(-) diff --git a/README.md b/README.md index 080ae31dbec3..8cb24a04804a 100644 --- a/README.md +++ b/README.md @@ -232,7 +232,7 @@ The library started its life and is best known as "ImGui" only due to the fact t How can I tell whether to dispatch mouse/keyboard to imgui or to my application?
How can I display an image? What is ImTextureID, how does it works? -
How can I have multiple widgets with the same label, or without any label? (Yes). A primer on labels and ID stack. +
How can I have multiple widgets with the same label or without a label? A primer on labels and the ID Stack.
How can I load a different font than the default?
How can I easily use icons in my application?
How can I load multiple fonts? @@ -301,7 +301,7 @@ Inspiration, feedback, and testing for early versions: Casey Muratori, Atman Bin Ongoing dear imgui development is financially supported on [**Patreon**](http://www.patreon.com/imgui) and by private sponsors. Double-chocolate sponsors: -- Blizzard +- Blizzard Entertainment - Media Molecule - Mobigame - Insomniac Games @@ -311,10 +311,10 @@ Double-chocolate sponsors: - DotEmu Salty caramel supporters: -- Jetha Chan, Wild Sheep Studio, Pastagames, Mārtiņš Možeiko, Daniel Collin, Recognition Robotics, Chris Genova, ikrima, Glenn Fiedler, Geoffrey Evans, Dakko Dakko, Mercury Labs, Singularity Demo Group, Mischa Alff, Sebastien Ronsse, Lionel Landwerlin. +- Jetha Chan, Wild Sheep Studio, Pastagames, Mārtiņš Možeiko, Daniel Collin, Recognition Robotics, Chris Genova, ikrima, Glenn Fiedler, Geoffrey Evans, Dakko Dakko, Mercury Labs, Singularity Demo Group, Mischa Alff, Sebastien Ronsse, Lionel Landwerlin, Nikolay Ivanov, Ron Gilbert. Caramel supporters: -- Michel Courtine, César Leblic, Dale Kim, Alex Evans, Rui Figueira, Paul Patrashcu, Jerome Lanquetot, Ctrl Alt Ninja, Paul Fleming, Neil Henning, Stephan Dilly, Neil Blakey-Milner, Aleksei, NeiloGD, Justin Paver, FiniteSol, Vincent Pancaldi, James Billot, Robin Hübner, furrtek, Eric, Simon Barratt, Game Atelier, Julian Bosch, Simon Lundmark, Vincent Hamm, Farhan Wali, Jeff Roberts, Matt Reyer, Colin Riley, Victor Martins, Josh Simmons, Garrett Hoofman, Sergio Gonzales, Andrew Berridge, Roy Eltham, Game Preservation Society, Kit framework, Josh Faust, Martin Donlon, Quinton, Felix, Andrew Belt, Codecat, Cort Stratton, Claudio Canepa, Doug McNabb, Emmanuel Julien, Guillaume Chereau, Jeffrey Slutter, Jeremiah Deckard, r-lyeh, Roger Clark, Nekith, Joshua Fisher, Malte Hoffmann, Mustafa Karaalioglu, Merlyn Morgan-Graham, Per Vognsen, Fabian Giesen, Jan Staubach, Matt Hargett, John Shearer, Jesse Chounard, kingcoopa, Miloš Tošić, Jonas Bernemann, Johan Andersson, Nathan Hartman, Michael Labbe, Tomasz Golebiowski, Louis Schnellbach, Felipe Alfonso, Jimmy Andrews, Bojan Endrovski, Robin Berg Pettersen, Rachel Crawford, Edsel Malasig, Andrew Johnson. +- Michel Courtine, César Leblic, Dale Kim, Alex Evans, Rui Figueira, Paul Patrashcu, Jerome Lanquetot, Ctrl Alt Ninja, Paul Fleming, Neil Henning, Stephan Dilly, Neil Blakey-Milner, Aleksei, NeiloGD, Justin Paver, FiniteSol, Vincent Pancaldi, James Billot, Robin Hübner, furrtek, Eric, Simon Barratt, Game Atelier, Julian Bosch, Simon Lundmark, Vincent Hamm, Farhan Wali, Jeff Roberts, Matt Reyer, Colin Riley, Victor Martins, Josh Simmons, Garrett Hoofman, Sergio Gonzales, Andrew Berridge, Roy Eltham, Game Preservation Society, Kit framework, Josh Faust, Martin Donlon, Quinton, Felix, Andrew Belt, Codecat, Cort Stratton, Claudio Canepa, Doug McNabb, Emmanuel Julien, Guillaume Chereau, Jeffrey Slutter, Jeremiah Deckard, r-lyeh, Roger Clark, Nekith, Joshua Fisher, Malte Hoffmann, Mustafa Karaalioglu, Merlyn Morgan-Graham, Per Vognsen, Fabian Giesen, Jan Staubach, Matt Hargett, John Shearer, Jesse Chounard, kingcoopa, Miloš Tošić, Jonas Bernemann, Johan Andersson, Nathan Hartman, Michael Labbe, Tomasz Golebiowski, Louis Schnellbach, Felipe Alfonso, Jimmy Andrews, Bojan Endrovski, Robin Berg Pettersen, Rachel Crawford, Edsel Malasig, Andrew Johnson, Sean Hunter, Jordan Mellow. And other supporters; thanks! (Please contact me or PR if you would like to be added or removed from this list) diff --git a/imgui.cpp b/imgui.cpp index 33574f66edb4..5596d24edce6 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -30,7 +30,7 @@ - FREQUENTLY ASKED QUESTIONS (FAQ), TIPS - How can I tell whether to dispatch mouse/keyboard to imgui or to my application? - How can I display an image? What is ImTextureID, how does it works? - - How can I have multiple widgets with the same label? Can I have widget without a label? (Yes). A primer on labels and the ID stack. + - How can I have multiple widgets with the same label or without a label? A primer on labels and the ID Stack. - How can I load a different font than the default? - How can I easily use icons in my application? - How can I load multiple fonts? @@ -433,63 +433,66 @@ It could be an identifier to your OpenGL texture (cast GLuint to void*), a pointer to your custom engine material (cast MyMaterial* to void*), etc. At the end of the chain, your renderer takes this void* to cast it back into whatever it needs to select a current texture to render. Refer to examples applications, where each renderer (in a imgui_impl_xxxx.cpp file) is treating ImTextureID as a different thing. - (c++ tip: OpenGL uses integers to identify textures. You can safely store an integer into a void*, just cast it to void*, don't take it's address!) + (C++ tip: OpenGL uses integers to identify textures. You can safely store an integer into a void*, just cast it to void*, don't take it's address!) To display a custom image/texture within an ImGui window, you may use ImGui::Image(), ImGui::ImageButton(), ImDrawList::AddImage() functions. Dear ImGui will generate the geometry and draw calls using the ImTextureID that you passed and which your renderer can use. You may call ImGui::ShowMetricsWindow() to explore active draw lists and visualize/understand how the draw data is generated. It is your responsibility to get textures uploaded to your GPU. - Q: Can I have multiple widgets with the same label? Can I have widget without a label? - A: Yes. A primer on labels and the ID stack... + Q: How can I have multiple widgets with the same label or without a label? + A: A primer on labels and the ID Stack... - Elements that are typically not clickable, such as Text() items don't need an ID. - Interactive widgets require state to be carried over multiple frames (most typically Dear ImGui often needs to remember what is - the "active" widget). to do so they need a unique ID. unique ID are typically derived from a string label, an integer index or a pointer. + the "active" widget). To do so they need a unique ID. Unique ID are typically derived from a string label, an integer index or a pointer. - Button("OK"); // Label = "OK", ID = hash of "OK" - Button("Cancel"); // Label = "Cancel", ID = hash of "Cancel" + Button("OK"); // Label = "OK", ID = top of id stack + hash of "OK" + Button("Cancel"); // Label = "Cancel", ID = top of id stack + hash of "Cancel" - - ID are uniquely scoped within windows, tree nodes, etc. so no conflict can happen if you have two buttons called "OK" - in two different windows or in two different locations of a tree. + - ID are uniquely scoped within windows, tree nodes, etc. which all push to the ID stack. So having two buttons labeled "OK" + in two different windows or in two different locations of a tree is fine. - If you have a same ID twice in the same location, you'll have a conflict: Button("OK"); - Button("OK"); // ID collision! Both buttons will be treated as the same. + Button("OK"); // ID collision! Interacting with either button will trigger the first one. Fear not! this is easy to solve and there are many ways to solve it! - - When passing a label you can optionally specify extra unique ID information within string itself. + - Solving ID conflict in a simple/local context: + When passing a label you can optionally specify extra unique ID information within string itself. Use "##" to pass a complement to the ID that won't be visible to the end-user. This helps solving the simple collision cases when you know which items are going to be created. - Button("Play"); // Label = "Play", ID = hash of "Play" - Button("Play##foo1"); // Label = "Play", ID = hash of "Play##foo1" (different from above) - Button("Play##foo2"); // Label = "Play", ID = hash of "Play##foo2" (different from above) + Button("Play"); // Label = "Play", ID = top of id stack + hash of "Play" + Button("Play##foo1"); // Label = "Play", ID = top of id stack + hash of "Play##foo1" (different from above) + Button("Play##foo2"); // Label = "Play", ID = top of id stack + hash of "Play##foo2" (different from above) - If you want to completely hide the label, but still need an ID: - Checkbox("##On", &b); // Label = "", ID = hash of "##On" (no label!) + Checkbox("##On", &b); // Label = "", ID = top of id stack + hash of "##On" (no label!) - Occasionally/rarely you might want change a label while preserving a constant ID. This allows you to animate labels. For example you may want to include varying information in a window title bar, but windows are uniquely identified by their ID.. Use "###" to pass a label that isn't part of ID: - Button("Hello###ID"; // Label = "Hello", ID = hash of "ID" - Button("World###ID"; // Label = "World", ID = hash of "ID" (same as above) + Button("Hello###ID"; // Label = "Hello", ID = top of id stack + hash of "ID" + Button("World###ID"; // Label = "World", ID = top of id stack + hash of "ID" (same as above) sprintf(buf, "My game (%f FPS)###MyGame", fps); Begin(buf); // Variable label, ID = hash of "MyGame" - - Use PushID() / PopID() to create scopes and avoid ID conflicts within the same Window. + - Solving ID conflict in a more general manner: + Use PushID() / PopID() to create scopes and manipulate the ID stack, as to avoid ID conflicts within the same Window. This is the most convenient way of distinguishing ID if you are iterating and creating many UI elements. - You can push a pointer, a string or an integer value. Remember that ID are formed from the concatenation of _everything_ in the ID stack! + You can push a pointer, a string or an integer value into the ID stack. + Remember that ID are formed from the concatenation of _everything_ in the ID stack! for (int i = 0; i < 100; i++) { PushID(i); - Button("Click"); // Label = "Click", ID = hash of integer + "label" (unique) + Button("Click"); // Label = "Click", ID = top of id stack + hash of integer + hash of "Click" PopID(); } @@ -497,7 +500,7 @@ { MyObject* obj = Objects[i]; PushID(obj); - Button("Click"); // Label = "Click", ID = hash of pointer + "label" (unique) + Button("Click"); // Label = "Click", ID = top of id stack + hash of pointer + hash of "Click" PopID(); } @@ -505,35 +508,35 @@ { MyObject* obj = Objects[i]; PushID(obj->Name); - Button("Click"); // Label = "Click", ID = hash of string + "label" (unique) + Button("Click"); // Label = "Click", ID = top of id stack + hash of string + hash of "Click" PopID(); } - More example showing that you can stack multiple prefixes into the ID stack: - Button("Click"); // Label = "Click", ID = hash of "Click" + Button("Click"); // Label = "Click", ID = top of id stack + hash of "Click" PushID("node"); - Button("Click"); // Label = "Click", ID = hash of "node" + "Click" + Button("Click"); // Label = "Click", ID = top of id stack + hash of "node" + hash of "Click" PushID(my_ptr); - Button("Click"); // Label = "Click", ID = hash of "node" + ptr + "Click" + Button("Click"); // Label = "Click", ID = top of id stack + hash of "node" + hash of ptr + hash of "Click" PopID(); PopID(); - Tree nodes implicitly creates a scope for you by calling PushID(). - Button("Click"); // Label = "Click", ID = hash of "Click" + Button("Click"); // Label = "Click", ID = top of id stack + hash of "Click" if (TreeNode("node")) { - Button("Click"); // Label = "Click", ID = hash of "node" + "Click" + Button("Click"); // Label = "Click", ID = top of id stack + hash of "node" + hash of "Click" TreePop(); } - When working with trees, ID are used to preserve the open/close state of each tree node. Depending on your use cases you may want to use strings, indices or pointers as ID. - e.g. when displaying a single object that may change over time (dynamic 1-1 relationship), using a static string as ID will preserve your + e.g. when following a single pointer that may change over time, using a static string as ID will preserve your node open/closed state when the targeted object change. e.g. when displaying a list of objects, using indices or pointers as ID will preserve the node open/closed state differently. - experiment and see what makes more sense! + experiment and see what makes more sense in your situation! Q: How can I load a different font than the default? (default is an embedded version of ProggyClean.ttf, rendered at size 13) A: Use the font atlas to load the TTF/OTF file you want: From 77e234d9df88760c937246b367c7f04fbba73748 Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 3 Apr 2018 20:22:44 +0200 Subject: [PATCH 799/823] Comments --- imgui.cpp | 98 +++++++++++++++++++++++++++++++------------------------ 1 file changed, 56 insertions(+), 42 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 5596d24edce6..684ecf37eac7 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -11,9 +11,10 @@ // If you work for a company, please consider financial support, see README. For individuals: https://www.patreon.com/imgui // It is recommended that you don't modify imgui.cpp! It will become difficult for you to update the library. -// Note that 'ImGui::' is a namespace and so you can add functions into it from your own source files without modifying imgui.h or imgui.cpp. -// You may include imgui_internal.h to access internal data structures, but it doesn't come with any guarantee of forward compatibility. -// Discussing your changes on the GitHub Issue Tracker may lead you to a better solution or official support for them. +// Note that 'ImGui::' being a namespace, you can add functions into the namespace from your own source files, without +// modifying imgui.h or imgui.cpp. You may include imgui_internal.h to access internal data structures, but it doesn't +// come with any guarantee of forward compatibility. Discussing your changes on the GitHub Issue Tracker may lead you +// to a better solution or official support for them. /* @@ -53,8 +54,8 @@ - Minimize setup and maintenance - Minimize state storage on user side - Portable, minimize dependencies, run on target (consoles, phones, etc.) - - Efficient runtime and memory consumption (NB- we do allocate when "growing" content e.g. creating a window, opening a tree node - for the first time, etc. but a typical frame won't allocate anything) + - Efficient runtime and memory consumption (NB- we do allocate when "growing" content e.g. creating a window, + opening a tree node for the first time, etc. but a typical frame should not allocate anything) Designed for developers and content-creators, not the typical end-user! Some of the weaknesses includes: - Doesn't look fancy, doesn't animate @@ -91,8 +92,8 @@ READ FIRST - Read the FAQ below this section! - - Your code creates the UI, if your code doesn't run the UI is gone! == very dynamic UI, no construction/destructions steps, less data retention - on your side, no state duplication, less sync, less bugs. + - Your code creates the UI, if your code doesn't run the UI is gone! The UI can be highly dynamic, there are no construction + or destruction steps, less data retention on your side, less state duplication, less state synchronization, less bugs. - Call and read ImGui::ShowDemoWindow() for demo code demonstrating most features. - You can learn about immediate-mode gui principles at http://www.johno.se/book/imgui.html or watch http://mollyrocket.com/861 @@ -100,18 +101,18 @@ - Overwrite all the sources files except for imconfig.h (if you have made modification to your copy of imconfig.h) - Read the "API BREAKING CHANGES" section (below). This is where we list occasional API breaking changes. - If a function/type has been renamed / or marked obsolete, try to fix the name in your code before it is permanently removed from the public API. - If you have a problem with a missing function/symbols, search for its name in the code, there will likely be a comment about it. - Please report any issue to the GitHub page! + If a function/type has been renamed / or marked obsolete, try to fix the name in your code before it is permanently removed + from the public API. If you have a problem with a missing function/symbols, search for its name in the code, there will + likely be a comment about it. Please report any issue to the GitHub page! - Try to keep your copy of dear imgui reasonably up to date. GETTING STARTED WITH INTEGRATING DEAR IMGUI IN YOUR CODE/ENGINE + - Run and study the examples and demo to get acquainted with the library. - Add the Dear ImGui source files to your projects, using your preferred build system. It is recommended you build the .cpp files as part of your project and not as a library. - You can later customize the imconfig.h file to tweak some compilation time behavior, such as integrating imgui types with your own maths types. - - See examples/ folder for standalone sample applications. - - You may be able to grab and copy a ready made imgui_impl_*** file from the examples/. + - You may be able to grab and copy a ready made imgui_impl_*** file from the examples/ folder. - When using Dear ImGui, your programming IDE is your friend: follow the declaration of variables, functions and types to find comments about them. - Init: retrieve the ImGuiIO structure with ImGui::GetIO() and fill the fields marked 'Settings': at minimum you need to set io.DisplaySize @@ -199,7 +200,8 @@ MyEngineBindTexture(pcmd->TextureId); // We are using scissoring to clip some objects. All low-level graphics API supports it. - // If your engine doesn't support scissoring yet, you will get some small glitches (some elements outside their bounds) which you can fix later. + // If your engine doesn't support scissoring yet, you may ignore this at first. You will get some small glitches + // (some elements visible outside their bounds) but you can fix that once everywhere else works! MyEngineScissor((int)pcmd->ClipRect.x, (int)pcmd->ClipRect.y, (int)(pcmd->ClipRect.z - pcmd->ClipRect.x), (int)(pcmd->ClipRect.w - pcmd->ClipRect.y)); // Render 'pcmd->ElemCount/3' indexed triangles. @@ -215,22 +217,25 @@ - When calling NewFrame(), the 'io.WantCaptureMouse'/'io.WantCaptureKeyboard'/'io.WantTextInput' flags are updated. They tell you if ImGui intends to use your inputs. So for example, if 'io.WantCaptureMouse' is set you would typically want to hide mouse inputs from the rest of your application. Read the FAQ below for more information about those flags. + - Please read the FAQ above. Amusingly, it is called a FAQ because people frequently have the same issues! USING GAMEPAD/KEYBOARD NAVIGATION CONTROLS [BETA] - The gamepad/keyboard navigation is in Beta. Ask questions and report issues at https://github.com/ocornut/imgui/issues/787 - The initial focus was to support game controllers, but keyboard is becoming increasingly and decently usable. - Keyboard: - - Set io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard to enable. NewFrame() will automatically fill io.NavInputs[] based on your io.KeyDown[] + io.KeyMap[] arrays. - - When keyboard navigation is active (io.NavActive + ImGuiConfigFlags_NavEnableKeyboard), the io.WantCaptureKeyboard flag will be set. - For more advanced uses, you may want to read from: + - Set io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard to enable. + NewFrame() will automatically fill io.NavInputs[] based on your io.KeyDown[] + io.KeyMap[] arrays. + - When keyboard navigation is active (io.NavActive + ImGuiConfigFlags_NavEnableKeyboard), the io.WantCaptureKeyboard flag + will be set. For more advanced uses, you may want to read from: - io.NavActive: true when a window is focused and it doesn't have the ImGuiWindowFlags_NoNavInputs flag set. - io.NavVisible: true when the navigation cursor is visible (and usually goes false when mouse is used). - or query focus information with e.g. IsWindowFocused(), IsItemFocused() etc. functions. Please reach out if you think the game vs navigation input sharing could be improved. - Gamepad: - Set io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad to enable. - - Backend: Set io.BackendFlags |= ImGuiBackendFlags_HasGamepad + fill the io.NavInputs[] fields before calling NewFrame(). Note that io.NavInputs[] is cleared by EndFrame(). + - Backend: Set io.BackendFlags |= ImGuiBackendFlags_HasGamepad + fill the io.NavInputs[] fields before calling NewFrame(). + Note that io.NavInputs[] is cleared by EndFrame(). - See 'enum ImGuiNavInput_' in imgui.h for a description of inputs. For each entry of io.NavInputs[], set the following values: 0.0f= not held. 1.0f= fully held. Pass intermediate 0.0f..1.0f values for analog triggers/sticks. - We uses a simple >0.0f test for activation testing, and won't attempt to test for a dead-zone. @@ -444,14 +449,15 @@ - Elements that are typically not clickable, such as Text() items don't need an ID. - - Interactive widgets require state to be carried over multiple frames (most typically Dear ImGui often needs to remember what is - the "active" widget). To do so they need a unique ID. Unique ID are typically derived from a string label, an integer index or a pointer. + - Interactive widgets require state to be carried over multiple frames (most typically Dear ImGui + often needs to remember what is the "active" widget). To do so they need a unique ID. Unique ID + are typically derived from a string label, an integer index or a pointer. Button("OK"); // Label = "OK", ID = top of id stack + hash of "OK" Button("Cancel"); // Label = "Cancel", ID = top of id stack + hash of "Cancel" - - ID are uniquely scoped within windows, tree nodes, etc. which all push to the ID stack. So having two buttons labeled "OK" - in two different windows or in two different locations of a tree is fine. + - ID are uniquely scoped within windows, tree nodes, etc. which all pushes to the ID stack. Having + two buttons labeled "OK" in different windows or different tree locations is fine. - If you have a same ID twice in the same location, you'll have a conflict: @@ -461,9 +467,10 @@ Fear not! this is easy to solve and there are many ways to solve it! - Solving ID conflict in a simple/local context: - When passing a label you can optionally specify extra unique ID information within string itself. + When passing a label you can optionally specify extra ID information within string itself. Use "##" to pass a complement to the ID that won't be visible to the end-user. - This helps solving the simple collision cases when you know which items are going to be created. + This helps solving the simple collision cases when you know e.g. at compilation time which items + are going to be created: Button("Play"); // Label = "Play", ID = top of id stack + hash of "Play" Button("Play##foo1"); // Label = "Play", ID = top of id stack + hash of "Play##foo1" (different from above) @@ -473,9 +480,9 @@ Checkbox("##On", &b); // Label = "", ID = top of id stack + hash of "##On" (no label!) - - Occasionally/rarely you might want change a label while preserving a constant ID. This allows you to animate labels. - For example you may want to include varying information in a window title bar, but windows are uniquely identified by their ID.. - Use "###" to pass a label that isn't part of ID: + - Occasionally/rarely you might want change a label while preserving a constant ID. This allows + you to animate labels. For example you may want to include varying information in a window title bar, + but windows are uniquely identified by their ID. Use "###" to pass a label that isn't part of ID: Button("Hello###ID"; // Label = "Hello", ID = top of id stack + hash of "ID" Button("World###ID"; // Label = "World", ID = top of id stack + hash of "ID" (same as above) @@ -484,8 +491,9 @@ Begin(buf); // Variable label, ID = hash of "MyGame" - Solving ID conflict in a more general manner: - Use PushID() / PopID() to create scopes and manipulate the ID stack, as to avoid ID conflicts within the same Window. - This is the most convenient way of distinguishing ID if you are iterating and creating many UI elements. + Use PushID() / PopID() to create scopes and manipulate the ID stack, as to avoid ID conflicts + within the same window. This is the most convenient way of distinguishing ID when iterating and + creating many UI elements programmatically. You can push a pointer, a string or an integer value into the ID stack. Remember that ID are formed from the concatenation of _everything_ in the ID stack! @@ -533,25 +541,28 @@ - When working with trees, ID are used to preserve the open/close state of each tree node. Depending on your use cases you may want to use strings, indices or pointers as ID. - e.g. when following a single pointer that may change over time, using a static string as ID will preserve your - node open/closed state when the targeted object change. - e.g. when displaying a list of objects, using indices or pointers as ID will preserve the node open/closed state differently. - experiment and see what makes more sense in your situation! + e.g. when following a single pointer that may change over time, using a static string as ID + will preserve your node open/closed state when the targeted object change. + e.g. when displaying a list of objects, using indices or pointers as ID will preserve the + node open/closed state differently. See what makes more sense in your situation! - Q: How can I load a different font than the default? (default is an embedded version of ProggyClean.ttf, rendered at size 13) + Q: How can I load a different font than the default? A: Use the font atlas to load the TTF/OTF file you want: ImGuiIO& io = ImGui::GetIO(); io.Fonts->AddFontFromFileTTF("myfontfile.ttf", size_in_pixels); io.Fonts->GetTexDataAsRGBA32() or GetTexDataAsAlpha8() + (default is ProggyClean.ttf, rendered at size 13, embedded in dear imgui's source code) - New programmers: remember that in C/C++ and most programming languages if you want to use a backslash \ in a string literal you need to write a double backslash "\\": - io.Fonts->AddFontFromFileTTF("MyDataFolder\MyFontFile.ttf", size_in_pixels); // WRONG + New programmers: remember that in C/C++ and most programming languages if you want to use a + backslash \ within a string literal, you need to write it double backslash "\\": + io.Fonts->AddFontFromFileTTF("MyDataFolder\MyFontFile.ttf", size_in_pixels); // WRONG (you are escape the M here!) io.Fonts->AddFontFromFileTTF("MyDataFolder\\MyFontFile.ttf", size_in_pixels); // CORRECT io.Fonts->AddFontFromFileTTF("MyDataFolder/MyFontFile.ttf", size_in_pixels); // ALSO CORRECT Q: How can I easily use icons in my application? - A: The most convenient and practical way is to merge an icon font such as FontAwesome inside you main font. Then you can refer to icons within your - strings. Read 'How can I load multiple fonts?' and the file 'misc/fonts/README.txt' for instructions and useful header files. + A: The most convenient and practical way is to merge an icon font such as FontAwesome inside you + main font. Then you can refer to icons within your strings. Read 'How can I load multiple fonts?' + and the file 'misc/fonts/README.txt' for instructions and useful header files. Q: How can I load multiple fonts? A: Use the font atlas to pack them into a single texture: @@ -596,13 +607,16 @@ builder.BuildRanges(&ranges); // Build the final result (ordered ranges with all the unique characters submitted) io.Fonts->AddFontFromFileTTF("myfontfile.ttf", size_in_pixels, NULL, ranges.Data); - All your strings needs to use UTF-8 encoding. In C++11 you can encode a string literal in UTF-8 by using the u8"hello" syntax. - Specifying literal in your source code using a local code page (such as CP-923 for Japanese or CP-1251 for Cyrillic) will NOT work! + All your strings needs to use UTF-8 encoding. In C++11 you can encode a string literal in UTF-8 + by using the u8"hello" syntax. Specifying literal in your source code using a local code page + (such as CP-923 for Japanese or CP-1251 for Cyrillic) will NOT work! Otherwise you can convert yourself to UTF-8 or load text data from file already saved as UTF-8. - Text input: it is up to your application to pass the right character code to io.AddInputCharacter(). The applications in examples/ are doing that. - For languages using IME, on Windows you can copy the Hwnd of your application to io.ImeWindowHandle. - The default implementation of io.ImeSetInputScreenPosFn() on Windows will set your IME position correctly. + Text input: it is up to your application to pass the right character code by calling + io.AddInputCharacter(). The applications in examples/ are doing that. For languages relying + on an Input Method Editor (IME), on Windows you can copy the Hwnd of your application in the + io.ImeWindowHandle field. The default implementation of io.ImeSetInputScreenPosFn() will set + your Microsoft IME position correctly. Q: How can I use the drawing facilities without an ImGui window? (using ImDrawList API) A: - You can create a dummy window. Call SetNextWindowBgAlpha(0.0f), call Begin() with NoTitleBar|NoResize|NoMove|NoScrollbar|NoSavedSettings|NoInputs flags. From 78610a54d21361f62231b5c0f93c911037865faa Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 3 Apr 2018 20:55:30 +0200 Subject: [PATCH 800/823] Fixed Clang zealous cast-call warning (on par with GCC) which decided to warn against explicit C-style casts now. --- imgui.cpp | 13 +++++++------ imgui_draw.cpp | 3 ++- imgui_internal.h | 2 +- 3 files changed, 10 insertions(+), 8 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 684ecf37eac7..8eb666b8864d 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -687,14 +687,15 @@ #pragma clang diagnostic ignored "-Wglobal-constructors" // warning : declaration requires a global destructor // similar to above, not sure what the exact difference it. #pragma clang diagnostic ignored "-Wsign-conversion" // warning : implicit conversion changes signedness // #pragma clang diagnostic ignored "-Wformat-pedantic" // warning : format specifies type 'void *' but the argument has type 'xxxx *' // unreasonable, would lead to casting every %p arg to void*. probably enabled by -pedantic. -#pragma clang diagnostic ignored "-Wint-to-void-pointer-cast" // warning : cast to 'void *' from smaller integer type 'int' // +#pragma clang diagnostic ignored "-Wint-to-void-pointer-cast" // warning : cast to 'void *' from smaller integer type 'int' +#pragma clang diagnostic ignored "-Wcast-qual" // warning : cast from 'const xxxx *' to 'xxxx *' drops const qualifier #elif defined(__GNUC__) #pragma GCC diagnostic ignored "-Wunused-function" // warning: 'xxxx' defined but not used #pragma GCC diagnostic ignored "-Wint-to-pointer-cast" // warning: cast to pointer from integer of different size #pragma GCC diagnostic ignored "-Wformat" // warning: format '%p' expects argument of type 'void*', but argument 6 has type 'ImGuiWindow*' #pragma GCC diagnostic ignored "-Wdouble-promotion" // warning: implicit conversion from 'float' to 'double' when passing argument to function #pragma GCC diagnostic ignored "-Wconversion" // warning: conversion to 'xxxx' from 'xxxx' may alter its value -#pragma GCC diagnostic ignored "-Wcast-qual" // warning: cast from type 'xxxx' to type 'xxxx' casts away qualifiers +#pragma GCC diagnostic ignored "-Wcast-qual" // warning: cast from type 'const xxxx *' to type 'xxxx *' casts away qualifiers #pragma GCC diagnostic ignored "-Wformat-nonliteral" // warning: format not a string literal, format string not checked #pragma GCC diagnostic ignored "-Wstrict-overflow" // warning: assuming signed overflow does not occur when assuming that (X - c) > X is always false #endif @@ -1025,11 +1026,11 @@ char* ImStrdup(const char *str) return (char*)memcpy(buf, (const void*)str, len); } -char* ImStrchrRange(const char* str, const char* str_end, char c) +const char* ImStrchrRange(const char* str, const char* str_end, char c) { for ( ; str < str_end; str++) if (*str == c) - return (char*)str; + return str; return NULL; } @@ -3762,7 +3763,7 @@ static void LoadIniSettingsFromMemory(const char* buf_readonly) line_end[-1] = 0; const char* name_end = line_end - 1; const char* type_start = line + 1; - char* type_end = ImStrchrRange(type_start, name_end, ']'); + char* type_end = (char*)ImStrchrRange(type_start, name_end, ']'); const char* name_start = type_end ? ImStrchrRange(type_end + 1, name_end, '[') : NULL; if (!type_end || !name_start) { @@ -9424,7 +9425,7 @@ struct ImGuiPlotArrayGetterData static float Plot_ArrayGetter(void* data, int idx) { ImGuiPlotArrayGetterData* plot_data = (ImGuiPlotArrayGetterData*)data; - const float v = *(float*)(void*)((unsigned char*)plot_data->Values + (size_t)idx * plot_data->Stride); + const float v = *(const float*)(const void*)((const unsigned char*)plot_data->Values + (size_t)idx * plot_data->Stride); return v; } diff --git a/imgui_draw.cpp b/imgui_draw.cpp index a2d0215f411f..4eba63941350 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -41,6 +41,7 @@ #pragma clang diagnostic ignored "-Wfloat-equal" // warning : comparing floating point with == or != is unsafe // storing and comparing against same constants ok. #pragma clang diagnostic ignored "-Wglobal-constructors" // warning : declaration requires a global destructor // similar to above, not sure what the exact difference it. #pragma clang diagnostic ignored "-Wsign-conversion" // warning : implicit conversion changes signedness // +#pragma clang diagnostic ignored "-Wcast-qual" // warning : cast from 'const xxxx *' to 'xxx *' drops const qualifier // #if __has_warning("-Wcomma") #pragma clang diagnostic ignored "-Wcomma" // warning : possible misuse of comma operator here // #endif @@ -54,7 +55,7 @@ #pragma GCC diagnostic ignored "-Wunused-function" // warning: 'xxxx' defined but not used #pragma GCC diagnostic ignored "-Wdouble-promotion" // warning: implicit conversion from 'float' to 'double' when passing argument to function #pragma GCC diagnostic ignored "-Wconversion" // warning: conversion to 'xxxx' from 'xxxx' may alter its value -#pragma GCC diagnostic ignored "-Wcast-qual" // warning: cast from type 'xxxx' to type 'xxxx' casts away qualifiers +#pragma GCC diagnostic ignored "-Wcast-qual" // warning: cast from type 'const xxxx *' to type 'xxxx *' casts away qualifiers #endif //------------------------------------------------------------------------- diff --git a/imgui_internal.h b/imgui_internal.h index b5c5b0e4e184..65edf576bb18 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -113,7 +113,7 @@ IMGUI_API int ImStricmp(const char* str1, const char* str2); IMGUI_API int ImStrnicmp(const char* str1, const char* str2, size_t count); IMGUI_API void ImStrncpy(char* dst, const char* src, size_t count); IMGUI_API char* ImStrdup(const char* str); -IMGUI_API char* ImStrchrRange(const char* str_begin, const char* str_end, char c); +IMGUI_API const char* ImStrchrRange(const char* str_begin, const char* str_end, char c); IMGUI_API int ImStrlenW(const ImWchar* str); IMGUI_API const ImWchar*ImStrbolW(const ImWchar* buf_mid_line, const ImWchar* buf_begin); // Find beginning-of-line IMGUI_API const char* ImStristr(const char* haystack, const char* haystack_end, const char* needle, const char* needle_end); From 84fbc49403d1e18ba0774f453eb72bcf7c9701ec Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 3 Apr 2018 22:13:35 +0200 Subject: [PATCH 801/823] BeginChild: named child don't include the full id inside their name (#1698) --- imgui.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/imgui.cpp b/imgui.cpp index 8eb666b8864d..2f00e0ba2bf9 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -5097,7 +5097,7 @@ static bool BeginChildEx(const char* name, ImGuiID id, const ImVec2& size_arg, b char title[256]; if (name) - ImFormatString(title, IM_ARRAYSIZE(title), "%s/%s_%08X", parent_window->Name, name, id); + ImFormatString(title, IM_ARRAYSIZE(title), "%s/%s", parent_window->Name, name); else ImFormatString(title, IM_ARRAYSIZE(title), "%s/%08X", parent_window->Name, id); From 1e116e6c1777399415a8873e3709546ee990b15e Mon Sep 17 00:00:00 2001 From: omar Date: Tue, 3 Apr 2018 23:18:43 +0200 Subject: [PATCH 802/823] Removed need for -Wnocast-qual on modern Clang/Xcode as a token of good behavior. Unfortunately the old stb_ decompress code is a little const clunky. + warning fix in stb_textedit which is already in master afaik. --- imgui.cpp | 12 +++++------- imgui_draw.cpp | 46 +++++++++++++++++++++++----------------------- stb_textedit.h | 3 +-- 3 files changed, 29 insertions(+), 32 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 2f00e0ba2bf9..1f0bec9c00f4 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -688,14 +688,12 @@ #pragma clang diagnostic ignored "-Wsign-conversion" // warning : implicit conversion changes signedness // #pragma clang diagnostic ignored "-Wformat-pedantic" // warning : format specifies type 'void *' but the argument has type 'xxxx *' // unreasonable, would lead to casting every %p arg to void*. probably enabled by -pedantic. #pragma clang diagnostic ignored "-Wint-to-void-pointer-cast" // warning : cast to 'void *' from smaller integer type 'int' -#pragma clang diagnostic ignored "-Wcast-qual" // warning : cast from 'const xxxx *' to 'xxxx *' drops const qualifier #elif defined(__GNUC__) #pragma GCC diagnostic ignored "-Wunused-function" // warning: 'xxxx' defined but not used #pragma GCC diagnostic ignored "-Wint-to-pointer-cast" // warning: cast to pointer from integer of different size #pragma GCC diagnostic ignored "-Wformat" // warning: format '%p' expects argument of type 'void*', but argument 6 has type 'ImGuiWindow*' #pragma GCC diagnostic ignored "-Wdouble-promotion" // warning: implicit conversion from 'float' to 'double' when passing argument to function #pragma GCC diagnostic ignored "-Wconversion" // warning: conversion to 'xxxx' from 'xxxx' may alter its value -#pragma GCC diagnostic ignored "-Wcast-qual" // warning: cast from type 'const xxxx *' to type 'xxxx *' casts away qualifiers #pragma GCC diagnostic ignored "-Wformat-nonliteral" // warning: format not a string literal, format string not checked #pragma GCC diagnostic ignored "-Wstrict-overflow" // warning: assuming signed overflow does not occur when assuming that (X - c) > X is always false #endif @@ -3763,7 +3761,7 @@ static void LoadIniSettingsFromMemory(const char* buf_readonly) line_end[-1] = 0; const char* name_end = line_end - 1; const char* type_start = line + 1; - char* type_end = (char*)ImStrchrRange(type_start, name_end, ']'); + char* type_end = (char*)(intptr_t)ImStrchrRange(type_start, name_end, ']'); const char* name_start = type_end ? ImStrchrRange(type_end + 1, name_end, '[') : NULL; if (!type_end || !name_start) { @@ -3839,8 +3837,8 @@ static void MarkIniSettingsDirty(ImGuiWindow* window) // FIXME: Add a more explicit sort order in the window structure. static int IMGUI_CDECL ChildWindowComparer(const void* lhs, const void* rhs) { - const ImGuiWindow* a = *(const ImGuiWindow**)lhs; - const ImGuiWindow* b = *(const ImGuiWindow**)rhs; + const ImGuiWindow* const a = *(const ImGuiWindow* const *)lhs; + const ImGuiWindow* const b = *(const ImGuiWindow* const *)rhs; if (int d = (a->Flags & ImGuiWindowFlags_Popup) - (b->Flags & ImGuiWindowFlags_Popup)) return d; if (int d = (a->Flags & ImGuiWindowFlags_Tooltip) - (b->Flags & ImGuiWindowFlags_Tooltip)) @@ -12935,14 +12933,14 @@ bool ImGui::SetDragDropPayload(const char* type, const void* data, size_t data_s // Store in heap g.DragDropPayloadBufHeap.resize((int)data_size); payload.Data = g.DragDropPayloadBufHeap.Data; - memcpy((void*)payload.Data, data, data_size); + memcpy((void*)(intptr_t)payload.Data, data, data_size); } else if (data_size > 0) { // Store locally memset(&g.DragDropPayloadBufLocal, 0, sizeof(g.DragDropPayloadBufLocal)); payload.Data = g.DragDropPayloadBufLocal; - memcpy((void*)payload.Data, data, data_size); + memcpy((void*)(intptr_t)payload.Data, data, data_size); } else { diff --git a/imgui_draw.cpp b/imgui_draw.cpp index 4eba63941350..b7ba849bfab3 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -41,7 +41,6 @@ #pragma clang diagnostic ignored "-Wfloat-equal" // warning : comparing floating point with == or != is unsafe // storing and comparing against same constants ok. #pragma clang diagnostic ignored "-Wglobal-constructors" // warning : declaration requires a global destructor // similar to above, not sure what the exact difference it. #pragma clang diagnostic ignored "-Wsign-conversion" // warning : implicit conversion changes signedness // -#pragma clang diagnostic ignored "-Wcast-qual" // warning : cast from 'const xxxx *' to 'xxx *' drops const qualifier // #if __has_warning("-Wcomma") #pragma clang diagnostic ignored "-Wcomma" // warning : possible misuse of comma operator here // #endif @@ -55,7 +54,6 @@ #pragma GCC diagnostic ignored "-Wunused-function" // warning: 'xxxx' defined but not used #pragma GCC diagnostic ignored "-Wdouble-promotion" // warning: implicit conversion from 'float' to 'double' when passing argument to function #pragma GCC diagnostic ignored "-Wconversion" // warning: conversion to 'xxxx' from 'xxxx' may alter its value -#pragma GCC diagnostic ignored "-Wcast-qual" // warning: cast from type 'const xxxx *' to type 'xxxx *' casts away qualifiers #endif //------------------------------------------------------------------------- @@ -84,11 +82,13 @@ namespace IMGUI_STB_NAMESPACE #pragma clang diagnostic ignored "-Wunused-function" #pragma clang diagnostic ignored "-Wmissing-prototypes" #pragma clang diagnostic ignored "-Wimplicit-fallthrough" +#pragma clang diagnostic ignored "-Wcast-qual" // warning : cast from 'const xxxx *' to 'xxx *' drops const qualifier // #endif #ifdef __GNUC__ #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wtype-limits" // warning: comparison is always true due to limited range of data type [-Wtype-limits] +#pragma GCC diagnostic ignored "-Wcast-qual" // warning: cast from type 'const xxxx *' to type 'xxxx *' casts away qualifiers #endif #ifndef IMGUI_DISABLE_STB_RECT_PACK_IMPLEMENTATION @@ -1508,8 +1508,8 @@ ImFont* ImFontAtlas::AddFont(const ImFontConfig* font_cfg) } // Default font TTF is compressed with stb_compress then base85 encoded (see misc/fonts/binary_to_compressed_c.cpp for encoder) -static unsigned int stb_decompress_length(unsigned char *input); -static unsigned int stb_decompress(unsigned char *output, unsigned char *i, unsigned int length); +static unsigned int stb_decompress_length(const unsigned char *input); +static unsigned int stb_decompress(unsigned char *output, const unsigned char *input, unsigned int length); static const char* GetDefaultCompressedFontDataTTFBase85(); static unsigned int Decode85Byte(char c) { return c >= '\\' ? c-36 : c-35; } static void Decode85(const unsigned char* src, unsigned char* dst) @@ -1576,9 +1576,9 @@ ImFont* ImFontAtlas::AddFontFromMemoryTTF(void* ttf_data, int ttf_size, float si ImFont* ImFontAtlas::AddFontFromMemoryCompressedTTF(const void* compressed_ttf_data, int compressed_ttf_size, float size_pixels, const ImFontConfig* font_cfg_template, const ImWchar* glyph_ranges) { - const unsigned int buf_decompressed_size = stb_decompress_length((unsigned char*)compressed_ttf_data); + const unsigned int buf_decompressed_size = stb_decompress_length((const unsigned char*)compressed_ttf_data); unsigned char* buf_decompressed_data = (unsigned char *)ImGui::MemAlloc(buf_decompressed_size); - stb_decompress(buf_decompressed_data, (unsigned char*)compressed_ttf_data, (unsigned int)compressed_ttf_size); + stb_decompress(buf_decompressed_data, (const unsigned char*)compressed_ttf_data, (unsigned int)compressed_ttf_size); ImFontConfig font_cfg = font_cfg_template ? *font_cfg_template : ImFontConfig(); IM_ASSERT(font_cfg.FontData == NULL); @@ -2756,27 +2756,28 @@ void ImGui::RenderRectFilledRangeH(ImDrawList* draw_list, const ImRect& rect, Im // Decompression from stb.h (public domain) by Sean Barrett https://github.com/nothings/stb/blob/master/stb.h //----------------------------------------------------------------------------- -static unsigned int stb_decompress_length(unsigned char *input) +static unsigned int stb_decompress_length(const unsigned char *input) { return (input[8] << 24) + (input[9] << 16) + (input[10] << 8) + input[11]; } -static unsigned char *stb__barrier, *stb__barrier2, *stb__barrier3, *stb__barrier4; +static unsigned char *stb__barrier_out_e, *stb__barrier_out_b; +static const unsigned char *stb__barrier_in_b; static unsigned char *stb__dout; -static void stb__match(unsigned char *data, unsigned int length) +static void stb__match(const unsigned char *data, unsigned int length) { // INVERSE of memmove... write each byte before copying the next... - IM_ASSERT (stb__dout + length <= stb__barrier); - if (stb__dout + length > stb__barrier) { stb__dout += length; return; } - if (data < stb__barrier4) { stb__dout = stb__barrier+1; return; } + IM_ASSERT(stb__dout + length <= stb__barrier_out_e); + if (stb__dout + length > stb__barrier_out_e) { stb__dout += length; return; } + if (data < stb__barrier_out_b) { stb__dout = stb__barrier_out_e+1; return; } while (length--) *stb__dout++ = *data++; } -static void stb__lit(unsigned char *data, unsigned int length) +static void stb__lit(const unsigned char *data, unsigned int length) { - IM_ASSERT (stb__dout + length <= stb__barrier); - if (stb__dout + length > stb__barrier) { stb__dout += length; return; } - if (data < stb__barrier2) { stb__dout = stb__barrier+1; return; } + IM_ASSERT(stb__dout + length <= stb__barrier_out_e); + if (stb__dout + length > stb__barrier_out_e) { stb__dout += length; return; } + if (data < stb__barrier_in_b) { stb__dout = stb__barrier_out_e+1; return; } memcpy(stb__dout, data, length); stb__dout += length; } @@ -2785,7 +2786,7 @@ static void stb__lit(unsigned char *data, unsigned int length) #define stb__in3(x) ((i[x] << 16) + stb__in2((x)+1)) #define stb__in4(x) ((i[x] << 24) + stb__in3((x)+1)) -static unsigned char *stb_decompress_token(unsigned char *i) +static const unsigned char *stb_decompress_token(const unsigned char *i) { if (*i >= 0x20) { // use fewer if's for cases that expand small if (*i >= 0x80) stb__match(stb__dout-i[1]-1, i[0] - 0x80 + 1), i += 2; @@ -2833,21 +2834,20 @@ static unsigned int stb_adler32(unsigned int adler32, unsigned char *buffer, uns return (unsigned int)(s2 << 16) + (unsigned int)s1; } -static unsigned int stb_decompress(unsigned char *output, unsigned char *i, unsigned int length) +static unsigned int stb_decompress(unsigned char *output, const unsigned char *i, unsigned int /*length*/) { unsigned int olen; if (stb__in4(0) != 0x57bC0000) return 0; if (stb__in4(4) != 0) return 0; // error! stream is > 4GB olen = stb_decompress_length(i); - stb__barrier2 = i; - stb__barrier3 = i+length; - stb__barrier = output + olen; - stb__barrier4 = output; + stb__barrier_in_b = i; + stb__barrier_out_e = output + olen; + stb__barrier_out_b = output; i += 16; stb__dout = output; for (;;) { - unsigned char *old_i = i; + const unsigned char *old_i = i; i = stb_decompress_token(i); if (i == old_i) { if (*i == 0x05 && i[1] == 0xfa) { diff --git a/stb_textedit.h b/stb_textedit.h index 4b731a0c2295..7324fb6b4a45 100644 --- a/stb_textedit.h +++ b/stb_textedit.h @@ -677,9 +677,8 @@ static int stb_textedit_cut(STB_TEXTEDIT_STRING *str, STB_TexteditState *state) } // API paste: replace existing selection with passed-in text -static int stb_textedit_paste(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, STB_TEXTEDIT_CHARTYPE const *ctext, int len) +static int stb_textedit_paste(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, STB_TEXTEDIT_CHARTYPE const *text, int len) { - STB_TEXTEDIT_CHARTYPE *text = (STB_TEXTEDIT_CHARTYPE *) ctext; // if there's a selection, the paste should delete it stb_textedit_clamp(str, state); stb_textedit_delete_selection(str,state); From 2fa113c8955b5aa0c4af0180f0a834130fabf718 Mon Sep 17 00:00:00 2001 From: Francisco Demartino Date: Tue, 3 Apr 2018 19:03:55 -0300 Subject: [PATCH 803/823] README.md: add link to Gallery Part 6 --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 8cb24a04804a..13cfbe952c20 100644 --- a/README.md +++ b/README.md @@ -164,7 +164,8 @@ User screenshots:
[Gallery Part 2](https://github.com/ocornut/imgui/issues/539) (Feb 2016 to Aug 2016)
[Gallery Part 3](https://github.com/ocornut/imgui/issues/772) (Aug 2016 to Jan 2017)
[Gallery Part 4](https://github.com/ocornut/imgui/issues/973) (Jan 2017 to Aug 2017) -
[Gallery Part 5](https://github.com/ocornut/imgui/issues/1269) (Aug 2017 onward) +
[Gallery Part 5](https://github.com/ocornut/imgui/issues/1269) (Aug 2017 to Feb 2018) +
[Gallery Part 6](https://github.com/ocornut/imgui/issues/1607) (Feb 2018 onward)
Also see the [Mega screenshots](https://github.com/ocornut/imgui/issues/1273) for an idea of the available features. Various tools From cd1e6e384f7a8a8c194d4182db534cb1510873e1 Mon Sep 17 00:00:00 2001 From: omar Date: Wed, 4 Apr 2018 12:39:24 +0200 Subject: [PATCH 804/823] Tooltip windows uses PopupBorderSize (#1697) + commented out debug stuff. --- imgui.cpp | 4 +++- imgui.h | 4 ++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 1f0bec9c00f4..acda1fb19d60 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -4825,6 +4825,7 @@ void ImGui::OpenPopupEx(ImGuiID id) popup_ref.OpenMousePos = g.IO.MousePos; popup_ref.OpenPopupPos = (!g.NavDisableHighlight && g.NavDisableMouseHover) ? NavCalcPreferredMousePos() : g.IO.MousePos; + //printf("[%05d] OpenPopupEx(0x%08X)\n", g.FrameCount, id); if (g.OpenPopupStack.Size < current_stack_size + 1) { g.OpenPopupStack.push_back(popup_ref); @@ -5727,7 +5728,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) // Lock window rounding, border size and rounding so that altering the border sizes for children doesn't have side-effects. window->WindowRounding = (flags & ImGuiWindowFlags_ChildWindow) ? style.ChildRounding : ((flags & ImGuiWindowFlags_Popup) && !(flags & ImGuiWindowFlags_Modal)) ? style.PopupRounding : style.WindowRounding; - window->WindowBorderSize = (flags & ImGuiWindowFlags_ChildWindow) ? style.ChildBorderSize : ((flags & ImGuiWindowFlags_Popup) && !(flags & ImGuiWindowFlags_Modal)) ? style.PopupBorderSize : style.WindowBorderSize; + window->WindowBorderSize = (flags & ImGuiWindowFlags_ChildWindow) ? style.ChildBorderSize : ((flags & (ImGuiWindowFlags_Popup | ImGuiWindowFlags_Tooltip)) && !(flags & ImGuiWindowFlags_Modal)) ? style.PopupBorderSize : style.WindowBorderSize; window->WindowPadding = style.WindowPadding; if ((flags & ImGuiWindowFlags_ChildWindow) && !(flags & (ImGuiWindowFlags_AlwaysUseWindowPadding | ImGuiWindowFlags_Popup)) && window->WindowBorderSize == 0.0f) window->WindowPadding = ImVec2(0.0f, (flags & ImGuiWindowFlags_MenuBar) ? style.WindowPadding.y : 0.0f); @@ -6391,6 +6392,7 @@ void ImGui::FocusWindow(ImGuiWindow* window) g.NavId = window ? window->NavLastIds[0] : 0; // Restore NavId g.NavIdIsAlive = false; g.NavLayer = 0; + //printf("[%05d] FocusWindow(\"%s\")\n", g.FrameCount, window ? window->Name : NULL); } // Passing NULL allow to disable keyboard focus diff --git a/imgui.h b/imgui.h index a79705bd0f83..1e8b9aff1f63 100644 --- a/imgui.h +++ b/imgui.h @@ -963,8 +963,8 @@ struct ImGuiStyle ImVec2 WindowTitleAlign; // Alignment for title bar text. Defaults to (0.0f,0.5f) for left-aligned,vertically centered. float ChildRounding; // Radius of child window corners rounding. Set to 0.0f to have rectangular windows. float ChildBorderSize; // Thickness of border around child windows. Generally set to 0.0f or 1.0f. (Other values are not well tested and more CPU/GPU costly). - float PopupRounding; // Radius of popup window corners rounding. - float PopupBorderSize; // Thickness of border around popup windows. Generally set to 0.0f or 1.0f. (Other values are not well tested and more CPU/GPU costly). + float PopupRounding; // Radius of popup window corners rounding. (Note that tooltip windows use WindowRounding) + float PopupBorderSize; // Thickness of border around popup/tooltip windows. Generally set to 0.0f or 1.0f. (Other values are not well tested and more CPU/GPU costly). ImVec2 FramePadding; // Padding within a framed rectangle (used by most widgets). float FrameRounding; // Radius of frame corners rounding. Set to 0.0f to have rectangular frame (used by most widgets). float FrameBorderSize; // Thickness of border around frames. Generally set to 0.0f or 1.0f. (Other values are not well tested and more CPU/GPU costly). From 4649967112f71b149cc4c8e67c28d815d5edf0e9 Mon Sep 17 00:00:00 2001 From: omar Date: Wed, 4 Apr 2018 15:01:01 +0200 Subject: [PATCH 805/823] Added extra comments and assertions to avoid user combining ImGuiCond flags. (#1694) --- CHANGELOG.txt | 7 +++++-- imgui.cpp | 7 +++++++ imgui.h | 2 +- 3 files changed, 13 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.txt b/CHANGELOG.txt index 266c7ff58925..b9647414ec8a 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -206,7 +206,8 @@ Breaking Changes: - Renamed `ImGuiTextBuffer::append()` helper to `appendf()`, and `appendv()` to `appendfv()` for consistency. If you copied the 'Log' demo in your code, it uses appendv() so that needs to be renamed. - ImDrawList: Removed 'bool anti_aliased = true' final parameter of `ImDrawList::AddPolyline()` and `ImDrawList::AddConvexPolyFilled()`. Prefer manipulating ImDrawList::Flags if you need to toggle them during the frame. - Style, ImDrawList: Renamed `style.AntiAliasedShapes` to `style.AntiAliasedFill` for consistency and as a way to explicitly break code that manipulate those flag at runtime. You can now manipulate ImDrawList::Flags. -- Style, Begin: Removed `ImGuiWindowFlags_ShowBorders` window flag. Borders are now fully set up in the ImGuiStyle structure (see e.g. `style.FrameBorderSize`, `style.WindowBorderSize`). Use `ImGui::ShowStyleEditor()` to look them up. +- Style, Begin: Removed `ImGuiWindowFlags_ShowBorders` window flag. Borders are now fully set up in the ImGuiStyle structure (see e.g. `style.FrameBorderSize`, `style.WindowBorderSize`, `style.PopupBorderSize`). + Use `ImGui::ShowStyleEditor()` to look them up. Please note that the style system will keep evolving (hopefully stabilizing in Q1 2018), and so custom styles will probably subtly break over time. It is recommended that you use the `StyleColorsClassic()`, `StyleColorsDark()`, `StyleColorsLight()` functions. Also see `ShowStyleSelector()`. - Style: Removed `ImGuiCol_ComboBg` in favor of combo boxes using `ImGuiCol_PopupBg` for consistency. Combo are normal popups. @@ -231,7 +232,8 @@ Other Changes: - Style: Added StyleColorsDark() style. (#707) [@dougbinks] - Style: Added StyleColorsLight() style. Best used with frame borders + thicker font than the default font. (#707) - Style: Added style.PopupRounding setting. (#1112) -- Style: Added style.FrameBorderSize, style.WindowBorderSize. Removed ImGuiWindowFlags_ShowBorders window flag! Borders are now fully set up in the ImGuiStyle structure. Use ImGui::ShowStyleEditor() to look them up. (#707, fix #819, #1031) +- Style: Added style.FrameBorderSize, style.WindowBorderSize, style.PopupBorderSize. Removed ImGuiWindowFlags_ShowBorders window flag! + Borders are now fully set up in the ImGuiStyle structure. Use ImGui::ShowStyleEditor() to look them up. (#707, fix #819, #1031) - Style: Various small changes to the classic style (most noticeably, buttons are now using blue shades). (#707) - Style: Renamed ImGuiCol_ChildWindowBg to ImGuiCol_ChildBg. - Style: Renamed style.ChildWindowRounding to style.ChildRounding, ImGuiStyleVar_ChildWindowRounding to ImGuiStyleVar_ChildRounding. @@ -261,6 +263,7 @@ Other Changes: - Window: Using the ImGuiWindowFlags_NoScrollWithMouse flag on a child window forwards the mouse wheel event to the parent window, unless either ImGuiWindowFlags_NoInputs or ImGuiWindowFlags_NoScrollbar are also set. (#1380, #1502) - Window: Active Modal window always set the WantCaptureKeyboard flag. (#744) - Window: Moving window doesn't use accumulating MouseDelta so straying out of imgui boundaries keeps moved imgui window at the same cursor-relative position. +- Window: BeginChild() which an explicit name doesn't include the hash within the internal window name. (#1698) - IsWindowFocused(): Added ImGuiFocusedFlags_ChildWindows flag to include child windows in the focused test. (#1382). - IsWindowFocused(): Added ImGuiFocusedFlags_RootWindow flag to start focused test from the root (top-most) window. Obsolete IsRootWindowFocused(). (#1382) - IsWindowHovered(): Added ImGuiHoveredFlags_ChildWindows flag to include child windows in the hovered test. (#1382). diff --git a/imgui.cpp b/imgui.cpp index acda1fb19d60..6aeedb5889c2 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -6846,6 +6846,8 @@ static void SetWindowPos(ImGuiWindow* window, const ImVec2& pos, ImGuiCond cond) // Test condition (NB: bit 0 is always true) and clear flags for next time if (cond && (window->SetWindowPosAllowFlags & cond) == 0) return; + + IM_ASSERT(cond == 0 || ImIsPowerOfTwo(cond)); // Make sure the user doesn't attempt to combine multiple condition flags. window->SetWindowPosAllowFlags &= ~(ImGuiCond_Once | ImGuiCond_FirstUseEver | ImGuiCond_Appearing); window->SetWindowPosVal = ImVec2(FLT_MAX, FLT_MAX); @@ -6880,6 +6882,8 @@ static void SetWindowSize(ImGuiWindow* window, const ImVec2& size, ImGuiCond con // Test condition (NB: bit 0 is always true) and clear flags for next time if (cond && (window->SetWindowSizeAllowFlags & cond) == 0) return; + + IM_ASSERT(cond == 0 || ImIsPowerOfTwo(cond)); // Make sure the user doesn't attempt to combine multiple condition flags. window->SetWindowSizeAllowFlags &= ~(ImGuiCond_Once | ImGuiCond_FirstUseEver | ImGuiCond_Appearing); // Set @@ -6971,6 +6975,7 @@ void ImGui::SetWindowFocus(const char* name) void ImGui::SetNextWindowPos(const ImVec2& pos, ImGuiCond cond, const ImVec2& pivot) { ImGuiContext& g = *GImGui; + IM_ASSERT(cond == 0 || ImIsPowerOfTwo(cond)); // Make sure the user doesn't attempt to combine multiple condition flags. g.NextWindowData.PosVal = pos; g.NextWindowData.PosPivotVal = pivot; g.NextWindowData.PosCond = cond ? cond : ImGuiCond_Always; @@ -6979,6 +6984,7 @@ void ImGui::SetNextWindowPos(const ImVec2& pos, ImGuiCond cond, const ImVec2& pi void ImGui::SetNextWindowSize(const ImVec2& size, ImGuiCond cond) { ImGuiContext& g = *GImGui; + IM_ASSERT(cond == 0 || ImIsPowerOfTwo(cond)); // Make sure the user doesn't attempt to combine multiple condition flags. g.NextWindowData.SizeVal = size; g.NextWindowData.SizeCond = cond ? cond : ImGuiCond_Always; } @@ -7002,6 +7008,7 @@ void ImGui::SetNextWindowContentSize(const ImVec2& size) void ImGui::SetNextWindowCollapsed(bool collapsed, ImGuiCond cond) { ImGuiContext& g = *GImGui; + IM_ASSERT(cond == 0 || ImIsPowerOfTwo(cond)); // Make sure the user doesn't attempt to combine multiple condition flags. g.NextWindowData.CollapsedVal = collapsed; g.NextWindowData.CollapsedCond = cond ? cond : ImGuiCond_Always; } diff --git a/imgui.h b/imgui.h index 1e8b9aff1f63..c4b658d55c06 100644 --- a/imgui.h +++ b/imgui.h @@ -937,7 +937,7 @@ enum ImGuiMouseCursor_ }; // Condition for ImGui::SetWindow***(), SetNextWindow***(), SetNextTreeNode***() functions -// All those functions treat 0 as a shortcut to ImGuiCond_Always. From the point of view of the user use this as an enum (don't combine multiple values into flags). +// Important: Treat as a regular enum! Do NOT combine multiple values using binary operators! All the functions above treat 0 as a shortcut to ImGuiCond_Always. enum ImGuiCond_ { ImGuiCond_Always = 1 << 0, // Set the variable From 5aa3f99b4c76c1212394bd55e2bacaf54594197b Mon Sep 17 00:00:00 2001 From: omar Date: Wed, 4 Apr 2018 17:21:36 +0200 Subject: [PATCH 806/823] Internal: using more consistent comparaison with HiddenFrames to not imply it could be -1. Tweaked comments. --- imgui.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 6aeedb5889c2..710e85edd753 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -3245,7 +3245,7 @@ static void ImGui::NavUpdate() g.NavScoringCount = 0; #if IMGUI_DEBUG_NAV_RECTS if (g.NavWindow) { for (int layer = 0; layer < 2; layer++) g.OverlayDrawList.AddRect(g.NavWindow->Pos + g.NavWindow->NavRectRel[layer].Min, g.NavWindow->Pos + g.NavWindow->NavRectRel[layer].Max, IM_COL32(255,200,0,255)); } // [DEBUG] - if (g.NavWindow) { ImU32 col = (g.NavWindow->HiddenFrames <= 0) ? IM_COL32(255,0,255,255) : IM_COL32(255,0,0,255); ImVec2 p = NavCalcPreferredMousePos(); char buf[32]; ImFormatString(buf, 32, "%d", g.NavLayer); g.OverlayDrawList.AddCircleFilled(p, 3.0f, col); g.OverlayDrawList.AddText(NULL, 13.0f, p + ImVec2(8,-4), col, buf); } + if (g.NavWindow) { ImU32 col = (g.NavWindow->HiddenFrames == 0) ? IM_COL32(255,0,255,255) : IM_COL32(255,0,0,255); ImVec2 p = NavCalcPreferredMousePos(); char buf[32]; ImFormatString(buf, 32, "%d", g.NavLayer); g.OverlayDrawList.AddCircleFilled(p, 3.0f, col); g.OverlayDrawList.AddText(NULL, 13.0f, p + ImVec2(8,-4), col, buf); } #endif } @@ -3902,7 +3902,7 @@ static void AddWindowToDrawData(ImVector* out_render_list, ImGuiWin for (int i = 0; i < window->DC.ChildWindows.Size; i++) { ImGuiWindow* child = window->DC.ChildWindows[i]; - if (child->Active && child->HiddenFrames <= 0) // clipped children may have been marked not active + if (child->Active && child->HiddenFrames == 0) // clipped children may have been marked not active AddWindowToDrawData(out_render_list, child); } } @@ -4070,10 +4070,10 @@ void ImGui::Render() for (int n = 0; n != g.Windows.Size; n++) { ImGuiWindow* window = g.Windows[n]; - if (window->Active && window->HiddenFrames <= 0 && (window->Flags & ImGuiWindowFlags_ChildWindow) == 0 && window != window_to_render_front_most) + if (window->Active && window->HiddenFrames == 0 && (window->Flags & ImGuiWindowFlags_ChildWindow) == 0 && window != window_to_render_front_most) AddWindowToDrawDataSelectLayer(window); } - if (window_to_render_front_most && window_to_render_front_most->Active && window_to_render_front_most->HiddenFrames <= 0) // NavWindowingTarget is always temporarily displayed as the front-most window + if (window_to_render_front_most && window_to_render_front_most->Active && window_to_render_front_most->HiddenFrames == 0) // NavWindowingTarget is always temporarily displayed as the front-most window AddWindowToDrawDataSelectLayer(window_to_render_front_most); g.DrawDataBuilder.FlattenIntoSingleLayer(); @@ -4773,7 +4773,7 @@ void ImGui::BeginTooltipEx(ImGuiWindowFlags extra_flags, bool override_previous_ if (ImGuiWindow* window = FindWindowByName(window_name)) if (window->Active) { - // Hide previous tooltips. We can't easily "reset" the content of a window so we create a new one. + // Hide previous tooltip from being displayed. We can't easily "reset" the content of a window so we create a new one. window->HiddenFrames = 1; ImFormatString(window_name, IM_ARRAYSIZE(window_name), "##Tooltip_%02d", ++g.TooltipOverrideCount); } @@ -5619,7 +5619,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) // Update the Appearing flag bool window_just_activated_by_user = (window->LastFrameActive < current_frame - 1); // Not using !WasActive because the implicit "Debug" window would always toggle off->on - const bool window_just_appearing_after_hidden_for_resize = (window->HiddenFrames == 1); + const bool window_just_appearing_after_hidden_for_resize = (window->HiddenFrames > 0); if (flags & ImGuiWindowFlags_Popup) { ImGuiPopupRef& popup_ref = g.OpenPopupStack[g.CurrentPopupStack.Size]; @@ -5775,7 +5775,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) // Calculate auto-fit size, handle automatic resize const ImVec2 size_auto_fit = CalcSizeAutoFit(window, window->SizeContents); ImVec2 size_full_modified(FLT_MAX, FLT_MAX); - if (flags & ImGuiWindowFlags_AlwaysAutoResize && !window->Collapsed) + if ((flags & ImGuiWindowFlags_AlwaysAutoResize) && !window->Collapsed) { // Using SetNextWindowSize() overrides ImGuiWindowFlags_AlwaysAutoResize, so it can be used on tooltips/popups, etc. if (!window_size_x_set_by_api) @@ -5785,7 +5785,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) } else if (window->AutoFitFramesX > 0 || window->AutoFitFramesY > 0) { - // Auto-fit only grows during the first few frames + // Auto-fit may only grow window during the first few frames // We still process initial auto-fit on collapsed windows to get a window width, but otherwise don't honor ImGuiWindowFlags_AlwaysAutoResize when collapsed. if (!window_size_x_set_by_api && window->AutoFitFramesX > 0) window->SizeFull.x = size_full_modified.x = window->AutoFitOnlyGrows ? ImMax(window->SizeFull.x, size_auto_fit.x) : size_auto_fit.x; From fc30462f18fa03b9004324567118b76e0e930209 Mon Sep 17 00:00:00 2001 From: omar Date: Wed, 4 Apr 2018 19:35:08 +0200 Subject: [PATCH 807/823] Hide new windows for one frame until they calculate their size. Also fixes SetNextWindowPos() given a non-zero pivot. (#1694) --- CHANGELOG.txt | 1 + imgui.cpp | 9 +++++++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.txt b/CHANGELOG.txt index b9647414ec8a..b359fb7bcad6 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -257,6 +257,7 @@ Other Changes: - Window: Fixed a one frame glitch. When an appearing window claimed the focus themselves, the title bar wouldn't use the focused color for one frame. - Window: Added ImGuiWindowFlags_ResizeFromAnySide flag to resize from any borders or from the lower-left corner of a window. This requires your backend to honor GetMouseCursor() requests for full usability. (#822) - Window: Sizing fixes when useing SetNextWindowSize() on individual axises. +- Window: Hide new window for one frame until they calculate their size. Also fixes SetNextWindowPos() given a non-zero pivot. (#1694) - Window: Made mouse wheel scrolling accomodate better to windows that are smaller than the scroll step. - Window: SetNextWindowContentSize() adjust for the size of decorations (title bar/menu bar), but _not_ for borders are we consistently make borders not affect layout. If you need a non-child window of an exact size with border enabled but zero window padding, you'll need to accodomate for the border size yourself. diff --git a/imgui.cpp b/imgui.cpp index 710e85edd753..dc1ff9238572 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -5597,7 +5597,8 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) // Find or create ImGuiWindow* window = FindWindowByName(name); - if (!window) + const bool window_just_created = (window == NULL); + if (window_just_created) { ImVec2 size_on_first_use = (g.NextWindowData.SizeCond != 0) ? g.NextWindowData.SizeVal : ImVec2(0.0f, 0.0f); // Any condition flag will do since we are creating a new window here. window = CreateNewWindow(name, size_on_first_use, flags); @@ -5759,7 +5760,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) // Hide popup/tooltip window when re-opening while we measure size (because we recycle the windows) if (window->HiddenFrames > 0) window->HiddenFrames--; - if ((flags & (ImGuiWindowFlags_Popup | ImGuiWindowFlags_Tooltip)) != 0 && window_just_activated_by_user) + if (window_just_activated_by_user && (flags & (ImGuiWindowFlags_Popup | ImGuiWindowFlags_Tooltip)) != 0) { window->HiddenFrames = 1; if (flags & ImGuiWindowFlags_AlwaysAutoResize) @@ -5772,6 +5773,10 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) } } + // Hide new windows for one frame until they calculate their size + if (window_just_created && (!window_size_x_set_by_api || !window_size_y_set_by_api)) + window->HiddenFrames = 1; + // Calculate auto-fit size, handle automatic resize const ImVec2 size_auto_fit = CalcSizeAutoFit(window, window->SizeContents); ImVec2 size_full_modified(FLT_MAX, FLT_MAX); From 5f4001a81199be348ee1aa628e2d9eebbc83fb41 Mon Sep 17 00:00:00 2001 From: omar Date: Wed, 4 Apr 2018 20:48:49 +0200 Subject: [PATCH 808/823] Contribution guidelines --- .github/CONTRIBUTING.md | 20 +++++++++++--------- .github/issue_template.md | 4 ++-- 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index 05bf73fd444d..23abe87f95cd 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -2,28 +2,30 @@ Hello! -You may use the Issue tracker to submit bug reports, feature requests or suggestions. You may ask for help or advices as well, however please read this wall of text before doing so. Thank you! +You may use the Issue Tracker to submit bug reports, feature requests or suggestions. You may ask for help or advice as well. However please read this wall of text before doing so. The amount of incomplete or ambiguous requests occasionally becomes overwhelming, so please do your best to clarify your request. Thank you! **Prerequisites for new users of dear imgui:** - Please read the FAQ in imgui.cpp. - Please read misc/fonts/README.txt if your question relates to fonts or text. - Please run ImGui::ShowDemoWindow() to explore the demo and its sources. -- Please use the Search function to look for similar issues. You may also browse issues by tags. +- Please use the Search function of GitHub to look for similar issues. You may also browse issues by tags. +- Please use the Search function of your IDE to search in the code for comments related to your situation. - If you get a assert, use a debugger to locate the line triggering it and read the comments around the assert. **Guidelines to report an issue or ask a question:** -- Try to provide a Minimal, Complete and Verifiable Example ([MCVE](https://stackoverflow.com/help/mcve)) to demonstrate your problem. An ideal submission includes a small piece of code that anyone can paste in one of the examples/ application to understand and reproduce it. Narrowing your problem to its shortest and purest form is often the easiest way to understand it. Sometimes while creating the MCVE you will end up solving the problem! +- Try to provide a Minimal, Complete and Verifiable Example ([MCVE](https://stackoverflow.com/help/mcve)) to demonstrate your problem. An ideal submission includes a small piece of code that anyone can paste in one of the examples/ application to understand and reproduce it. Narrowing your problem to its shortest and purest form is often the easiest way to understand it. Often while creating the MCVE you will end up solving the problem! - Try to attach screenshots to clarify the context. They often convey useful information that are omitted by the description. You can drag pictures/files here (prefer github attachments over 3rd party hosting). - If you are discussing an assert or a crash, please provide a debugger callstack. - Please provide your imgui version number. -- Please state if you have made substancial modifications to your copy of imgui. -- When discussing issues related to rendering or inputs, please state which OS you are using, and if you are using a vanilla copy of one of the back end (imgui_impl_xxx files), or modified one, or if you built your own. -- When requesting a new feature or pushing code, please describe the usage context (how you intend to use it, why you need it, etc.). +- Please state if you have made substantial modifications to your copy of imgui. +- When discussing issues related to rendering or inputs, please state which OS you are using, and if you are using a vanilla copy of one of the back end (imgui_impl_xxx files), or a modified one, or if you built your own. +- When requesting a new feature, please describe the usage context (how you intend to use it, why you need it, etc.). +- Due to frequent abuse of this service from a certain category of users, if your GitHub account is anonymous and was created five minutes ago please understand that your post will receive more scrutiny and less patience for incomplete questions. If you have been using dear imgui for a while and/or have been using C/C++ for several years and/or have demonstrated good behavior here, it is ok to not fullfill every item to the letter. Those are guidelines and experienced users of dear imgui will know what information are useful in a given context. ## How to create an Pull Request -- If you are adding a feature, please explain the context of the change: what do you need the feature for? -- Try to attach screenshots to clarify the context and demonstrate the feature at a glance. -- Make sure you create a branch for the pull request. In Git, 1 PR is associated to 1 branch. If you keep pushing to the same branch after you submitted the PR, your new commits will appear in the PR. +- If you are adding a feature, please describe the usage context (how you intend to use it, why you need it, etc.). +- Try to attach screenshots to clarify the context and demonstrate the feature at a glance. You can drag pictures/files here (prefer github attachments over 3rd party hosting). +- Make sure you create a branch for the pull request. In Git, 1 PR is associated to 1 branch. If you keep pushing to the same branch after you submitted the PR, your new commits will appear in the PR (we can still cherry-pick individual commits). diff --git a/.github/issue_template.md b/.github/issue_template.md index ae4eb7b5d9b9..6d57049e0597 100644 --- a/.github/issue_template.md +++ b/.github/issue_template.md @@ -1,5 +1,5 @@ -You may use the Issue tracker to ask for help, submit bug reports, feature requests or suggestions. -Please carefully read this document before doing so: +You may use the Issue Tracker to ask for help and submit bug reports, feature requests or suggestions. +PLEASE CAREFULLY READ THIS DOCUMENT before doing so: [CONTRIBUTING.md](https://github.com/ocornut/imgui/blob/master/.github/CONTRIBUTING.md). You can include code snippets using `Begin()` for short in-line snippets, or: From 18a243bef04bdcae699305fd63571fb4a60b8e19 Mon Sep 17 00:00:00 2001 From: omar Date: Fri, 6 Apr 2018 17:50:50 +0200 Subject: [PATCH 809/823] Columns: Fixed calling Columns() again with the same number of columns. (#125) --- imgui.cpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index dc1ff9238572..66c8fce96f6d 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -12705,11 +12705,15 @@ void ImGui::Columns(int columns_count, const char* id, bool border) { ImGuiWindow* window = GetCurrentWindow(); IM_ASSERT(columns_count >= 1); - if (window->DC.ColumnsSet != NULL && window->DC.ColumnsSet->Count != columns_count) - EndColumns(); - + ImGuiColumnsFlags flags = (border ? 0 : ImGuiColumnsFlags_NoBorder); //flags |= ImGuiColumnsFlags_NoPreserveWidths; // NB: Legacy behavior + if (window->DC.ColumnsSet != NULL && window->DC.ColumnsSet->Count == columns_count && window->DC.ColumnsSet->Flags == flags) + return; + + if (window->DC.ColumnsSet != NULL) + EndColumns(); + if (columns_count != 1) BeginColumns(id, columns_count, flags); } From 72b7f48870931685f3ede4e0489f0fec2c472464 Mon Sep 17 00:00:00 2001 From: omar Date: Fri, 6 Apr 2018 18:12:21 +0200 Subject: [PATCH 810/823] Renamed ImGuiConfigFlags_NoSetMouseCursor to ImGuiConfigFlags_NoMouseCursorChange. Followup to 75c3793db5316626de94cb77c4529093e987ba15 two weeks ago. (#787, #1495, #1202) + comments --- CHANGELOG.txt | 2 +- examples/directx10_example/imgui_impl_dx10.cpp | 4 ++-- examples/directx11_example/imgui_impl_dx11.cpp | 4 ++-- examples/directx12_example/imgui_impl_dx12.cpp | 4 ++-- examples/directx9_example/imgui_impl_dx9.cpp | 4 ++-- examples/opengl2_example/imgui_impl_glfw_gl2.cpp | 4 ++-- examples/opengl3_example/imgui_impl_glfw_gl3.cpp | 4 ++-- .../sdl_opengl2_example/imgui_impl_sdl_gl2.cpp | 4 ++-- .../sdl_opengl3_example/imgui_impl_sdl_gl3.cpp | 4 ++-- examples/vulkan_example/imgui_impl_glfw_vulkan.cpp | 4 ++-- imgui.h | 14 +++++++------- imgui_demo.cpp | 10 ++++++---- 12 files changed, 32 insertions(+), 30 deletions(-) diff --git a/CHANGELOG.txt b/CHANGELOG.txt index b359fb7bcad6..7837f7217f2e 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -91,7 +91,7 @@ Other Changes: - Context: Removed allocator parameters from CreateContext(), they are now setup with SetAllocatorFunctions() and shared by all contexts. (#1565, #586, #992, #1007, #1558) - Context: You may pass a ImFontAtlas to CreateContext() to specify a font atlas to share. Shared font atlas are not owned by the context and not destroyed along with it. - Context: Added IMGUI_DISABLE_DEFAULT_ALLOCATORS to disable linking with malloc/free. (#1565, #586, #992, #1007, #1558) -- IO: Added io.ConfigFlags for user application to store settings for imgui and for the back-end (currently: _NavEnableKeyboard, _NavEnableGamepad, _NavEnableSetMousePos, _NoSetMouseCursor). +- IO: Added io.ConfigFlags for user application to store settings for imgui and for the back-end (currently: _NavEnableKeyboard, _NavEnableGamepad, _NavEnableSetMousePos, _NoMouseCursorChange). - IO: Added io.BackendFlags for back-end to store its capabilities (currently: _HasGamepad, _HasMouseCursors, _HasSetMousePos). This will be used more in the next version. - IO: Added ImGuiKey_Insert, ImGuiKey_Space keys. Setup in all example bindings. (#1541) - IO: Added Horizontal Mouse Wheel support for horizontal scrolling. (#1463) [@tseeker] diff --git a/examples/directx10_example/imgui_impl_dx10.cpp b/examples/directx10_example/imgui_impl_dx10.cpp index ae6dadc9406b..4fc24e252c85 100644 --- a/examples/directx10_example/imgui_impl_dx10.cpp +++ b/examples/directx10_example/imgui_impl_dx10.cpp @@ -10,7 +10,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) -// 2018-03-20: Misc: Setup io.BackendFlags ImGuiBackendFlags_HasMouseCursors and ImGuiBackendFlags_HasSetMousePos flags + honor ImGuiConfigFlags_NoSetMouseCursor flag. +// 2018-03-20: Misc: Setup io.BackendFlags ImGuiBackendFlags_HasMouseCursors and ImGuiBackendFlags_HasSetMousePos flags + honor ImGuiConfigFlags_NoMouseCursorChange flag. // 2018-02-20: Inputs: Added support for mouse cursors (ImGui::GetMouseCursor() value and WM_SETCURSOR message handling). // 2018-02-16: Misc: Obsoleted the io.RenderDrawListsFn callback and exposed ImGui_ImplDX10_RenderDrawData() in the .h file so you can call it yourself. // 2018-02-06: Misc: Removed call to ImGui::Shutdown() which is not available from 1.60 WIP, user needs to call CreateContext/DestroyContext themselves. @@ -247,7 +247,7 @@ void ImGui_ImplDX10_RenderDrawData(ImDrawData* draw_data) static bool ImGui_ImplWin32_UpdateMouseCursor() { ImGuiIO& io = ImGui::GetIO(); - if (io.ConfigFlags & ImGuiConfigFlags_NoSetMouseCursor) + if (io.ConfigFlags & ImGuiConfigFlags_NoMouseCursorChange) return false; ImGuiMouseCursor imgui_cursor = io.MouseDrawCursor ? ImGuiMouseCursor_None : ImGui::GetMouseCursor(); diff --git a/examples/directx11_example/imgui_impl_dx11.cpp b/examples/directx11_example/imgui_impl_dx11.cpp index 6249120a078e..de7f3a8ef00f 100644 --- a/examples/directx11_example/imgui_impl_dx11.cpp +++ b/examples/directx11_example/imgui_impl_dx11.cpp @@ -10,7 +10,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) -// 2018-03-20: Misc: Setup io.BackendFlags ImGuiBackendFlags_HasMouseCursors and ImGuiBackendFlags_HasSetMousePos flags + honor ImGuiConfigFlags_NoSetMouseCursor flag. +// 2018-03-20: Misc: Setup io.BackendFlags ImGuiBackendFlags_HasMouseCursors and ImGuiBackendFlags_HasSetMousePos flags + honor ImGuiConfigFlags_NoMouseCursorChange flag. // 2018-02-20: Inputs: Added support for mouse cursors (ImGui::GetMouseCursor() value and WM_SETCURSOR message handling). // 2018-02-16: Misc: Obsoleted the io.RenderDrawListsFn callback and exposed ImGui_ImplDX11_RenderDrawData() in the .h file so you can call it yourself. // 2018-02-06: Misc: Removed call to ImGui::Shutdown() which is not available from 1.60 WIP, user needs to call CreateContext/DestroyContext themselves. @@ -254,7 +254,7 @@ void ImGui_ImplDX11_RenderDrawData(ImDrawData* draw_data) static bool ImGui_ImplWin32_UpdateMouseCursor() { ImGuiIO& io = ImGui::GetIO(); - if (io.ConfigFlags & ImGuiConfigFlags_NoSetMouseCursor) + if (io.ConfigFlags & ImGuiConfigFlags_NoMouseCursorChange) return false; ImGuiMouseCursor imgui_cursor = io.MouseDrawCursor ? ImGuiMouseCursor_None : ImGui::GetMouseCursor(); diff --git a/examples/directx12_example/imgui_impl_dx12.cpp b/examples/directx12_example/imgui_impl_dx12.cpp index d327c36e9fd6..6965323c7c28 100644 --- a/examples/directx12_example/imgui_impl_dx12.cpp +++ b/examples/directx12_example/imgui_impl_dx12.cpp @@ -11,7 +11,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) -// 2018-03-20: Misc: Setup io.BackendFlags ImGuiBackendFlags_HasMouseCursors and ImGuiBackendFlags_HasSetMousePos flags + honor ImGuiConfigFlags_NoSetMouseCursor flag. +// 2018-03-20: Misc: Setup io.BackendFlags ImGuiBackendFlags_HasMouseCursors and ImGuiBackendFlags_HasSetMousePos flags + honor ImGuiConfigFlags_NoMouseCursorChange flag. // 2018-02-22: Merged into master with all Win32 code synchronized to other examples. #include "imgui.h" @@ -225,7 +225,7 @@ void ImGui_ImplDX12_RenderDrawData(ImDrawData* draw_data) static bool ImGui_ImplWin32_UpdateMouseCursor() { ImGuiIO& io = ImGui::GetIO(); - if (io.ConfigFlags & ImGuiConfigFlags_NoSetMouseCursor) + if (io.ConfigFlags & ImGuiConfigFlags_NoMouseCursorChange) return false; ImGuiMouseCursor imgui_cursor = io.MouseDrawCursor ? ImGuiMouseCursor_None : ImGui::GetMouseCursor(); diff --git a/examples/directx9_example/imgui_impl_dx9.cpp b/examples/directx9_example/imgui_impl_dx9.cpp index 967e07e332bf..ed2ea519ff15 100644 --- a/examples/directx9_example/imgui_impl_dx9.cpp +++ b/examples/directx9_example/imgui_impl_dx9.cpp @@ -10,7 +10,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) -// 2018-03-20: Misc: Setup io.BackendFlags ImGuiBackendFlags_HasMouseCursors and ImGuiBackendFlags_HasSetMousePos flags + honor ImGuiConfigFlags_NoSetMouseCursor flag. +// 2018-03-20: Misc: Setup io.BackendFlags ImGuiBackendFlags_HasMouseCursors and ImGuiBackendFlags_HasSetMousePos flags + honor ImGuiConfigFlags_NoMouseCursorChange flag. // 2018-02-20: Inputs: Added support for mouse cursors (ImGui::GetMouseCursor() value and WM_SETCURSOR message handling). // 2018-02-16: Misc: Obsoleted the io.RenderDrawListsFn callback and exposed ImGui_ImplDX9_RenderDrawData() in the .h file so you can call it yourself. // 2018-02-06: Misc: Removed call to ImGui::Shutdown() which is not available from 1.60 WIP, user needs to call CreateContext/DestroyContext themselves. @@ -187,7 +187,7 @@ void ImGui_ImplDX9_RenderDrawData(ImDrawData* draw_data) static bool ImGui_ImplWin32_UpdateMouseCursor() { ImGuiIO& io = ImGui::GetIO(); - if (io.ConfigFlags & ImGuiConfigFlags_NoSetMouseCursor) + if (io.ConfigFlags & ImGuiConfigFlags_NoMouseCursorChange) return false; ImGuiMouseCursor imgui_cursor = io.MouseDrawCursor ? ImGuiMouseCursor_None : ImGui::GetMouseCursor(); diff --git a/examples/opengl2_example/imgui_impl_glfw_gl2.cpp b/examples/opengl2_example/imgui_impl_glfw_gl2.cpp index 2789f0d1b893..5e2e8fd45cc0 100644 --- a/examples/opengl2_example/imgui_impl_glfw_gl2.cpp +++ b/examples/opengl2_example/imgui_impl_glfw_gl2.cpp @@ -19,7 +19,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) -// 2018-03-20: Misc: Setup io.BackendFlags ImGuiBackendFlags_HasMouseCursors and ImGuiBackendFlags_HasSetMousePos flags + honor ImGuiConfigFlags_NoSetMouseCursor flag. +// 2018-03-20: Misc: Setup io.BackendFlags ImGuiBackendFlags_HasMouseCursors and ImGuiBackendFlags_HasSetMousePos flags + honor ImGuiConfigFlags_NoMouseCursorChange flag. // 2018-02-20: Inputs: Added support for mouse cursors (ImGui::GetMouseCursor() value and WM_SETCURSOR message handling). // 2018-02-20: Inputs: Renamed GLFW callbacks exposed in .h to not include GL2 in their name. // 2018-02-16: Misc: Obsoleted the io.RenderDrawListsFn callback and exposed ImGui_ImplGlfwGL2_RenderDrawData() in the .h file so you can call it yourself. @@ -345,7 +345,7 @@ void ImGui_ImplGlfwGL2_NewFrame() } // Update OS/hardware mouse cursor if imgui isn't drawing a software cursor - if ((io.ConfigFlags & ImGuiConfigFlags_NoSetMouseCursor) == 0 && glfwGetInputMode(g_Window, GLFW_CURSOR) != GLFW_CURSOR_DISABLED) + if ((io.ConfigFlags & ImGuiConfigFlags_NoMouseCursorChange) == 0 && glfwGetInputMode(g_Window, GLFW_CURSOR) != GLFW_CURSOR_DISABLED) { ImGuiMouseCursor cursor = ImGui::GetMouseCursor(); if (io.MouseDrawCursor || cursor == ImGuiMouseCursor_None) diff --git a/examples/opengl3_example/imgui_impl_glfw_gl3.cpp b/examples/opengl3_example/imgui_impl_glfw_gl3.cpp index 348a0b04730f..588939414be5 100644 --- a/examples/opengl3_example/imgui_impl_glfw_gl3.cpp +++ b/examples/opengl3_example/imgui_impl_glfw_gl3.cpp @@ -13,7 +13,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) -// 2018-03-20: Misc: Setup io.BackendFlags ImGuiBackendFlags_HasMouseCursors and ImGuiBackendFlags_HasSetMousePos flags + honor ImGuiConfigFlags_NoSetMouseCursor flag. +// 2018-03-20: Misc: Setup io.BackendFlags ImGuiBackendFlags_HasMouseCursors and ImGuiBackendFlags_HasSetMousePos flags + honor ImGuiConfigFlags_NoMouseCursorChange flag. // 2018-03-06: OpenGL: Added const char* glsl_version parameter to ImGui_ImplGlfwGL3_Init() so user can override the GLSL version e.g. "#version 150". // 2018-02-23: OpenGL: Create the VAO in the render function so the setup can more easily be used with multiple shared GL context. // 2018-02-20: Inputs: Added support for mouse cursors (ImGui::GetMouseCursor() value and WM_SETCURSOR message handling). @@ -477,7 +477,7 @@ void ImGui_ImplGlfwGL3_NewFrame() } // Update OS/hardware mouse cursor if imgui isn't drawing a software cursor - if ((io.ConfigFlags & ImGuiConfigFlags_NoSetMouseCursor) == 0 && glfwGetInputMode(g_Window, GLFW_CURSOR) != GLFW_CURSOR_DISABLED) + if ((io.ConfigFlags & ImGuiConfigFlags_NoMouseCursorChange) == 0 && glfwGetInputMode(g_Window, GLFW_CURSOR) != GLFW_CURSOR_DISABLED) { ImGuiMouseCursor cursor = ImGui::GetMouseCursor(); if (io.MouseDrawCursor || cursor == ImGuiMouseCursor_None) diff --git a/examples/sdl_opengl2_example/imgui_impl_sdl_gl2.cpp b/examples/sdl_opengl2_example/imgui_impl_sdl_gl2.cpp index 0149864df562..a8a76b4cf266 100644 --- a/examples/sdl_opengl2_example/imgui_impl_sdl_gl2.cpp +++ b/examples/sdl_opengl2_example/imgui_impl_sdl_gl2.cpp @@ -21,7 +21,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) -// 2018-03-20: Misc: Setup io.BackendFlags ImGuiBackendFlags_HasMouseCursors flag + honor ImGuiConfigFlags_NoSetMouseCursor flag. +// 2018-03-20: Misc: Setup io.BackendFlags ImGuiBackendFlags_HasMouseCursors flag + honor ImGuiConfigFlags_NoMouseCursorChange flag. // 2018-02-16: Inputs: Added support for mouse cursors, honoring ImGui::GetMouseCursor() value. // 2018-02-16: Misc: Obsoleted the io.RenderDrawListsFn callback and exposed ImGui_ImplSdlGL2_RenderDrawData() in the .h file so you can call it yourself. // 2018-02-06: Misc: Removed call to ImGui::Shutdown() which is not available from 1.60 WIP, user needs to call CreateContext/DestroyContext themselves. @@ -336,7 +336,7 @@ void ImGui_ImplSdlGL2_NewFrame(SDL_Window *window) #endif // Update OS/hardware mouse cursor if imgui isn't drawing a software cursor - if ((io.ConfigFlags & ImGuiConfigFlags_NoSetMouseCursor) == 0) + if ((io.ConfigFlags & ImGuiConfigFlags_NoMouseCursorChange) == 0) { ImGuiMouseCursor cursor = ImGui::GetMouseCursor(); if (io.MouseDrawCursor || cursor == ImGuiMouseCursor_None) diff --git a/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.cpp b/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.cpp index 8b04b933a78c..3ce4ecb73321 100644 --- a/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.cpp +++ b/examples/sdl_opengl3_example/imgui_impl_sdl_gl3.cpp @@ -14,7 +14,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) -// 2018-03-20: Misc: Setup io.BackendFlags ImGuiBackendFlags_HasMouseCursors flag + honor ImGuiConfigFlags_NoSetMouseCursor flag. +// 2018-03-20: Misc: Setup io.BackendFlags ImGuiBackendFlags_HasMouseCursors flag + honor ImGuiConfigFlags_NoMouseCursorChange flag. // 2018-03-06: OpenGL: Added const char* glsl_version parameter to ImGui_ImplSdlGL3_Init() so user can override the GLSL version e.g. "#version 150". // 2018-02-23: OpenGL: Create the VAO in the render function so the setup can more easily be used with multiple shared GL context. // 2018-02-16: Inputs: Added support for mouse cursors, honoring ImGui::GetMouseCursor() value. @@ -469,7 +469,7 @@ void ImGui_ImplSdlGL3_NewFrame(SDL_Window* window) #endif // Update OS/hardware mouse cursor if imgui isn't drawing a software cursor - if ((io.ConfigFlags & ImGuiConfigFlags_NoSetMouseCursor) == 0) + if ((io.ConfigFlags & ImGuiConfigFlags_NoMouseCursorChange) == 0) { ImGuiMouseCursor cursor = ImGui::GetMouseCursor(); if (io.MouseDrawCursor || cursor == ImGuiMouseCursor_None) diff --git a/examples/vulkan_example/imgui_impl_glfw_vulkan.cpp b/examples/vulkan_example/imgui_impl_glfw_vulkan.cpp index 44e7296360d6..0ea155a2b4a8 100644 --- a/examples/vulkan_example/imgui_impl_glfw_vulkan.cpp +++ b/examples/vulkan_example/imgui_impl_glfw_vulkan.cpp @@ -10,7 +10,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) -// 2018-03-20: Misc: Setup io.BackendFlags ImGuiBackendFlags_HasMouseCursors flag + honor ImGuiConfigFlags_NoSetMouseCursor flag. +// 2018-03-20: Misc: Setup io.BackendFlags ImGuiBackendFlags_HasMouseCursors flag + honor ImGuiConfigFlags_NoMouseCursorChange flag. // 2018-02-20: Inputs: Added support for mouse cursors (ImGui::GetMouseCursor() value and WM_SETCURSOR message handling). // 2018-02-20: Inputs: Renamed GLFW callbacks exposed in .h to not include Vulkan in their name. // 2018-02-16: Misc: Obsoleted the io.RenderDrawListsFn callback, ImGui_ImplGlfwVulkan_Render() calls ImGui_ImplGlfwVulkan_RenderDrawData() itself. @@ -870,7 +870,7 @@ void ImGui_ImplGlfwVulkan_NewFrame() } // Update OS/hardware mouse cursor if imgui isn't drawing a software cursor - if ((io.ConfigFlags & ImGuiConfigFlags_NoSetMouseCursor) == 0) + if ((io.ConfigFlags & ImGuiConfigFlags_NoMouseCursorChange) == 0) { ImGuiMouseCursor cursor = ImGui::GetMouseCursor(); if (io.MouseDrawCursor || cursor == ImGuiMouseCursor_None) diff --git a/imgui.h b/imgui.h index c4b658d55c06..7e4b871880cd 100644 --- a/imgui.h +++ b/imgui.h @@ -534,8 +534,8 @@ namespace ImGui IMGUI_API void ResetMouseDragDelta(int button = 0); // IMGUI_API ImGuiMouseCursor GetMouseCursor(); // get desired cursor type, reset in ImGui::NewFrame(), this is updated during the frame. valid before Render(). If you use software rendering by setting io.MouseDrawCursor ImGui will render those for you IMGUI_API void SetMouseCursor(ImGuiMouseCursor type); // set desired cursor type - IMGUI_API void CaptureKeyboardFromApp(bool capture = true); // manually override io.WantCaptureKeyboard flag next frame (said flag is entirely left for your application handle). e.g. force capture keyboard when your widget is being hovered. - IMGUI_API void CaptureMouseFromApp(bool capture = true); // manually override io.WantCaptureMouse flag next frame (said flag is entirely left for your application handle). + IMGUI_API void CaptureKeyboardFromApp(bool capture = true); // manually override io.WantCaptureKeyboard flag next frame (said flag is entirely left for your application to handle). e.g. force capture keyboard when your widget is being hovered. + IMGUI_API void CaptureMouseFromApp(bool capture = true); // manually override io.WantCaptureMouse flag next frame (said flag is entirely left for your application to handle). // Clipboard Utilities (also see the LogToClipboard() function to capture or output text data to the clipboard) IMGUI_API const char* GetClipboardText(); @@ -777,9 +777,9 @@ enum ImGuiConfigFlags_ { ImGuiConfigFlags_NavEnableKeyboard = 1 << 0, // Master keyboard navigation enable flag. NewFrame() will automatically fill io.NavInputs[] based on io.KeyDown[]. ImGuiConfigFlags_NavEnableGamepad = 1 << 1, // Master gamepad navigation enable flag. This is mostly to instruct your imgui back-end to fill io.NavInputs[]. Back-end also needs to set ImGuiBackendFlags_HasGamepad. - ImGuiConfigFlags_NavEnableSetMousePos = 1 << 2, // Request navigation to allow moving the mouse cursor. May be useful on TV/console systems where moving a virtual mouse is awkward. Will update io.MousePos and set io.WantSetMousePos=true. If enabled you MUST honor io.WantSetMousePos requests in your binding, otherwise ImGui will react as if the mouse is jumping around back and forth. - ImGuiConfigFlags_NavNoCaptureKeyboard = 1 << 3, // Do not set the io.WantCaptureKeyboard flag with io.NavActive is set. - ImGuiConfigFlags_NoSetMouseCursor = 1 << 4, // Request back-end to not alter mouse cursor configuration. + ImGuiConfigFlags_NavEnableSetMousePos = 1 << 2, // Instruct navigation to move the mouse cursor. May be useful on TV/console systems where moving a virtual mouse is awkward. Will update io.MousePos and set io.WantSetMousePos=true. If enabled you MUST honor io.WantSetMousePos requests in your binding, otherwise ImGui will react as if the mouse is jumping around back and forth. + ImGuiConfigFlags_NavNoCaptureKeyboard = 1 << 3, // Instruct navigation to not set the io.WantCaptureKeyboard flag with io.NavActive is set. + ImGuiConfigFlags_NoMouseCursorChange = 1 << 4, // Instruct back-end to not alter mouse cursor shape and visibility. // User storage (to allow your back-end/engine to communicate to code that may be shared between multiple projects. Those flags are not used by core ImGui) ImGuiConfigFlags_IsSRGB = 1 << 20, // Application is SRGB-aware. @@ -1072,8 +1072,8 @@ struct ImGuiIO // Output - Retrieve after calling NewFrame() //------------------------------------------------------------------ - bool WantCaptureMouse; // When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application. This is set by ImGui when it wants to use your mouse (e.g. unclicked mouse is hovering a window, or a widget is active). - bool WantCaptureKeyboard; // When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application. This is set by ImGui when it wants to use your keyboard inputs. + bool WantCaptureMouse; // When io.WantCaptureMouse is true, imgui will use the mouse inputs, do not dispatch them to your main game/application. (e.g. unclicked mouse is hovering over an imgui window, widget is active, mouse was clicked over an imgui window, etc.). + bool WantCaptureKeyboard; // When io.WantCaptureKeyboard is true, imgui will use the keyboard inputs, do not dispatch them to your main game/application. (e.g. InputText active, or an imgui window is focused and navigation is enabled, etc.). bool WantTextInput; // Mobile/console: when io.WantTextInput is true, you may display an on-screen keyboard. This is set by ImGui when it wants textual keyboard input to happen (e.g. when a InputText widget is active). bool WantSetMousePos; // MousePos has been altered, back-end should reposition mouse on next frame. Set only when ImGuiConfigFlags_NavEnableSetMousePos flag is enabled. bool NavActive; // Directional navigation is currently allowed (will handle ImGuiKey_NavXXX events) = a window is focused and it doesn't use the ImGuiWindowFlags_NoNavInputs flag. diff --git a/imgui_demo.cpp b/imgui_demo.cpp index b3d423919f19..3f18e48ebb82 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -1850,12 +1850,14 @@ void ImGui::ShowDemoWindow(bool* p_open) ImGui::Text("NavActive: %d, NavVisible: %d", io.NavActive, io.NavVisible); ImGui::Checkbox("io.MouseDrawCursor", &io.MouseDrawCursor); - ImGui::SameLine(); ShowHelpMarker("Request ImGui to render a mouse cursor for you in software. Note that a mouse cursor rendered via your application GPU rendering path will feel more laggy than hardware cursor, but will be more in sync with your other visuals.\n\nSome desktop applications may use both kinds of cursors (e.g. enable software cursor only when resizing/dragging something)."); + ImGui::SameLine(); ShowHelpMarker("Instruct ImGui to render a mouse cursor for you in software. Note that a mouse cursor rendered via your application GPU rendering path will feel more laggy than hardware cursor, but will be more in sync with your other visuals.\n\nSome desktop applications may use both kinds of cursors (e.g. enable software cursor only when resizing/dragging something)."); + ImGui::CheckboxFlags("io.ConfigFlags: NavEnableGamepad", (unsigned int *)&io.ConfigFlags, ImGuiConfigFlags_NavEnableGamepad); ImGui::CheckboxFlags("io.ConfigFlags: NavEnableKeyboard", (unsigned int *)&io.ConfigFlags, ImGuiConfigFlags_NavEnableKeyboard); - ImGui::CheckboxFlags("io.ConfigFlags: NavEnableSetMousePos", (unsigned int *)&io.ConfigFlags, ImGuiConfigFlags_NavEnableSetMousePos); - ImGui::CheckboxFlags("io.ConfigFlags: NoSetMouseCursor", (unsigned int *)&io.ConfigFlags, ImGuiConfigFlags_NoSetMouseCursor); - ImGui::SameLine(); ShowHelpMarker("Request ImGui to move your move cursor when using gamepad/keyboard navigation. NewFrame() will change io.MousePos and set the io.WantSetMousePos flag, your backend will need to apply the new mouse position."); + ImGui::CheckboxFlags("io.ConfigFlags: NavEnableSetMousePos", (unsigned int *)&io.ConfigFlags, ImGuiConfigFlags_NavEnableSetMousePos); + ImGui::SameLine(); ShowHelpMarker("Instruct navigation to move the mouse cursor. See comment for ImGuiConfigFlags_NavEnableSetMousePos."); + ImGui::CheckboxFlags("io.ConfigFlags: NoMouseCursorChange", (unsigned int *)&io.ConfigFlags, ImGuiConfigFlags_NoMouseCursorChange); + ImGui::SameLine(); ShowHelpMarker("Instruct back-end to not alter mouse cursor shape and visibility."); if (ImGui::TreeNode("Keyboard, Mouse & Navigation State")) { From 2464e62a1ad9a7c8f2d9f898f54484af8ca3a524 Mon Sep 17 00:00:00 2001 From: omar Date: Fri, 6 Apr 2018 18:17:41 +0200 Subject: [PATCH 811/823] IO: Added ImGuiConfigFlags_NoMouse to force clear/disable mouse inputs in NewFrame(). --- CHANGELOG.txt | 8 +++++++- imgui.cpp | 5 +++++ imgui.h | 3 ++- 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.txt b/CHANGELOG.txt index 7837f7217f2e..0d2cbf9822b7 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -91,7 +91,13 @@ Other Changes: - Context: Removed allocator parameters from CreateContext(), they are now setup with SetAllocatorFunctions() and shared by all contexts. (#1565, #586, #992, #1007, #1558) - Context: You may pass a ImFontAtlas to CreateContext() to specify a font atlas to share. Shared font atlas are not owned by the context and not destroyed along with it. - Context: Added IMGUI_DISABLE_DEFAULT_ALLOCATORS to disable linking with malloc/free. (#1565, #586, #992, #1007, #1558) -- IO: Added io.ConfigFlags for user application to store settings for imgui and for the back-end (currently: _NavEnableKeyboard, _NavEnableGamepad, _NavEnableSetMousePos, _NoMouseCursorChange). +- IO: Added io.ConfigFlags for user application to store settings for imgui and for the back-end: + - ImGuiConfigFlags_NavEnableKeyboard: Enable keyboard navigation. + - ImGuiConfigFlags_NavEnableGamepad: Enable gamepad navigation (provided ImGuiBackendFlags_HasGamepad is also set by back-end). + - ImGuiConfigFlags_NavEnableSetMousePos: Instruct navigation to move the mouse cursor. May be useful on TV/console systems where moving a virtual mouse is awkward. + - ImGuiConfigFlags_NoMouseCursorChange: Instruct back-end to not alter mouse cursor shape and visibility (by default the example back-end use mouse cursor API of the platform when available) + - ImGuiConfigFlags_NoMouse: Instruct imgui to clear mouse position/buttons in NewFrame(). This allows ignoring the mouse information passed by the back-end. + - ImGuiConfigFlags_IsSRGB, ImGuiConfigFlags_IsTouchScreen: Flags for general application use. - IO: Added io.BackendFlags for back-end to store its capabilities (currently: _HasGamepad, _HasMouseCursors, _HasSetMousePos). This will be used more in the next version. - IO: Added ImGuiKey_Insert, ImGuiKey_Space keys. Setup in all example bindings. (#1541) - IO: Added Horizontal Mouse Wheel support for horizontal scrolling. (#1463) [@tseeker] diff --git a/imgui.cpp b/imgui.cpp index 66c8fce96f6d..c2bc03659c67 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -3373,6 +3373,11 @@ void ImGui::NewFrame() // Update mouse input state // If mouse just appeared or disappeared (usually denoted by -FLT_MAX component, but in reality we test for -256000.0f) we cancel out movement in MouseDelta + if (g.IO.ConfigFlags & ImGuiConfigFlags_NoMouse) + { + g.IO.MousePos = ImVec2(-FLT_MAX, -FLT_MAX); + memset(g.IO.MouseDown, 0, sizeof(g.IO.MouseDown)); + } if (IsMousePosValid(&g.IO.MousePos) && IsMousePosValid(&g.IO.MousePosPrev)) g.IO.MouseDelta = g.IO.MousePos - g.IO.MousePosPrev; else diff --git a/imgui.h b/imgui.h index 7e4b871880cd..57ce6f44ddfe 100644 --- a/imgui.h +++ b/imgui.h @@ -779,7 +779,8 @@ enum ImGuiConfigFlags_ ImGuiConfigFlags_NavEnableGamepad = 1 << 1, // Master gamepad navigation enable flag. This is mostly to instruct your imgui back-end to fill io.NavInputs[]. Back-end also needs to set ImGuiBackendFlags_HasGamepad. ImGuiConfigFlags_NavEnableSetMousePos = 1 << 2, // Instruct navigation to move the mouse cursor. May be useful on TV/console systems where moving a virtual mouse is awkward. Will update io.MousePos and set io.WantSetMousePos=true. If enabled you MUST honor io.WantSetMousePos requests in your binding, otherwise ImGui will react as if the mouse is jumping around back and forth. ImGuiConfigFlags_NavNoCaptureKeyboard = 1 << 3, // Instruct navigation to not set the io.WantCaptureKeyboard flag with io.NavActive is set. - ImGuiConfigFlags_NoMouseCursorChange = 1 << 4, // Instruct back-end to not alter mouse cursor shape and visibility. + ImGuiConfigFlags_NoMouse = 1 << 4, // Instruct imgui to clear mouse position/buttons in NewFrame(). This allows ignoring the mouse information back-end + ImGuiConfigFlags_NoMouseCursorChange = 1 << 5, // Instruct back-end to not alter mouse cursor shape and visibility. // User storage (to allow your back-end/engine to communicate to code that may be shared between multiple projects. Those flags are not used by core ImGui) ImGuiConfigFlags_IsSRGB = 1 << 20, // Application is SRGB-aware. From ac2027c41553789db5e7bff726ea52fb8a4db00a Mon Sep 17 00:00:00 2001 From: omar Date: Fri, 6 Apr 2018 18:43:31 +0200 Subject: [PATCH 812/823] NewFrame: Extract some code into a NewFrameUpdateMouseInputs function. Moved settings saving higher up in the function so it is next to its peers. --- imgui.cpp | 124 +++++++++++++++++++++++++---------------------- imgui_internal.h | 2 +- 2 files changed, 67 insertions(+), 59 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index c2bc03659c67..e8e2632507b8 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -755,7 +755,8 @@ static void NavUpdate(); static void NavUpdateWindowing(); static void NavProcessItem(ImGuiWindow* window, const ImRect& nav_bb, const ImGuiID id); -static void UpdateMovingWindow(); +static void NewFrameUpdateMovingWindow(); +static void NewFrameUpdateMouseInputs(); static void UpdateManualResize(ImGuiWindow* window, const ImVec2& size_auto_fit, int* border_held, int resize_grip_count, ImU32 resize_grip_col[4]); static void FocusFrontMostActiveWindow(ImGuiWindow* ignore_window); } @@ -3249,7 +3250,7 @@ static void ImGui::NavUpdate() #endif } -static void ImGui::UpdateMovingWindow() +static void ImGui::NewFrameUpdateMovingWindow() { ImGuiContext& g = *GImGui; if (g.MovingWindow && g.MovingWindow->MoveId == g.ActiveId && g.ActiveIdSource == ImGuiInputSource_Mouse) @@ -3288,6 +3289,59 @@ static void ImGui::UpdateMovingWindow() } } +static void ImGui::NewFrameUpdateMouseInputs() +{ + ImGuiContext& g = *GImGui; + if (g.IO.ConfigFlags & ImGuiConfigFlags_NoMouse) + { + g.IO.MousePos = ImVec2(-FLT_MAX, -FLT_MAX); + memset(g.IO.MouseDown, 0, sizeof(g.IO.MouseDown)); + } + + // If mouse just appeared or disappeared (usually denoted by -FLT_MAX component, but in reality we test for -256000.0f) we cancel out movement in MouseDelta + if (ImGui::IsMousePosValid(&g.IO.MousePos) && ImGui::IsMousePosValid(&g.IO.MousePosPrev)) + g.IO.MouseDelta = g.IO.MousePos - g.IO.MousePosPrev; + else + g.IO.MouseDelta = ImVec2(0.0f, 0.0f); + if (g.IO.MouseDelta.x != 0.0f || g.IO.MouseDelta.y != 0.0f) + g.NavDisableMouseHover = false; + + g.IO.MousePosPrev = g.IO.MousePos; + for (int i = 0; i < IM_ARRAYSIZE(g.IO.MouseDown); i++) + { + g.IO.MouseClicked[i] = g.IO.MouseDown[i] && g.IO.MouseDownDuration[i] < 0.0f; + g.IO.MouseReleased[i] = !g.IO.MouseDown[i] && g.IO.MouseDownDuration[i] >= 0.0f; + g.IO.MouseDownDurationPrev[i] = g.IO.MouseDownDuration[i]; + g.IO.MouseDownDuration[i] = g.IO.MouseDown[i] ? (g.IO.MouseDownDuration[i] < 0.0f ? 0.0f : g.IO.MouseDownDuration[i] + g.IO.DeltaTime) : -1.0f; + g.IO.MouseDoubleClicked[i] = false; + if (g.IO.MouseClicked[i]) + { + if (g.Time - g.IO.MouseClickedTime[i] < g.IO.MouseDoubleClickTime) + { + if (ImLengthSqr(g.IO.MousePos - g.IO.MouseClickedPos[i]) < g.IO.MouseDoubleClickMaxDist * g.IO.MouseDoubleClickMaxDist) + g.IO.MouseDoubleClicked[i] = true; + g.IO.MouseClickedTime[i] = -FLT_MAX; // so the third click isn't turned into a double-click + } + else + { + g.IO.MouseClickedTime[i] = g.Time; + } + g.IO.MouseClickedPos[i] = g.IO.MousePos; + g.IO.MouseDragMaxDistanceAbs[i] = ImVec2(0.0f, 0.0f); + g.IO.MouseDragMaxDistanceSqr[i] = 0.0f; + } + else if (g.IO.MouseDown[i]) + { + ImVec2 mouse_delta = g.IO.MousePos - g.IO.MouseClickedPos[i]; + g.IO.MouseDragMaxDistanceAbs[i].x = ImMax(g.IO.MouseDragMaxDistanceAbs[i].x, mouse_delta.x < 0.0f ? -mouse_delta.x : mouse_delta.x); + g.IO.MouseDragMaxDistanceAbs[i].y = ImMax(g.IO.MouseDragMaxDistanceAbs[i].y, mouse_delta.y < 0.0f ? -mouse_delta.y : mouse_delta.y); + g.IO.MouseDragMaxDistanceSqr[i] = ImMax(g.IO.MouseDragMaxDistanceSqr[i], ImLengthSqr(mouse_delta)); + } + if (g.IO.MouseClicked[i]) // Clicking any mouse button reactivate mouse hovering which may have been deactivated by gamepad/keyboard navigation + g.NavDisableMouseHover = false; + } +} + void ImGui::NewFrame() { IM_ASSERT(GImGui != NULL && "No current context. Did you call ImGui::CreateContext() or ImGui::SetCurrentContext()?"); @@ -3318,6 +3372,14 @@ void ImGui::NewFrame() g.SettingsLoaded = true; } + // Save settings (with a delay so we don't spam disk too much) + if (g.SettingsDirtyTimer > 0.0f) + { + g.SettingsDirtyTimer -= g.IO.DeltaTime; + if (g.SettingsDirtyTimer <= 0.0f) + SaveIniSettingsToDisk(g.IO.IniFilename); + } + g.Time += g.IO.DeltaTime; g.FrameCount += 1; g.TooltipOverrideCount = 0; @@ -3372,53 +3434,7 @@ void ImGui::NewFrame() NavUpdate(); // Update mouse input state - // If mouse just appeared or disappeared (usually denoted by -FLT_MAX component, but in reality we test for -256000.0f) we cancel out movement in MouseDelta - if (g.IO.ConfigFlags & ImGuiConfigFlags_NoMouse) - { - g.IO.MousePos = ImVec2(-FLT_MAX, -FLT_MAX); - memset(g.IO.MouseDown, 0, sizeof(g.IO.MouseDown)); - } - if (IsMousePosValid(&g.IO.MousePos) && IsMousePosValid(&g.IO.MousePosPrev)) - g.IO.MouseDelta = g.IO.MousePos - g.IO.MousePosPrev; - else - g.IO.MouseDelta = ImVec2(0.0f, 0.0f); - if (g.IO.MouseDelta.x != 0.0f || g.IO.MouseDelta.y != 0.0f) - g.NavDisableMouseHover = false; - - g.IO.MousePosPrev = g.IO.MousePos; - for (int i = 0; i < IM_ARRAYSIZE(g.IO.MouseDown); i++) - { - g.IO.MouseClicked[i] = g.IO.MouseDown[i] && g.IO.MouseDownDuration[i] < 0.0f; - g.IO.MouseReleased[i] = !g.IO.MouseDown[i] && g.IO.MouseDownDuration[i] >= 0.0f; - g.IO.MouseDownDurationPrev[i] = g.IO.MouseDownDuration[i]; - g.IO.MouseDownDuration[i] = g.IO.MouseDown[i] ? (g.IO.MouseDownDuration[i] < 0.0f ? 0.0f : g.IO.MouseDownDuration[i] + g.IO.DeltaTime) : -1.0f; - g.IO.MouseDoubleClicked[i] = false; - if (g.IO.MouseClicked[i]) - { - if (g.Time - g.IO.MouseClickedTime[i] < g.IO.MouseDoubleClickTime) - { - if (ImLengthSqr(g.IO.MousePos - g.IO.MouseClickedPos[i]) < g.IO.MouseDoubleClickMaxDist * g.IO.MouseDoubleClickMaxDist) - g.IO.MouseDoubleClicked[i] = true; - g.IO.MouseClickedTime[i] = -FLT_MAX; // so the third click isn't turned into a double-click - } - else - { - g.IO.MouseClickedTime[i] = g.Time; - } - g.IO.MouseClickedPos[i] = g.IO.MousePos; - g.IO.MouseDragMaxDistanceAbs[i] = ImVec2(0.0f, 0.0f); - g.IO.MouseDragMaxDistanceSqr[i] = 0.0f; - } - else if (g.IO.MouseDown[i]) - { - ImVec2 mouse_delta = g.IO.MousePos - g.IO.MouseClickedPos[i]; - g.IO.MouseDragMaxDistanceAbs[i].x = ImMax(g.IO.MouseDragMaxDistanceAbs[i].x, mouse_delta.x < 0.0f ? -mouse_delta.x : mouse_delta.x); - g.IO.MouseDragMaxDistanceAbs[i].y = ImMax(g.IO.MouseDragMaxDistanceAbs[i].y, mouse_delta.y < 0.0f ? -mouse_delta.y : mouse_delta.y); - g.IO.MouseDragMaxDistanceSqr[i] = ImMax(g.IO.MouseDragMaxDistanceSqr[i], ImLengthSqr(mouse_delta)); - } - if (g.IO.MouseClicked[i]) // Clicking any mouse button reactivate mouse hovering which may have been deactivated by gamepad/keyboard navigation - g.NavDisableMouseHover = false; - } + NewFrameUpdateMouseInputs(); // Calculate frame-rate for the user, as a purely luxurious feature g.FramerateSecPerFrameAccum += g.IO.DeltaTime - g.FramerateSecPerFrame[g.FramerateSecPerFrameIdx]; @@ -3427,15 +3443,7 @@ void ImGui::NewFrame() g.IO.Framerate = 1.0f / (g.FramerateSecPerFrameAccum / (float)IM_ARRAYSIZE(g.FramerateSecPerFrame)); // Handle user moving window with mouse (at the beginning of the frame to avoid input lag or sheering) - UpdateMovingWindow(); - - // Delay saving settings so we don't spam disk too much - if (g.SettingsDirtyTimer > 0.0f) - { - g.SettingsDirtyTimer -= g.IO.DeltaTime; - if (g.SettingsDirtyTimer <= 0.0f) - SaveIniSettingsToDisk(g.IO.IniFilename); - } + NewFrameUpdateMovingWindow(); // Find the window we are hovering // - Child windows can extend beyond the limit of their parent so we need to derive HoveredRootWindow from HoveredWindow. diff --git a/imgui_internal.h b/imgui_internal.h index 65edf576bb18..62a09e41c76b 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -1118,7 +1118,7 @@ namespace ImGui IMGUI_API int ParseFormatPrecision(const char* fmt, int default_value); IMGUI_API float RoundScalar(float value, int decimal_precision); - // Shade functions + // Shade functions (write over already created vertices) IMGUI_API void ShadeVertsLinearColorGradientKeepAlpha(ImDrawVert* vert_start, ImDrawVert* vert_end, ImVec2 gradient_p0, ImVec2 gradient_p1, ImU32 col0, ImU32 col1); IMGUI_API void ShadeVertsLinearAlphaGradientForLeftToRightText(ImDrawVert* vert_start, ImDrawVert* vert_end, float gradient_p0_x, float gradient_p1_x); IMGUI_API void ShadeVertsLinearUV(ImDrawVert* vert_start, ImDrawVert* vert_end, const ImVec2& a, const ImVec2& b, const ImVec2& uv_a, const ImVec2& uv_b, bool clamp); From c1bdab6d5b3f43cad415070e0060cf532b45baff Mon Sep 17 00:00:00 2001 From: omar Date: Fri, 6 Apr 2018 19:28:00 +0200 Subject: [PATCH 813/823] Comments about io.WantCapture flags + todo entries. --- TODO.txt | 5 +++++ imgui.cpp | 22 ++++++++++++---------- imgui.h | 4 ++-- 3 files changed, 19 insertions(+), 12 deletions(-) diff --git a/TODO.txt b/TODO.txt index 0c54dad3e9b9..fc42b21f9492 100644 --- a/TODO.txt +++ b/TODO.txt @@ -249,6 +249,8 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i - nav: cannot access menubar of a flattened child window with Alt/menu key (not a very common use case..). - nav: esc/enter default behavior for popups, e.g. be able to mark an "ok" or "cancel" button that would get triggered by those keys. - nav: when activating a button that changes label (without a static ID) or disappear, can we somehow automatically recover into a nearest highlight item? + - nav: there's currently no way to completely clear focus with the keyboard. depending on patterns used by the application to dispatch inputs, it may be desirable. + - nav: configuration flag to disable global shortcuts (currently only CTRL-tab) ? - focus: preserve ActiveId/focus stack state, e.g. when opening a menu and close it, previously selected InputText() focus gets restored (#622) - focus: SetKeyboardFocusHere() on with >= 0 offset could be done on same frame (else latch and modulate on beginning of next frame) - focus: unable to use SetKeyboardFocusHere() on clipped widgets. (#787) @@ -263,6 +265,9 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i - misc: fix for compilation settings where stdcall isn't the default (e.g. vectorcall) (#1230) - misc: PushItemFlag(): add a flag to disable keyboard capture when used with mouse? (#1682) + - web/emscriptem: refactor some examples to facilitate integration with emscripten main loop system. (#1713, #336) + - web/emscriptem: tweak OpenGL renderers to support OpenGL ES. (#1713, #336) + - remote: make a system like RemoteImGui first-class citizen/project (#75) - demo: add vertical separator demo diff --git a/imgui.cpp b/imgui.cpp index e8e2632507b8..e7a97dd5081d 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -214,9 +214,9 @@ } - The examples/ folders contains many functional implementation of the pseudo-code above. - - When calling NewFrame(), the 'io.WantCaptureMouse'/'io.WantCaptureKeyboard'/'io.WantTextInput' flags are updated. - They tell you if ImGui intends to use your inputs. So for example, if 'io.WantCaptureMouse' is set you would typically want to hide - mouse inputs from the rest of your application. Read the FAQ below for more information about those flags. + - When calling NewFrame(), the 'io.WantCaptureMouse', 'io.WantCaptureKeyboard' and 'io.WantTextInput' flags are updated. + They tell you if ImGui intends to use your inputs. When a flag is set you want to hide the corresponding inputs from the rest of your application. + However, in both cases you need to pass on the inputs to imgui. Read the FAQ below for more information about those flags. - Please read the FAQ above. Amusingly, it is called a FAQ because people frequently have the same issues! USING GAMEPAD/KEYBOARD NAVIGATION CONTROLS [BETA] @@ -420,17 +420,19 @@ ====================================== Q: How can I tell whether to dispatch mouse/keyboard to imgui or to my application? - A: You can read the 'io.WantCaptureMouse'/'io.WantCaptureKeyboard'/'io.WantTextInput' flags from the ImGuiIO structure. + A: You can read the 'io.WantCaptureMouse', 'io.WantCaptureKeyboard' and 'io.WantTextInput' flags from the ImGuiIO structure. - When 'io.WantCaptureMouse' is set, imgui wants to use your mouse state, and you may want to discard/hide the inputs from the rest of your application. - When 'io.WantCaptureKeyboard' is set, imgui wants to use your keyboard state, and you may want to discard/hide the inputs from the rest of your application. - When 'io.WantTextInput' is set to may want to notify your OS to popup an on-screen keyboard, if available (e.g. on a mobile phone, or console OS). - The 'io.WantCaptureMouse' is more accurate that any attempt to "check if the mouse is hovering a window" (don't do that!). - It handle mouse dragging correctly (both dragging that started over your application or over an imgui window) and handle e.g. modal windows blocking inputs. - Those flags are updated by ImGui::NewFrame(). Preferably read the flags after calling NewFrame() if you can afford it, but reading them before is also - perfectly fine, as the bool toggle fairly rarely. - (Advanced note: text input releases focus on Return 'KeyDown', so the following Return 'KeyUp' event that your application receive will typically + Note: you should always pass your mouse/keyboard inputs to imgui, even when the io.WantCaptureXXX flag are set false. + This is because imgui needs to detect that you clicked in the void to unfocus its windows. + Note: The 'io.WantCaptureMouse' is more accurate that any attempt to "check if the mouse is hovering a window" (don't do that!). + It handle mouse dragging correctly (both dragging that started over your application or over an imgui window) and handle e.g. modal windows blocking inputs. + Those flags are updated by ImGui::NewFrame(). Preferably read the flags after calling NewFrame() if you can afford it, but reading them before is also + perfectly fine, as the bool toggle fairly rarely. If you have on a touch device, you might find use for an early call to NewFrameUpdateHoveredWindowAndCaptureFlags(). + Note: Text input widget releases focus on "Return KeyDown", so the subsequent "Return KeyUp" event that your application receive will typically have 'io.WantCaptureKeyboard=false'. Depending on your application logic it may or not be inconvenient. You might want to track which key-downs - were for Dear ImGui, e.g. with an array of bool, and filter out the corresponding key-ups.) + were targetted for Dear ImGui, e.g. with an array of bool, and filter out the corresponding key-ups.) Q: How can I display an image? What is ImTextureID, how does it works? A: ImTextureID is a void* used to pass renderer-agnostic texture references around until it hits your render function. diff --git a/imgui.h b/imgui.h index 57ce6f44ddfe..1c152db5ab52 100644 --- a/imgui.h +++ b/imgui.h @@ -1073,8 +1073,8 @@ struct ImGuiIO // Output - Retrieve after calling NewFrame() //------------------------------------------------------------------ - bool WantCaptureMouse; // When io.WantCaptureMouse is true, imgui will use the mouse inputs, do not dispatch them to your main game/application. (e.g. unclicked mouse is hovering over an imgui window, widget is active, mouse was clicked over an imgui window, etc.). - bool WantCaptureKeyboard; // When io.WantCaptureKeyboard is true, imgui will use the keyboard inputs, do not dispatch them to your main game/application. (e.g. InputText active, or an imgui window is focused and navigation is enabled, etc.). + bool WantCaptureMouse; // When io.WantCaptureMouse is true, imgui will use the mouse inputs, do not dispatch them to your main game/application (in both cases, always pass on mouse inputs to imgui). (e.g. unclicked mouse is hovering over an imgui window, widget is active, mouse was clicked over an imgui window, etc.). + bool WantCaptureKeyboard; // When io.WantCaptureKeyboard is true, imgui will use the keyboard inputs, do not dispatch them to your main game/application (in both cases, always pass keyboard inputs to imgui). (e.g. InputText active, or an imgui window is focused and navigation is enabled, etc.). bool WantTextInput; // Mobile/console: when io.WantTextInput is true, you may display an on-screen keyboard. This is set by ImGui when it wants textual keyboard input to happen (e.g. when a InputText widget is active). bool WantSetMousePos; // MousePos has been altered, back-end should reposition mouse on next frame. Set only when ImGuiConfigFlags_NavEnableSetMousePos flag is enabled. bool NavActive; // Directional navigation is currently allowed (will handle ImGuiKey_NavXXX events) = a window is focused and it doesn't use the ImGuiWindowFlags_NoNavInputs flag. From e88fb10d7ce1c0833e846c4b8a0ae241a3bc1320 Mon Sep 17 00:00:00 2001 From: omar Date: Fri, 6 Apr 2018 19:29:00 +0200 Subject: [PATCH 814/823] NewFrame: Extract some code into a NewFrameUpdateHoveredWindowAndCaptureFlags() which can be of use with touch-based inputs systems. --- imgui.cpp | 108 ++++++++++++++++++++++++++--------------------- imgui_internal.h | 2 + 2 files changed, 61 insertions(+), 49 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index e7a97dd5081d..e5631274c3ed 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -3344,6 +3344,62 @@ static void ImGui::NewFrameUpdateMouseInputs() } } +// The reason this is exposed in imgui_internal.h is: on touch-based system that don't have hovering, we want to dispatch inputs to the right target (imgui vs imgui+app) +void ImGui::NewFrameUpdateHoveredWindowAndCaptureFlags() +{ + ImGuiContext& g = *GImGui; + + // Find the window hovered by mouse: + // - Child windows can extend beyond the limit of their parent so we need to derive HoveredRootWindow from HoveredWindow. + // - When moving a window we can skip the search, which also conveniently bypasses the fact that window->WindowRectClipped is lagging as this point of the frame. + // - We also support the moved window toggling the NoInputs flag after moving has started in order to be able to detect windows below it, which is useful for e.g. docking mechanisms. + g.HoveredWindow = (g.MovingWindow && !(g.MovingWindow->Flags & ImGuiWindowFlags_NoInputs)) ? g.MovingWindow : FindHoveredWindow(); + g.HoveredRootWindow = g.HoveredWindow ? g.HoveredWindow->RootWindow : NULL; + + // Modal windows prevents cursor from hovering behind them. + ImGuiWindow* modal_window = GetFrontMostModalRootWindow(); + if (modal_window) + if (g.HoveredRootWindow && !IsWindowChildOf(g.HoveredRootWindow, modal_window)) + g.HoveredRootWindow = g.HoveredWindow = NULL; + + // We track click ownership. When clicked outside of a window the click is owned by the application and won't report hovering nor request capture even while dragging over our windows afterward. + int mouse_earliest_button_down = -1; + bool mouse_any_down = false; + for (int i = 0; i < IM_ARRAYSIZE(g.IO.MouseDown); i++) + { + if (g.IO.MouseClicked[i]) + g.IO.MouseDownOwned[i] = (g.HoveredWindow != NULL) || (!g.OpenPopupStack.empty()); + mouse_any_down |= g.IO.MouseDown[i]; + if (g.IO.MouseDown[i]) + if (mouse_earliest_button_down == -1 || g.IO.MouseClickedTime[i] < g.IO.MouseClickedTime[mouse_earliest_button_down]) + mouse_earliest_button_down = i; + } + const bool mouse_avail_to_imgui = (mouse_earliest_button_down == -1) || g.IO.MouseDownOwned[mouse_earliest_button_down]; + + // If mouse was first clicked outside of ImGui bounds we also cancel out hovering. + // FIXME: For patterns of drag and drop across OS windows, we may need to rework/remove this test (first committed 311c0ca9 on 2015/02) + const bool mouse_dragging_extern_payload = g.DragDropActive && (g.DragDropSourceFlags & ImGuiDragDropFlags_SourceExtern) != 0; + if (!mouse_avail_to_imgui && !mouse_dragging_extern_payload) + g.HoveredWindow = g.HoveredRootWindow = NULL; + + // Update io.WantCaptureMouse for the user application (true = dispatch mouse info to imgui, false = dispatch mouse info to imgui + app) + if (g.WantCaptureMouseNextFrame != -1) + g.IO.WantCaptureMouse = (g.WantCaptureMouseNextFrame != 0); + else + g.IO.WantCaptureMouse = (mouse_avail_to_imgui && (g.HoveredWindow != NULL || mouse_any_down)) || (!g.OpenPopupStack.empty()); + + // Update io.WantCaptureKeyboard for the user application (true = dispatch keyboard info to imgui, false = dispatch keyboard info to imgui + app) + if (g.WantCaptureKeyboardNextFrame != -1) + g.IO.WantCaptureKeyboard = (g.WantCaptureKeyboardNextFrame != 0); + else + g.IO.WantCaptureKeyboard = (g.ActiveId != 0) || (modal_window != NULL); + if (g.IO.NavActive && (g.IO.ConfigFlags & ImGuiConfigFlags_NavEnableKeyboard) && !(g.IO.ConfigFlags & ImGuiConfigFlags_NavNoCaptureKeyboard)) + g.IO.WantCaptureKeyboard = true; + + // Update io.WantTextInput flag, this is to allow systems without a keyboard (e.g. mobile, hand-held) to show a software keyboard if possible + g.IO.WantTextInput = (g.WantTextInputNextFrame != -1) ? (g.WantTextInputNextFrame != 0) : 0; +} + void ImGui::NewFrame() { IM_ASSERT(GImGui != NULL && "No current context. Did you call ImGui::CreateContext() or ImGui::SetCurrentContext()?"); @@ -3446,63 +3502,17 @@ void ImGui::NewFrame() // Handle user moving window with mouse (at the beginning of the frame to avoid input lag or sheering) NewFrameUpdateMovingWindow(); - - // Find the window we are hovering - // - Child windows can extend beyond the limit of their parent so we need to derive HoveredRootWindow from HoveredWindow. - // - When moving a window we can skip the search, which also conveniently bypasses the fact that window->WindowRectClipped is lagging as this point. - // - We also support the moved window toggling the NoInputs flag after moving has started in order to be able to detect windows below it, which is useful for e.g. docking mechanisms. - g.HoveredWindow = (g.MovingWindow && !(g.MovingWindow->Flags & ImGuiWindowFlags_NoInputs)) ? g.MovingWindow : FindHoveredWindow(); - g.HoveredRootWindow = g.HoveredWindow ? g.HoveredWindow->RootWindow : NULL; - - ImGuiWindow* modal_window = GetFrontMostModalRootWindow(); - if (modal_window != NULL) - { + NewFrameUpdateHoveredWindowAndCaptureFlags(); + + if (ImGuiWindow* modal_window = GetFrontMostModalRootWindow()) g.ModalWindowDarkeningRatio = ImMin(g.ModalWindowDarkeningRatio + g.IO.DeltaTime * 6.0f, 1.0f); - if (g.HoveredRootWindow && !IsWindowChildOf(g.HoveredRootWindow, modal_window)) - g.HoveredRootWindow = g.HoveredWindow = NULL; - } else - { g.ModalWindowDarkeningRatio = 0.0f; - } - // Update the WantCaptureMouse/WantCaptureKeyboard flags, so user can capture/discard the inputs away from the rest of their application. - // When clicking outside of a window we assume the click is owned by the application and won't request capture. We need to track click ownership. - int mouse_earliest_button_down = -1; - bool mouse_any_down = false; - for (int i = 0; i < IM_ARRAYSIZE(g.IO.MouseDown); i++) - { - if (g.IO.MouseClicked[i]) - g.IO.MouseDownOwned[i] = (g.HoveredWindow != NULL) || (!g.OpenPopupStack.empty()); - mouse_any_down |= g.IO.MouseDown[i]; - if (g.IO.MouseDown[i]) - if (mouse_earliest_button_down == -1 || g.IO.MouseClickedTime[i] < g.IO.MouseClickedTime[mouse_earliest_button_down]) - mouse_earliest_button_down = i; - } - bool mouse_avail_to_imgui = (mouse_earliest_button_down == -1) || g.IO.MouseDownOwned[mouse_earliest_button_down]; - if (g.WantCaptureMouseNextFrame != -1) - g.IO.WantCaptureMouse = (g.WantCaptureMouseNextFrame != 0); - else - g.IO.WantCaptureMouse = (mouse_avail_to_imgui && (g.HoveredWindow != NULL || mouse_any_down)) || (!g.OpenPopupStack.empty()); - - if (g.WantCaptureKeyboardNextFrame != -1) - g.IO.WantCaptureKeyboard = (g.WantCaptureKeyboardNextFrame != 0); - else - g.IO.WantCaptureKeyboard = (g.ActiveId != 0) || (modal_window != NULL); - if (g.IO.NavActive && (g.IO.ConfigFlags & ImGuiConfigFlags_NavEnableKeyboard) && !(g.IO.ConfigFlags & ImGuiConfigFlags_NavNoCaptureKeyboard)) - g.IO.WantCaptureKeyboard = true; - - g.IO.WantTextInput = (g.WantTextInputNextFrame != -1) ? (g.WantTextInputNextFrame != 0) : 0; g.MouseCursor = ImGuiMouseCursor_Arrow; g.WantCaptureMouseNextFrame = g.WantCaptureKeyboardNextFrame = g.WantTextInputNextFrame = -1; g.OsImePosRequest = ImVec2(1.0f, 1.0f); // OS Input Method Editor showing on top-left of our window by default - // If mouse was first clicked outside of ImGui bounds we also cancel out hovering. - // FIXME: For patterns of drag and drop across OS windows, we may need to rework/remove this test (first committed 311c0ca9 on 2015/02) - bool mouse_dragging_extern_payload = g.DragDropActive && (g.DragDropSourceFlags & ImGuiDragDropFlags_SourceExtern) != 0; - if (!mouse_avail_to_imgui && !mouse_dragging_extern_payload) - g.HoveredWindow = g.HoveredRootWindow = NULL; - // Mouse wheel scrolling, scale if (g.HoveredWindow && !g.HoveredWindow->Collapsed && (g.IO.MouseWheel != 0.0f || g.IO.MouseWheelH != 0.0f)) { diff --git a/imgui_internal.h b/imgui_internal.h index 62a09e41c76b..6a795eca87df 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -1017,6 +1017,8 @@ namespace ImGui IMGUI_API void Initialize(ImGuiContext* context); IMGUI_API void Shutdown(ImGuiContext* context); // Since 1.60 this is a _private_ function. You can call DestroyContext() to destroy the context created by CreateContext(). + IMGUI_API void NewFrameUpdateHoveredWindowAndCaptureFlags(); + IMGUI_API void MarkIniSettingsDirty(); IMGUI_API ImGuiSettingsHandler* FindSettingsHandler(const char* type_name); IMGUI_API ImGuiWindowSettings* FindWindowSettings(ImGuiID id); From 0734a12d25693355db3c1e1801fe63a24723142b Mon Sep 17 00:00:00 2001 From: omar Date: Fri, 6 Apr 2018 23:05:53 +0200 Subject: [PATCH 815/823] IO: ImGuiConfigFlags_NoMouse disable hovering so it is not destructive. Amend 2464e62a1ad9a7c8f2d9f898f54484af8ca3a524 --- imgui.cpp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index e5631274c3ed..69fdea6a8b7c 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -3294,11 +3294,6 @@ static void ImGui::NewFrameUpdateMovingWindow() static void ImGui::NewFrameUpdateMouseInputs() { ImGuiContext& g = *GImGui; - if (g.IO.ConfigFlags & ImGuiConfigFlags_NoMouse) - { - g.IO.MousePos = ImVec2(-FLT_MAX, -FLT_MAX); - memset(g.IO.MouseDown, 0, sizeof(g.IO.MouseDown)); - } // If mouse just appeared or disappeared (usually denoted by -FLT_MAX component, but in reality we test for -256000.0f) we cancel out movement in MouseDelta if (ImGui::IsMousePosValid(&g.IO.MousePos) && ImGui::IsMousePosValid(&g.IO.MousePosPrev)) @@ -3362,6 +3357,10 @@ void ImGui::NewFrameUpdateHoveredWindowAndCaptureFlags() if (g.HoveredRootWindow && !IsWindowChildOf(g.HoveredRootWindow, modal_window)) g.HoveredRootWindow = g.HoveredWindow = NULL; + // Disabled mouse? + if (g.IO.ConfigFlags & ImGuiConfigFlags_NoMouse) + g.HoveredWindow = g.HoveredRootWindow = NULL; + // We track click ownership. When clicked outside of a window the click is owned by the application and won't report hovering nor request capture even while dragging over our windows afterward. int mouse_earliest_button_down = -1; bool mouse_any_down = false; From c2fc9789831774cd9fec60eb79ced81ee4782bc2 Mon Sep 17 00:00:00 2001 From: omar Date: Fri, 6 Apr 2018 23:25:25 +0200 Subject: [PATCH 816/823] Style: Default style is now StyleColorsDark()! Toward a 1.60 release :) (#707) --- CHANGELOG.txt | 9 +++++---- imgui.cpp | 3 ++- imgui.h | 8 ++++---- 3 files changed, 11 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.txt b/CHANGELOG.txt index 0d2cbf9822b7..eba9b0657439 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -50,7 +50,7 @@ Breaking Changes: If you were adding or subtracting to ImFont::DisplayOffset check if your fonts are correctly aligned vertically. (#1619) - BeginDragDropSource(): temporarily removed the optional mouse_button=0 parameter because it is not really usable in many situations at the moment. - Obsoleted the io.RenderDrawListsFn callback, you can call your graphics engine render function after ImGui::Render(). Use ImGui::GetDrawData() to retrieve the ImDrawData* to display. - - Reorganized context handling to be more explicit, + - Reorganized context handling to be more explicit, (#1599) - YOU NOW NEED TO CALL ImGui::CreateContext() AT THE BEGINNING OF YOUR APP, AND CALL ImGui::DestroyContext() AT THE END. - removed Shutdown() function, as DestroyContext() serve this purpose. - you may pass a ImFontAtlas* pointer to CreateContext() to share a font atlas between contexts. Otherwhise CreateContext() will create its own font atlas instance. @@ -86,10 +86,10 @@ Other Changes: - Navigation: Style: Added ImGuiCol_NavHighlight, ImGuiCol_NavWindowingHighlight colors. (#787) - Navigation: TreeNode: Added ImGuiTreeNodeFlags_NavLeftJumpsBackHere flag to allow Nav Left direction to jump back to parent tree node from any of its child. (#1079) - Navigation: IO: Added io.ConfigFlags (input), io.NavActive (output), io.NavVisible (output). (#787) -- Context: Removed the default global context and font atlas instances, which caused various problems to users of multiple contexts and DLL users. (#1565) +- Context: Removed the default global context and font atlas instances, which caused various problems to users of multiple contexts and DLL users. (#1565, #1599) YOU NOW NEED TO CALL ImGui::CreateContext() AT THE BEGINNING OF YOUR APP, AND CALL ImGui::DestroyContext() AT THE END. Existing apps will assert/crash without it. -- Context: Removed allocator parameters from CreateContext(), they are now setup with SetAllocatorFunctions() and shared by all contexts. (#1565, #586, #992, #1007, #1558) -- Context: You may pass a ImFontAtlas to CreateContext() to specify a font atlas to share. Shared font atlas are not owned by the context and not destroyed along with it. +- Context: Added SetAllocatorFunctions() to rewire memory allocators (as a replacement to previous parameters to CreateContext()). Allocators are shared by all contexts and imgui helpers. (#1565, #586, #992, #1007, #1558) +- Context: You may pass a ImFontAtlas to CreateContext() to specify a font atlas to share. Shared font atlas are not owned by the context and not destroyed along with it. (#1599) - Context: Added IMGUI_DISABLE_DEFAULT_ALLOCATORS to disable linking with malloc/free. (#1565, #586, #992, #1007, #1558) - IO: Added io.ConfigFlags for user application to store settings for imgui and for the back-end: - ImGuiConfigFlags_NavEnableKeyboard: Enable keyboard navigation. @@ -111,6 +111,7 @@ Other Changes: - InputText: Added alternative clipboard shortcuts: Shift+Delete (cut), Ctrl+Insert (copy), Shift+Insert (paste). (#1541) - InputText: Fixed losing Cursor X position when clicking outside on an item that's submitted after the InputText(). It was only noticeable when restoring focus programmatically. (#1418, #1554) - InputText: Added ImGuiInputTextFlags_CharsScientific flag to also allow 'e'/'E' for input of values using scientific notation. Automatically used by InputFloat. +- Style: Default style is now StyleColorsDark(), instead of the old StyleColorsClassic(). (#707) - Style: Enable window border by default. (#707) - Style: Exposed ImGuiStyleVar_WindowTitleAlign, ImGuiStyleVar_ScrollbarSize, ImGuiStyleVar_ScrollbarRounding, ImGuiStyleVar_GrabRounding + added an assert to reduce accidental breakage. (#1181) - Style: Added style.MouseCursorScale help when using the software mouse cursor facility. (#939). diff --git a/imgui.cpp b/imgui.cpp index 69fdea6a8b7c..5b10471c148f 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -837,7 +837,8 @@ ImGuiStyle::ImGuiStyle() AntiAliasedFill = true; // Enable anti-aliasing on filled shapes (rounded rectangles, circles, etc.) CurveTessellationTol = 1.25f; // Tessellation tolerance when using PathBezierCurveTo() without a specific number of segments. Decrease for highly tessellated curves (higher quality, more polygons), increase to reduce quality. - ImGui::StyleColorsClassic(this); + // Default theme + ImGui::StyleColorsDark(this); } // To scale your entire UI (e.g. if you want your app to use High DPI or generally be DPI aware) you may use this helper function. Scaling the fonts is done separately and is up to you. diff --git a/imgui.h b/imgui.h index 1c152db5ab52..90411301f13f 100644 --- a/imgui.h +++ b/imgui.h @@ -162,8 +162,8 @@ namespace ImGui IMGUI_API const char* GetVersion(); // get a version string e.g. "1.23" // Styles - IMGUI_API void StyleColorsDark(ImGuiStyle* dst = NULL); // new, recommended style - IMGUI_API void StyleColorsClassic(ImGuiStyle* dst = NULL); // old, classic imgui style (default) + IMGUI_API void StyleColorsDark(ImGuiStyle* dst = NULL); // new, recommended style (default) + IMGUI_API void StyleColorsClassic(ImGuiStyle* dst = NULL); // classic imgui style IMGUI_API void StyleColorsLight(ImGuiStyle* dst = NULL); // best used with borders and a custom, thicker font // Windows @@ -570,13 +570,13 @@ enum ImGuiWindowFlags_ ImGuiWindowFlags_AlwaysVerticalScrollbar= 1 << 14, // Always show vertical scrollbar (even if ContentSize.y < Size.y) ImGuiWindowFlags_AlwaysHorizontalScrollbar=1<< 15, // Always show horizontal scrollbar (even if ContentSize.x < Size.x) ImGuiWindowFlags_AlwaysUseWindowPadding = 1 << 16, // Ensure child windows without border uses style.WindowPadding (ignored by default for non-bordered child windows, because more convenient) - ImGuiWindowFlags_ResizeFromAnySide = 1 << 17, // (WIP) Enable resize from any corners and borders. Your back-end needs to honor the different values of io.MouseCursor set by imgui. + ImGuiWindowFlags_ResizeFromAnySide = 1 << 17, // [BETA] Enable resize from any corners and borders. Your back-end needs to honor the different values of io.MouseCursor set by imgui. ImGuiWindowFlags_NoNavInputs = 1 << 18, // No gamepad/keyboard navigation within the window ImGuiWindowFlags_NoNavFocus = 1 << 19, // No focusing toward this window with gamepad/keyboard navigation (e.g. skipped by CTRL+TAB) ImGuiWindowFlags_NoNav = ImGuiWindowFlags_NoNavInputs | ImGuiWindowFlags_NoNavFocus, // [Internal] - ImGuiWindowFlags_NavFlattened = 1 << 23, // (WIP) Allow gamepad/keyboard navigation to cross over parent border to this child (only use on child that have no scrolling!) + ImGuiWindowFlags_NavFlattened = 1 << 23, // [BETA] Allow gamepad/keyboard navigation to cross over parent border to this child (only use on child that have no scrolling!) ImGuiWindowFlags_ChildWindow = 1 << 24, // Don't use! For internal use by BeginChild() ImGuiWindowFlags_Tooltip = 1 << 25, // Don't use! For internal use by BeginTooltip() ImGuiWindowFlags_Popup = 1 << 26, // Don't use! For internal use by BeginPopup() From c712f7275de3814febbf085e3ee115f472c4a1d5 Mon Sep 17 00:00:00 2001 From: omar Date: Sat, 7 Apr 2018 10:25:51 +0200 Subject: [PATCH 817/823] Fixed unused variable warning. --- imgui.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/imgui.cpp b/imgui.cpp index 5b10471c148f..a351aa5dbc65 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -3504,7 +3504,7 @@ void ImGui::NewFrame() NewFrameUpdateMovingWindow(); NewFrameUpdateHoveredWindowAndCaptureFlags(); - if (ImGuiWindow* modal_window = GetFrontMostModalRootWindow()) + if (GetFrontMostModalRootWindow() != NULL) g.ModalWindowDarkeningRatio = ImMin(g.ModalWindowDarkeningRatio + g.IO.DeltaTime * 6.0f, 1.0f); else g.ModalWindowDarkeningRatio = 0.0f; From 82b7a39f31105e2e08c021b6911496ae062d9c17 Mon Sep 17 00:00:00 2001 From: omar Date: Sat, 7 Apr 2018 10:38:01 +0200 Subject: [PATCH 818/823] Fixed a few zealous warnings. --- imgui.cpp | 16 ++++++++-------- imgui_draw.cpp | 4 ++-- imgui_internal.h | 2 +- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index a351aa5dbc65..4e424802ec97 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1381,8 +1381,8 @@ ImU32 ImGui::GetColorU32(ImU32 col) float style_alpha = GImGui->Style.Alpha; if (style_alpha >= 1.0f) return col; - int a = (col & IM_COL32_A_MASK) >> IM_COL32_A_SHIFT; - a = (int)(a * style_alpha); // We don't need to clamp 0..255 because Style.Alpha is in 0..1 range. + ImU32 a = (col & IM_COL32_A_MASK) >> IM_COL32_A_SHIFT; + a = (ImU32)(a * style_alpha); // We don't need to clamp 0..255 because Style.Alpha is in 0..1 range. return (col & ~IM_COL32_A_MASK) | (a << IM_COL32_A_SHIFT); } @@ -1473,7 +1473,7 @@ void* ImFileLoadToMemory(const char* filename, const char* file_open_mode, int* } int file_size = (int)file_size_signed; - void* file_data = ImGui::MemAlloc(file_size + padding_bytes); + void* file_data = ImGui::MemAlloc((size_t)(file_size + padding_bytes)); if (file_data == NULL) { fclose(f); @@ -1486,7 +1486,7 @@ void* ImFileLoadToMemory(const char* filename, const char* file_open_mode, int* return NULL; } if (padding_bytes > 0) - memset((void *)(((char*)file_data) + file_size), 0, padding_bytes); + memset((void *)(((char*)file_data) + file_size), 0, (size_t)padding_bytes); fclose(f); if (out_file_size) @@ -1773,7 +1773,7 @@ void ImGuiTextBuffer::appendfv(const char* fmt, va_list args) } Buf.resize(needed_sz); - ImFormatStringV(&Buf[write_off - 1], len + 1, fmt, args_copy); + ImFormatStringV(&Buf[write_off - 1], (size_t)len + 1, fmt, args_copy); } void ImGuiTextBuffer::appendf(const char* fmt, ...) @@ -8502,7 +8502,7 @@ static size_t GDataTypeSize[ImGuiDataType_COUNT] = // NB: This is _not_ a full expression evaluator. We should probably add one though.. static bool DataTypeApplyOpFromText(const char* buf, const char* initial_value_buf, ImGuiDataType data_type, void* data_ptr, const char* scalar_format) { - while (ImCharIsSpace(*buf)) + while (ImCharIsSpace((unsigned int)*buf)) buf++; // We don't support '-' op because it would conflict with inputing negative value. @@ -8511,7 +8511,7 @@ static bool DataTypeApplyOpFromText(const char* buf, const char* initial_value_b if (op == '+' || op == '*' || op == '/') { buf++; - while (ImCharIsSpace(*buf)) + while (ImCharIsSpace((unsigned int)*buf)) buf++; } else @@ -11748,7 +11748,7 @@ bool ImGui::ColorEdit4(const char* label, float col[4], ImGuiColorEditFlags flag { value_changed = true; char* p = buf; - while (*p == '#' || ImCharIsSpace(*p)) + while (*p == '#' || ImCharIsSpace((unsigned int)*p)) p++; i[0] = i[1] = i[2] = i[3] = 0; if (alpha) diff --git a/imgui_draw.cpp b/imgui_draw.cpp index b7ba849bfab3..de8ccb801cdd 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -2435,7 +2435,7 @@ ImVec2 ImFont::CalcTextSizeA(float size, float max_width, float wrap_width, cons while (s < text_end) { const char c = *s; - if (ImCharIsSpace(c)) { s++; } else if (c == '\n') { s++; break; } else { break; } + if (ImCharIsSpace((unsigned int)c)) { s++; } else if (c == '\n') { s++; break; } else { break; } } continue; } @@ -2560,7 +2560,7 @@ void ImFont::RenderText(ImDrawList* draw_list, float size, ImVec2 pos, ImU32 col while (s < text_end) { const char c = *s; - if (ImCharIsSpace(c)) { s++; } else if (c == '\n') { s++; break; } else { break; } + if (ImCharIsSpace((unsigned int)c)) { s++; } else if (c == '\n') { s++; break; } else { break; } } continue; } diff --git a/imgui_internal.h b/imgui_internal.h index 6a795eca87df..61bde2d120cb 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -98,7 +98,7 @@ IMGUI_API int ImTextCountUtf8BytesFromStr(const ImWchar* in_text, cons IMGUI_API ImU32 ImHash(const void* data, int data_size, ImU32 seed = 0); // Pass data_size==0 for zero-terminated strings IMGUI_API void* ImFileLoadToMemory(const char* filename, const char* file_open_mode, int* out_file_size = NULL, int padding_bytes = 0); IMGUI_API FILE* ImFileOpen(const char* filename, const char* file_open_mode); -static inline bool ImCharIsSpace(int c) { return c == ' ' || c == '\t' || c == 0x3000; } +static inline bool ImCharIsSpace(unsigned int c) { return c == ' ' || c == '\t' || c == 0x3000; } static inline bool ImIsPowerOfTwo(int v) { return v != 0 && (v & (v - 1)) == 0; } static inline int ImUpperPowerOfTwo(int v) { v--; v |= v >> 1; v |= v >> 2; v |= v >> 4; v |= v >> 8; v |= v >> 16; v++; return v; } From 6d0c720451561364387b31ad21b52efa23bd7323 Mon Sep 17 00:00:00 2001 From: omar Date: Sat, 7 Apr 2018 23:06:06 +0200 Subject: [PATCH 819/823] Internals: Removed unused internal variant of ArrowButton(). --- imgui.cpp | 26 -------------------------- imgui_internal.h | 1 - 2 files changed, 27 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 4e424802ec97..2a07ef882b02 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -7803,32 +7803,6 @@ bool ImGui::CloseButton(ImGuiID id, const ImVec2& pos, float radius) return pressed; } -// [Internal] -bool ImGui::ArrowButton(ImGuiID id, ImGuiDir dir, ImVec2 padding, ImGuiButtonFlags flags) -{ - ImGuiContext& g = *GImGui; - ImGuiWindow* window = g.CurrentWindow; - if (window->SkipItems) - return false; - - const ImGuiStyle& style = g.Style; - - const ImRect bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(g.FontSize + padding.x * 2.0f, g.FontSize + padding.y * 2.0f)); - ItemSize(bb, style.FramePadding.y); - if (!ItemAdd(bb, id)) - return false; - - bool hovered, held; - bool pressed = ButtonBehavior(bb, id, &hovered, &held, flags); - - const ImU32 col = GetColorU32((hovered && held) ? ImGuiCol_ButtonActive : hovered ? ImGuiCol_ButtonHovered : ImGuiCol_Button); - RenderNavHighlight(bb, id); - RenderFrame(bb.Min, bb.Max, col, true, style.FrameRounding); - RenderArrow(bb.Min + padding, dir, 1.0f); - - return pressed; -} - void ImGui::Image(ImTextureID user_texture_id, const ImVec2& size, const ImVec2& uv0, const ImVec2& uv1, const ImVec4& tint_col, const ImVec4& border_col) { ImGuiWindow* window = GetCurrentWindow(); diff --git a/imgui_internal.h b/imgui_internal.h index 61bde2d120cb..63d43e55aa7e 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -1092,7 +1092,6 @@ namespace ImGui IMGUI_API bool ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool* out_held, ImGuiButtonFlags flags = 0); IMGUI_API bool ButtonEx(const char* label, const ImVec2& size_arg = ImVec2(0,0), ImGuiButtonFlags flags = 0); IMGUI_API bool CloseButton(ImGuiID id, const ImVec2& pos, float radius); - IMGUI_API bool ArrowButton(ImGuiID id, ImGuiDir dir, ImVec2 padding, ImGuiButtonFlags flags = 0); IMGUI_API bool SliderBehavior(const ImRect& frame_bb, ImGuiID id, float* v, float v_min, float v_max, float power, int decimal_precision, ImGuiSliderFlags flags = 0); IMGUI_API bool SliderFloatN(const char* label, float* v, int components, float v_min, float v_max, const char* display_format, float power); From 3a29ddbcfabd52ae77a779e6188291783c2d193b Mon Sep 17 00:00:00 2001 From: omar Date: Sat, 7 Apr 2018 23:07:23 +0200 Subject: [PATCH 820/823] Version 1.60 --- CHANGELOG.txt | 56 +++++++++++++++++++++++------------------------- README.md | 2 +- imgui.cpp | 24 ++++++++++----------- imgui_demo.cpp | 2 +- imgui_draw.cpp | 2 +- imgui_internal.h | 2 +- 6 files changed, 43 insertions(+), 45 deletions(-) diff --git a/CHANGELOG.txt b/CHANGELOG.txt index eba9b0657439..253f2ddc143e 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -37,52 +37,53 @@ HOW TO UPDATE? ----------------------------------------------------------------------- -VERSION 1.60 WIP (Latest, currently in development) +VERSION 1.60 (Released 2018-04-07) +Decorated log: https://github.com/ocornut/imgui/releases/tag/v1.60 The gamepad/keyboard navigation branch (which has been in the work since July 2016) has been merged. -Gamepad/keyboard navigation is still marked as Beta and has to be enabled explicitely. +Gamepad/keyboard navigation is still marked as Beta and has to be enabled explicitly. Various internal refactors have also been done, as part of the navigation work and as part of the upcoing viewport/docking work. Breaking Changes: -(IN PROGRESS, WILL ADD TO THIS LIST AS WE WORK ON 1.60) - - Fonts: changed ImFont::DisplayOffset.y to defaults to 0 instead of +1. Fixed vertical rounding of Ascent/Descent to match TrueType renderer. - If you were adding or subtracting to ImFont::DisplayOffset check if your fonts are correctly aligned vertically. (#1619) - - BeginDragDropSource(): temporarily removed the optional mouse_button=0 parameter because it is not really usable in many situations at the moment. - - Obsoleted the io.RenderDrawListsFn callback, you can call your graphics engine render function after ImGui::Render(). Use ImGui::GetDrawData() to retrieve the ImDrawData* to display. - - Reorganized context handling to be more explicit, (#1599) + - Obsoleted the io.RenderDrawListsFn callback, you can call your graphics engine render function after ImGui::Render(). + e.g. with example back-ends, call ImDrawData* draw_data = ImGui::GetDrawData(); ImGui_ImplXXXX_RenderDrawData(draw_data). + - Reorganized context handling to be more explicit: (#1599) - YOU NOW NEED TO CALL ImGui::CreateContext() AT THE BEGINNING OF YOUR APP, AND CALL ImGui::DestroyContext() AT THE END. - - removed Shutdown() function, as DestroyContext() serve this purpose. + - removed Shutdown() function, as DestroyContext() serve this purpose. If you are using an old back-end from the examples/ folder, remove the line that calls Shutdown(). - you may pass a ImFontAtlas* pointer to CreateContext() to share a font atlas between contexts. Otherwhise CreateContext() will create its own font atlas instance. - removed allocator parameters from CreateContext(), they are now setup with SetAllocatorFunctions(), and shared by all contexts. - removed the default global context and font atlas instance, which were confusing for users of DLL reloading and users of multiple contexts. - - Moved sample TTF files from extra_fonts/ to misc/fonts/. If you loaded files directly from the imgui repo you may need to update your paths. - Renamed ImGuiStyleVar_Count_ to ImGuiStyleVar_COUNT and ImGuiMouseCursor_Count_ to ImGuiMouseCursor_COUNT for consistency with other public enums. + - Fonts: Moved sample TTF files from extra_fonts/ to misc/fonts/. If you loaded files directly from the imgui repo you may need to update your paths. + - Fonts: changed ImFont::DisplayOffset.y to defaults to 0 instead of +1. Fixed vertical rounding of Ascent/Descent to match TrueType renderer. + If you were adding or subtracting (not assigning) to ImFont::DisplayOffset check if your fonts are correctly aligned vertically. (#1619) + - BeginDragDropSource(): temporarily removed the optional mouse_button=0 parameter because it is not really usable in many situations at the moment. - Obsoleted IsAnyWindowHovered() in favor of IsWindowHovered(ImGuiHoveredFlags_AnyWindow). Kept redirection function (will obsolete). - Obsoleted IsAnyWindowFocused() in favor of IsWindowFocused(ImGuiFocusedFlags_AnyWindow). Kept redirection function (will obsolete). - - Renamed io.WantMoveMouse to io.WantSetMousePos for consistency and ease of understanding (was added in 1.52, _not_ used by core, and honored by some binding ahead of merging the Nav branch). + - Renamed io.WantMoveMouse to io.WantSetMousePos for consistency and ease of understanding (was added in 1.52, not used by core, and honored by some binding ahead of merging the Nav branch). - Removed ImGuiCol_CloseButton, ImGuiCol_CloseButtonActive, ImGuiCol_CloseButtonHovered style colors as the closing cross uses regular button colors now. - Renamed ImGuiSizeConstraintCallback to ImGuiSizeCallback, ImGuiSizeConstraintCallbackData to ImGuiSizeCallbackData. - Removed CalcItemRectClosestPoint() which was weird and not really used by anyone except demo code. If you need it it's easy to replicate on your side. Other Changes: -(IN PROGRESS, WILL ADD TO THIS LIST AS WE WORK ON 1.60) - Doc: Added a Changelog file in the repository to ease comparing versions (it goes back to dear imgui 1.48), until now it was only on GitHub. -- Navigation: merged in the gamepad/keyboard navigation (about one million changes!). (#787, #323) +- Navigation: merged in the gamepad/keyboard navigation (about a million changes!). (#787, #323) The initial focus was to support game controllers, but keyboard is becoming increasingly and decently usable. + - To use Gamepad Navigation: + - Set io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad to enable. + - Backend: Set io.BackendFlags |= ImGuiBackendFlags_HasGamepad + fill the io.NavInputs[] fields before calling NewFrame(). Read imgui.cpp for more details. + - See https://github.com/ocornut/imgui/issues/1599 for recommended gamepad mapping or download PNG/PSD at http://goo.gl/9LgVZW + - See 'enum ImGuiNavInput_' in imgui.h for a description of inputs. Read imgui.cpp for more details. - To use Keyboard Navigation: - Set io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard to enable. NewFrame() will automatically fill io.NavInputs[] based on your io.KeyDown[] + io.KeyMap[] arrays. + - Basic controls: arrows to navigate, Alt to enter menus, Space to activate item, Enter to edit text, Escape to cancel/close, Ctrl-Tab to focus windows, etc. - When keyboard navigation is active (io.NavActive + ImGuiConfigFlags_NavEnableKeyboard), the io.WantCaptureKeyboard flag will be set. For more advanced uses, you may want to read from io.NavActive or io.NavVisible. Read imgui.cpp for more details. - - To use Gamepad Navigation: - - Set io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad to enable. - - Backend: Set io.BackendFlags |= ImGuiBackendFlags_HasGamepad + fill the io.NavInputs[] fields before calling NewFrame(). Note that io.NavInputs[] is cleared by EndFrame(). - - See https://github.com/ocornut/imgui/issues/1599 for recommended gamepad mapping. - - See 'enum ImGuiNavInput_' in imgui.h for a description of inputs. Read imgui.cpp for more details. - Navigation: SetItemDefaultFocus() sets the navigation position in addition to scrolling. (#787) - Navigation: Added IsItemFocused(), added IsAnyItemFocused(). (#787) -- Navigation: Added window flags: ImGuiWindowFlags_NoNav (ImGuiWindowFlags_NoNavInputs | ImGuiWindowFlags_NoNavFocus). +- Navigation: Added window flags: ImGuiWindowFlags_NoNav (== ImGuiWindowFlags_NoNavInputs | ImGuiWindowFlags_NoNavFocus). - Navigation: Style: Added ImGuiCol_NavHighlight, ImGuiCol_NavWindowingHighlight colors. (#787) - Navigation: TreeNode: Added ImGuiTreeNodeFlags_NavLeftJumpsBackHere flag to allow Nav Left direction to jump back to parent tree node from any of its child. (#1079) - Navigation: IO: Added io.ConfigFlags (input), io.NavActive (output), io.NavVisible (output). (#787) @@ -102,11 +103,10 @@ Other Changes: - IO: Added ImGuiKey_Insert, ImGuiKey_Space keys. Setup in all example bindings. (#1541) - IO: Added Horizontal Mouse Wheel support for horizontal scrolling. (#1463) [@tseeker] - IO: Added IsAnyMouseDown() helper which is helpful for bindings to handle mouse capturing. -- Window: Clicking on a window with the ImGuiWIndowFlags_NoMove flags takes an ActiveId so we can't hover something else when dragging afterwards. (ref #1381, #1337) +- Window: Clicking on a window with the ImGuiWIndowFlags_NoMove flags takes an ActiveId so we can't hover something else when dragging afterwards. (#1381, #1337) - Window: IsWindowHovered(): Added ImGuiHoveredFlags_AnyWindow, ImGuiFocusedFlags_AnyWindow flags (See Breaking Changes). Added to demo. (#1382) - Window: Added SetNextWindowBgAlpha() helper. Particularly helpul since the legacy 5-parameters version of Begin() has been marked as obsolete in 1.53. (#1567) - Window: Fixed SetNextWindowContentSize() with 0.0f on Y axis (or SetNextWindowContentWidth()) overwriting the contents size. Got broken on Dec 10 (1.53). (#1363) -- Window: CloseButton: Fixed cross positioning being a little off. - ArrowButton: Added ArrowButton() given a cardinal direction (e.g. ImGuiDir_Left). - InputText: Added alternative clipboard shortcuts: Shift+Delete (cut), Ctrl+Insert (copy), Shift+Insert (paste). (#1541) - InputText: Fixed losing Cursor X position when clicking outside on an item that's submitted after the InputText(). It was only noticeable when restoring focus programmatically. (#1418, #1554) @@ -115,7 +115,7 @@ Other Changes: - Style: Enable window border by default. (#707) - Style: Exposed ImGuiStyleVar_WindowTitleAlign, ImGuiStyleVar_ScrollbarSize, ImGuiStyleVar_ScrollbarRounding, ImGuiStyleVar_GrabRounding + added an assert to reduce accidental breakage. (#1181) - Style: Added style.MouseCursorScale help when using the software mouse cursor facility. (#939). -- Style: Close button nows display a cross before hovering. Uses button colors for highlight when hovering. (#707) +- Style: Close button nows display a cross before hovering. Fixed cross positioning being a little off. Uses button colors for highlight when hovering. (#707) - Popup: OpenPopup() Always reopen existing popup. (Removed imgui_internal.h's OpenPopupEx() which was used for this.) (#1497, #1533). - Popup: BeginPopupContextItem(), BeginPopupContextWindow(), BeginPopupContextVoid(), OpenPopupOnItemClick() all react on mouse release instead of mouse press. (~#439) - Popup: Better handling of user mistakenly calling OpenPopup() every frame (with reopen_existing option). The error will now be more visible and easier to understand. (#1497) @@ -141,7 +141,7 @@ Other Changes: - Combo: Arrow button isn't displayed over frame background so its blended color matches other buttons. Left side of the button isn't rounded. - PlotLines: plot a flat line if scale_min==scale_max. (#1621) - Fonts: Changed DisplayOffset.y to defaults to 0 instead of +1. Fixed rounding of Ascent/Descent to match TrueType renderer. - If you were adding or subtracting to ImFont::DisplayOffset check if your fonts are correctly aligned vertically. (#1619) + If you were adding or subtracting (not assigning) to ImFont::DisplayOffset check if your fonts are correctly aligned vertically. (#1619) - Fonts: Updated stb_truetype from 1.14 to stb_truetype 1.19. (w/ include fix from some platforms #1622) - Fonts: Added optional FreeType rasterizer in misc/freetype. Moved from imgui_club repo. (#618) [@Vuhdo, @mikesart, @ocornut] - Fonts: Moved extra_fonts/ to misc/fonts/. @@ -152,7 +152,7 @@ Other Changes: - ImFontAtlas: Added ImFontAtlasFlags_NoMouseCursors flag to disable baking software mouse cursors, mostly to save texture memory on very low end hardware. (#1613) - ImDrawList: Fixed AddRect() with antialiasing disabled (lower-right corner pixel was often missing, rounding looks a little better.) (#1646) - ImDrawList: Added CloneOutput() helper to facilitate the cloning of ImDrawData or ImDrawList for multi-threaded rendering. -- Misc: Functions passed to libc qsort are explicitely marked cdecl to support compiling with vectorcall as the default calling convention. (#1230, #1611) [@RandyGaul] +- Misc: Functions passed to libc qsort are explicitly marked cdecl to support compiling with vectorcall as the default calling convention. (#1230, #1611) [@RandyGaul] - Misc: ImVec2: added [] operator. This is becoming desirable for some code working of either axes independently. Better adding it sooner than later. - Misc: NewFrame(): Added an assert to detect incorrect filling of the io.KeyMap[] array earlier. (#1555) - Misc: Added IM_OFFSETOF() helper in imgui.h (previously was in imgui_internal.h) @@ -161,7 +161,6 @@ Other Changes: - Misc: Added IMGUI_USER_CONFIG to define a custom configuration filename. (#255, #1573, #1144, #41) - Misc: Added IMGUI_STB_TRUETYPE_FILENAME and IMGUI_STB_RECT_PACK_FILENAME compile time directives to use another version of the stb_ files. - Misc: Updated stb_rect_pack from 0.10 to 0.11 (minor changes). -- Misc: Added ImGuiConfigFlags_IsSRGB and ImGuiConfigFlags_IsTouchScreen user flags (for io.ConfigFlags). (Those flags are not used by ImGui itself, they only exists to make it easy for the engine/back-end to pass information to the application in a standard manner.) - Metrics: Added display of Columns state. - Demo: Improved Selectable() examples. (#1528) @@ -193,8 +192,7 @@ Other Changes: - Examples: Vulkan: Visual Studio: Added .vcxproj file. - Examples: Apple: Fixed filenames in OSX xcode project. Various other Mac friendly fixes. [@gerryhernandez etc.] - Examples: Visual Studio: Disabled extraneous function-level check in Release build. -- Internals: Lots of refactoring! -- Various minor fixes, tweaks, optimizations, comments. +- Various fixes, tweaks, internal refactoring, optimizations, comments. ----------------------------------------------------------------------- @@ -559,7 +557,7 @@ Other Changes: - ImFont: Added GetGlyphRangesThai() helper. [@nProtect] - ImFont: CalcWordWrapPositionA() fixed font scaling with fallback character. - ImFont: Calculate and store the approximate texture surface to get an idea of how costly each source font is. -- ImFontConfig: Added GlyphOffset to explicitely offset glyphs at font build time, useful for merged fonts. Removed MergeGlyphCenterV. (BREAKING API) +- ImFontConfig: Added GlyphOffset to explicitly offset glyphs at font build time, useful for merged fonts. Removed MergeGlyphCenterV. (BREAKING API) - Clarified asserts in CheckStacksSize() when there is a stack mismatch. - Context: Support for #define-ing GImGui and IMGUI_SET_CURRENT_CONTEXT_FUNC to enable custom thread-based hackery (#586) - Updated stb_truetype.h to 1.14 (added OTF support, removed warnings). (#883, #976) @@ -583,7 +581,7 @@ Other Changes: - Examples: OpenGL2: Uploading font texture as RGBA32 to increase compatibility with users shaders for beginners. (#824) - Examples: Vulkan: Countless fixes and improvements. (#785, #804, #910, #1017, #1039, #1041, #1042, #1043, #1080) [@martty, @Loftilus, @ParticlePeter, @SaschaWillems] - Examples: DirectX9/10/10: Only call SetCursor(NULL) is io.MouseDrawCursor is set. (#585, #909) -- Examples: DirectX9: Explicitely setting viewport to match that other examples are doing. (#937) +- Examples: DirectX9: Explicitly setting viewport to match that other examples are doing. (#937) - Examples: GLFW+OpenGL3: Fixed Shutdown() calling GL functions with NULL parameters if NewFrame was never called. (#800) - Examples: GLFW+OpenGL2: Renaming opengl_example/ to opengl2_example/ for clarity. - Examples: SDL+OpenGL: explicitly setting GL_UNPACK_ROW_LENGTH to reduce issues because SDL changes it. (#752) diff --git a/README.md b/README.md index 13cfbe952c20..b087c83486d7 100644 --- a/README.md +++ b/README.md @@ -96,7 +96,7 @@ Demo Binaries ------------- You should be able to build the examples from sources (tested on Windows/Mac/Linux). If you don't, let me know! If you want to have a quick look at some Dear ImGui features, you can download Windows binaries of the demo app here: -- [imgui-demo-binaries-20180207.zip](http://www.miracleworld.net/imgui/binaries/imgui-demo-binaries-20180207.zip) (Windows binaries, Dear ImGui 1.60 WIP built 2018/01/07, 5 executables) +- [imgui-demo-binaries-20180407.zip](http://www.miracleworld.net/imgui/binaries/imgui-demo-binaries-20180407.zip) (Windows binaries, Dear ImGui 1.60 built 2018/04/07, 5 executables) The demo applications are unfortunately not yet DPI aware so expect some blurryness on a 4K screen. For DPI awareness you can load/reload your font at different scale, and scale your Style with `style.ScaleAllSizes()`. diff --git a/imgui.cpp b/imgui.cpp index 2a07ef882b02..33b35193861e 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.60 WIP +// dear imgui, v1.60 // (main code and documentation) // Call and read ImGui::ShowDemoWindow() in imgui_demo.cpp for demo code. @@ -83,7 +83,7 @@ - You can apply arithmetic operators +,*,/ on numerical values. Use +- to subtract (because - would set a negative value!) - Controls are automatically adjusted for OSX to match standard OSX text editing operations. - General Keyboard controls: enable with ImGuiConfigFlags_NavEnableKeyboard. - - General Gamepad controls: enable with ImGuiConfigFlags_NavEnableGamepad. See suggested mappings in imgui.h ImGuiNavInput_ + download PNG/PSD at goo.gl/9LgVZW. + - General Gamepad controls: enable with ImGuiConfigFlags_NavEnableGamepad. See suggested mappings in imgui.h ImGuiNavInput_ + download PNG/PSD at http://goo.gl/9LgVZW PROGRAMMER GUIDE @@ -223,15 +223,6 @@ - The gamepad/keyboard navigation is in Beta. Ask questions and report issues at https://github.com/ocornut/imgui/issues/787 - The initial focus was to support game controllers, but keyboard is becoming increasingly and decently usable. - - Keyboard: - - Set io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard to enable. - NewFrame() will automatically fill io.NavInputs[] based on your io.KeyDown[] + io.KeyMap[] arrays. - - When keyboard navigation is active (io.NavActive + ImGuiConfigFlags_NavEnableKeyboard), the io.WantCaptureKeyboard flag - will be set. For more advanced uses, you may want to read from: - - io.NavActive: true when a window is focused and it doesn't have the ImGuiWindowFlags_NoNavInputs flag set. - - io.NavVisible: true when the navigation cursor is visible (and usually goes false when mouse is used). - - or query focus information with e.g. IsWindowFocused(), IsItemFocused() etc. functions. - Please reach out if you think the game vs navigation input sharing could be improved. - Gamepad: - Set io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad to enable. - Backend: Set io.BackendFlags |= ImGuiBackendFlags_HasGamepad + fill the io.NavInputs[] fields before calling NewFrame(). @@ -241,7 +232,16 @@ - We uses a simple >0.0f test for activation testing, and won't attempt to test for a dead-zone. Your code will probably need to transform your raw inputs (such as e.g. remapping your 0.2..0.9 raw input range to 0.0..1.0 imgui range, etc.). - You can download PNG/PSD files depicting the gamepad controls for common controllers at: goo.gl/9LgVZW. - - If you need to share inputs between your game and the imgui parts, the easiest approach is to go all-or-nothing, with a buttons combo to toggle the target. + - If you need to share inputs between your game and the imgui parts, the easiest approach is to go all-or-nothing, with a buttons combo + to toggle the target. Please reach out if you think the game vs navigation input sharing could be improved. + - Keyboard: + - Set io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard to enable. + NewFrame() will automatically fill io.NavInputs[] based on your io.KeyDown[] + io.KeyMap[] arrays. + - When keyboard navigation is active (io.NavActive + ImGuiConfigFlags_NavEnableKeyboard), the io.WantCaptureKeyboard flag + will be set. For more advanced uses, you may want to read from: + - io.NavActive: true when a window is focused and it doesn't have the ImGuiWindowFlags_NoNavInputs flag set. + - io.NavVisible: true when the navigation cursor is visible (and usually goes false when mouse is used). + - or query focus information with e.g. IsWindowFocused(ImGuiFocusedFlags_AnyWindow), IsItemFocused() etc. functions. Please reach out if you think the game vs navigation input sharing could be improved. - Mouse: - PS4 users: Consider emulating a mouse cursor with DualShock4 touch pad or a spare analog stick as a mouse-emulation fallback. diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 3f18e48ebb82..8b7b5450b918 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.60 WIP +// dear imgui, v1.60 // (demo code) // Message to the person tempted to delete this file when integrating ImGui into their code base: diff --git a/imgui_draw.cpp b/imgui_draw.cpp index de8ccb801cdd..00650329e936 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -1,4 +1,4 @@ -// dear imgui, v1.60 WIP +// dear imgui, v1.60 // (drawing and font code) // Contains implementation for diff --git a/imgui_internal.h b/imgui_internal.h index 63d43e55aa7e..0af53025dabb 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -1,4 +1,4 @@ -// dear imgui, v1.60 WIP +// dear imgui, v1.60 // (internals) // You may use this file to debug, understand or extend ImGui features but we don't provide any guarantee of forward compatibility! From 8acda8420252fdbbe688e9b70618c32654db3495 Mon Sep 17 00:00:00 2001 From: omar Date: Sun, 8 Apr 2018 12:27:11 +0200 Subject: [PATCH 821/823] Nav: Fixed comment. (#1599) --- imgui.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/imgui.h b/imgui.h index 90411301f13f..85bdb0bacf2d 100644 --- a/imgui.h +++ b/imgui.h @@ -744,8 +744,8 @@ enum ImGuiKey_ enum ImGuiNavInput_ { // Gamepad Mapping - ImGuiNavInput_Activate, // activate / open / toggle / tweak value // e.g. Circle (PS4), A (Xbox), A (Switch), Space (Keyboard) - ImGuiNavInput_Cancel, // cancel / close / exit // e.g. Cross (PS4), B (Xbox), B (Switch), Escape (Keyboard) + ImGuiNavInput_Activate, // activate / open / toggle / tweak value // e.g. Cross (PS4), A (Xbox), A (Switch), Space (Keyboard) + ImGuiNavInput_Cancel, // cancel / close / exit // e.g. Circle (PS4), B (Xbox), B (Switch), Escape (Keyboard) ImGuiNavInput_Input, // text input / on-screen keyboard // e.g. Triang.(PS4), Y (Xbox), X (Switch), Return (Keyboard) ImGuiNavInput_Menu, // tap: toggle menu / hold: focus, move, resize // e.g. Square (PS4), X (Xbox), Y (Switch), Alt (Keyboard) ImGuiNavInput_DpadLeft, // move / tweak / resize window (w/ PadMenu) // e.g. D-pad Left/Right/Up/Down (Gamepads), Arrow keys (Keyboard) From 54fca1d1b888a6556221e62bdf0cf5043d3749a2 Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 9 Apr 2018 13:13:06 +0200 Subject: [PATCH 822/823] Fixed erroneous call to io.Fonts->ClearInputData() + ClearTexData() that was left in DX10 example but removed in 1.47 (Nov 2015) in every other back-ends. (fixes 6cee2fca94ff308762d0d183cd93ddb62bf40435) (#1733, ~#1731) + assert --- examples/directx10_example/imgui_impl_dx10.cpp | 5 +---- imgui_draw.cpp | 1 + 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/examples/directx10_example/imgui_impl_dx10.cpp b/examples/directx10_example/imgui_impl_dx10.cpp index 4fc24e252c85..90bcfdf38bd3 100644 --- a/examples/directx10_example/imgui_impl_dx10.cpp +++ b/examples/directx10_example/imgui_impl_dx10.cpp @@ -10,6 +10,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2018-04-09: Misc: Fixed erroneous call to io.Fonts->ClearInputData() + ClearTexData() that was left in DX10 example but removed in 1.47 (Nov 2015) on other back-ends. // 2018-03-20: Misc: Setup io.BackendFlags ImGuiBackendFlags_HasMouseCursors and ImGuiBackendFlags_HasSetMousePos flags + honor ImGuiConfigFlags_NoMouseCursorChange flag. // 2018-02-20: Inputs: Added support for mouse cursors (ImGui::GetMouseCursor() value and WM_SETCURSOR message handling). // 2018-02-16: Misc: Obsoleted the io.RenderDrawListsFn callback and exposed ImGui_ImplDX10_RenderDrawData() in the .h file so you can call it yourself. @@ -412,10 +413,6 @@ static void ImGui_ImplDX10_CreateFontsTexture() desc.MaxLOD = 0.f; g_pd3dDevice->CreateSamplerState(&desc, &g_pFontSampler); } - - // Cleanup (don't clear the input data if you want to append new fonts later) - io.Fonts->ClearInputData(); - io.Fonts->ClearTexData(); } bool ImGui_ImplDX10_CreateDeviceObjects() diff --git a/imgui_draw.cpp b/imgui_draw.cpp index 00650329e936..2606c1af80e0 100644 --- a/imgui_draw.cpp +++ b/imgui_draw.cpp @@ -1640,6 +1640,7 @@ bool ImFontAtlas::GetMouseCursorTexData(ImGuiMouseCursor cursor_type, ImVec2* ou if (Flags & ImFontAtlasFlags_NoMouseCursors) return false; + IM_ASSERT(CustomRectIds[0] != -1); ImFontAtlas::CustomRect& r = CustomRects[CustomRectIds[0]]; IM_ASSERT(r.ID == FONT_ATLAS_DEFAULT_TEX_DATA_ID); ImVec2 pos = FONT_ATLAS_DEFAULT_TEX_CURSOR_DATA[cursor_type][0] + ImVec2((float)r.X, (float)r.Y); From dd079fe6e6aec0c7a71d8a441079b8de23f4ca56 Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 9 Apr 2018 13:52:24 +0200 Subject: [PATCH 823/823] Version 1.60 (missed the string). Will retag. --- imgui.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/imgui.h b/imgui.h index 85bdb0bacf2d..d1174bd300e0 100644 --- a/imgui.h +++ b/imgui.h @@ -1,4 +1,4 @@ -// dear imgui, v1.60 WIP +// dear imgui, v1.60 // (headers) // See imgui.cpp file for documentation. @@ -21,7 +21,7 @@ #include // ptrdiff_t, NULL #include // memset, memmove, memcpy, strlen, strchr, strcpy, strcmp -#define IMGUI_VERSION "1.60 WIP" +#define IMGUI_VERSION "1.60" // Define attributes of all API symbols declarations, e.g. for DLL under Windows. #ifndef IMGUI_API