mirror of
https://github.com/Drezil/imgui.git
synced 2025-07-13 08:19:55 +02:00
Compare commits
90 Commits
features/i
...
v1.83
Author | SHA1 | Date | |
---|---|---|---|
ad5d1a8429 | |||
142c866bd9 | |||
88a24fb896 | |||
029c83c73e | |||
c708299ca9 | |||
8877eab393 | |||
b474bff6c6 | |||
5d77b6f274 | |||
45f5ed52c1 | |||
fd06dc511f | |||
4181ccceea | |||
3c72e5142b | |||
e7e170c534 | |||
26a1bbfe1e | |||
41030cbfe2 | |||
83bdfef8e0 | |||
4ce6bd8cff | |||
32c453ae53 | |||
cbcd89152b | |||
a8dcab8e2a | |||
ea9122b0ac | |||
4c9f0cec27 | |||
84545dbe6f | |||
393941ceea | |||
2c3f25d2d9 | |||
9b90639577 | |||
10a1c5b021 | |||
788e91aece | |||
89162a04f4 | |||
d28535f351 | |||
2dec7b3301 | |||
7cdb3850e7 | |||
04e98fbe6b | |||
7b8932554e | |||
b493cae8c9 | |||
21428ad3f4 | |||
4540177ce7 | |||
e61e8aea9c | |||
daf97832f1 | |||
06545c4f2a | |||
bfc4a3347a | |||
6d53884487 | |||
25fbff2156 | |||
fdda8b8c12 | |||
936f53229d | |||
770f9daab3 | |||
690a90bd35 | |||
5fed6bdc72 | |||
7c9c5dbe9a | |||
858ea17eba | |||
05a20ca738 | |||
b957300260 | |||
d6a5cc7934 | |||
bcdc8bcc4b | |||
c283a1da5b | |||
92b7b1f72b | |||
5f45047fb6 | |||
71dda216ef | |||
f08566b4d7 | |||
feb8b1e32d | |||
00d570e280 | |||
f0fc822837 | |||
2403ed92a3 | |||
3c7177c6a7 | |||
45c45d2506 | |||
84e6fe4fc7 | |||
951c84969b | |||
eab3ae473c | |||
c6c15a44fa | |||
1dcd3a45cc | |||
688e06490e | |||
475c0fcc39 | |||
a58271c079 | |||
aa5431fde2 | |||
6f360d6040 | |||
1491d2c916 | |||
186b734db0 | |||
6d3a980f38 | |||
59da01901e | |||
6e4770ea5c | |||
61a0908713 | |||
412d6f7efe | |||
0c5b0c8b97 | |||
a1a39c632a | |||
4bf646e4b0 | |||
64aab8480a | |||
ebe6ac5fb5 | |||
35b1148efb | |||
352f64697c | |||
d94644261d |
3
.github/workflows/build.yml
vendored
3
.github/workflows/build.yml
vendored
@ -254,10 +254,11 @@ jobs:
|
||||
EOF
|
||||
g++ -I. -Wall -Wformat -o example_single_file example_single_file.cpp
|
||||
|
||||
- name: Build example_null (with large ImDrawIdx)
|
||||
- name: Build example_null (with large ImDrawIdx + pointer ImTextureID)
|
||||
run: |
|
||||
cat > example_single_file.cpp <<'EOF'
|
||||
|
||||
#define ImTextureID void*
|
||||
#define ImDrawIdx unsigned int
|
||||
#define IMGUI_IMPLEMENTATION
|
||||
#include "misc/single_file/imgui_single_file.h"
|
||||
|
3
.gitignore
vendored
3
.gitignore
vendored
@ -26,6 +26,9 @@ ipch
|
||||
*.VC.db
|
||||
*.VC.VC.opendb
|
||||
|
||||
## Commonly used CMake directories
|
||||
/build*/
|
||||
|
||||
## Xcode artifacts
|
||||
project.xcworkspace
|
||||
xcuserdata
|
||||
|
@ -15,6 +15,7 @@
|
||||
|
||||
// CHANGELOG
|
||||
// (minor and older changes stripped away, please see git history for details)
|
||||
// 2021-05-19: Renderer: Replaced direct access to ImDrawCmd::TextureId with a call to ImDrawCmd::GetTexID(). (will become a requirement)
|
||||
// 2021-02-18: Change blending equation to preserve alpha in output buffer.
|
||||
// 2020-08-10: Inputs: Fixed horizontal mouse wheel direction.
|
||||
// 2019-12-05: Inputs: Added support for ImGuiMouseCursor_NotAllowed mouse cursor.
|
||||
@ -157,7 +158,7 @@ void ImGui_ImplAllegro5_RenderDrawData(ImDrawData* draw_data)
|
||||
else
|
||||
{
|
||||
// Draw
|
||||
ALLEGRO_BITMAP* texture = (ALLEGRO_BITMAP*)pcmd->TextureId;
|
||||
ALLEGRO_BITMAP* texture = (ALLEGRO_BITMAP*)pcmd->GetTexID();
|
||||
al_set_clipping_rectangle(pcmd->ClipRect.x - clip_off.x, pcmd->ClipRect.y - clip_off.y, pcmd->ClipRect.z - pcmd->ClipRect.x, pcmd->ClipRect.w - pcmd->ClipRect.y);
|
||||
al_draw_prim(&vertices[0], g_VertexDecl, texture, idx_offset, idx_offset + pcmd->ElemCount, ALLEGRO_PRIM_TRIANGLE_LIST);
|
||||
}
|
||||
|
@ -80,7 +80,7 @@ int32_t ImGui_ImplAndroid_HandleInputEvent(AInputEvent* input_event)
|
||||
if((AMotionEvent_getToolType(input_event, event_pointer_index) == AMOTION_EVENT_TOOL_TYPE_FINGER)
|
||||
|| (AMotionEvent_getToolType(input_event, event_pointer_index) == AMOTION_EVENT_TOOL_TYPE_UNKNOWN))
|
||||
{
|
||||
io.MouseDown[0] = (event_action == AMOTION_EVENT_ACTION_DOWN) ? true : false;
|
||||
io.MouseDown[0] = (event_action == AMOTION_EVENT_ACTION_DOWN);
|
||||
io.MousePos = ImVec2(AMotionEvent_getX(input_event, event_pointer_index), AMotionEvent_getY(input_event, event_pointer_index));
|
||||
}
|
||||
break;
|
||||
@ -88,9 +88,9 @@ int32_t ImGui_ImplAndroid_HandleInputEvent(AInputEvent* input_event)
|
||||
case AMOTION_EVENT_ACTION_BUTTON_RELEASE:
|
||||
{
|
||||
int32_t button_state = AMotionEvent_getButtonState(input_event);
|
||||
io.MouseDown[0] = (button_state & AMOTION_EVENT_BUTTON_PRIMARY) ? true : false;
|
||||
io.MouseDown[1] = (button_state & AMOTION_EVENT_BUTTON_SECONDARY) ? true : false;
|
||||
io.MouseDown[2] = (button_state & AMOTION_EVENT_BUTTON_TERTIARY) ? true : false;
|
||||
io.MouseDown[0] = ((button_state & AMOTION_EVENT_BUTTON_PRIMARY) != 0);
|
||||
io.MouseDown[1] = ((button_state & AMOTION_EVENT_BUTTON_SECONDARY) != 0);
|
||||
io.MouseDown[2] = ((button_state & AMOTION_EVENT_BUTTON_TERTIARY) != 0);
|
||||
}
|
||||
break;
|
||||
case AMOTION_EVENT_ACTION_HOVER_MOVE: // Hovering: Tool moves while NOT pressed (such as a physical mouse)
|
||||
|
@ -11,6 +11,7 @@
|
||||
|
||||
// CHANGELOG
|
||||
// (minor and older changes stripped away, please see git history for details)
|
||||
// 2021-05-19: DirectX10: Replaced direct access to ImDrawCmd::TextureId with a call to ImDrawCmd::GetTexID(). (will become a requirement)
|
||||
// 2021-02-18: DirectX10: Change blending equation to preserve alpha in output buffer.
|
||||
// 2019-07-21: DirectX10: Backup, clear and restore Geometry Shader is any is bound when calling ImGui_ImplDX10_RenderDrawData().
|
||||
// 2019-05-29: DirectX10: Added support for large mesh (64K+ vertices), enable ImGuiBackendFlags_RendererHasVtxOffset flag.
|
||||
@ -190,7 +191,7 @@ void ImGui_ImplDX10_RenderDrawData(ImDrawData* draw_data)
|
||||
DXGI_FORMAT IndexBufferFormat;
|
||||
ID3D10InputLayout* InputLayout;
|
||||
};
|
||||
BACKUP_DX10_STATE old;
|
||||
BACKUP_DX10_STATE old = {};
|
||||
old.ScissorRectsCount = old.ViewportsCount = D3D10_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE;
|
||||
ctx->RSGetScissorRects(&old.ScissorRectsCount, old.ScissorRects);
|
||||
ctx->RSGetViewports(&old.ViewportsCount, old.Viewports);
|
||||
@ -238,7 +239,7 @@ void ImGui_ImplDX10_RenderDrawData(ImDrawData* draw_data)
|
||||
ctx->RSSetScissorRects(1, &r);
|
||||
|
||||
// Bind texture, Draw
|
||||
ID3D10ShaderResourceView* texture_srv = (ID3D10ShaderResourceView*)pcmd->TextureId;
|
||||
ID3D10ShaderResourceView* texture_srv = (ID3D10ShaderResourceView*)pcmd->GetTexID();
|
||||
ctx->PSSetShaderResources(0, 1, &texture_srv);
|
||||
ctx->DrawIndexed(pcmd->ElemCount, pcmd->IdxOffset + global_idx_offset, pcmd->VtxOffset + global_vtx_offset);
|
||||
}
|
||||
@ -293,6 +294,7 @@ static void ImGui_ImplDX10_CreateFontsTexture()
|
||||
subResource.SysMemPitch = desc.Width * 4;
|
||||
subResource.SysMemSlicePitch = 0;
|
||||
g_pd3dDevice->CreateTexture2D(&desc, &subResource, &pTexture);
|
||||
IM_ASSERT(pTexture != NULL);
|
||||
|
||||
// Create texture view
|
||||
D3D10_SHADER_RESOURCE_VIEW_DESC srv_desc;
|
||||
|
@ -11,6 +11,7 @@
|
||||
|
||||
// CHANGELOG
|
||||
// (minor and older changes stripped away, please see git history for details)
|
||||
// 2021-05-19: DirectX11: Replaced direct access to ImDrawCmd::TextureId with a call to ImDrawCmd::GetTexID(). (will become a requirement)
|
||||
// 2021-02-18: DirectX11: Change blending equation to preserve alpha in output buffer.
|
||||
// 2019-08-01: DirectX11: Fixed code querying the Geometry Shader state (would generally error with Debug layer enabled).
|
||||
// 2019-07-21: DirectX11: Backup, clear and restore Geometry Shader is any is bound when calling ImGui_ImplDX10_RenderDrawData. Clearing Hull/Domain/Compute shaders without backup/restore.
|
||||
@ -198,7 +199,7 @@ void ImGui_ImplDX11_RenderDrawData(ImDrawData* draw_data)
|
||||
DXGI_FORMAT IndexBufferFormat;
|
||||
ID3D11InputLayout* InputLayout;
|
||||
};
|
||||
BACKUP_DX11_STATE old;
|
||||
BACKUP_DX11_STATE old = {};
|
||||
old.ScissorRectsCount = old.ViewportsCount = D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE;
|
||||
ctx->RSGetScissorRects(&old.ScissorRectsCount, old.ScissorRects);
|
||||
ctx->RSGetViewports(&old.ViewportsCount, old.Viewports);
|
||||
@ -248,7 +249,7 @@ void ImGui_ImplDX11_RenderDrawData(ImDrawData* draw_data)
|
||||
ctx->RSSetScissorRects(1, &r);
|
||||
|
||||
// Bind texture, Draw
|
||||
ID3D11ShaderResourceView* texture_srv = (ID3D11ShaderResourceView*)pcmd->TextureId;
|
||||
ID3D11ShaderResourceView* texture_srv = (ID3D11ShaderResourceView*)pcmd->GetTexID();
|
||||
ctx->PSSetShaderResources(0, 1, &texture_srv);
|
||||
ctx->DrawIndexed(pcmd->ElemCount, pcmd->IdxOffset + global_idx_offset, pcmd->VtxOffset + global_vtx_offset);
|
||||
}
|
||||
@ -305,6 +306,7 @@ static void ImGui_ImplDX11_CreateFontsTexture()
|
||||
subResource.SysMemPitch = desc.Width * 4;
|
||||
subResource.SysMemSlicePitch = 0;
|
||||
g_pd3dDevice->CreateTexture2D(&desc, &subResource, &pTexture);
|
||||
IM_ASSERT(pTexture != NULL);
|
||||
|
||||
// Create texture view
|
||||
D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
|
||||
|
@ -15,6 +15,7 @@
|
||||
|
||||
// CHANGELOG
|
||||
// (minor and older changes stripped away, please see git history for details)
|
||||
// 2021-05-19: DirectX12: Replaced direct access to ImDrawCmd::TextureId with a call to ImDrawCmd::GetTexID(). (will become a requirement)
|
||||
// 2021-02-18: DirectX12: Change blending equation to preserve alpha in output buffer.
|
||||
// 2021-01-11: DirectX12: Improve Windows 7 compatibility (for D3D12On7) by loading d3d12.dll dynamically.
|
||||
// 2020-09-16: DirectX12: Avoid rendering calls with zero-sized scissor rectangle since it generates a validation layer warning.
|
||||
@ -239,7 +240,9 @@ void ImGui_ImplDX12_RenderDrawData(ImDrawData* draw_data, ID3D12GraphicsCommandL
|
||||
const D3D12_RECT r = { (LONG)(pcmd->ClipRect.x - clip_off.x), (LONG)(pcmd->ClipRect.y - clip_off.y), (LONG)(pcmd->ClipRect.z - clip_off.x), (LONG)(pcmd->ClipRect.w - clip_off.y) };
|
||||
if (r.right > r.left && r.bottom > r.top)
|
||||
{
|
||||
ctx->SetGraphicsRootDescriptorTable(1, *(D3D12_GPU_DESCRIPTOR_HANDLE*)&pcmd->TextureId);
|
||||
D3D12_GPU_DESCRIPTOR_HANDLE texture_handle = {};
|
||||
texture_handle.ptr = (UINT64)(intptr_t)pcmd->GetTexID();
|
||||
ctx->SetGraphicsRootDescriptorTable(1, texture_handle);
|
||||
ctx->RSSetScissorRects(1, &r);
|
||||
ctx->DrawIndexedInstanced(pcmd->ElemCount, 1, pcmd->IdxOffset + global_idx_offset, pcmd->VtxOffset + global_vtx_offset, 0);
|
||||
}
|
||||
|
@ -11,6 +11,9 @@
|
||||
|
||||
// CHANGELOG
|
||||
// (minor and older changes stripped away, please see git history for details)
|
||||
// 2021-05-19: DirectX9: Replaced direct access to ImDrawCmd::TextureId with a call to ImDrawCmd::GetTexID(). (will become a requirement)
|
||||
// 2021-04-23: DirectX9: Explicitly setting up more graphics states to increase compatibility with unusual non-default states.
|
||||
// 2021-03-18: DirectX9: Calling IDirect3DStateBlock9::Capture() after CreateStateBlock() as a workaround for state restoring issues (see #3857).
|
||||
// 2021-03-03: DirectX9: Added support for IMGUI_USE_BGRA_PACKED_COLOR in user's imconfig file.
|
||||
// 2021-02-18: DirectX9: Change blending equation to preserve alpha in output buffer.
|
||||
// 2019-05-29: DirectX9: Added support for large mesh (64K+ vertices), enable ImGuiBackendFlags_RendererHasVtxOffset flag.
|
||||
@ -65,11 +68,13 @@ static void ImGui_ImplDX9_SetupRenderState(ImDrawData* draw_data)
|
||||
// Setup render state: fixed-pipeline, alpha-blending, no face culling, no depth testing, shade mode (for gradient)
|
||||
g_pd3dDevice->SetPixelShader(NULL);
|
||||
g_pd3dDevice->SetVertexShader(NULL);
|
||||
g_pd3dDevice->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID);
|
||||
g_pd3dDevice->SetRenderState(D3DRS_SHADEMODE, D3DSHADE_GOURAUD);
|
||||
g_pd3dDevice->SetRenderState(D3DRS_ZWRITEENABLE, FALSE);
|
||||
g_pd3dDevice->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE);
|
||||
g_pd3dDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
|
||||
g_pd3dDevice->SetRenderState(D3DRS_LIGHTING, FALSE);
|
||||
g_pd3dDevice->SetRenderState(D3DRS_ZENABLE, FALSE);
|
||||
g_pd3dDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
|
||||
g_pd3dDevice->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE);
|
||||
g_pd3dDevice->SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_ADD);
|
||||
g_pd3dDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
|
||||
g_pd3dDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
|
||||
@ -77,8 +82,12 @@ static void ImGui_ImplDX9_SetupRenderState(ImDrawData* draw_data)
|
||||
g_pd3dDevice->SetRenderState(D3DRS_SRCBLENDALPHA, D3DBLEND_ONE);
|
||||
g_pd3dDevice->SetRenderState(D3DRS_DESTBLENDALPHA, D3DBLEND_INVSRCALPHA);
|
||||
g_pd3dDevice->SetRenderState(D3DRS_SCISSORTESTENABLE, TRUE);
|
||||
g_pd3dDevice->SetRenderState(D3DRS_SHADEMODE, D3DSHADE_GOURAUD);
|
||||
g_pd3dDevice->SetRenderState(D3DRS_FOGENABLE, FALSE);
|
||||
g_pd3dDevice->SetRenderState(D3DRS_RANGEFOGENABLE, FALSE);
|
||||
g_pd3dDevice->SetRenderState(D3DRS_SPECULARENABLE, FALSE);
|
||||
g_pd3dDevice->SetRenderState(D3DRS_STENCILENABLE, FALSE);
|
||||
g_pd3dDevice->SetRenderState(D3DRS_CLIPPING, TRUE);
|
||||
g_pd3dDevice->SetRenderState(D3DRS_LIGHTING, FALSE);
|
||||
g_pd3dDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE);
|
||||
g_pd3dDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
|
||||
g_pd3dDevice->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE);
|
||||
@ -137,6 +146,11 @@ void ImGui_ImplDX9_RenderDrawData(ImDrawData* draw_data)
|
||||
IDirect3DStateBlock9* d3d9_state_block = NULL;
|
||||
if (g_pd3dDevice->CreateStateBlock(D3DSBT_ALL, &d3d9_state_block) < 0)
|
||||
return;
|
||||
if (d3d9_state_block->Capture() < 0)
|
||||
{
|
||||
d3d9_state_block->Release();
|
||||
return;
|
||||
}
|
||||
|
||||
// Backup the DX9 transform (DX9 documentation suggests that it is included in the StateBlock but it doesn't appear to)
|
||||
D3DMATRIX last_world, last_view, last_projection;
|
||||
@ -144,16 +158,25 @@ void ImGui_ImplDX9_RenderDrawData(ImDrawData* draw_data)
|
||||
g_pd3dDevice->GetTransform(D3DTS_VIEW, &last_view);
|
||||
g_pd3dDevice->GetTransform(D3DTS_PROJECTION, &last_projection);
|
||||
|
||||
// Allocate buffers
|
||||
CUSTOMVERTEX* vtx_dst;
|
||||
ImDrawIdx* idx_dst;
|
||||
if (g_pVB->Lock(0, (UINT)(draw_data->TotalVtxCount * sizeof(CUSTOMVERTEX)), (void**)&vtx_dst, D3DLOCK_DISCARD) < 0)
|
||||
{
|
||||
d3d9_state_block->Release();
|
||||
return;
|
||||
}
|
||||
if (g_pIB->Lock(0, (UINT)(draw_data->TotalIdxCount * sizeof(ImDrawIdx)), (void**)&idx_dst, D3DLOCK_DISCARD) < 0)
|
||||
{
|
||||
g_pVB->Unlock();
|
||||
d3d9_state_block->Release();
|
||||
return;
|
||||
}
|
||||
|
||||
// Copy and convert all vertices into a single contiguous buffer, convert colors to DX9 default format.
|
||||
// FIXME-OPT: This is a minor waste of resource, the ideal is to use imconfig.h and
|
||||
// 1) to avoid repacking colors: #define IMGUI_USE_BGRA_PACKED_COLOR
|
||||
// 2) to avoid repacking vertices: #define IMGUI_OVERRIDE_DRAWVERT_STRUCT_LAYOUT struct ImDrawVert { ImVec2 pos; float z; ImU32 col; ImVec2 uv; }
|
||||
CUSTOMVERTEX* vtx_dst;
|
||||
ImDrawIdx* idx_dst;
|
||||
if (g_pVB->Lock(0, (UINT)(draw_data->TotalVtxCount * sizeof(CUSTOMVERTEX)), (void**)&vtx_dst, D3DLOCK_DISCARD) < 0)
|
||||
return;
|
||||
if (g_pIB->Lock(0, (UINT)(draw_data->TotalIdxCount * sizeof(ImDrawIdx)), (void**)&idx_dst, D3DLOCK_DISCARD) < 0)
|
||||
return;
|
||||
for (int n = 0; n < draw_data->CmdListsCount; n++)
|
||||
{
|
||||
const ImDrawList* cmd_list = draw_data->CmdLists[n];
|
||||
@ -204,7 +227,7 @@ void ImGui_ImplDX9_RenderDrawData(ImDrawData* draw_data)
|
||||
else
|
||||
{
|
||||
const RECT r = { (LONG)(pcmd->ClipRect.x - clip_off.x), (LONG)(pcmd->ClipRect.y - clip_off.y), (LONG)(pcmd->ClipRect.z - clip_off.x), (LONG)(pcmd->ClipRect.w - clip_off.y) };
|
||||
const LPDIRECT3DTEXTURE9 texture = (LPDIRECT3DTEXTURE9)pcmd->TextureId;
|
||||
const LPDIRECT3DTEXTURE9 texture = (LPDIRECT3DTEXTURE9)pcmd->GetTexID();
|
||||
g_pd3dDevice->SetTexture(0, texture);
|
||||
g_pd3dDevice->SetScissorRect(&r);
|
||||
g_pd3dDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, pcmd->VtxOffset + global_vtx_offset, 0, (UINT)cmd_list->VtxBuffer.Size, pcmd->IdxOffset + global_idx_offset, pcmd->ElemCount / 3);
|
||||
|
@ -113,10 +113,13 @@ void ImGui_ImplGlfw_KeyCallback(GLFWwindow* window, int key, int scancode, int a
|
||||
g_PrevUserCallbackKey(window, key, scancode, action, mods);
|
||||
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
if (action == GLFW_PRESS)
|
||||
io.KeysDown[key] = true;
|
||||
if (action == GLFW_RELEASE)
|
||||
io.KeysDown[key] = false;
|
||||
if (key >= 0 && key < IM_ARRAYSIZE(io.KeysDown))
|
||||
{
|
||||
if (action == GLFW_PRESS)
|
||||
io.KeysDown[key] = true;
|
||||
if (action == GLFW_RELEASE)
|
||||
io.KeysDown[key] = false;
|
||||
}
|
||||
|
||||
// Modifiers are not reliable across systems
|
||||
io.KeyCtrl = io.KeysDown[GLFW_KEY_LEFT_CONTROL] || io.KeysDown[GLFW_KEY_RIGHT_CONTROL];
|
||||
|
@ -12,6 +12,7 @@
|
||||
|
||||
// CHANGELOG
|
||||
// (minor and older changes stripped away, please see git history for details)
|
||||
// 2021-05-19: Renderer: Replaced direct access to ImDrawCmd::TextureId with a call to ImDrawCmd::GetTexID(). (will become a requirement)
|
||||
// 2019-07-21: Inputs: Added mapping for ImGuiKey_KeyPadEnter.
|
||||
// 2019-05-11: Inputs: Don't filter value from character callback before calling AddInputCharacter().
|
||||
// 2018-11-30: Misc: Setting up io.BackendPlatformName/io.BackendRendererName so they can be displayed in the About Window.
|
||||
@ -87,7 +88,7 @@ void ImGui_Marmalade_RenderDrawData(ImDrawData* draw_data)
|
||||
pCurrentMaterial->SetAlphaMode(CIwMaterial::ALPHA_BLEND);
|
||||
pCurrentMaterial->SetDepthWriteMode(CIwMaterial::DEPTH_WRITE_NORMAL);
|
||||
pCurrentMaterial->SetAlphaTestMode(CIwMaterial::ALPHATEST_DISABLED);
|
||||
pCurrentMaterial->SetTexture((CIwTexture*)pcmd->TextureId);
|
||||
pCurrentMaterial->SetTexture((CIwTexture*)pcmd->GetTexID());
|
||||
IwGxSetMaterial(pCurrentMaterial);
|
||||
IwGxDrawPrims(IW_GX_TRI_LIST, (uint16*)idx_buffer, pcmd->ElemCount);
|
||||
}
|
||||
|
@ -11,6 +11,7 @@
|
||||
|
||||
// CHANGELOG
|
||||
// (minor and older changes stripped away, please see git history for details)
|
||||
// 2021-05-19: Metal: Replaced direct access to ImDrawCmd::TextureId with a call to ImDrawCmd::GetTexID(). (will become a requirement)
|
||||
// 2021-02-18: Metal: Change blending equation to preserve alpha in output buffer.
|
||||
// 2021-01-25: Metal: Fixed texture storage mode when building on Mac Catalyst.
|
||||
// 2019-05-29: Metal: Added support for large mesh (64K+ vertices), enable ImGuiBackendFlags_RendererHasVtxOffset flag.
|
||||
@ -522,8 +523,8 @@ void ImGui_ImplMetal_DestroyDeviceObjects()
|
||||
|
||||
|
||||
// Bind texture, Draw
|
||||
if (pcmd->TextureId != NULL)
|
||||
[commandEncoder setFragmentTexture:(__bridge id<MTLTexture>)(pcmd->TextureId) atIndex:0];
|
||||
if (ImTextureID tex_id = pcmd->GetTexID())
|
||||
[commandEncoder setFragmentTexture:(__bridge id<MTLTexture>)(tex_id) atIndex:0];
|
||||
|
||||
[commandEncoder setVertexBufferOffset:(vertexBufferOffset + pcmd->VtxOffset * sizeof(ImDrawVert)) atIndex:0];
|
||||
[commandEncoder drawIndexedPrimitives:MTLPrimitiveTypeTriangle
|
||||
|
@ -18,6 +18,7 @@
|
||||
|
||||
// CHANGELOG
|
||||
// (minor and older changes stripped away, please see git history for details)
|
||||
// 2021-05-19: OpenGL: Replaced direct access to ImDrawCmd::TextureId with a call to ImDrawCmd::GetTexID(). (will become a requirement)
|
||||
// 2021-01-03: OpenGL: Backup, setup and restore GL_SHADE_MODEL state, disable GL_STENCIL_TEST and disable GL_NORMAL_ARRAY client state to increase compatibility with legacy OpenGL applications.
|
||||
// 2020-01-23: OpenGL: Backup, setup and restore GL_TEXTURE_ENV to increase compatibility with legacy OpenGL applications.
|
||||
// 2019-04-30: OpenGL: Added support for special ImDrawCallback_ResetRenderState callback to reset render state.
|
||||
@ -184,7 +185,7 @@ void ImGui_ImplOpenGL2_RenderDrawData(ImDrawData* draw_data)
|
||||
glScissor((int)clip_rect.x, (int)(fb_height - clip_rect.w), (int)(clip_rect.z - clip_rect.x), (int)(clip_rect.w - clip_rect.y));
|
||||
|
||||
// Bind texture, Draw
|
||||
glBindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->TextureId);
|
||||
glBindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->GetTexID());
|
||||
glDrawElements(GL_TRIANGLES, (GLsizei)pcmd->ElemCount, sizeof(ImDrawIdx) == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, idx_buffer);
|
||||
}
|
||||
}
|
||||
|
@ -13,6 +13,8 @@
|
||||
|
||||
// CHANGELOG
|
||||
// (minor and older changes stripped away, please see git history for details)
|
||||
// 2021-05-19: OpenGL: Replaced direct access to ImDrawCmd::TextureId with a call to ImDrawCmd::GetTexID(). (will become a requirement)
|
||||
// 2021-04-06: OpenGL: Don't try to read GL_CLIP_ORIGIN unless we're OpenGL 4.5 or greater.
|
||||
// 2021-02-18: OpenGL: Change blending equation to preserve alpha in output buffer.
|
||||
// 2021-01-03: OpenGL: Backup, setup and restore GL_STENCIL_TEST state.
|
||||
// 2020-10-23: OpenGL: Backup, setup and restore GL_PRIMITIVE_RESTART state.
|
||||
@ -262,11 +264,14 @@ static void ImGui_ImplOpenGL3_SetupRenderState(ImDrawData* draw_data, int fb_wid
|
||||
#endif
|
||||
|
||||
// Support for GL 4.5 rarely used glClipControl(GL_UPPER_LEFT)
|
||||
#if defined(GL_CLIP_ORIGIN) && !defined(__APPLE__)
|
||||
#if defined(GL_CLIP_ORIGIN)
|
||||
bool clip_origin_lower_left = true;
|
||||
GLenum current_clip_origin = 0; glGetIntegerv(GL_CLIP_ORIGIN, (GLint*)¤t_clip_origin);
|
||||
if (current_clip_origin == GL_UPPER_LEFT)
|
||||
clip_origin_lower_left = false;
|
||||
if (g_GlVersion >= 450)
|
||||
{
|
||||
GLenum current_clip_origin = 0; glGetIntegerv(GL_CLIP_ORIGIN, (GLint*)¤t_clip_origin);
|
||||
if (current_clip_origin == GL_UPPER_LEFT)
|
||||
clip_origin_lower_left = false;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Setup viewport, orthographic projection matrix
|
||||
@ -276,7 +281,7 @@ static void ImGui_ImplOpenGL3_SetupRenderState(ImDrawData* draw_data, int fb_wid
|
||||
float R = draw_data->DisplayPos.x + draw_data->DisplaySize.x;
|
||||
float T = draw_data->DisplayPos.y;
|
||||
float B = draw_data->DisplayPos.y + draw_data->DisplaySize.y;
|
||||
#if defined(GL_CLIP_ORIGIN) && !defined(__APPLE__)
|
||||
#if defined(GL_CLIP_ORIGIN)
|
||||
if (!clip_origin_lower_left) { float tmp = T; T = B; B = tmp; } // Swap top and bottom if origin is upper left
|
||||
#endif
|
||||
const float ortho_projection[4][4] =
|
||||
@ -403,7 +408,7 @@ void ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data)
|
||||
glScissor((int)clip_rect.x, (int)(fb_height - clip_rect.w), (int)(clip_rect.z - clip_rect.x), (int)(clip_rect.w - clip_rect.y));
|
||||
|
||||
// Bind texture, Draw
|
||||
glBindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->TextureId);
|
||||
glBindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->GetTexID());
|
||||
#ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_VTX_OFFSET
|
||||
if (g_GlVersion >= 320)
|
||||
glDrawElementsBaseVertex(GL_TRIANGLES, (GLsizei)pcmd->ElemCount, sizeof(ImDrawIdx) == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, (void*)(intptr_t)(pcmd->IdxOffset * sizeof(ImDrawIdx)), (GLint)pcmd->VtxOffset);
|
||||
|
@ -18,6 +18,7 @@
|
||||
|
||||
// CHANGELOG
|
||||
// (minor and older changes stripped away, please see git history for details)
|
||||
// 2021-04-19: Inputs: Added a fix for keys remaining stuck in pressed state when CMD-tabbing into different application.
|
||||
// 2021-01-27: Inputs: Added a fix for mouse position not being reported when mouse buttons other than left one are down.
|
||||
// 2020-10-28: Inputs: Added a fix for handling keypad-enter key.
|
||||
// 2020-05-25: Inputs: Added a fix for missing trackpad clicks when done with "soft tap".
|
||||
@ -30,12 +31,15 @@
|
||||
// 2018-11-30: Misc: Setting up io.BackendPlatformName so it can be displayed in the About Window.
|
||||
// 2018-07-07: Initial version.
|
||||
|
||||
@class ImFocusObserver;
|
||||
|
||||
// Data
|
||||
static CFAbsoluteTime g_Time = 0.0;
|
||||
static NSCursor* g_MouseCursors[ImGuiMouseCursor_COUNT] = {};
|
||||
static bool g_MouseCursorHidden = false;
|
||||
static bool g_MouseJustPressed[ImGuiMouseButton_COUNT] = {};
|
||||
static bool g_MouseDown[ImGuiMouseButton_COUNT] = {};
|
||||
static ImFocusObserver* g_FocusObserver = NULL;
|
||||
|
||||
// Undocumented methods for creating cursors.
|
||||
@interface NSCursor()
|
||||
@ -45,6 +49,31 @@ static bool g_MouseDown[ImGuiMouseButton_COUNT] = {};
|
||||
+ (id)_windowResizeEastWestCursor;
|
||||
@end
|
||||
|
||||
static void resetKeys()
|
||||
{
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
memset(io.KeysDown, 0, sizeof(io.KeysDown));
|
||||
io.KeyCtrl = io.KeyShift = io.KeyAlt = io.KeySuper = false;
|
||||
}
|
||||
|
||||
@interface ImFocusObserver : NSObject
|
||||
|
||||
- (void)onApplicationBecomeInactive:(NSNotification*)aNotification;
|
||||
|
||||
@end
|
||||
|
||||
@implementation ImFocusObserver
|
||||
|
||||
- (void)onApplicationBecomeInactive:(NSNotification*)aNotification
|
||||
{
|
||||
// Unfocused applications do not receive input events, therefore we must manually
|
||||
// release any pressed keys when application loses focus, otherwise they would remain
|
||||
// stuck in a pressed state. https://github.com/ocornut/imgui/issues/3832
|
||||
resetKeys();
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
// Functions
|
||||
bool ImGui_ImplOSX_Init()
|
||||
{
|
||||
@ -123,11 +152,18 @@ bool ImGui_ImplOSX_Init()
|
||||
return s_clipboard.Data;
|
||||
};
|
||||
|
||||
g_FocusObserver = [[ImFocusObserver alloc] init];
|
||||
[[NSNotificationCenter defaultCenter] addObserver:g_FocusObserver
|
||||
selector:@selector(onApplicationBecomeInactive:)
|
||||
name:NSApplicationDidResignActiveNotification
|
||||
object:nil];
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ImGui_ImplOSX_Shutdown()
|
||||
{
|
||||
g_FocusObserver = NULL;
|
||||
}
|
||||
|
||||
static void ImGui_ImplOSX_UpdateMouseCursorAndButtons()
|
||||
@ -200,13 +236,6 @@ static int mapCharacterToKey(int c)
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void resetKeys()
|
||||
{
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
for (int n = 0; n < IM_ARRAYSIZE(io.KeysDown); n++)
|
||||
io.KeysDown[n] = false;
|
||||
}
|
||||
|
||||
bool ImGui_ImplOSX_HandleEvent(NSEvent* event, NSView* view)
|
||||
{
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
|
@ -17,6 +17,7 @@
|
||||
|
||||
// CHANGELOG
|
||||
// (minor and older changes stripped away, please see git history for details)
|
||||
// 2021-03-22: Rework global mouse pos availability check listing supported platforms explicitly, effectively fixing mouse access on Raspberry Pi. (#2837, #3950)
|
||||
// 2020-05-25: Misc: Report a zero display-size when window is minimized, to be consistent with other backends.
|
||||
// 2020-02-20: Inputs: Fixed mapping for ImGuiKey_KeyPadEnter (using SDL_SCANCODE_KP_ENTER instead of SDL_SCANCODE_RETURN2).
|
||||
// 2019-12-17: Inputs: On Wayland, use SDL_GetMouseState (because there is no global mouse state).
|
||||
@ -177,8 +178,14 @@ static bool ImGui_ImplSDL2_Init(SDL_Window* window)
|
||||
g_MouseCursors[ImGuiMouseCursor_Hand] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_HAND);
|
||||
g_MouseCursors[ImGuiMouseCursor_NotAllowed] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_NO);
|
||||
|
||||
// Check and store if we are on Wayland
|
||||
g_MouseCanUseGlobalState = strncmp(SDL_GetCurrentVideoDriver(), "wayland", 7) != 0;
|
||||
// Check and store if we are on a SDL backend that supports global mouse position
|
||||
// ("wayland" and "rpi" don't support it, but we chose to use a white-list instead of a black-list)
|
||||
const char* sdl_backend = SDL_GetCurrentVideoDriver();
|
||||
const char* global_mouse_whitelist[] = { "windows", "cocoa", "x11", "DIVE", "VMAN" };
|
||||
g_MouseCanUseGlobalState = false;
|
||||
for (int n = 0; n < IM_ARRAYSIZE(global_mouse_whitelist); n++)
|
||||
if (strncmp(sdl_backend, global_mouse_whitelist[n], strlen(global_mouse_whitelist[n])) == 0)
|
||||
g_MouseCanUseGlobalState = true;
|
||||
|
||||
#ifdef _WIN32
|
||||
SDL_SysWMinfo wmInfo;
|
||||
@ -259,7 +266,7 @@ static void ImGui_ImplSDL2_UpdateMousePosAndButtons()
|
||||
{
|
||||
// SDL_GetMouseState() gives mouse position seemingly based on the last window entered/focused(?)
|
||||
// The creation of a new windows at runtime and SDL_CaptureMouse both seems to severely mess up with that, so we retrieve that position globally.
|
||||
// Won't use this workaround when on Wayland, as there is no global mouse position.
|
||||
// Won't use this workaround on SDL backends that have no global mouse position, like Wayland or RPI
|
||||
int wx, wy;
|
||||
SDL_GetWindowPosition(focused_window, &wx, &wy);
|
||||
SDL_GetGlobalMouseState(&mx, &my);
|
||||
|
@ -22,6 +22,7 @@
|
||||
|
||||
// CHANGELOG
|
||||
// (minor and older changes stripped away, please see git history for details)
|
||||
// 2021-03-22: Vulkan: Fix mapped memory validation error when buffer sizes are not multiple of VkPhysicalDeviceLimits::nonCoherentAtomSize.
|
||||
// 2021-02-18: Vulkan: Change blending equation to preserve alpha in output buffer.
|
||||
// 2021-01-27: Vulkan: Added support for custom function load and IMGUI_IMPL_VULKAN_NO_PROTOTYPES by using ImGui_ImplVulkan_LoadFunctions().
|
||||
// 2020-11-11: Vulkan: Added support for specifying which subpass to reference during VkPipeline creation.
|
||||
@ -343,7 +344,7 @@ static void CreateOrResizeBuffer(VkBuffer& buffer, VkDeviceMemory& buffer_memory
|
||||
|
||||
err = vkBindBufferMemory(v->Device, buffer, buffer_memory, 0);
|
||||
check_vk_result(err);
|
||||
p_buffer_size = new_size;
|
||||
p_buffer_size = req.size;
|
||||
}
|
||||
|
||||
static void ImGui_ImplVulkan_SetupRenderState(ImDrawData* draw_data, VkPipeline pipeline, VkCommandBuffer command_buffer, ImGui_ImplVulkanH_FrameRenderBuffers* rb, int fb_width, int fb_height)
|
||||
@ -429,9 +430,9 @@ void ImGui_ImplVulkan_RenderDrawData(ImDrawData* draw_data, VkCommandBuffer comm
|
||||
// Upload vertex/index data into a single contiguous GPU buffer
|
||||
ImDrawVert* vtx_dst = NULL;
|
||||
ImDrawIdx* idx_dst = NULL;
|
||||
VkResult err = vkMapMemory(v->Device, rb->VertexBufferMemory, 0, vertex_size, 0, (void**)(&vtx_dst));
|
||||
VkResult err = vkMapMemory(v->Device, rb->VertexBufferMemory, 0, rb->VertexBufferSize, 0, (void**)(&vtx_dst));
|
||||
check_vk_result(err);
|
||||
err = vkMapMemory(v->Device, rb->IndexBufferMemory, 0, index_size, 0, (void**)(&idx_dst));
|
||||
err = vkMapMemory(v->Device, rb->IndexBufferMemory, 0, rb->IndexBufferSize, 0, (void**)(&idx_dst));
|
||||
check_vk_result(err);
|
||||
for (int n = 0; n < draw_data->CmdListsCount; n++)
|
||||
{
|
||||
|
@ -12,6 +12,9 @@
|
||||
|
||||
// CHANGELOG
|
||||
// (minor and older changes stripped away, please see git history for details)
|
||||
// 2021-05-24: Add support for draw_data->FramebufferScale.
|
||||
// 2021-05-19: Replaced direct access to ImDrawCmd::TextureId with a call to ImDrawCmd::GetTexID(). (will become a requirement)
|
||||
// 2021-05-16: Update to latest WebGPU specs (compatible with Emscripten 2.0.20 and Chrome Canary 92).
|
||||
// 2021-02-18: Change blending equation to preserve alpha in output buffer.
|
||||
// 2021-01-28: Initial version.
|
||||
|
||||
@ -22,11 +25,16 @@
|
||||
|
||||
#define HAS_EMSCRIPTEN_VERSION(major, minor, tiny) (__EMSCRIPTEN_major__ > (major) || (__EMSCRIPTEN_major__ == (major) && __EMSCRIPTEN_minor__ > (minor)) || (__EMSCRIPTEN_major__ == (major) && __EMSCRIPTEN_minor__ == (minor) && __EMSCRIPTEN_tiny__ >= (tiny)))
|
||||
|
||||
#if defined(__EMSCRIPTEN__) && !HAS_EMSCRIPTEN_VERSION(2, 0, 20)
|
||||
#error "Requires at least emscripten 2.0.20"
|
||||
#endif
|
||||
|
||||
// Dear ImGui prototypes from imgui_internal.h
|
||||
extern ImGuiID ImHashData(const void* data_p, size_t data_size, ImU32 seed = 0);
|
||||
|
||||
// WebGPU data
|
||||
static WGPUDevice g_wgpuDevice = NULL;
|
||||
static WGPUQueue g_defaultQueue = NULL;
|
||||
static WGPUTextureFormat g_renderTargetFormat = WGPUTextureFormat_Undefined;
|
||||
static WGPURenderPipeline g_pipelineState = NULL;
|
||||
|
||||
@ -37,9 +45,9 @@ struct RenderResources
|
||||
WGPUSampler Sampler; // Sampler for the font texture
|
||||
WGPUBuffer Uniforms; // Shader uniforms
|
||||
WGPUBindGroup CommonBindGroup; // Resources bind-group to bind the common resources to pipeline
|
||||
WGPUBindGroupLayout ImageBindGroupLayout; // Bind group layout for image textures
|
||||
ImGuiStorage ImageBindGroups; // Resources bind-group to bind the font/image resources to pipeline (this is a key->value map)
|
||||
WGPUBindGroup ImageBindGroup; // Default font-resource of Dear ImGui
|
||||
WGPUBindGroupLayout ImageBindGroupLayout; // Cache layout used for the image bind group. Avoids allocating unnecessary JS objects when working with WebASM
|
||||
};
|
||||
static RenderResources g_resources;
|
||||
|
||||
@ -241,8 +249,8 @@ static void SafeRelease(RenderResources& res)
|
||||
SafeRelease(res.Sampler);
|
||||
SafeRelease(res.Uniforms);
|
||||
SafeRelease(res.CommonBindGroup);
|
||||
SafeRelease(res.ImageBindGroupLayout);
|
||||
SafeRelease(res.ImageBindGroup);
|
||||
SafeRelease(res.ImageBindGroupLayout);
|
||||
};
|
||||
|
||||
static void SafeRelease(FrameResources& res)
|
||||
@ -296,23 +304,21 @@ static void ImGui_ImplWGPU_SetupRenderState(ImDrawData* draw_data, WGPURenderPas
|
||||
{ 0.0f, 0.0f, 0.5f, 0.0f },
|
||||
{ (R+L)/(L-R), (T+B)/(B-T), 0.5f, 1.0f },
|
||||
};
|
||||
wgpuQueueWriteBuffer(wgpuDeviceGetDefaultQueue(g_wgpuDevice), g_resources.Uniforms, 0, mvp, sizeof(mvp));
|
||||
wgpuQueueWriteBuffer(g_defaultQueue, g_resources.Uniforms, 0, mvp, sizeof(mvp));
|
||||
}
|
||||
|
||||
// Setup viewport
|
||||
wgpuRenderPassEncoderSetViewport(ctx, 0, 0, draw_data->DisplaySize.x, draw_data->DisplaySize.y, 0, 1);
|
||||
wgpuRenderPassEncoderSetViewport(ctx, 0, 0, draw_data->FramebufferScale.x * draw_data->DisplaySize.x, draw_data->FramebufferScale.y * draw_data->DisplaySize.y, 0, 1);
|
||||
|
||||
// Bind shader and vertex buffers
|
||||
unsigned int stride = sizeof(ImDrawVert);
|
||||
unsigned int offset = 0;
|
||||
wgpuRenderPassEncoderSetVertexBuffer(ctx, 0, fr->VertexBuffer, offset, fr->VertexBufferSize * stride);
|
||||
wgpuRenderPassEncoderSetIndexBuffer(ctx, fr->IndexBuffer, sizeof(ImDrawIdx) == 2 ? WGPUIndexFormat_Uint16 : WGPUIndexFormat_Uint32, 0, fr->IndexBufferSize * sizeof(ImDrawIdx));
|
||||
wgpuRenderPassEncoderSetVertexBuffer(ctx, 0, fr->VertexBuffer, 0, 0);
|
||||
wgpuRenderPassEncoderSetIndexBuffer(ctx, fr->IndexBuffer, sizeof(ImDrawIdx) == 2 ? WGPUIndexFormat_Uint16 : WGPUIndexFormat_Uint32, 0, 0);
|
||||
wgpuRenderPassEncoderSetPipeline(ctx, g_pipelineState);
|
||||
wgpuRenderPassEncoderSetBindGroup(ctx, 0, g_resources.CommonBindGroup, 0, NULL);
|
||||
|
||||
// Setup blend factor
|
||||
WGPUColor blend_color = { 0.f, 0.f, 0.f, 0.f };
|
||||
wgpuRenderPassEncoderSetBlendColor(ctx, &blend_color);
|
||||
wgpuRenderPassEncoderSetBlendConstant(ctx, &blend_color);
|
||||
}
|
||||
|
||||
// Render function
|
||||
@ -331,7 +337,11 @@ void ImGui_ImplWGPU_RenderDrawData(ImDrawData* draw_data, WGPURenderPassEncoder
|
||||
// Create and grow vertex/index buffers if needed
|
||||
if (fr->VertexBuffer == NULL || fr->VertexBufferSize < draw_data->TotalVtxCount)
|
||||
{
|
||||
SafeRelease(fr->VertexBuffer);
|
||||
if (fr->VertexBuffer)
|
||||
{
|
||||
wgpuBufferDestroy(fr->VertexBuffer);
|
||||
wgpuBufferRelease(fr->VertexBuffer);
|
||||
}
|
||||
SafeRelease(fr->VertexBufferHost);
|
||||
fr->VertexBufferSize = draw_data->TotalVtxCount + 5000;
|
||||
|
||||
@ -351,7 +361,11 @@ void ImGui_ImplWGPU_RenderDrawData(ImDrawData* draw_data, WGPURenderPassEncoder
|
||||
}
|
||||
if (fr->IndexBuffer == NULL || fr->IndexBufferSize < draw_data->TotalIdxCount)
|
||||
{
|
||||
SafeRelease(fr->IndexBuffer);
|
||||
if (fr->IndexBuffer)
|
||||
{
|
||||
wgpuBufferDestroy(fr->IndexBuffer);
|
||||
wgpuBufferRelease(fr->IndexBuffer);
|
||||
}
|
||||
SafeRelease(fr->IndexBufferHost);
|
||||
fr->IndexBufferSize = draw_data->TotalIdxCount + 10000;
|
||||
|
||||
@ -383,8 +397,8 @@ void ImGui_ImplWGPU_RenderDrawData(ImDrawData* draw_data, WGPURenderPassEncoder
|
||||
}
|
||||
int64_t vb_write_size = ((char*)vtx_dst - (char*)fr->VertexBufferHost + 3) & ~3;
|
||||
int64_t ib_write_size = ((char*)idx_dst - (char*)fr->IndexBufferHost + 3) & ~3;
|
||||
wgpuQueueWriteBuffer(wgpuDeviceGetDefaultQueue(g_wgpuDevice), fr->VertexBuffer, 0, fr->VertexBufferHost, vb_write_size);
|
||||
wgpuQueueWriteBuffer(wgpuDeviceGetDefaultQueue(g_wgpuDevice), fr->IndexBuffer, 0, fr->IndexBufferHost, ib_write_size);
|
||||
wgpuQueueWriteBuffer(g_defaultQueue, fr->VertexBuffer, 0, fr->VertexBufferHost, vb_write_size);
|
||||
wgpuQueueWriteBuffer(g_defaultQueue, fr->IndexBuffer, 0, fr->IndexBufferHost, ib_write_size);
|
||||
|
||||
// Setup desired render state
|
||||
ImGui_ImplWGPU_SetupRenderState(draw_data, pass_encoder, fr);
|
||||
@ -393,6 +407,7 @@ void ImGui_ImplWGPU_RenderDrawData(ImDrawData* draw_data, WGPURenderPassEncoder
|
||||
// (Because we merged all buffers into a single one, we maintain our own offset into them)
|
||||
int global_vtx_offset = 0;
|
||||
int global_idx_offset = 0;
|
||||
ImVec2 clip_scale = draw_data->FramebufferScale;
|
||||
ImVec2 clip_off = draw_data->DisplayPos;
|
||||
for (int n = 0; n < draw_data->CmdListsCount; n++)
|
||||
{
|
||||
@ -412,24 +427,26 @@ void ImGui_ImplWGPU_RenderDrawData(ImDrawData* draw_data, WGPURenderPassEncoder
|
||||
else
|
||||
{
|
||||
// Bind custom texture
|
||||
auto bind_group = g_resources.ImageBindGroups.GetVoidPtr(ImHashData(&pcmd->TextureId, sizeof(ImTextureID)));
|
||||
ImTextureID tex_id = pcmd->GetTexID();
|
||||
ImGuiID tex_id_hash = ImHashData(&tex_id, sizeof(tex_id));
|
||||
auto bind_group = g_resources.ImageBindGroups.GetVoidPtr(tex_id_hash);
|
||||
if (bind_group)
|
||||
{
|
||||
wgpuRenderPassEncoderSetBindGroup(pass_encoder, 1, (WGPUBindGroup)bind_group, 0, NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
WGPUBindGroup image_bind_group = ImGui_ImplWGPU_CreateImageBindGroup(g_resources.ImageBindGroupLayout, (WGPUTextureView)pcmd->TextureId);
|
||||
g_resources.ImageBindGroups.SetVoidPtr(ImHashData(&pcmd->TextureId, sizeof(ImTextureID)), image_bind_group);
|
||||
WGPUBindGroup image_bind_group = ImGui_ImplWGPU_CreateImageBindGroup(g_resources.ImageBindGroupLayout, (WGPUTextureView)tex_id);
|
||||
g_resources.ImageBindGroups.SetVoidPtr(tex_id_hash, image_bind_group);
|
||||
wgpuRenderPassEncoderSetBindGroup(pass_encoder, 1, image_bind_group, 0, NULL);
|
||||
}
|
||||
|
||||
// Apply Scissor, Bind texture, Draw
|
||||
uint32_t clip_rect[4];
|
||||
clip_rect[0] = static_cast<uint32_t>(pcmd->ClipRect.x - clip_off.x);
|
||||
clip_rect[1] = static_cast<uint32_t>(pcmd->ClipRect.y - clip_off.y);
|
||||
clip_rect[2] = static_cast<uint32_t>(pcmd->ClipRect.z - clip_off.x);
|
||||
clip_rect[3] = static_cast<uint32_t>(pcmd->ClipRect.w - clip_off.y);
|
||||
clip_rect[0] = (uint32_t)(clip_scale.x * (pcmd->ClipRect.x - clip_off.x));
|
||||
clip_rect[1] = (uint32_t)(clip_scale.y * (pcmd->ClipRect.y - clip_off.y));
|
||||
clip_rect[2] = (uint32_t)(clip_scale.x * (pcmd->ClipRect.z - clip_off.x));
|
||||
clip_rect[3] = (uint32_t)(clip_scale.y * (pcmd->ClipRect.w - clip_off.y));
|
||||
wgpuRenderPassEncoderSetScissorRect(pass_encoder, clip_rect[0], clip_rect[1], clip_rect[2] - clip_rect[0], clip_rect[3] - clip_rect[1]);
|
||||
wgpuRenderPassEncoderDrawIndexed(pass_encoder, pcmd->ElemCount, 1, pcmd->IdxOffset + global_idx_offset, pcmd->VtxOffset + global_vtx_offset, 0);
|
||||
}
|
||||
@ -439,18 +456,6 @@ void ImGui_ImplWGPU_RenderDrawData(ImDrawData* draw_data, WGPURenderPassEncoder
|
||||
}
|
||||
}
|
||||
|
||||
static WGPUBuffer ImGui_ImplWGPU_CreateBufferFromData(const WGPUDevice& device, const void* data, uint64_t size, WGPUBufferUsage usage)
|
||||
{
|
||||
WGPUBufferDescriptor descriptor = {};
|
||||
descriptor.size = size;
|
||||
descriptor.usage = usage | WGPUBufferUsage_CopyDst;
|
||||
WGPUBuffer buffer = wgpuDeviceCreateBuffer(device, &descriptor);
|
||||
|
||||
WGPUQueue queue = wgpuDeviceGetDefaultQueue(g_wgpuDevice);
|
||||
wgpuQueueWriteBuffer(queue, buffer, 0, data, size);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
static void ImGui_ImplWGPU_CreateFontsTexture()
|
||||
{
|
||||
// Build texture atlas
|
||||
@ -466,7 +471,7 @@ static void ImGui_ImplWGPU_CreateFontsTexture()
|
||||
tex_desc.dimension = WGPUTextureDimension_2D;
|
||||
tex_desc.size.width = width;
|
||||
tex_desc.size.height = height;
|
||||
tex_desc.size.depth = 1;
|
||||
tex_desc.size.depthOrArrayLayers = 1;
|
||||
tex_desc.sampleCount = 1;
|
||||
tex_desc.format = WGPUTextureFormat_RGBA8Unorm;
|
||||
tex_desc.mipLevelCount = 1;
|
||||
@ -486,34 +491,17 @@ static void ImGui_ImplWGPU_CreateFontsTexture()
|
||||
|
||||
// Upload texture data
|
||||
{
|
||||
WGPUBuffer staging_buffer = ImGui_ImplWGPU_CreateBufferFromData(g_wgpuDevice, pixels, (uint32_t)(width * size_pp * height), WGPUBufferUsage_CopySrc);
|
||||
|
||||
WGPUBufferCopyView bufferCopyView = {};
|
||||
bufferCopyView.buffer = staging_buffer;
|
||||
bufferCopyView.layout.offset = 0;
|
||||
bufferCopyView.layout.bytesPerRow = width * size_pp;
|
||||
bufferCopyView.layout.rowsPerImage = height;
|
||||
|
||||
WGPUTextureCopyView textureCopyView = {};
|
||||
textureCopyView.texture = g_resources.FontTexture;
|
||||
textureCopyView.mipLevel = 0;
|
||||
textureCopyView.origin = { 0, 0, 0 };
|
||||
#if !defined(__EMSCRIPTEN__) || HAS_EMSCRIPTEN_VERSION(2, 0, 14)
|
||||
textureCopyView.aspect = WGPUTextureAspect_All;
|
||||
#endif
|
||||
|
||||
WGPUExtent3D copySize = { (uint32_t)width, (uint32_t)height, 1 };
|
||||
|
||||
WGPUCommandEncoderDescriptor enc_desc = {};
|
||||
WGPUCommandEncoder encoder = wgpuDeviceCreateCommandEncoder(g_wgpuDevice, &enc_desc);
|
||||
wgpuCommandEncoderCopyBufferToTexture(encoder, &bufferCopyView, &textureCopyView, ©Size);
|
||||
WGPUCommandBufferDescriptor cmd_buf_desc = {};
|
||||
WGPUCommandBuffer copy = wgpuCommandEncoderFinish(encoder, &cmd_buf_desc);
|
||||
WGPUQueue queue = wgpuDeviceGetDefaultQueue(g_wgpuDevice);
|
||||
wgpuQueueSubmit(queue, 1, ©);
|
||||
|
||||
wgpuCommandEncoderRelease(encoder);
|
||||
wgpuBufferRelease(staging_buffer);
|
||||
WGPUImageCopyTexture dst_view = {};
|
||||
dst_view.texture = g_resources.FontTexture;
|
||||
dst_view.mipLevel = 0;
|
||||
dst_view.origin = { 0, 0, 0 };
|
||||
dst_view.aspect = WGPUTextureAspect_All;
|
||||
WGPUTextureDataLayout layout = {};
|
||||
layout.offset = 0;
|
||||
layout.bytesPerRow = width * size_pp;
|
||||
layout.rowsPerImage = height;
|
||||
WGPUExtent3D size = { (uint32_t)width, (uint32_t)height, 1 };
|
||||
wgpuQueueWriteTexture(g_defaultQueue, &dst_view, pixels, (uint32_t)(width * size_pp * height), &layout, &size);
|
||||
}
|
||||
|
||||
// Create the associated sampler
|
||||
@ -525,9 +513,7 @@ static void ImGui_ImplWGPU_CreateFontsTexture()
|
||||
sampler_desc.addressModeU = WGPUAddressMode_Repeat;
|
||||
sampler_desc.addressModeV = WGPUAddressMode_Repeat;
|
||||
sampler_desc.addressModeW = WGPUAddressMode_Repeat;
|
||||
#if !defined(__EMSCRIPTEN__) || HAS_EMSCRIPTEN_VERSION(2, 0, 14)
|
||||
sampler_desc.maxAnisotropy = 1;
|
||||
#endif
|
||||
g_resources.Sampler = wgpuDeviceCreateSampler(g_wgpuDevice, &sampler_desc);
|
||||
}
|
||||
|
||||
@ -557,139 +543,82 @@ bool ImGui_ImplWGPU_CreateDeviceObjects()
|
||||
ImGui_ImplWGPU_InvalidateDeviceObjects();
|
||||
|
||||
// Create render pipeline
|
||||
WGPURenderPipelineDescriptor graphics_pipeline_desc = {};
|
||||
graphics_pipeline_desc.primitiveTopology = WGPUPrimitiveTopology_TriangleList;
|
||||
graphics_pipeline_desc.sampleCount = 1;
|
||||
graphics_pipeline_desc.sampleMask = UINT_MAX;
|
||||
|
||||
WGPUBindGroupLayoutEntry common_bg_layout_entries[2] = {};
|
||||
common_bg_layout_entries[0].binding = 0;
|
||||
common_bg_layout_entries[0].visibility = WGPUShaderStage_Vertex;
|
||||
#if !defined(__EMSCRIPTEN__) || HAS_EMSCRIPTEN_VERSION(2, 0, 14)
|
||||
common_bg_layout_entries[0].buffer.type = WGPUBufferBindingType_Uniform;
|
||||
#else
|
||||
common_bg_layout_entries[0].type = WGPUBindingType_UniformBuffer;
|
||||
#endif
|
||||
common_bg_layout_entries[1].binding = 1;
|
||||
common_bg_layout_entries[1].visibility = WGPUShaderStage_Fragment;
|
||||
#if !defined(__EMSCRIPTEN__) || HAS_EMSCRIPTEN_VERSION(2, 0, 14)
|
||||
common_bg_layout_entries[1].sampler.type = WGPUSamplerBindingType_Filtering;
|
||||
#else
|
||||
common_bg_layout_entries[1].type = WGPUBindingType_Sampler;
|
||||
#endif
|
||||
|
||||
WGPUBindGroupLayoutEntry image_bg_layout_entries[1] = {};
|
||||
image_bg_layout_entries[0].binding = 0;
|
||||
image_bg_layout_entries[0].visibility = WGPUShaderStage_Fragment;
|
||||
#if !defined(__EMSCRIPTEN__) || HAS_EMSCRIPTEN_VERSION(2, 0, 14)
|
||||
image_bg_layout_entries[0].texture.sampleType = WGPUTextureSampleType_Float;
|
||||
image_bg_layout_entries[0].texture.viewDimension = WGPUTextureViewDimension_2D;
|
||||
#else
|
||||
image_bg_layout_entries[0].type = WGPUBindingType_SampledTexture;
|
||||
#endif
|
||||
|
||||
WGPUBindGroupLayoutDescriptor common_bg_layout_desc = {};
|
||||
common_bg_layout_desc.entryCount = 2;
|
||||
common_bg_layout_desc.entries = common_bg_layout_entries;
|
||||
|
||||
WGPUBindGroupLayoutDescriptor image_bg_layout_desc = {};
|
||||
image_bg_layout_desc.entryCount = 1;
|
||||
image_bg_layout_desc.entries = image_bg_layout_entries;
|
||||
|
||||
WGPUBindGroupLayout bg_layouts[2];
|
||||
bg_layouts[0] = wgpuDeviceCreateBindGroupLayout(g_wgpuDevice, &common_bg_layout_desc);
|
||||
bg_layouts[1] = wgpuDeviceCreateBindGroupLayout(g_wgpuDevice, &image_bg_layout_desc);
|
||||
|
||||
WGPUPipelineLayoutDescriptor layout_desc = {};
|
||||
layout_desc.bindGroupLayoutCount = 2;
|
||||
layout_desc.bindGroupLayouts = bg_layouts;
|
||||
graphics_pipeline_desc.layout = wgpuDeviceCreatePipelineLayout(g_wgpuDevice, &layout_desc);
|
||||
WGPURenderPipelineDescriptor2 graphics_pipeline_desc = {};
|
||||
graphics_pipeline_desc.primitive.topology = WGPUPrimitiveTopology_TriangleList;
|
||||
graphics_pipeline_desc.primitive.stripIndexFormat = WGPUIndexFormat_Undefined;
|
||||
graphics_pipeline_desc.primitive.frontFace = WGPUFrontFace_CW;
|
||||
graphics_pipeline_desc.primitive.cullMode = WGPUCullMode_None;
|
||||
graphics_pipeline_desc.multisample.count = 1;
|
||||
graphics_pipeline_desc.multisample.mask = UINT_MAX;
|
||||
graphics_pipeline_desc.multisample.alphaToCoverageEnabled = false;
|
||||
graphics_pipeline_desc.layout = nullptr; // Use automatic layout generation
|
||||
|
||||
// Create the vertex shader
|
||||
WGPUProgrammableStageDescriptor vertex_shader_desc = ImGui_ImplWGPU_CreateShaderModule(__glsl_shader_vert_spv, sizeof(__glsl_shader_vert_spv) / sizeof(uint32_t));
|
||||
graphics_pipeline_desc.vertexStage = vertex_shader_desc;
|
||||
graphics_pipeline_desc.vertex.module = vertex_shader_desc.module;
|
||||
graphics_pipeline_desc.vertex.entryPoint = vertex_shader_desc.entryPoint;
|
||||
|
||||
// Vertex input configuration
|
||||
WGPUVertexAttributeDescriptor attribute_binding_desc[] =
|
||||
WGPUVertexAttribute attribute_desc[] =
|
||||
{
|
||||
{ WGPUVertexFormat_Float2, (uint64_t)IM_OFFSETOF(ImDrawVert, pos), 0 },
|
||||
{ WGPUVertexFormat_Float2, (uint64_t)IM_OFFSETOF(ImDrawVert, uv), 1 },
|
||||
{ WGPUVertexFormat_UChar4Norm, (uint64_t)IM_OFFSETOF(ImDrawVert, col), 2 },
|
||||
{ WGPUVertexFormat_Float32x2, (uint64_t)IM_OFFSETOF(ImDrawVert, pos), 0 },
|
||||
{ WGPUVertexFormat_Float32x2, (uint64_t)IM_OFFSETOF(ImDrawVert, uv), 1 },
|
||||
{ WGPUVertexFormat_Unorm8x4, (uint64_t)IM_OFFSETOF(ImDrawVert, col), 2 },
|
||||
};
|
||||
|
||||
WGPUVertexBufferLayoutDescriptor buffer_binding_desc;
|
||||
buffer_binding_desc.arrayStride = sizeof(ImDrawVert);
|
||||
buffer_binding_desc.stepMode = WGPUInputStepMode_Vertex;
|
||||
buffer_binding_desc.attributeCount = 3;
|
||||
buffer_binding_desc.attributes = attribute_binding_desc;
|
||||
WGPUVertexBufferLayout buffer_layouts[1];
|
||||
buffer_layouts[0].arrayStride = sizeof(ImDrawVert);
|
||||
buffer_layouts[0].stepMode = WGPUInputStepMode_Vertex;
|
||||
buffer_layouts[0].attributeCount = 3;
|
||||
buffer_layouts[0].attributes = attribute_desc;
|
||||
|
||||
WGPUVertexStateDescriptor vertex_state_desc = {};
|
||||
vertex_state_desc.indexFormat = WGPUIndexFormat_Undefined;
|
||||
vertex_state_desc.vertexBufferCount = 1;
|
||||
vertex_state_desc.vertexBuffers = &buffer_binding_desc;
|
||||
|
||||
graphics_pipeline_desc.vertexState = &vertex_state_desc;
|
||||
graphics_pipeline_desc.vertex.bufferCount = 1;
|
||||
graphics_pipeline_desc.vertex.buffers = buffer_layouts;
|
||||
|
||||
// Create the pixel shader
|
||||
WGPUProgrammableStageDescriptor pixel_shader_desc = ImGui_ImplWGPU_CreateShaderModule(__glsl_shader_frag_spv, sizeof(__glsl_shader_frag_spv) / sizeof(uint32_t));
|
||||
graphics_pipeline_desc.fragmentStage = &pixel_shader_desc;
|
||||
|
||||
// Create the blending setup
|
||||
WGPUColorStateDescriptor color_state = {};
|
||||
{
|
||||
color_state.format = g_renderTargetFormat;
|
||||
color_state.alphaBlend.operation = WGPUBlendOperation_Add;
|
||||
color_state.alphaBlend.srcFactor = WGPUBlendFactor_One;
|
||||
color_state.alphaBlend.dstFactor = WGPUBlendFactor_OneMinusSrcAlpha;
|
||||
color_state.colorBlend.operation = WGPUBlendOperation_Add;
|
||||
color_state.colorBlend.srcFactor = WGPUBlendFactor_SrcAlpha;
|
||||
color_state.colorBlend.dstFactor = WGPUBlendFactor_OneMinusSrcAlpha;
|
||||
color_state.writeMask = WGPUColorWriteMask_All;
|
||||
WGPUBlendState blend_state = {};
|
||||
blend_state.alpha.operation = WGPUBlendOperation_Add;
|
||||
blend_state.alpha.srcFactor = WGPUBlendFactor_One;
|
||||
blend_state.alpha.dstFactor = WGPUBlendFactor_OneMinusSrcAlpha;
|
||||
blend_state.color.operation = WGPUBlendOperation_Add;
|
||||
blend_state.color.srcFactor = WGPUBlendFactor_SrcAlpha;
|
||||
blend_state.color.dstFactor = WGPUBlendFactor_OneMinusSrcAlpha;
|
||||
|
||||
graphics_pipeline_desc.colorStateCount = 1;
|
||||
graphics_pipeline_desc.colorStates = &color_state;
|
||||
graphics_pipeline_desc.alphaToCoverageEnabled = false;
|
||||
}
|
||||
WGPUColorTargetState color_state = {};
|
||||
color_state.format = g_renderTargetFormat;
|
||||
color_state.blend = &blend_state;
|
||||
color_state.writeMask = WGPUColorWriteMask_All;
|
||||
|
||||
// Create the rasterizer state
|
||||
WGPURasterizationStateDescriptor raster_desc = {};
|
||||
{
|
||||
raster_desc.cullMode = WGPUCullMode_None;
|
||||
raster_desc.frontFace = WGPUFrontFace_CW;
|
||||
raster_desc.depthBias = 0;
|
||||
raster_desc.depthBiasClamp = 0;
|
||||
raster_desc.depthBiasSlopeScale = 0;
|
||||
graphics_pipeline_desc.rasterizationState = &raster_desc;
|
||||
}
|
||||
WGPUFragmentState fragment_state = {};
|
||||
fragment_state.module = pixel_shader_desc.module;
|
||||
fragment_state.entryPoint = pixel_shader_desc.entryPoint;
|
||||
fragment_state.targetCount = 1;
|
||||
fragment_state.targets = &color_state;
|
||||
|
||||
graphics_pipeline_desc.fragment = &fragment_state;
|
||||
|
||||
// Create depth-stencil State
|
||||
WGPUDepthStencilStateDescriptor depth_desc = {};
|
||||
{
|
||||
// Configure disabled state
|
||||
depth_desc.format = WGPUTextureFormat_Undefined;
|
||||
depth_desc.depthWriteEnabled = true;
|
||||
depth_desc.depthCompare = WGPUCompareFunction_Always;
|
||||
depth_desc.stencilReadMask = 0;
|
||||
depth_desc.stencilWriteMask = 0;
|
||||
depth_desc.stencilBack.compare = WGPUCompareFunction_Always;
|
||||
depth_desc.stencilBack.failOp = WGPUStencilOperation_Keep;
|
||||
depth_desc.stencilBack.depthFailOp = WGPUStencilOperation_Keep;
|
||||
depth_desc.stencilBack.passOp = WGPUStencilOperation_Keep;
|
||||
depth_desc.stencilFront.compare = WGPUCompareFunction_Always;
|
||||
depth_desc.stencilFront.failOp = WGPUStencilOperation_Keep;
|
||||
depth_desc.stencilFront.depthFailOp = WGPUStencilOperation_Keep;
|
||||
depth_desc.stencilFront.passOp = WGPUStencilOperation_Keep;
|
||||
WGPUDepthStencilState depth_stencil_state = {};
|
||||
depth_stencil_state.depthBias = 0;
|
||||
depth_stencil_state.depthBiasClamp = 0;
|
||||
depth_stencil_state.depthBiasSlopeScale = 0;
|
||||
|
||||
// No depth buffer corresponds to no configuration
|
||||
graphics_pipeline_desc.depthStencilState = NULL;
|
||||
}
|
||||
// Configure disabled depth-stencil state
|
||||
graphics_pipeline_desc.depthStencil = nullptr;
|
||||
|
||||
g_pipelineState = wgpuDeviceCreateRenderPipeline(g_wgpuDevice, &graphics_pipeline_desc);
|
||||
g_pipelineState = wgpuDeviceCreateRenderPipeline2(g_wgpuDevice, &graphics_pipeline_desc);
|
||||
|
||||
ImGui_ImplWGPU_CreateFontsTexture();
|
||||
ImGui_ImplWGPU_CreateUniformBuffer();
|
||||
|
||||
// Create resource bind group
|
||||
WGPUBindGroupLayout bg_layouts[2];
|
||||
bg_layouts[0] = wgpuRenderPipelineGetBindGroupLayout(g_pipelineState, 0);
|
||||
bg_layouts[1] = wgpuRenderPipelineGetBindGroupLayout(g_pipelineState, 1);
|
||||
|
||||
WGPUBindGroupEntry common_bg_entries[] =
|
||||
{
|
||||
{ 0, g_resources.Uniforms, 0, sizeof(Uniforms), 0, 0 },
|
||||
@ -701,10 +630,10 @@ bool ImGui_ImplWGPU_CreateDeviceObjects()
|
||||
common_bg_descriptor.entryCount = sizeof(common_bg_entries) / sizeof(WGPUBindGroupEntry);
|
||||
common_bg_descriptor.entries = common_bg_entries;
|
||||
g_resources.CommonBindGroup = wgpuDeviceCreateBindGroup(g_wgpuDevice, &common_bg_descriptor);
|
||||
g_resources.ImageBindGroupLayout = bg_layouts[1];
|
||||
|
||||
WGPUBindGroup image_bind_group = ImGui_ImplWGPU_CreateImageBindGroup(bg_layouts[1], g_resources.FontTextureView);
|
||||
g_resources.ImageBindGroup = image_bind_group;
|
||||
g_resources.ImageBindGroupLayout = bg_layouts[1];
|
||||
g_resources.ImageBindGroups.SetVoidPtr(ImHashData(&g_resources.FontTextureView, sizeof(ImTextureID)), image_bind_group);
|
||||
|
||||
SafeRelease(vertex_shader_desc.module);
|
||||
@ -737,6 +666,7 @@ bool ImGui_ImplWGPU_Init(WGPUDevice device, int num_frames_in_flight, WGPUTextur
|
||||
io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset; // We can honor the ImDrawCmd::VtxOffset field, allowing for large meshes.
|
||||
|
||||
g_wgpuDevice = device;
|
||||
g_defaultQueue = wgpuDeviceGetQueue(g_wgpuDevice);
|
||||
g_renderTargetFormat = rt_format;
|
||||
g_pFrameResources = new FrameResources[num_frames_in_flight];
|
||||
g_numFramesInFlight = num_frames_in_flight;
|
||||
@ -747,9 +677,9 @@ bool ImGui_ImplWGPU_Init(WGPUDevice device, int num_frames_in_flight, WGPUTextur
|
||||
g_resources.Sampler = NULL;
|
||||
g_resources.Uniforms = NULL;
|
||||
g_resources.CommonBindGroup = NULL;
|
||||
g_resources.ImageBindGroupLayout = NULL;
|
||||
g_resources.ImageBindGroups.Data.reserve(100);
|
||||
g_resources.ImageBindGroup = NULL;
|
||||
g_resources.ImageBindGroupLayout = NULL;
|
||||
|
||||
// Create buffers with a default size (they will later be grown as needed)
|
||||
for (int i = 0; i < num_frames_in_flight; i++)
|
||||
@ -771,6 +701,7 @@ void ImGui_ImplWGPU_Shutdown()
|
||||
ImGui_ImplWGPU_InvalidateDeviceObjects();
|
||||
delete[] g_pFrameResources;
|
||||
g_pFrameResources = NULL;
|
||||
wgpuQueueRelease(g_defaultQueue);
|
||||
g_wgpuDevice = NULL;
|
||||
g_numFramesInFlight = 0;
|
||||
g_frameIndex = UINT_MAX;
|
||||
|
@ -25,13 +25,14 @@
|
||||
|
||||
// Using XInput for gamepad (will load DLL dynamically)
|
||||
#ifndef IMGUI_IMPL_WIN32_DISABLE_GAMEPAD
|
||||
#include <XInput.h>
|
||||
#include <xinput.h>
|
||||
typedef DWORD (WINAPI *PFN_XInputGetCapabilities)(DWORD, DWORD, XINPUT_CAPABILITIES*);
|
||||
typedef DWORD (WINAPI *PFN_XInputGetState)(DWORD, XINPUT_STATE*);
|
||||
#endif
|
||||
|
||||
// CHANGELOG
|
||||
// (minor and older changes stripped away, please see git history for details)
|
||||
// 2021-03-23: Inputs: Clearing keyboard down array when losing focus (WM_KILLFOCUS).
|
||||
// 2021-02-18: Added ImGui_ImplWin32_EnableAlphaCompositing(). Non Visual Studio users will need to link with dwmapi.lib (MinGW/gcc: use -ldwmapi).
|
||||
// 2021-02-17: Fixed ImGui_ImplWin32_EnableDpiAwareness() attempting to get SetProcessDpiAwareness from shcore.dll on Windows 8 whereas it is only supported on Windows 8.1.
|
||||
// 2021-01-25: Inputs: Dynamically loading XInput DLL.
|
||||
@ -134,7 +135,7 @@ bool ImGui_ImplWin32_Init(void* hwnd)
|
||||
break;
|
||||
}
|
||||
#endif // IMGUI_IMPL_WIN32_DISABLE_GAMEPAD
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -148,7 +149,7 @@ void ImGui_ImplWin32_Shutdown()
|
||||
g_XInputGetCapabilities = NULL;
|
||||
g_XInputGetState = NULL;
|
||||
#endif // IMGUI_IMPL_WIN32_DISABLE_GAMEPAD
|
||||
|
||||
|
||||
g_hWnd = NULL;
|
||||
g_Time = 0;
|
||||
g_TicksPerSecond = 0;
|
||||
@ -193,6 +194,7 @@ static bool ImGui_ImplWin32_UpdateMouseCursor()
|
||||
static void ImGui_ImplWin32_UpdateMousePos()
|
||||
{
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
IM_ASSERT(g_hWnd != 0);
|
||||
|
||||
// Set OS mouse position if requested (rarely used, only when ImGuiConfigFlags_NavEnableSetMousePos is enabled by user)
|
||||
if (io.WantSetMousePos)
|
||||
@ -372,6 +374,9 @@ IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hwnd, UINT msg, WPARA
|
||||
if (wParam < 256)
|
||||
io.KeysDown[wParam] = 0;
|
||||
return 0;
|
||||
case WM_KILLFOCUS:
|
||||
memset(io.KeysDown, 0, sizeof(io.KeysDown));
|
||||
return 0;
|
||||
case WM_CHAR:
|
||||
// You can also use ToAscii()+GetKeyboardState() to retrieve characters.
|
||||
if (wParam > 0 && wParam < 0x10000)
|
||||
|
@ -17,6 +17,8 @@ your application or engine to easily integrate Dear ImGui.** Each backend is typ
|
||||
An application usually combines 1 Platform backend + 1 Renderer backend + main Dear ImGui sources.
|
||||
For example, the [example_win32_directx11](https://github.com/ocornut/imgui/tree/master/examples/example_win32_directx11) application combines imgui_impl_win32.cpp + imgui_impl_dx11.cpp. There are 20+ examples in the [examples/](https://github.com/ocornut/imgui/blob/master/examples/) folder. See [EXAMPLES.MD](https://github.com/ocornut/imgui/blob/master/docs/EXAMPLES.md) for details.
|
||||
|
||||
**Once Dear ImGui is setup and running, run and refer to `ImGui::ShowDemoWindow()` in imgui_demo.cpp for usage of the end-user API.**
|
||||
|
||||
|
||||
### What are backends
|
||||
|
||||
|
@ -32,9 +32,93 @@ HOW TO UPDATE?
|
||||
|
||||
|
||||
-----------------------------------------------------------------------
|
||||
VERSION 1.82 WIP (In Progresss)
|
||||
VERSION 1.83 (Released 2011-05-24)
|
||||
-----------------------------------------------------------------------
|
||||
|
||||
Decorated log: https://github.com/ocornut/imgui/releases/tag/v1.83
|
||||
|
||||
Breaking Changes:
|
||||
|
||||
- Backends: Obsoleted direct access to ImDrawCmd::TextureId in favor of calling ImDrawCmd::GetTexID(). (#3761) [@thedmd]
|
||||
- If you are using official backends from the source tree: you have nothing to do.
|
||||
- If you copied old backend code or using your own: change access to draw_cmd->TextureId to draw_cmd->GetTexID().
|
||||
Why are we doing this?
|
||||
- This change will be required in the future when adding support for incremental texture atlas updates.
|
||||
- Please note this won't break soon, but we are making the change ahead of time.
|
||||
|
||||
Other Changes:
|
||||
|
||||
- Scrolling: Fix scroll tracking with e.g. SetScrollHereX/Y() when WindowPadding < ItemSpacing.
|
||||
- Scrolling: Fix scroll snapping on edge of scroll region when both scrollbars are enabled.
|
||||
- Scrolling: Fix mouse wheel axis swap when using SHIFT on macOS (system already does it). (#4010)
|
||||
- Window: Fix IsWindowAppearing() from returning true twice in most cases. (#3982, #1497, #1061)
|
||||
- Nav: Fixed toggling menu layer while an InputText() is active not stealing active id. (#787)
|
||||
- Nav: Fixed pressing Escape to leave menu layer while in a popup or child window. (#787)
|
||||
- Nav, InputText: Fixed accidental menu toggling while typing non-ascii characters using AltGR. [@rokups] (#370)
|
||||
- Nav: Fixed using SetItemDefaultFocus() on windows with _NavFlattened flag. (#787)
|
||||
- Nav: Fixed Tabbing initial activation from skipping the first item if it is tabbable through. (#787)
|
||||
- Nav: Fixed fast CTRL+Tab (where keys are only held for one single frame) from properly enabling the
|
||||
menu layer of target window if it doesn't have other active layers.
|
||||
- Tables: Expose TableSetColumnEnabled() in public api. (#3935)
|
||||
- Tables: Better preserve widths when columns count changes. (#4046)
|
||||
- Tables: Sharing more memory buffers between tables, reducing general memory footprints. (#3740)
|
||||
- TabBar: Fixed mouse reordering with very fast movements (e.g. crossing multiple tabs in a single
|
||||
frame and then immediately standing still (would only affect automation/bots). [@rokups]
|
||||
- Menus: made MenuItem() in a menu bar reflect the 'selected' argument with a highlight. (#4128) [@mattelegende]
|
||||
- Drags, Sliders, Inputs: Specifying a NULL format to Float functions default them to "%.3f" to be
|
||||
consistent with the compile-time default. (#3922)
|
||||
- DragScalar: Add default value for v_speed argument to match higher-level functions. (#3922) [@eliasdaler]
|
||||
- ColorEdit4: Alpha default to 255 (instead of 0) when omitted in hex input. (#3973) [@squadack]
|
||||
- InputText: Do not filter private unicode codepoints (e.g. icons) when pasted from clipboard. (#4005) [@dougbinks]
|
||||
- InputText: Align caret/cursor to pixel coordinates. (#4080) [@elvissteinjr]
|
||||
- InputText: Fixed CTRL+Arrow or OSX double-click leaking the presence of spaces when ImGuiInputTextFlags_Password
|
||||
is used. (#4155, #4156) [@michael-swan]
|
||||
- LabelText: Fixed clipping of multi-line value text when label is single-line. (#4004)
|
||||
- LabelText: Fixed vertical alignment of single-line value text when label is multi-line. (#4004)
|
||||
- Combos: Changed the combo popup to use a different id to also using a context menu with the default item id.
|
||||
Fixed using BeginPopupContextItem() with no parameter after a combo. (#4167)
|
||||
- Popups: Added 'OpenPopup(ImGuiID id)' overload to facilitate calling from nested stacks. (#3993, #331) [@zlash]
|
||||
- Tweak computation of io.Framerate so it is less biased toward high-values in the first 120 frames. (#4138)
|
||||
- Optimization: Disabling some of MSVC most aggressive Debug runtime checks for some simple/low-level functions
|
||||
(e.g. ImVec2, ImVector) leading to a 10-20% increase of performances with MSVC "default" Debug settings.
|
||||
- ImDrawList: Add and use SSE-enabled ImRsqrt() in place of 1.0f / ImSqrt(). (#4091) [@wolfpld]
|
||||
- ImDrawList: Fixed/improved thickness of thick strokes with sharp angles. (#4053, #3366, #2964, #2868, #2518, #2183)
|
||||
Effectively introduced a regression in 1.67 (Jan 2019), and a fix in 1.70 (Apr 2019) but the fix wasn't actually on
|
||||
par with original version. Now incorporating the correct revert.
|
||||
- ImDrawList: Fixed PathArcTo() regression from 1.82 preventing use of counter-clockwise angles. (#4030, #3491) [@thedmd]
|
||||
- Demo: Improved popups demo and comments.
|
||||
- Metrics: Added "Fonts" section with same information as available in "Style Editor">"Fonts".
|
||||
- Backends: SDL: Rework global mouse pos availability check listing supported platforms explicitly,
|
||||
effectively fixing mouse access on Raspberry Pi. (#2837, #3950) [@lethal-guitar, @hinxx]
|
||||
- Backends: Win32: Clearing keyboard down array when losing focus (WM_KILLFOCUS). (#2062, #3532, #3961)
|
||||
[@1025798851]
|
||||
- Backends: OSX: Fix keys remaining stuck when CMD-tabbing to a different application. (#3832) [@rokups]
|
||||
- Backends: DirectX9: calling IDirect3DStateBlock9::Capture() after CreateStateBlock() which appears to
|
||||
workaround/fix state restoring issues. Unknown exactly why so, bit of a cargo-cult fix. (#3857)
|
||||
- Backends: DirectX9: explicitly setting up more graphics states to increase compatibility with unusual
|
||||
non-default states. (#4063)
|
||||
- Backends: DirectX10, DirectX11: fixed a crash when backing/restoring state if nothing is bound when
|
||||
entering the rendering function. (#4045) [@Nemirtingas]
|
||||
- Backends: GLFW: Adding bound check in KeyCallback because GLFW appears to send -1 on some setups. [#4124]
|
||||
- Backends: Vulkan: Fix mapped memory Vulkan validation error when buffer sizes are not multiple of
|
||||
VkPhysicalDeviceLimits::nonCoherentAtomSize. (#3957) [@AgentX1994]
|
||||
- Backends: WebGPU: Update to latest specs (Chrome Canary 92 and Emscripten 2.0.20). (#4116, #3632) [@bfierz, @Kangz]
|
||||
- Backends: OpenGL3: Don't try to read GL_CLIP_ORIGIN unless we're OpenGL 4.5. (#3998, #2366, #2186) [@s7jones]
|
||||
- Examples: OpenGL: Add OpenGL ES 2.0 support to modern GL examples. (#2837, #3951) [@lethal-guitar, @hinxx]
|
||||
- Examples: Vulkan: Rebuild swapchain on VK_SUBOPTIMAL_KHR. (#3881)
|
||||
- Examples: Vulkan: Prefer using discrete GPU if there are more than one available. (#4012) [@rokups]
|
||||
- Examples: SDL2: Link with shell32.lib required by SDL2main.lib since SDL 2.0.12. [#3988]
|
||||
- Examples: Android: Make Android example build compatible with Gradle 7.0. (#3446)
|
||||
- Docs: Improvements to description of using colored glyphs/emojis. (#4169, #3369)
|
||||
- Docs: Improvements to minor mistakes in documentation comments (#3923) [@ANF-Studios]
|
||||
|
||||
|
||||
-----------------------------------------------------------------------
|
||||
VERSION 1.82 (Released 2021-02-15)
|
||||
-----------------------------------------------------------------------
|
||||
|
||||
Decorated log: https://github.com/ocornut/imgui/releases/tag/v1.82
|
||||
|
||||
Breaking Changes:
|
||||
|
||||
- Removed redirecting functions/enums names that were marked obsolete in 1.66 (September 2018):
|
||||
@ -75,9 +159,9 @@ Breaking Changes:
|
||||
|
||||
Other Changes:
|
||||
|
||||
- Window, Nav: Fixed crash when calling SetWindowFocus(NULL) at the time a new window appears. (#3865) [@nem0]
|
||||
- Window: Shrink close button hit-testing region when it covers an abnormally high portion of the window visible
|
||||
area (e.g. when window is collapsed + moved in a corner) to facilitate moving the window away. (#3825)
|
||||
- Window, Nav: Fixed crash when calling SetWindowFocus(NULL) as the time a new window appears. (#3865) [@nem0]
|
||||
- Nav: Various fixes for losing gamepad/keyboard navigation reference point when a window reappears or
|
||||
when it appears while gamepad/keyboard are not being used. (#787)
|
||||
- Drags: Fixed crash when using DragScalar() directly (not via common wrapper like DragFloat() etc.)
|
||||
@ -86,26 +170,27 @@ Other Changes:
|
||||
format specifier (e.g. using "%f123" as a format string). [@rokups]
|
||||
- Drags, Sliders: Fixed a bug where using custom formatting flags (',$,_) supported by stb_sprintf.h
|
||||
would cause incorrect value to be displayed. (#3604) [@rokups]
|
||||
- Drags, Sliders: Support ImGuiSliderFlags_Logarithmic flag with integers. Because why not? (#3786)
|
||||
- Tables: Fixed unaligned accesses when using TableSetBgColor(ImGuiTableBgTarget_CellBg). (#3872)
|
||||
- IsItemHovered(): fixed return value false positive when used after EndChild(), EndGroup() or widgets using
|
||||
either of them, when the hovered location is located within a child window, e.g. InputTextMultiline().
|
||||
This is intended to have no side effects, but brace yourself for the possible comeback.. (#3851, #1370)
|
||||
- Drag and Drop: can use BeginDragDropSource() for other than the left mouse button as long as the item
|
||||
has an ID (for ID-less items will add new functionalities later). (#1637, #3885)
|
||||
- Added GetAllocatorFunctions() to facilitate sharing allocators accross DLL boundaries. (#3836)
|
||||
- ImFontAtlas: Added 'bool TexPixelsUseColors' output to help backend decide of underlying texture format. (#3369)
|
||||
This can currently only ever be set by the Freetype renderer.
|
||||
- imgui_freetype: Added ImGuiFreeTypeBuilderFlags_Bitmap flag to request Freetype loading bitmap data.
|
||||
This may have an effect on size and must be called with correct size values. (#3879) [@metarutaiga]
|
||||
- ImDrawList: PathArcTo() now supports "int num_segments = 0" (new default) and adaptively tesselate.
|
||||
The adapative tesselation uses look up tables, tends to be faster than old PathArcTo() while maintaining
|
||||
quality for large arcs (tesselation quality derived from "style.CircleTessellationMaxError") (#3491) [@thedmd]
|
||||
- ImDrawList: PathArcToFast() also adaptively tesselate efficiently. This means that large rounded corners
|
||||
- ImDrawList: PathArcTo() now supports "int num_segments = 0" (new default) and adaptively tessellate.
|
||||
The adaptive tessellation uses look up tables, tends to be faster than old PathArcTo() while maintaining
|
||||
quality for large arcs (tessellation quality derived from "style.CircleTessellationMaxError") (#3491) [@thedmd]
|
||||
- ImDrawList: PathArcToFast() also adaptively tessellate efficiently. This means that large rounded corners
|
||||
in e.g. hi-dpi settings will generally look better. (#3491) [@thedmd]
|
||||
- ImDrawList: AddCircle, AddCircleFilled(): Tweaked default segment count calculation to honor MaxError
|
||||
with more accuracy. Made default segment count always even for better looking result. (#3808) [@thedmd]
|
||||
- Misc: Added GetAllocatorFunctions() to facilitate sharing allocators across DLL boundaries. (#3836)
|
||||
- Misc: Added 'debuggers/imgui.gdb' and 'debuggers/imgui.natstepfilter' (along with existing 'imgui.natvis')
|
||||
scriptss to configure popular debuggers into skipping trivial functions when using StepInto. [@rokups]
|
||||
scripts to configure popular debuggers into skipping trivial functions when using StepInto. [@rokups]
|
||||
- Backends: Android: Added native Android backend. (#3446) [@duddel]
|
||||
- Backends: Win32: Added ImGui_ImplWin32_EnableAlphaCompositing() to facilitate experimenting with
|
||||
alpha compositing and transparent windows. (#2766, #3447 etc.).
|
||||
@ -115,7 +200,7 @@ Other Changes:
|
||||
(#2693, #2764, #2766, #2873, #3447, #3813, #3816) [@ocornut, @thedmd, @ShawnM427, @Ubpa, @aiekick]
|
||||
- Backends: DX9: Fix to support IMGUI_USE_BGRA_PACKED_COLOR. (#3844) [@Xiliusha]
|
||||
- Backends: DX9: Fix to support colored glyphs, using newly introduced 'TexPixelsUseColors' info. (#3844)
|
||||
- Examples: Android: Added Android + GL ES2 example. (#3446) [@duddel]
|
||||
- Examples: Android: Added Android + GL ES3 example. (#3446) [@duddel]
|
||||
- Examples: Reworked setup of clear color to be compatible with transparent values.
|
||||
- CI: Use a dedicated "scheduled" workflow to trigger scheduled builds. Forks may disable this workflow if
|
||||
scheduled builds builds are not required. [@rokups]
|
||||
@ -126,6 +211,8 @@ Other Changes:
|
||||
VERSION 1.81 (Released 2021-02-10)
|
||||
-----------------------------------------------------------------------
|
||||
|
||||
Decorated log: https://github.com/ocornut/imgui/releases/tag/v1.81
|
||||
|
||||
Breaking Changes:
|
||||
|
||||
- ListBox helpers:
|
||||
@ -315,6 +402,7 @@ Other Changes:
|
||||
- Examples: DirectX12: Move ImGui::Render() call above the first barrier to clarify its lack of effect on the graphics pipe.
|
||||
- CI: Fix testing for Windows DLL builds. (#3603, #3601) [@iboB]
|
||||
- Docs: Improved the wiki and added a https://github.com/ocornut/imgui/wiki/Useful-Widgets page. [@Xipiryon]
|
||||
[2021/05/20: moved to https://github.com/ocornut/imgui/wiki/Useful-Extensions]
|
||||
- Docs: Split examples/README.txt into docs/BACKENDS.md and docs/EXAMPLES.md, and improved them.
|
||||
- Docs: Consistently renamed all occurrences of "binding" and "back-end" to "backend" in comments and docs.
|
||||
|
||||
@ -341,7 +429,7 @@ Breaking Changes:
|
||||
- Renamed ImGuiSliderFlags_ClampOnInput to ImGuiSliderFlags_AlwaysClamp. Kept redirection enum (will obsolete).
|
||||
- Renamed OpenPopupContextItem() back to OpenPopupOnItemClick(), REVERTED CHANGE FROM 1.77.
|
||||
For variety of reason this is more self-explanatory and less error-prone. Kept inline redirection function.
|
||||
- Removed return value from OpenPopupOnItemClick() - returned true on mouse release on item - because it
|
||||
- Removed return value from OpenPopupOnItemClick() - returned true on mouse release on an item - because it
|
||||
is inconsistent with other popups API and makes others misleading. It's also and unnecessary: you can
|
||||
use IsWindowAppearing() after BeginPopup() for a similar result.
|
||||
|
||||
@ -1281,7 +1369,7 @@ Breaking Changes:
|
||||
|
||||
- Removed io.DisplayVisibleMin/DisplayVisibleMax (which were marked obsolete and removed from viewport/docking branch already).
|
||||
- Made it illegal/assert when io.DisplayTime == 0.0f (with an exception for the first frame).
|
||||
If for some reason your time step calculation gives you a zero value, replace it with a arbitrary small value!
|
||||
If for some reason your time step calculation gives you a zero value, replace it with a arbitrarily small value!
|
||||
|
||||
Other Changes:
|
||||
|
||||
|
@ -3,7 +3,11 @@ _(You may browse this at https://github.com/ocornut/imgui/blob/master/docs/EXAMP
|
||||
## Dear ImGui: Examples
|
||||
|
||||
**The [examples/](https://github.com/ocornut/imgui/blob/master/examples) folder example applications (standalone, ready-to-build) for variety of
|
||||
platforms and graphics APIs.** They all use standard backends from the [backends/](https://github.com/ocornut/imgui/blob/master/backends) folder.
|
||||
platforms and graphics APIs.** They all use standard backends from the [backends/](https://github.com/ocornut/imgui/blob/master/backends) folder (see [BACKENDS.md](https://github.com/ocornut/imgui/blob/master/docs/BACKENDS.md)).
|
||||
|
||||
The purpose of Examples is to showcase integration with backends, let you try Dear ImGui, and guide you toward
|
||||
integrating Dear ImGui in your own application/game/engine.
|
||||
**Once Dear ImGui is setup and running, run and refer to `ImGui::ShowDemoWindow()` in imgui_demo.cpp for usage of the end-user API.**
|
||||
|
||||
You can find Windows binaries for some of those example applications at:
|
||||
http://www.dearimgui.org/binaries
|
||||
|
31
docs/FAQ.md
31
docs/FAQ.md
@ -16,12 +16,12 @@ or view this file with any Markdown viewer.
|
||||
| [Which version should I get?](#q-which-version-should-i-get) |
|
||||
| **Q&A: Integration** |
|
||||
| **[How to get started?](#q-how-to-get-started)** |
|
||||
| **[How can I tell whether to dispatch mouse/keyboard to Dear ImGui or to my application?](#q-how-can-i-tell-whether-to-dispatch-mousekeyboard-to-dear-imgui-or-to-my-application)** |
|
||||
| **[How can I tell whether to dispatch mouse/keyboard to Dear ImGui or my application?](#q-how-can-i-tell-whether-to-dispatch-mousekeyboard-to-dear-imgui-or-my-application)** |
|
||||
| [How can I enable keyboard or gamepad controls?](#q-how-can-i-enable-keyboard-or-gamepad-controls) |
|
||||
| [How can I use this on a machine without mouse, keyboard or screen? (input share, remote display)](#q-how-can-i-use-this-on-a-machine-without-mouse-keyboard-or-screen-input-share-remote-display) |
|
||||
| [I integrated Dear ImGui in my engine and little squares are showing instead of text..](#q-i-integrated-dear-imgui-in-my-engine-and-little-squares-are-showing-instead-of-text) |
|
||||
| [I integrated Dear ImGui in my engine and some elements are clipping or disappearing when I move windows around..](#q-i-integrated-dear-imgui-in-my-engine-and-some-elements-are-clipping-or-disappearing-when-i-move-windows-around) |
|
||||
| [I integrated Dear ImGui in my engine and some elements are displaying outside their expected windows boundaries..](#q-i-integrated-dear-imgui-in-my-engine-and-some-elements-are-displaying-outside-their-expected-windows-boundaries) |
|
||||
| [I integrated Dear ImGui in my engine and little squares are showing instead of text...](#q-i-integrated-dear-imgui-in-my-engine-and-little-squares-are-showing-instead-of-text) |
|
||||
| [I integrated Dear ImGui in my engine and some elements are clipping or disappearing when I move windows around...](#q-i-integrated-dear-imgui-in-my-engine-and-some-elements-are-clipping-or-disappearing-when-i-move-windows-around) |
|
||||
| [I integrated Dear ImGui in my engine and some elements are displaying outside their expected windows boundaries...](#q-i-integrated-dear-imgui-in-my-engine-and-some-elements-are-displaying-outside-their-expected-windows-boundaries) |
|
||||
| **Q&A: Usage** |
|
||||
| **[Why is my widget not reacting when I click on it?<br>How can I have widgets with an empty label?<br>How can I have multiple widgets with the same label?](#q-why-is-my-widget-not-reacting-when-i-click-on-it)** |
|
||||
| [How can I display an image? What is ImTextureID, how does it work?](#q-how-can-i-display-an-image-what-is-imtextureid-how-does-it-work)|
|
||||
@ -47,7 +47,7 @@ or view this file with any Markdown viewer.
|
||||
|
||||
### Q: Where is the documentation?
|
||||
|
||||
**This library is poorly documented at the moment and expects of the user to be acquainted with C/C++.**
|
||||
**This library is poorly documented at the moment and expects the user to be acquainted with C/C++.**
|
||||
- The [Wiki](https://github.com/ocornut/imgui/wiki) is a hub to many resources and links.
|
||||
- Dozens of standalone example applications using e.g. OpenGL/DirectX are provided in the [examples/](https://github.com/ocornut/imgui/blob/master/examples/) folder to explain how to integrate Dear ImGui with your own engine/application. You can run those applications and explore them.
|
||||
- See demo code in [imgui_demo.cpp](https://github.com/ocornut/imgui/blob/master/imgui_demo.cpp) and particularly the `ImGui::ShowDemoWindow()` function. The demo covers most features of Dear ImGui, so you can read the code and see its output.
|
||||
@ -55,7 +55,7 @@ or view this file with any Markdown viewer.
|
||||
- See documentation and comments at the top of [imgui.cpp](https://github.com/ocornut/imgui/blob/master/imgui.cpp) + general API comments in [imgui.h](https://github.com/ocornut/imgui/blob/master/imgui.h).
|
||||
- The [Glossary](https://github.com/ocornut/imgui/wiki/Glossary) page may be useful.
|
||||
- The [Issues](https://github.com/ocornut/imgui/issues) and [Discussions](https://github.com/ocornut/imgui/discussions) sections can be searched for past questions and issues.
|
||||
- Your programming IDE is your friend, find the type or function declaration to find comments associated to it.
|
||||
- Your programming IDE is your friend, find the type or function declaration to find comments associated with it.
|
||||
- The `ImGui::ShowMetricsWindow()` function exposes lots of internal information and tools. Although it is primary designed as a debugging tool, having access to that information tends to help understands concepts.
|
||||
|
||||
##### [Return to Index](#index)
|
||||
@ -81,9 +81,6 @@ You may use the [docking](https://github.com/ocornut/imgui/tree/docking) branch
|
||||
|
||||
Many projects are using this branch and it is kept in sync with master regularly.
|
||||
|
||||
You may merge in the [tables](https://github.com/ocornut/imgui/tree/tables) branch which includes:
|
||||
- [Table features](https://github.com/ocornut/imgui/issues/2957)
|
||||
|
||||
##### [Return to Index](#index)
|
||||
|
||||
----
|
||||
@ -101,7 +98,7 @@ The [Wiki](https://github.com/ocornut/imgui/wiki) is a hub to many resources and
|
||||
|
||||
---
|
||||
|
||||
### Q: How can I tell whether to dispatch mouse/keyboard to Dear ImGui or to my application?
|
||||
### Q: How can I tell whether to dispatch mouse/keyboard to Dear ImGui or my application?
|
||||
|
||||
You can read the `io.WantCaptureMouse`, `io.WantCaptureKeyboard` and `io.WantTextInput` flags from the ImGuiIO structure.
|
||||
- When `io.WantCaptureMouse` is set, you need to discard/hide the mouse inputs from your underlying application.
|
||||
@ -116,7 +113,7 @@ void MyLowLevelMouseButtonHandler(int button, bool down)
|
||||
// (1) ALWAYS forward mouse data to ImGui! This is automatic with default backends. With your own backend:
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
io.MouseDown[button] = down;
|
||||
|
||||
|
||||
// (2) ONLY forward mouse data to your underlying app/game.
|
||||
if (!io.WantCaptureMouse)
|
||||
my_game->HandleMouseData(...);
|
||||
@ -162,7 +159,7 @@ Console SDK also sometimes provide equivalent tooling or wrapper for Synergy-lik
|
||||
|
||||
---
|
||||
|
||||
### Q: I integrated Dear ImGui in my engine and little squares are showing instead of text..
|
||||
### Q: I integrated Dear ImGui in my engine and little squares are showing instead of text...
|
||||
This usually means that: your font texture wasn't uploaded into GPU, or your shader or other rendering state are not reading from the right texture (e.g. texture wasn't bound).
|
||||
If this happens using the standard backends it is probably that the texture failed to upload, which could happens if for some reason your texture is too big. Also see [docs/FONTS.md](https://github.com/ocornut/imgui/blob/master/docs/FONTS.md).
|
||||
|
||||
@ -170,8 +167,8 @@ If this happens using the standard backends it is probably that the texture fail
|
||||
|
||||
---
|
||||
|
||||
### Q: I integrated Dear ImGui in my engine and some elements are clipping or disappearing when I move windows around..
|
||||
### Q: I integrated Dear ImGui in my engine and some elements are displaying outside their expected windows boundaries..
|
||||
### Q: I integrated Dear ImGui in my engine and some elements are clipping or disappearing when I move windows around...
|
||||
### Q: I integrated Dear ImGui in my engine and some elements are displaying outside their expected windows boundaries...
|
||||
You are probably mishandling the clipping rectangles in your render function.
|
||||
Each draw command needs the triangle rendered using the clipping rectangle provided in the ImDrawCmd structure (`ImDrawCmd->CllipRect`).
|
||||
Rectangles provided by Dear ImGui are defined as
|
||||
@ -373,7 +370,7 @@ ImGui::Image((void*)texture, ImVec2(texture->Width, texture->Height));
|
||||
The renderer function called after ImGui::Render() will receive that same value that the user code passed:
|
||||
```cpp
|
||||
// Cast ImTextureID / void* stored in the draw command as our texture type
|
||||
MyTexture* texture = (MyTexture*)pcmd->TextureId;
|
||||
MyTexture* texture = (MyTexture*)pcmd->GetTexID();
|
||||
MyEngineBindTexture2D(texture);
|
||||
```
|
||||
Once you understand this design you will understand that loading image files and turning them into displayable textures is not within the scope of Dear ImGui.
|
||||
@ -654,11 +651,11 @@ There is an auto-generated [c-api for Dear ImGui (cimgui)](https://github.com/ci
|
||||
# Q&A: Community
|
||||
|
||||
### Q: How can I help?
|
||||
- Businesses: please reach out to `contact AT dearimgui.com` if you work in a place using Dear ImGui! We can discuss ways for your company to fund development via invoiced technical support, maintenance or sponsoring contacts. This is among the most useful thing you can do for Dear ImGui. With increased funding we can hire more people working on this project.
|
||||
- Businesses: please reach out to `contact AT dearimgui.com` if you work in a place using Dear ImGui! We can discuss ways for your company to fund development via invoiced technical support, maintenance or sponsoring contacts. This is among the most useful thing you can do for Dear ImGui. With increased funding, we can hire more people working on this project.
|
||||
- Individuals: you can support continued maintenance and development via PayPal donations. See [README](https://github.com/ocornut/imgui/blob/master/docs/README.md).
|
||||
- If you are experienced with Dear ImGui and C++, look at [GitHub Issues](https://github.com/ocornut/imgui/issues), [GitHub Discussions](https://github.com/ocornut/imgui/discussions), the [Wiki](https://github.com/ocornut/imgui/wiki), read [docs/TODO.txt](https://github.com/ocornut/imgui/blob/master/docs/TODO.txt) and see how you want to help and can help!
|
||||
- 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](https://github.com/ocornut/imgui/issues/3488). Visuals are ideal as they inspire other programmers. Disclosing your use of dear imgui help the library grow credibility, and help other teams and programmers with taking decisions.
|
||||
You may post screenshot or links in the [gallery threads](https://github.com/ocornut/imgui/issues/3488). Visuals are ideal as they inspire other programmers. Disclosing your use of Dear ImGui helps 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 or sometimes incomplete PR.
|
||||
|
||||
##### [Return to Index](#index)
|
||||
|
@ -5,7 +5,7 @@ _(You may browse this at https://github.com/ocornut/imgui/blob/master/docs/FONTS
|
||||
The code in imgui.cpp embeds a copy of 'ProggyClean.ttf' (by Tristan Grimmer),
|
||||
a 13 pixels high, pixel-perfect font used by default. We embed it in the source code so you can use Dear ImGui without any file system access. ProggyClean does not scale smoothly, therefore it is recommended that you load your own file when using Dear ImGui in an application aiming to look nice and wanting to support multiple resolutions.
|
||||
|
||||
You may also load external .TTF/.OTF files.
|
||||
You may also load external .TTF/.OTF files.
|
||||
In the [misc/fonts/](https://github.com/ocornut/imgui/tree/master/misc/fonts) folder you can find a few suggested fonts, provided as a convenience.
|
||||
|
||||
**Also read the FAQ:** https://www.dearimgui.org/faq (there is a Fonts section!)
|
||||
@ -14,8 +14,9 @@ In the [misc/fonts/](https://github.com/ocornut/imgui/tree/master/misc/fonts) fo
|
||||
- [Readme First](#readme-first)
|
||||
- [How should I handle DPI in my application?](#how-should-i-handle-dpi-in-my-application)
|
||||
- [Fonts Loading Instructions](#font-loading-instructions)
|
||||
- [Using Icons](#using-icons)
|
||||
- [Using FreeType Rasterizer](#using-freetype-rasterizer)
|
||||
- [Using Icon Fonts](#using-icon-fonts)
|
||||
- [Using FreeType Rasterizer (imgui_freetype)](#using-freetype-rasterizer-imgui_freetype)
|
||||
- [Using Colorful Glyphs/Emojis](#using-colorful-glyphsemojis)
|
||||
- [Using Custom Glyph Ranges](#using-custom-glyph-ranges)
|
||||
- [Using Custom Colorful Icons](#using-custom-colorful-icons)
|
||||
- [Using Font Data Embedded In Source Code](#using-font-data-embedded-in-source-code)
|
||||
@ -26,7 +27,7 @@ In the [misc/fonts/](https://github.com/ocornut/imgui/tree/master/misc/fonts) fo
|
||||
---------------------------------------
|
||||
## Readme First
|
||||
|
||||
- All loaded fonts glyphs are rendered into a single texture atlas ahead of time. Calling either of `io.Fonts->GetTexDataAsAlpha8()`, `io.Fonts->GetTexDataAsRGBA32()` or `io.Fonts->Build()` will build the atlas.
|
||||
- All loaded fonts glyphs are rendered into a single texture atlas ahead of time. Calling either of `io.Fonts->GetTexDataAsAlpha8()`, `io.Fonts->GetTexDataAsRGBA32()` or `io.Fonts->Build()` will build the atlas.
|
||||
|
||||
- You can use the style editor `ImGui::ShowStyleEditor()` in the "Fonts" section to browse your fonts and understand what's going on if you have an issue. You can also reach it in `Demo->Tools->Style Editor->Fonts`:
|
||||
|
||||
@ -160,13 +161,13 @@ Some solutions:
|
||||
|
||||
##### [Return to Index](#index)
|
||||
|
||||
## Using Icons
|
||||
## Using Icon Fonts
|
||||
|
||||
Using an icon font (such as [FontAwesome](http://fontawesome.io) or [OpenFontIcons](https://github.com/traverseda/OpenFontIcons)) is an easy and practical way to use icons in your Dear ImGui application.
|
||||
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.
|
||||
|
||||
|
||||
So you can use `ICON_FA_SEARCH` as a string that will render as a "Search" icon.
|
||||
|
||||
Example Setup:
|
||||
@ -197,7 +198,7 @@ Here's an application using icons ("Avoyd", https://www.avoyd.com):
|
||||
|
||||
##### [Return to Index](#index)
|
||||
|
||||
## Using FreeType Rasterizer
|
||||
## Using FreeType Rasterizer (imgui_freetype)
|
||||
|
||||
- Dear ImGui uses imstb\_truetype.h to rasterize fonts (with optional oversampling). This technique and its implementation are not ideal for fonts rendered at small sizes, which may appear a little blurry or hard to read.
|
||||
- There is an implementation of the ImFontAtlas builder using FreeType that you can use in the [misc/freetype/](https://github.com/ocornut/imgui/tree/master/misc/freetype) folder.
|
||||
@ -207,6 +208,28 @@ Here's an application using icons ("Avoyd", https://www.avoyd.com):
|
||||
|
||||
##### [Return to Index](#index)
|
||||
|
||||
## Using Colorful Glyphs/Emojis
|
||||
|
||||
- Rendering of colored emojis is only supported by imgui_freetype with FreeType 2.10+.
|
||||
- You will need to load fonts with the `ImGuiFreeTypeBuilderFlags_LoadColor` flag.
|
||||
- Emojis are frequently encoded in upper Unicode layers (character codes >0x10000) and will need dear imgui compiled with `IMGUI_USE_WCHAR32`.
|
||||
- Not all types of color fonts are supported by FreeType at the moment.
|
||||
- Stateful Unicode features such as skin tone modifiers are not supported by the text renderer.
|
||||
|
||||

|
||||
|
||||
```cpp
|
||||
io.Fonts->AddFontFromFileTTF("../../../imgui_dev/data/fonts/NotoSans-Regular.ttf", 16.0f);
|
||||
static ImWchar ranges[] = { 0x1, 0x1FFFF, 0 };
|
||||
static ImFontConfig cfg;
|
||||
cfg.OversampleH = cfg.OversampleV = 1;
|
||||
cfg.MergeMode = true;
|
||||
cfg.FontBuilderFlags |= ImGuiFreeTypeBuilderFlags_LoadColor;
|
||||
io.Fonts->AddFontFromFileTTF("C:\\Windows\\Fonts\\seguiemj.ttf", 16.0f, &cfg, ranges);
|
||||
```
|
||||
|
||||
##### [Return to Index](#index)
|
||||
|
||||
## Using Custom Glyph Ranges
|
||||
|
||||
You can use the `ImFontGlyphRangesBuilder` helper to create glyph ranges based on text input. For example: 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.
|
||||
@ -226,7 +249,7 @@ io.Fonts->Build(); // Build the atlas while
|
||||
|
||||
## Using Custom Colorful Icons
|
||||
|
||||
**(This is a BETA api, use if you are familiar with dear imgui and with your rendering backend)**
|
||||
As an alternative to rendering colorful glyphs using imgui_freetype with `ImGuiFreeTypeBuilderFlags_LoadColor`, you may allocate your own space in the texture atlas and write yourself into it. **(This is a BETA api, use if you are familiar with dear imgui and with your rendering backend)**
|
||||
|
||||
- You can use the `ImFontAtlas::AddCustomRect()` and `ImFontAtlas::AddCustomRectFontGlyph()` api to register rectangles that will be packed into the font atlas texture. Register them before building the atlas, then call Build()`.
|
||||
- You can then use `ImFontAtlas::GetCustomRectByIndex(int)` to query the position/size of your rectangle within the texture, and blit/copy any graphics data of your choice into those rectangles.
|
||||
@ -315,7 +338,7 @@ Some fonts files are available in the `misc/fonts/` folder:
|
||||
<br>https://fonts.google.com/specimen/Roboto
|
||||
|
||||
**Cousine-Regular.ttf**, by Steve Matteson
|
||||
<br>Digitized data copyright (c) 2010 Google Corporation.
|
||||
<br>Digitized data copyright (c) 2010 Google Corporation.
|
||||
<br>Licensed under the SIL Open Font License, Version 1.1
|
||||
<br>https://fonts.google.com/specimen/Cousine
|
||||
|
||||
|
@ -105,7 +105,7 @@ Calling the `ImGui::ShowDemoWindow()` function will create a demo window showcas
|
||||

|
||||
|
||||
You should be able to build the examples from sources (tested on Windows/Mac/Linux). If you don't, let us 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-20200918.zip](https://www.dearimgui.org/binaries/imgui-demo-binaries-20200918.zip) (Windows, 1.78 WIP, built 2020/09/18, master branch) or [older demo binaries](https://www.dearimgui.org/binaries).
|
||||
- [imgui-demo-binaries-20210331.zip](https://www.dearimgui.org/binaries/imgui-demo-binaries-20210331.zip) (Windows, 1.83 WIP, built 2021/03/31, master branch) or [older demo binaries](https://www.dearimgui.org/binaries).
|
||||
|
||||
The demo applications are not DPI aware so expect some blurriness on a 4K screen. For DPI awareness in your application, you can load/reload your font at different scale, and scale your style with `style.ScaleAllSizes()` (see [FAQ](https://www.dearimgui.org/faq)).
|
||||
|
||||
@ -125,7 +125,7 @@ Officially maintained backends/bindings (in repository):
|
||||
- Frameworks: AGS/Adventure Game Studio, Amethyst, Blender, bsf, Cinder, Cocos2d-x, Diligent Engine, Flexium, GML/Game Maker Studio2, GLEQ, Godot, GTK3+OpenGL3, Irrlicht Engine, LÖVE+LUA, Magnum, Monogame, NanoRT, nCine, Nim Game Lib, Nintendo 3DS & Switch (homebrew), Ogre, openFrameworks, OSG/OpenSceneGraph, Orx, Photoshop, px_render, Qt/QtDirect3D, SDL_Renderer, SFML, Sokol, Unity, Unreal Engine 4, vtk, VulkanHpp, VulkanSceneGraph, Win32 GDI, WxWidgets.
|
||||
- Note that C bindings ([cimgui](https://github.com/cimgui/cimgui)) are auto-generated, you can use its json/lua output to generate bindings for other languages.
|
||||
|
||||
[Useful widgets and extensions](https://github.com/ocornut/imgui/wiki/Useful-Widgets) wiki page:
|
||||
[Useful Extensions/Widgets](https://github.com/ocornut/imgui/wiki/Useful-Extensions) wiki page:
|
||||
- Text editors, node editors, timeline editors, plotting, software renderers, remote network access, memory editors, gizmos etc.
|
||||
|
||||
Also see [Wiki](https://github.com/ocornut/imgui/wiki) for more links and ideas.
|
||||
@ -143,7 +143,7 @@ Some of the goals for 2021 are:
|
||||
|
||||
For more user-submitted screenshots of projects using Dear ImGui, check out the [Gallery Threads](https://github.com/ocornut/imgui/issues/3488)!
|
||||
|
||||
For a list of third-party widgets and extensions, check out the [Useful Widgets](https://github.com/ocornut/imgui/wiki/Useful-Widgets) wiki page.
|
||||
For a list of third-party widgets and extensions, check out the [Useful Extensions/Widgets](https://github.com/ocornut/imgui/wiki/Useful-Extensions) wiki page.
|
||||
|
||||
Custom engine
|
||||
[](https://cloud.githubusercontent.com/assets/8225057/20628927/33e14cac-b329-11e6-80f6-9524e93b048a.png)
|
||||
@ -196,13 +196,13 @@ Sponsors
|
||||
Ongoing Dear ImGui development is currently financially supported by users and private sponsors:
|
||||
|
||||
*Platinum-chocolate sponsors*
|
||||
- [Blizzard](https://careers.blizzard.com/en-us/openings/engineering/all/all/all/1), [Google](https://github.com/google/filament), [Nvidia](https://developer.nvidia.com/nvidia-omniverse), [Ubisoft](https://montreal.ubisoft.com/en/ubisoft-sponsors-user-interface-library-for-c-dear-imgui/)
|
||||
- [Blizzard](https://careers.blizzard.com/en-us/openings/engineering/all/all/all/1), [Google](https://github.com/google/filament), [Nvidia](https://developer.nvidia.com/nvidia-omniverse)
|
||||
|
||||
*Double-chocolate and Salty caramel sponsors*
|
||||
- [Activision](https://careers.activision.com/c/programmingsoftware-engineering-jobs), [Aras Pranckevičius](https://aras-p.info), [Arkane Studios](https://www.arkane-studios.com), [Framefield](http://framefield.com), [Grinding Gear Games](https://www.grindinggear.com), [Kylotonn](https://www.kylotonn.com), [Next Level Games](https://www.nextlevelgames.com), [RAD Game Tools](http://www.radgametools.com/), [Supercell](http://www.supercell.com)
|
||||
- [Activision](https://careers.activision.com/c/programmingsoftware-engineering-jobs), [Aras Pranckevičius](https://aras-p.info), [Arkane Studios](https://www.arkane-studios.com), [Framefield](http://framefield.com), [Grinding Gear Games](https://www.grindinggear.com), [Kylotonn](https://www.kylotonn.com), [Next Level Games](https://www.nextlevelgames.com), [RAD Game Tools](http://www.radgametools.com/), [O-Net Communications (USA)](http://en.o-netcom.com), [Supercell](https://supercell.com), [Ubisoft](https://montreal.ubisoft.com/en/ubisoft-sponsors-user-interface-library-for-c-dear-imgui)
|
||||
|
||||
Please see [detailed list of Dear ImGui supporters](https://github.com/ocornut/imgui/wiki/Sponsors) for past sponsors.
|
||||
From November 2014 to December 2019, ongoing development has also been financially supported by its users on Patreon and through individual donations.
|
||||
From November 2014 to December 2019, ongoing development has also been financially supported by its users on Patreon and through individual donations.
|
||||
|
||||
**THANK YOU to all past and present supporters for helping to keep this project alive and thriving!**
|
||||
|
||||
@ -214,12 +214,14 @@ Dear ImGui is using software and services provided free of charge for open sourc
|
||||
Credits
|
||||
-------
|
||||
|
||||
Developed by [Omar Cornut](http://www.miracleworld.net) and every direct or indirect [contributors](https://github.com/ocornut/imgui/graphs/contributors) to the GitHub. The early version of this library was developed with the support of [Media Molecule](http://www.mediamolecule.com) and first used internally on the game [Tearaway](http://tearaway.mediamolecule.com) (PS Vita).
|
||||
Developed by [Omar Cornut](https://www.miracleworld.net) and every direct or indirect [contributors](https://github.com/ocornut/imgui/graphs/contributors) to the GitHub. The early version of this library was developed with the support of [Media Molecule](https://www.mediamolecule.com) and first used internally on the game [Tearaway](https://tearaway.mediamolecule.com) (PS Vita).
|
||||
|
||||
Recurring contributors (2020): Omar Cornut [@ocornut](https://github.com/ocornut), Rokas Kupstys [@rokups](https://github.com/rokups), Ben Carter [@ShironekoBen](https://github.com/ShironekoBen).
|
||||
A large portion of work on automation systems, regression tests and other features are currently unpublished.
|
||||
|
||||
Omar: "I first discovered the IMGUI paradigm at [Q-Games](http://www.q-games.com) where Atman Binstock had dropped his own simple implementation in the codebase, which I spent quite some time improving and thinking about. It turned out that Atman was exposed to the concept directly by working with Casey. When I moved to Media Molecule I rewrote a new library trying to overcome the flaws and limitations of the first one I've worked with. It became this library and since then I have spent an unreasonable amount of time iterating and improving it."
|
||||
Sponsoring, support contracts and other B2B transactions are hosted and handled by [Lizardcube](https://www.lizardcube.com).
|
||||
|
||||
Omar: "I first discovered the IMGUI paradigm at [Q-Games](https://www.q-games.com) where Atman Binstock had dropped his own simple implementation in the codebase, which I spent quite some time improving and thinking about. It turned out that Atman was exposed to the concept directly by working with Casey. When I moved to Media Molecule I rewrote a new library trying to overcome the flaws and limitations of the first one I've worked with. It became this library and since then I have spent an unreasonable amount of time iterating and improving it."
|
||||
|
||||
Embeds [ProggyClean.ttf](http://upperbounds.net) font by Tristan Grimmer (MIT license).
|
||||
|
||||
|
@ -352,7 +352,7 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i
|
||||
- nav/windowing: Resizing window will currently fail with certain types of resizing constraints/callback applied
|
||||
- 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)
|
||||
- focus: unable to use SetKeyboardFocusHere() on clipped widgets. (#787, #343)
|
||||
|
||||
- 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)
|
||||
|
@ -1 +1,7 @@
|
||||
See EXAMPLES and BACKENDS files in the docs/ folder.
|
||||
See BACKENDS and EXAMPLES files in the docs/ folder.
|
||||
|
||||
Backends = Helper code to facilitate integration with platforms/graphics api (used by Examples + should be used by your app).
|
||||
Examples = Standalone applications showcasing integration with platforms/graphics api.
|
||||
|
||||
Once Dear ImGui is running (in either examples or your own application/game/engine),
|
||||
run and refer to ImGui::ShowDemoWindow() in imgui_demo.cpp for the end-user API.
|
||||
|
@ -1,12 +1,12 @@
|
||||
buildscript {
|
||||
ext.kotlin_version = '1.4.30'
|
||||
ext.kotlin_version = '1.4.31'
|
||||
repositories {
|
||||
google()
|
||||
jcenter()
|
||||
mavenCentral()
|
||||
|
||||
}
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:4.0.1'
|
||||
classpath 'com.android.tools.build:gradle:4.1.0'
|
||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
||||
|
||||
}
|
||||
@ -15,7 +15,7 @@ buildscript {
|
||||
allprojects {
|
||||
repositories {
|
||||
google()
|
||||
jcenter()
|
||||
mavenCentral()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -147,7 +147,7 @@ static void main_loop(void* window)
|
||||
wgpu_swap_chain_height = height;
|
||||
|
||||
WGPUSwapChainDescriptor swap_chain_desc = {};
|
||||
swap_chain_desc.usage = WGPUTextureUsage_OutputAttachment;
|
||||
swap_chain_desc.usage = WGPUTextureUsage_RenderAttachment;
|
||||
swap_chain_desc.format = WGPUTextureFormat_RGBA8Unorm;
|
||||
swap_chain_desc.width = width;
|
||||
swap_chain_desc.height = height;
|
||||
@ -202,11 +202,11 @@ static void main_loop(void* window)
|
||||
// Rendering
|
||||
ImGui::Render();
|
||||
|
||||
WGPURenderPassColorAttachmentDescriptor color_attachments = {};
|
||||
WGPURenderPassColorAttachment color_attachments = {};
|
||||
color_attachments.loadOp = WGPULoadOp_Clear;
|
||||
color_attachments.storeOp = WGPUStoreOp_Store;
|
||||
color_attachments.clearColor = { clear_color.x * clear_color.w, clear_color.y * clear_color.w, clear_color.z * clear_color.w, clear_color.w };
|
||||
color_attachments.attachment = wgpuSwapChainGetCurrentTextureView(wgpu_swap_chain);
|
||||
color_attachments.view = wgpuSwapChainGetCurrentTextureView(wgpu_swap_chain);
|
||||
WGPURenderPassDescriptor render_pass_desc = {};
|
||||
render_pass_desc.colorAttachmentCount = 1;
|
||||
render_pass_desc.colorAttachments = &color_attachments;
|
||||
@ -221,7 +221,7 @@ static void main_loop(void* window)
|
||||
|
||||
WGPUCommandBufferDescriptor cmd_buffer_desc = {};
|
||||
WGPUCommandBuffer cmd_buffer = wgpuCommandEncoderFinish(encoder, &cmd_buffer_desc);
|
||||
WGPUQueue queue = wgpuDeviceGetDefaultQueue(wgpu_device);
|
||||
WGPUQueue queue = wgpuDeviceGetQueue(wgpu_device);
|
||||
wgpuQueueSubmit(queue, 1, &cmd_buffer);
|
||||
}
|
||||
|
||||
|
@ -14,9 +14,10 @@ SOURCES += $(IMGUI_DIR)/backends/imgui_impl_glfw.cpp $(IMGUI_DIR)/backends/imgui
|
||||
OBJS = $(addsuffix .o, $(basename $(notdir $(SOURCES))))
|
||||
|
||||
LIBS = -framework Metal -framework MetalKit -framework Cocoa -framework IOKit -framework CoreVideo -framework QuartzCore
|
||||
LIBS += -L/usr/local/lib -lglfw
|
||||
LIBS += -L/usr/local/lib -L/opt/homebrew/lib
|
||||
LIBS += -lglfw
|
||||
|
||||
CXXFLAGS = -I$(IMGUI_DIR) -I$(IMGUI_DIR)/backends -I/usr/local/include
|
||||
CXXFLAGS = -I$(IMGUI_DIR) -I$(IMGUI_DIR)/backends -I/usr/local/include -I/opt/homebrew/include
|
||||
CXXFLAGS += -Wall -Wformat
|
||||
CFLAGS = $(CXXFLAGS)
|
||||
|
||||
|
@ -41,11 +41,11 @@ endif
|
||||
ifeq ($(UNAME_S), Darwin) #APPLE
|
||||
ECHO_MESSAGE = "Mac OS X"
|
||||
LIBS += -framework OpenGL -framework Cocoa -framework IOKit -framework CoreVideo
|
||||
LIBS += -L/usr/local/lib -L/opt/local/lib
|
||||
LIBS += -L/usr/local/lib -L/opt/local/lib -L/opt/homebrew/lib
|
||||
#LIBS += -lglfw3
|
||||
LIBS += -lglfw
|
||||
|
||||
CXXFLAGS += -I/usr/local/include -I/opt/local/include
|
||||
CXXFLAGS += -I/usr/local/include -I/opt/local/include -I/opt/homebrew/include
|
||||
CFLAGS = $(CXXFLAGS)
|
||||
endif
|
||||
|
||||
|
@ -21,15 +21,19 @@ SOURCES += $(IMGUI_DIR)/imgui.cpp $(IMGUI_DIR)/imgui_demo.cpp $(IMGUI_DIR)/imgui
|
||||
SOURCES += $(IMGUI_DIR)/backends/imgui_impl_glfw.cpp $(IMGUI_DIR)/backends/imgui_impl_opengl3.cpp
|
||||
OBJS = $(addsuffix .o, $(basename $(notdir $(SOURCES))))
|
||||
UNAME_S := $(shell uname -s)
|
||||
LINUX_GL_LIBS = -lGL
|
||||
|
||||
CXXFLAGS = -I$(IMGUI_DIR) -I$(IMGUI_DIR)/backends
|
||||
CXXFLAGS += -g -Wall -Wformat
|
||||
LIBS =
|
||||
|
||||
##---------------------------------------------------------------------
|
||||
## OPENGL LOADER
|
||||
## OPENGL LOADER / OPENGL ES
|
||||
##---------------------------------------------------------------------
|
||||
|
||||
## See below for OpenGL ES option (no loader required) - comment out
|
||||
## the following if you want to use OpenGL ES instead of Desktop GL.
|
||||
|
||||
## Using OpenGL loader: gl3w [default]
|
||||
SOURCES += ../libs/gl3w/GL/gl3w.c
|
||||
CXXFLAGS += -I../libs/gl3w -DIMGUI_IMPL_OPENGL_LOADER_GL3W
|
||||
@ -56,13 +60,18 @@ CXXFLAGS += -I../libs/gl3w -DIMGUI_IMPL_OPENGL_LOADER_GL3W
|
||||
# CXXFLAGS += -DIMGUI_IMPL_OPENGL_LOADER_GLBINDING2
|
||||
# LIBS += -lglbinding
|
||||
|
||||
## Using OpenGL ES, no loader required
|
||||
## This assumes a GL ES library available in the system, e.g. libGLESv2.so
|
||||
# CXXFLAGS += -DIMGUI_IMPL_OPENGL_ES2
|
||||
# LINUX_GL_LIBS = -lGLESv2
|
||||
|
||||
##---------------------------------------------------------------------
|
||||
## BUILD FLAGS PER PLATFORM
|
||||
##---------------------------------------------------------------------
|
||||
|
||||
ifeq ($(UNAME_S), Linux) #LINUX
|
||||
ECHO_MESSAGE = "Linux"
|
||||
LIBS += -lGL `pkg-config --static --libs glfw3`
|
||||
LIBS += $(LINUX_GL_LIBS) `pkg-config --static --libs glfw3`
|
||||
|
||||
CXXFLAGS += `pkg-config --cflags glfw3`
|
||||
CFLAGS = $(CXXFLAGS)
|
||||
@ -71,11 +80,11 @@ endif
|
||||
ifeq ($(UNAME_S), Darwin) #APPLE
|
||||
ECHO_MESSAGE = "Mac OS X"
|
||||
LIBS += -framework OpenGL -framework Cocoa -framework IOKit -framework CoreVideo
|
||||
LIBS += -L/usr/local/lib -L/opt/local/lib
|
||||
LIBS += -L/usr/local/lib -L/opt/local/lib -L/opt/homebrew/lib
|
||||
#LIBS += -lglfw3
|
||||
LIBS += -lglfw
|
||||
|
||||
CXXFLAGS += -I/usr/local/include -I/opt/local/include
|
||||
CXXFLAGS += -I/usr/local/include -I/opt/local/include -I/opt/homebrew/include
|
||||
CFLAGS = $(CXXFLAGS)
|
||||
endif
|
||||
|
||||
|
@ -8,11 +8,13 @@
|
||||
#include "imgui_impl_opengl3.h"
|
||||
#include <stdio.h>
|
||||
|
||||
#if defined(IMGUI_IMPL_OPENGL_ES2)
|
||||
#include <GLES2/gl2.h>
|
||||
// About Desktop OpenGL function loaders:
|
||||
// Modern desktop OpenGL doesn't have a standard portable header file to load OpenGL function pointers.
|
||||
// Helper libraries are often used for this purpose! Here we are supporting a few common ones (gl3w, glew, glad).
|
||||
// You may use another loader/header of your choice (glext, glLoadGen, etc.), or chose to manually implement your own.
|
||||
#if defined(IMGUI_IMPL_OPENGL_LOADER_GL3W)
|
||||
#elif defined(IMGUI_IMPL_OPENGL_LOADER_GL3W)
|
||||
#include <GL/gl3w.h> // Initialize with gl3wInit()
|
||||
#elif defined(IMGUI_IMPL_OPENGL_LOADER_GLEW)
|
||||
#include <GL/glew.h> // Initialize with glewInit()
|
||||
@ -57,7 +59,13 @@ int main(int, char**)
|
||||
return 1;
|
||||
|
||||
// Decide GL+GLSL versions
|
||||
#ifdef __APPLE__
|
||||
#if defined(IMGUI_IMPL_OPENGL_ES2)
|
||||
// GL ES 2.0 + GLSL 100
|
||||
const char* glsl_version = "#version 100";
|
||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 2);
|
||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0);
|
||||
glfwWindowHint(GLFW_CLIENT_API, GLFW_OPENGL_ES_API);
|
||||
#elif defined(__APPLE__)
|
||||
// GL 3.2 + GLSL 150
|
||||
const char* glsl_version = "#version 150";
|
||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
|
||||
|
@ -122,10 +122,22 @@ static void SetupVulkan(const char** extensions, uint32_t extensions_count)
|
||||
err = vkEnumeratePhysicalDevices(g_Instance, &gpu_count, gpus);
|
||||
check_vk_result(err);
|
||||
|
||||
// If a number >1 of GPUs got reported, you should find the best fit GPU for your purpose
|
||||
// e.g. VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU if available, or with the greatest memory available, etc.
|
||||
// for sake of simplicity we'll just take the first one, assuming it has a graphics queue family.
|
||||
g_PhysicalDevice = gpus[0];
|
||||
// If a number >1 of GPUs got reported, find discrete GPU if present, or use first one available. This covers
|
||||
// most common cases (multi-gpu/integrated+dedicated graphics). Handling more complicated setups (multiple
|
||||
// dedicated GPUs) is out of scope of this sample.
|
||||
int use_gpu = 0;
|
||||
for (int i = 0; i < (int)gpu_count; i++)
|
||||
{
|
||||
VkPhysicalDeviceProperties properties;
|
||||
vkGetPhysicalDeviceProperties(gpus[i], &properties);
|
||||
if (properties.deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU)
|
||||
{
|
||||
use_gpu = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
g_PhysicalDevice = gpus[use_gpu];
|
||||
free(gpus);
|
||||
}
|
||||
|
||||
@ -253,7 +265,7 @@ static void FrameRender(ImGui_ImplVulkanH_Window* wd, ImDrawData* draw_data)
|
||||
VkSemaphore image_acquired_semaphore = wd->FrameSemaphores[wd->SemaphoreIndex].ImageAcquiredSemaphore;
|
||||
VkSemaphore render_complete_semaphore = wd->FrameSemaphores[wd->SemaphoreIndex].RenderCompleteSemaphore;
|
||||
err = vkAcquireNextImageKHR(g_Device, wd->Swapchain, UINT64_MAX, image_acquired_semaphore, VK_NULL_HANDLE, &wd->FrameIndex);
|
||||
if (err == VK_ERROR_OUT_OF_DATE_KHR)
|
||||
if (err == VK_ERROR_OUT_OF_DATE_KHR || err == VK_SUBOPTIMAL_KHR)
|
||||
{
|
||||
g_SwapChainRebuild = true;
|
||||
return;
|
||||
@ -326,7 +338,7 @@ static void FramePresent(ImGui_ImplVulkanH_Window* wd)
|
||||
info.pSwapchains = &wd->Swapchain;
|
||||
info.pImageIndices = &wd->FrameIndex;
|
||||
VkResult err = vkQueuePresentKHR(g_Queue, &info);
|
||||
if (err == VK_ERROR_OUT_OF_DATE_KHR)
|
||||
if (err == VK_ERROR_OUT_OF_DATE_KHR || err == VK_SUBOPTIMAL_KHR)
|
||||
{
|
||||
g_SwapChainRebuild = true;
|
||||
return;
|
||||
|
@ -3,6 +3,6 @@
|
||||
@set OUT_EXE=example_sdl_directx11
|
||||
@set INCLUDES=/I..\.. /I..\..\backends /I%SDL2_DIR%\include /I "%WindowsSdkDir%Include\um" /I "%WindowsSdkDir%Include\shared" /I "%DXSDK_DIR%Include"
|
||||
@set SOURCES=main.cpp ..\..\backends\imgui_impl_sdl.cpp ..\..\backends\imgui_impl_dx11.cpp ..\..\imgui*.cpp
|
||||
@set LIBS=/LIBPATH:%SDL2_DIR%\lib\x86 SDL2.lib SDL2main.lib /LIBPATH:"%DXSDK_DIR%/Lib/x86" d3d11.lib d3dcompiler.lib
|
||||
@set LIBS=/LIBPATH:%SDL2_DIR%\lib\x86 SDL2.lib SDL2main.lib /LIBPATH:"%DXSDK_DIR%/Lib/x86" d3d11.lib d3dcompiler.lib shell32.lib
|
||||
mkdir %OUT_DIR%
|
||||
cl /nologo /Zi /MD %INCLUDES% %SOURCES% /Fe%OUT_DIR%/%OUT_EXE%.exe /Fo%OUT_DIR%/ /link %LIBS% /subsystem:console
|
||||
|
@ -103,7 +103,7 @@ int main(int, char**)
|
||||
if (event.type == SDL_WINDOWEVENT && event.window.event == SDL_WINDOWEVENT_CLOSE && event.window.windowID == SDL_GetWindowID(window))
|
||||
done = true;
|
||||
if (event.type == SDL_WINDOWEVENT && event.window.event == SDL_WINDOWEVENT_RESIZED && event.window.windowID == SDL_GetWindowID(window))
|
||||
{
|
||||
{
|
||||
// Release all outstanding references to the swap chain's buffers before resizing.
|
||||
CleanupRenderTarget();
|
||||
g_pSwapChain->ResizeBuffers(0, 0, 0, DXGI_FORMAT_UNKNOWN, 0);
|
||||
|
@ -14,12 +14,12 @@ cl /Zi /MD /I.. /I..\.. /I%SDL2_DIR%\include main.cpp ..\..\backends\imgui_impl_
|
||||
- On Linux and similar Unixes
|
||||
|
||||
```
|
||||
c++ `sdl2-config --cflags` -I .. -I ../.. main.cpp ../../backends/imgui_impl_sdl.cpp ../../backends/imgui_impl_opengl2.cpp ../../imgui*.cpp `sdl2-config --libs` -lGL
|
||||
c++ `sdl2-config --cflags` -I .. -I ../.. -I ../../backends main.cpp ../../backends/imgui_impl_sdl.cpp ../../backends/imgui_impl_opengl2.cpp ../../imgui*.cpp `sdl2-config --libs` -lGL
|
||||
```
|
||||
|
||||
- On Mac OS X
|
||||
|
||||
```
|
||||
brew install sdl2
|
||||
c++ `sdl2-config --cflags` -I .. -I ../.. main.cpp ../../backends/imgui_impl_sdl.cpp ../../backends/imgui_impl_opengl2.cpp ../../imgui*.cpp `sdl2-config --libs` -framework OpenGl
|
||||
c++ `sdl2-config --cflags` -I .. -I ../.. -I ../../backends main.cpp ../../backends/imgui_impl_sdl.cpp ../../backends/imgui_impl_opengl2.cpp ../../imgui*.cpp `sdl2-config --libs` -framework OpenGl
|
||||
```
|
||||
|
@ -3,6 +3,6 @@
|
||||
@set OUT_EXE=example_sdl_opengl2
|
||||
@set INCLUDES=/I..\.. /I..\..\backends /I%SDL2_DIR%\include
|
||||
@set SOURCES=main.cpp ..\..\backends\imgui_impl_sdl.cpp ..\..\backends\imgui_impl_opengl2.cpp ..\..\imgui*.cpp
|
||||
@set LIBS=/LIBPATH:%SDL2_DIR%\lib\x86 SDL2.lib SDL2main.lib opengl32.lib
|
||||
@set LIBS=/LIBPATH:%SDL2_DIR%\lib\x86 SDL2.lib SDL2main.lib opengl32.lib shell32.lib
|
||||
mkdir %OUT_DIR%
|
||||
cl /nologo /Zi /MD %INCLUDES% %SOURCES% /Fe%OUT_DIR%/%OUT_EXE%.exe /Fo%OUT_DIR%/ /link %LIBS% /subsystem:console
|
||||
|
@ -21,15 +21,19 @@ SOURCES += $(IMGUI_DIR)/imgui.cpp $(IMGUI_DIR)/imgui_demo.cpp $(IMGUI_DIR)/imgui
|
||||
SOURCES += $(IMGUI_DIR)/backends/imgui_impl_sdl.cpp $(IMGUI_DIR)/backends/imgui_impl_opengl3.cpp
|
||||
OBJS = $(addsuffix .o, $(basename $(notdir $(SOURCES))))
|
||||
UNAME_S := $(shell uname -s)
|
||||
LINUX_GL_LIBS = -lGL
|
||||
|
||||
CXXFLAGS = -I$(IMGUI_DIR) -I$(IMGUI_DIR)/backends
|
||||
CXXFLAGS += -g -Wall -Wformat
|
||||
LIBS =
|
||||
|
||||
##---------------------------------------------------------------------
|
||||
## OPENGL LOADER
|
||||
## OPENGL LOADER / OPENGL ES
|
||||
##---------------------------------------------------------------------
|
||||
|
||||
## See below for OpenGL ES option (no loader required) - comment out
|
||||
## the following if you want to use OpenGL ES instead of Desktop GL.
|
||||
|
||||
## Using OpenGL loader: gl3w [default]
|
||||
SOURCES += ../libs/gl3w/GL/gl3w.c
|
||||
CXXFLAGS += -I../libs/gl3w -DIMGUI_IMPL_OPENGL_LOADER_GL3W
|
||||
@ -56,13 +60,21 @@ CXXFLAGS += -I../libs/gl3w -DIMGUI_IMPL_OPENGL_LOADER_GL3W
|
||||
# CXXFLAGS += -DIMGUI_IMPL_OPENGL_LOADER_GLBINDING2
|
||||
# LIBS += -lglbinding
|
||||
|
||||
## Using OpenGL ES, no loader required
|
||||
## This assumes a GL ES library available in the system, e.g. libGLESv2.so
|
||||
# CXXFLAGS += -DIMGUI_IMPL_OPENGL_ES2
|
||||
# LINUX_GL_LIBS = -lGLESv2
|
||||
## If you're on a Raspberry Pi and want to use the legacy drivers,
|
||||
## use the following instead:
|
||||
# LINUX_GL_LIBS = -L/opt/vc/lib -lbrcmGLESv2
|
||||
|
||||
##---------------------------------------------------------------------
|
||||
## BUILD FLAGS PER PLATFORM
|
||||
##---------------------------------------------------------------------
|
||||
|
||||
ifeq ($(UNAME_S), Linux) #LINUX
|
||||
ECHO_MESSAGE = "Linux"
|
||||
LIBS += -lGL -ldl `sdl2-config --libs`
|
||||
LIBS += $(LINUX_GL_LIBS) -ldl `sdl2-config --libs`
|
||||
|
||||
CXXFLAGS += `sdl2-config --cflags`
|
||||
CFLAGS = $(CXXFLAGS)
|
||||
|
@ -14,12 +14,12 @@ cl /Zi /MD /I.. /I..\.. /I%SDL2_DIR%\include /I..\libs\gl3w main.cpp ..\..\backe
|
||||
- On Linux and similar Unixes
|
||||
|
||||
```
|
||||
c++ `sdl2-config --cflags` -I .. -I ../.. -I ../libs/gl3w main.cpp ../../backends/imgui_impl_sdl.cpp ../../backends/imgui_impl_opengl3.cpp ../../imgui*.cpp ../libs/gl3w/GL/gl3w.c `sdl2-config --libs` -lGL -ldl
|
||||
c++ `sdl2-config --cflags` -I .. -I ../.. -I ../../backends -I ../libs/gl3w main.cpp ../../backends/imgui_impl_sdl.cpp ../../backends/imgui_impl_opengl3.cpp ../../imgui*.cpp ../libs/gl3w/GL/gl3w.c `sdl2-config --libs` -lGL -ldl
|
||||
```
|
||||
|
||||
- On Mac OS X
|
||||
|
||||
```
|
||||
brew install sdl2
|
||||
c++ `sdl2-config --cflags` -I .. -I ../.. -I ../libs/gl3w main.cpp ../../backends/imgui_impl_sdl.cpp ../../backends/imgui_impl_opengl3.cpp ../../imgui*.cpp ../libs/gl3w/GL/gl3w.c `sdl2-config --libs` -framework OpenGl -framework CoreFoundation
|
||||
c++ `sdl2-config --cflags` -I .. -I ../.. -I ../../backends -I ../libs/gl3w main.cpp ../../backends/imgui_impl_sdl.cpp ../../backends/imgui_impl_opengl3.cpp ../../imgui*.cpp ../libs/gl3w/GL/gl3w.c `sdl2-config --libs` -framework OpenGl -framework CoreFoundation
|
||||
```
|
||||
|
@ -3,6 +3,6 @@
|
||||
@set OUT_EXE=example_sdl_opengl3
|
||||
@set INCLUDES=/I..\.. /I..\..\backends /I%SDL2_DIR%\include /I..\libs\gl3w
|
||||
@set SOURCES=main.cpp ..\..\backends\imgui_impl_sdl.cpp ..\..\backends\imgui_impl_opengl3.cpp ..\..\imgui*.cpp ..\libs\gl3w\GL\gl3w.c
|
||||
@set LIBS=/LIBPATH:%SDL2_DIR%\lib\x86 SDL2.lib SDL2main.lib opengl32.lib
|
||||
@set LIBS=/LIBPATH:%SDL2_DIR%\lib\x86 SDL2.lib SDL2main.lib opengl32.lib shell32.lib
|
||||
mkdir %OUT_DIR%
|
||||
cl /nologo /Zi /MD %INCLUDES% %SOURCES% /Fe%OUT_DIR%/%OUT_EXE%.exe /Fo%OUT_DIR%/ /link %LIBS% /subsystem:console
|
||||
|
@ -10,11 +10,13 @@
|
||||
#include <stdio.h>
|
||||
#include <SDL.h>
|
||||
|
||||
#if defined(IMGUI_IMPL_OPENGL_ES2)
|
||||
#include <GLES2/gl2.h>
|
||||
// About Desktop OpenGL function loaders:
|
||||
// Modern desktop OpenGL doesn't have a standard portable header file to load OpenGL function pointers.
|
||||
// Helper libraries are often used for this purpose! Here we are supporting a few common ones (gl3w, glew, glad).
|
||||
// You may use another loader/header of your choice (glext, glLoadGen, etc.), or chose to manually implement your own.
|
||||
#if defined(IMGUI_IMPL_OPENGL_LOADER_GL3W)
|
||||
#elif defined(IMGUI_IMPL_OPENGL_LOADER_GL3W)
|
||||
#include <GL/gl3w.h> // Initialize with gl3wInit()
|
||||
#elif defined(IMGUI_IMPL_OPENGL_LOADER_GLEW)
|
||||
#include <GL/glew.h> // Initialize with glewInit()
|
||||
@ -49,7 +51,14 @@ int main(int, char**)
|
||||
}
|
||||
|
||||
// Decide GL+GLSL versions
|
||||
#ifdef __APPLE__
|
||||
#if defined(IMGUI_IMPL_OPENGL_ES2)
|
||||
// GL ES 2.0 + GLSL 100
|
||||
const char* glsl_version = "#version 100";
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, 0);
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES);
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2);
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);
|
||||
#elif defined(__APPLE__)
|
||||
// GL 3.2 Core + GLSL 150
|
||||
const char* glsl_version = "#version 150";
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, SDL_GL_CONTEXT_FORWARD_COMPATIBLE_FLAG); // Always required on Mac
|
||||
|
10
examples/example_sdl_vulkan/build_win32.bat
Normal file
10
examples/example_sdl_vulkan/build_win32.bat
Normal file
@ -0,0 +1,10 @@
|
||||
@REM Build for Visual Studio compiler. Run your copy of vcvars32.bat or vcvarsall.bat to setup command-line compiler.
|
||||
|
||||
@set OUT_EXE=example_sdl_vulkan
|
||||
@set INCLUDES=/I..\.. /I..\..\backends /I%SDL2_DIR%\include /I %VULKAN_SDK%\include
|
||||
@set SOURCES=main.cpp ..\..\backends\imgui_impl_sdl.cpp ..\..\backends\imgui_impl_vulkan.cpp ..\..\imgui*.cpp
|
||||
@set LIBS=/LIBPATH:%SDL2_DIR%\lib\x86 /libpath:%VULKAN_SDK%\lib32 SDL2.lib SDL2main.lib shell32.lib vulkan-1.lib
|
||||
|
||||
@set OUT_DIR=Debug
|
||||
mkdir %OUT_DIR%
|
||||
cl /nologo /Zi /MD %INCLUDES% %SOURCES% /Fe%OUT_DIR%/%OUT_EXE%.exe /Fo%OUT_DIR%/ /link %LIBS% /subsystem:console
|
@ -114,10 +114,22 @@ static void SetupVulkan(const char** extensions, uint32_t extensions_count)
|
||||
err = vkEnumeratePhysicalDevices(g_Instance, &gpu_count, gpus);
|
||||
check_vk_result(err);
|
||||
|
||||
// If a number >1 of GPUs got reported, you should find the best fit GPU for your purpose
|
||||
// e.g. VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU if available, or with the greatest memory available, etc.
|
||||
// for sake of simplicity we'll just take the first one, assuming it has a graphics queue family.
|
||||
g_PhysicalDevice = gpus[0];
|
||||
// If a number >1 of GPUs got reported, find discrete GPU if present, or use first one available. This covers
|
||||
// most common cases (multi-gpu/integrated+dedicated graphics). Handling more complicated setups (multiple
|
||||
// dedicated GPUs) is out of scope of this sample.
|
||||
int use_gpu = 0;
|
||||
for (int i = 0; i < (int)gpu_count; i++)
|
||||
{
|
||||
VkPhysicalDeviceProperties properties;
|
||||
vkGetPhysicalDeviceProperties(gpus[i], &properties);
|
||||
if (properties.deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU)
|
||||
{
|
||||
use_gpu = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
g_PhysicalDevice = gpus[use_gpu];
|
||||
free(gpus);
|
||||
}
|
||||
|
||||
@ -245,7 +257,7 @@ static void FrameRender(ImGui_ImplVulkanH_Window* wd, ImDrawData* draw_data)
|
||||
VkSemaphore image_acquired_semaphore = wd->FrameSemaphores[wd->SemaphoreIndex].ImageAcquiredSemaphore;
|
||||
VkSemaphore render_complete_semaphore = wd->FrameSemaphores[wd->SemaphoreIndex].RenderCompleteSemaphore;
|
||||
err = vkAcquireNextImageKHR(g_Device, wd->Swapchain, UINT64_MAX, image_acquired_semaphore, VK_NULL_HANDLE, &wd->FrameIndex);
|
||||
if (err == VK_ERROR_OUT_OF_DATE_KHR)
|
||||
if (err == VK_ERROR_OUT_OF_DATE_KHR || err == VK_SUBOPTIMAL_KHR)
|
||||
{
|
||||
g_SwapChainRebuild = true;
|
||||
return;
|
||||
@ -318,7 +330,7 @@ static void FramePresent(ImGui_ImplVulkanH_Window* wd)
|
||||
info.pSwapchains = &wd->Swapchain;
|
||||
info.pImageIndices = &wd->FrameIndex;
|
||||
VkResult err = vkQueuePresentKHR(g_Queue, &info);
|
||||
if (err == VK_ERROR_OUT_OF_DATE_KHR)
|
||||
if (err == VK_ERROR_OUT_OF_DATE_KHR || err == VK_SUBOPTIMAL_KHR)
|
||||
{
|
||||
g_SwapChainRebuild = true;
|
||||
return;
|
||||
|
@ -78,21 +78,24 @@ int main(int, char**)
|
||||
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)
|
||||
bool done = false;
|
||||
while (!done)
|
||||
{
|
||||
// Poll and handle messages (inputs, window resize, etc.)
|
||||
// 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))
|
||||
MSG msg;
|
||||
while (::PeekMessage(&msg, NULL, 0U, 0U, PM_REMOVE))
|
||||
{
|
||||
::TranslateMessage(&msg);
|
||||
::DispatchMessage(&msg);
|
||||
continue;
|
||||
if (msg.message == WM_QUIT)
|
||||
done = true;
|
||||
}
|
||||
if (done)
|
||||
break;
|
||||
|
||||
// Start the Dear ImGui frame
|
||||
ImGui_ImplDX10_NewFrame();
|
||||
|
@ -78,21 +78,24 @@ int main(int, char**)
|
||||
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)
|
||||
bool done = false;
|
||||
while (!done)
|
||||
{
|
||||
// Poll and handle messages (inputs, window resize, etc.)
|
||||
// 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))
|
||||
MSG msg;
|
||||
while (::PeekMessage(&msg, NULL, 0U, 0U, PM_REMOVE))
|
||||
{
|
||||
::TranslateMessage(&msg);
|
||||
::DispatchMessage(&msg);
|
||||
continue;
|
||||
if (msg.message == WM_QUIT)
|
||||
done = true;
|
||||
}
|
||||
if (done)
|
||||
break;
|
||||
|
||||
// Start the Dear ImGui frame
|
||||
ImGui_ImplDX11_NewFrame();
|
||||
|
@ -117,21 +117,24 @@ int main(int, char**)
|
||||
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)
|
||||
bool done = false;
|
||||
while (!done)
|
||||
{
|
||||
// Poll and handle messages (inputs, window resize, etc.)
|
||||
// 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))
|
||||
MSG msg;
|
||||
while (::PeekMessage(&msg, NULL, 0U, 0U, PM_REMOVE))
|
||||
{
|
||||
::TranslateMessage(&msg);
|
||||
::DispatchMessage(&msg);
|
||||
continue;
|
||||
if (msg.message == WM_QUIT)
|
||||
done = true;
|
||||
}
|
||||
if (done)
|
||||
break;
|
||||
|
||||
// Start the Dear ImGui frame
|
||||
ImGui_ImplDX12_NewFrame();
|
||||
|
@ -76,21 +76,24 @@ int main(int, char**)
|
||||
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)
|
||||
bool done = false;
|
||||
while (!done)
|
||||
{
|
||||
// Poll and handle messages (inputs, window resize, etc.)
|
||||
// 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))
|
||||
MSG msg;
|
||||
while (::PeekMessage(&msg, NULL, 0U, 0U, PM_REMOVE))
|
||||
{
|
||||
::TranslateMessage(&msg);
|
||||
::DispatchMessage(&msg);
|
||||
continue;
|
||||
if (msg.message == WM_QUIT)
|
||||
done = true;
|
||||
}
|
||||
if (done)
|
||||
break;
|
||||
|
||||
// Start the Dear ImGui frame
|
||||
ImGui_ImplDX9_NewFrame();
|
||||
|
@ -42,7 +42,8 @@
|
||||
//#define IMGUI_ENABLE_OSX_DEFAULT_CLIPBOARD_FUNCTIONS // [OSX] Implement default OSX clipboard handler (need to link with '-framework ApplicationServices', this is why this is not the default).
|
||||
//#define IMGUI_DISABLE_DEFAULT_FORMAT_FUNCTIONS // Don't implement ImFormatString/ImFormatStringV so you can implement them yourself (e.g. if you don't want to link with vsnprintf)
|
||||
//#define IMGUI_DISABLE_DEFAULT_MATH_FUNCTIONS // Don't implement ImFabs/ImSqrt/ImPow/ImFmod/ImCos/ImSin/ImAcos/ImAtan2 so you can implement them yourself.
|
||||
//#define IMGUI_DISABLE_DEFAULT_FILE_FUNCTIONS // Don't implement ImFileOpen/ImFileClose/ImFileRead/ImFileWrite so you can implement them yourself if you don't want to link with fopen/fclose/fread/fwrite. This will also disable the LogToTTY() function.
|
||||
//#define IMGUI_DISABLE_FILE_FUNCTIONS // Don't implement ImFileOpen/ImFileClose/ImFileRead/ImFileWrite and ImFileHandle at all (replace them with dummies)
|
||||
//#define IMGUI_DISABLE_DEFAULT_FILE_FUNCTIONS // Don't implement ImFileOpen/ImFileClose/ImFileRead/ImFileWrite and ImFileHandle so you can implement them yourself if you don't want to link with fopen/fclose/fread/fwrite. This will also disable the LogToTTY() function.
|
||||
//#define IMGUI_DISABLE_DEFAULT_ALLOCATORS // Don't implement default allocators calling malloc()/free() to avoid linking with them. You will need to call ImGui::SetAllocatorFunctions().
|
||||
|
||||
//---- Include imgui_user.h at the end of imgui.h as a convenience
|
||||
|
64
imgui.h
64
imgui.h
@ -1,4 +1,4 @@
|
||||
// dear imgui, v1.82 WIP
|
||||
// dear imgui, v1.83
|
||||
// (headers)
|
||||
|
||||
// Help:
|
||||
@ -11,9 +11,9 @@
|
||||
// - FAQ http://dearimgui.org/faq
|
||||
// - Homepage & latest https://github.com/ocornut/imgui
|
||||
// - Releases & changelog https://github.com/ocornut/imgui/releases
|
||||
// - Gallery https://github.com/ocornut/imgui/issues/3488 (please post your screenshots/video there!)
|
||||
// - Gallery https://github.com/ocornut/imgui/issues/3793 (please post your screenshots/video there!)
|
||||
// - Wiki https://github.com/ocornut/imgui/wiki (lots of good stuff there)
|
||||
// - Glossary https://github.com/ocornut/imgui/wiki/Glossary
|
||||
// - Wiki https://github.com/ocornut/imgui/wiki
|
||||
// - Issues & support https://github.com/ocornut/imgui/issues
|
||||
// - Discussions https://github.com/ocornut/imgui/discussions
|
||||
|
||||
@ -60,8 +60,8 @@ Index of this file:
|
||||
|
||||
// Version
|
||||
// (Integer encoded as XYYZZ for use in #if preprocessor conditionals. Work in progress versions typically starts at XYY99 then bounce up to XYY00, XYY01 etc. when release tagging happens)
|
||||
#define IMGUI_VERSION "1.82 WIP"
|
||||
#define IMGUI_VERSION_NUM 18104
|
||||
#define IMGUI_VERSION "1.83"
|
||||
#define IMGUI_VERSION_NUM 18300
|
||||
#define IMGUI_CHECKVERSION() ImGui::DebugCheckVersionAndDataLayout(IMGUI_VERSION, sizeof(ImGuiIO), sizeof(ImGuiStyle), sizeof(ImVec2), sizeof(ImVec4), sizeof(ImDrawVert), sizeof(ImDrawIdx))
|
||||
#define IMGUI_HAS_TABLE
|
||||
|
||||
@ -100,7 +100,20 @@ Index of this file:
|
||||
#define IM_FMTLIST(FMT)
|
||||
#endif
|
||||
|
||||
// Disable some of MSVC most aggressive Debug runtime checks in function header/footer (used in some simple/low-level functions)
|
||||
#if defined(_MSC_VER) && !defined(__clang__) && !defined(IMGUI_DEBUG_PARANOID)
|
||||
#define IM_MSVC_RUNTIME_CHECKS_OFF __pragma(runtime_checks("",off)) __pragma(check_stack(off)) __pragma(strict_gs_check(push,off))
|
||||
#define IM_MSVC_RUNTIME_CHECKS_RESTORE __pragma(runtime_checks("",restore)) __pragma(check_stack()) __pragma(strict_gs_check(pop))
|
||||
#else
|
||||
#define IM_MSVC_RUNTIME_CHECKS_OFF
|
||||
#define IM_MSVC_RUNTIME_CHECKS_RESTORE
|
||||
#endif
|
||||
|
||||
// Warnings
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning (push)
|
||||
#pragma warning (disable: 26495) // [Static Analyzer] Variable 'XXX' is uninitialized. Always initialize a member variable (type.6).
|
||||
#endif
|
||||
#if defined(__clang__)
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wold-style-cast"
|
||||
@ -227,6 +240,7 @@ typedef unsigned long long ImU64; // 64-bit unsigned integer (post C++11)
|
||||
#endif
|
||||
|
||||
// 2D vector (often used to store positions or sizes)
|
||||
IM_MSVC_RUNTIME_CHECKS_OFF
|
||||
struct ImVec2
|
||||
{
|
||||
float x, y;
|
||||
@ -249,6 +263,7 @@ struct ImVec4
|
||||
IM_VEC4_CLASS_EXTRA // Define additional constructors and implicit cast operators in imconfig.h to convert back and forth between your math types and ImVec4.
|
||||
#endif
|
||||
};
|
||||
IM_MSVC_RUNTIME_CHECKS_RESTORE
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// [SECTION] Dear ImGui end-user API functions
|
||||
@ -376,7 +391,7 @@ namespace ImGui
|
||||
IMGUI_API void PushStyleVar(ImGuiStyleVar idx, float val); // modify a style float variable. always use this if you modify the style after NewFrame().
|
||||
IMGUI_API void PushStyleVar(ImGuiStyleVar idx, const ImVec2& val); // modify a style ImVec2 variable. always use this if you modify the style after NewFrame().
|
||||
IMGUI_API void PopStyleVar(int count = 1);
|
||||
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); // == tab stop enable. 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 PopButtonRepeat();
|
||||
@ -507,8 +522,8 @@ namespace ImGui
|
||||
IMGUI_API bool DragInt3(const char* label, int v[3], float v_speed = 1.0f, int v_min = 0, int v_max = 0, const char* format = "%d", ImGuiSliderFlags flags = 0);
|
||||
IMGUI_API bool DragInt4(const char* label, int v[4], float v_speed = 1.0f, int v_min = 0, int v_max = 0, const char* format = "%d", ImGuiSliderFlags flags = 0);
|
||||
IMGUI_API bool DragIntRange2(const char* label, int* v_current_min, int* v_current_max, float v_speed = 1.0f, int v_min = 0, int v_max = 0, const char* format = "%d", const char* format_max = NULL, ImGuiSliderFlags flags = 0);
|
||||
IMGUI_API bool DragScalar(const char* label, ImGuiDataType data_type, void* p_data, float v_speed, const void* p_min = NULL, const void* p_max = NULL, const char* format = NULL, ImGuiSliderFlags flags = 0);
|
||||
IMGUI_API bool DragScalarN(const char* label, ImGuiDataType data_type, void* p_data, int components, float v_speed, const void* p_min = NULL, const void* p_max = NULL, const char* format = NULL, ImGuiSliderFlags flags = 0);
|
||||
IMGUI_API bool DragScalar(const char* label, ImGuiDataType data_type, void* p_data, float v_speed = 1.0f, const void* p_min = NULL, const void* p_max = NULL, const char* format = NULL, ImGuiSliderFlags flags = 0);
|
||||
IMGUI_API bool DragScalarN(const char* label, ImGuiDataType data_type, void* p_data, int components, float v_speed = 1.0f, const void* p_min = NULL, const void* p_max = NULL, const char* format = NULL, ImGuiSliderFlags flags = 0);
|
||||
|
||||
// Widgets: Regular Sliders
|
||||
// - CTRL+Click on any slider to turn them into an input box. Manually input values aren't clamped and can go off-bounds.
|
||||
@ -614,13 +629,14 @@ namespace ImGui
|
||||
// - Use BeginMenuBar() on a window ImGuiWindowFlags_MenuBar to append to its menu bar.
|
||||
// - Use BeginMainMenuBar() to create a menu bar at the top of the screen and append to it.
|
||||
// - Use BeginMenu() to create a menu. You can call BeginMenu() multiple time with the same identifier to append more items to it.
|
||||
// - Not that MenuItem() keyboardshortcuts are displayed as a convenience but _not processed_ by Dear ImGui at the moment.
|
||||
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 BeginMainMenuBar(); // create and append to a full screen menu-bar.
|
||||
IMGUI_API void EndMainMenuBar(); // only call EndMainMenuBar() if BeginMainMenuBar() 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 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 = NULL, bool selected = false, bool enabled = true); // return true when activated.
|
||||
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
|
||||
|
||||
// Tooltips
|
||||
@ -650,18 +666,20 @@ namespace ImGui
|
||||
// - CloseCurrentPopup(): use inside the BeginPopup()/EndPopup() scope to close manually.
|
||||
// - CloseCurrentPopup() is called by default by Selectable()/MenuItem() when activated (FIXME: need some options).
|
||||
// - Use ImGuiPopupFlags_NoOpenOverExistingPopup to avoid opening a popup if there's already one at the same level. This is equivalent to e.g. testing for !IsAnyPopupOpen() prior to OpenPopup().
|
||||
// - Use IsWindowAppearing() after BeginPopup() to tell if a window just opened.
|
||||
IMGUI_API void OpenPopup(const char* str_id, ImGuiPopupFlags popup_flags = 0); // call to mark popup as open (don't call every frame!).
|
||||
IMGUI_API void OpenPopupOnItemClick(const char* str_id = NULL, ImGuiPopupFlags popup_flags = 1); // helper to open popup when clicked on last item. return true when just opened. (note: actually triggers on the mouse _released_ event to be consistent with popup behaviors)
|
||||
IMGUI_API void OpenPopup(ImGuiID id, ImGuiPopupFlags popup_flags = 0); // id overload to facilitate calling from nested stacks
|
||||
IMGUI_API void OpenPopupOnItemClick(const char* str_id = NULL, ImGuiPopupFlags popup_flags = 1); // helper to open popup when clicked on last item. Default to ImGuiPopupFlags_MouseButtonRight == 1. (note: actually triggers on the mouse _released_ event to be consistent with popup behaviors)
|
||||
IMGUI_API void CloseCurrentPopup(); // manually close the popup we have begin-ed into.
|
||||
// Popups: open+begin combined functions helpers
|
||||
// - Helpers to do OpenPopup+BeginPopup where the Open action is triggered by e.g. hovering an item and right-clicking.
|
||||
// - They are convenient to easily create context menus, hence the name.
|
||||
// - IMPORTANT: Notice that BeginPopupContextXXX takes ImGuiPopupFlags just like OpenPopup() and unlike BeginPopup(). For full consistency, we may add ImGuiWindowFlags to the BeginPopupContextXXX functions in the future.
|
||||
// - IMPORTANT: we exceptionally default their flags to 1 (== ImGuiPopupFlags_MouseButtonRight) for backward compatibility with older API taking 'int mouse_button = 1' parameter, so if you add other flags remember to re-add the ImGuiPopupFlags_MouseButtonRight.
|
||||
IMGUI_API bool BeginPopupContextItem(const char* str_id = NULL, ImGuiPopupFlags popup_flags = 1); // open+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 BeginPopupContextItem(const char* str_id = NULL, ImGuiPopupFlags popup_flags = 1); // open+begin popup when clicked on last item. Use str_id==NULL to associate the popup to previous item. 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, ImGuiPopupFlags popup_flags = 1);// open+begin popup when clicked on current window.
|
||||
IMGUI_API bool BeginPopupContextVoid(const char* str_id = NULL, ImGuiPopupFlags popup_flags = 1); // open+begin popup when clicked in void (where there are no windows).
|
||||
// Popups: test function
|
||||
// Popups: query functions
|
||||
// - IsPopupOpen(): return true if the popup is open at the current BeginPopup() level of the popup stack.
|
||||
// - IsPopupOpen() with ImGuiPopupFlags_AnyPopupId: return true if any popup is open at the current BeginPopup() level of the popup stack.
|
||||
// - IsPopupOpen() with ImGuiPopupFlags_AnyPopupId + ImGuiPopupFlags_AnyPopupLevel: return true if any popup is open.
|
||||
@ -723,6 +741,7 @@ namespace ImGui
|
||||
IMGUI_API int TableGetRowIndex(); // return current row index.
|
||||
IMGUI_API const char* TableGetColumnName(int column_n = -1); // return "" if column didn't have a name declared by TableSetupColumn(). Pass -1 to use current column.
|
||||
IMGUI_API ImGuiTableColumnFlags TableGetColumnFlags(int column_n = -1); // return column flags so you can query their Enabled/Visible/Sorted/Hovered status flags. Pass -1 to use current column.
|
||||
IMGUI_API void TableSetColumnEnabled(int column_n, bool v);// change enabled/disabled state of a column, set to false to hide the column. Note that end-user can use the context menu to change this themselves (right-click in headers, or right-click in columns body with ImGuiTableFlags_ContextMenuInBody)
|
||||
IMGUI_API void TableSetBgColor(ImGuiTableBgTarget target, ImU32 color, int column_n = -1); // change the color of a cell, row, or column. See ImGuiTableBgTarget_ flags for details.
|
||||
|
||||
// Legacy Columns API (2020: prefer using Tables!)
|
||||
@ -777,7 +796,7 @@ namespace ImGui
|
||||
IMGUI_API void SetItemDefaultFocus(); // make last item the default focused item of a window.
|
||||
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.
|
||||
|
||||
// Item/Widgets Utilities
|
||||
// Item/Widgets Utilities and Query Functions
|
||||
// - Most of the functions are referring to the previous Item that has been submitted.
|
||||
// - See Demo Window under "Widgets->Querying Status" for an interactive visualization of most of those functions.
|
||||
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.
|
||||
@ -802,7 +821,7 @@ namespace ImGui
|
||||
// - Currently represents the Platform Window created by the application which is hosting our Dear ImGui windows.
|
||||
// - In 'docking' branch with multi-viewport enabled, we extend this concept to have multiple active viewports.
|
||||
// - In the future we will extend this concept further to also represent Platform Monitor and support a "no main platform window" operation mode.
|
||||
IMGUI_API ImGuiViewport* GetMainViewport(); // return primary/default viewport.
|
||||
IMGUI_API ImGuiViewport* GetMainViewport(); // return primary/default viewport. This can never be NULL.
|
||||
|
||||
// Miscellaneous Utilities
|
||||
IMGUI_API bool IsRectVisible(const ImVec2& size); // test if rectangle (of given size, starting from cursor position) is visible / not clipped.
|
||||
@ -872,6 +891,7 @@ namespace ImGui
|
||||
IMGUI_API const char* SaveIniSettingsToMemory(size_t* out_ini_size = NULL); // return a zero-terminated string with the .ini data which you can save by your own mean. call when io.WantSaveIniSettings is set, then save data by your own mean and clear io.WantSaveIniSettings.
|
||||
|
||||
// Debug Utilities
|
||||
// - This is used by the IMGUI_CHECKVERSION() macro.
|
||||
IMGUI_API bool DebugCheckVersionAndDataLayout(const char* version_str, size_t sz_io, size_t sz_style, size_t sz_vec2, size_t sz_vec4, size_t sz_drawvert, size_t sz_drawidx); // This is called by IMGUI_CHECKVERSION() macro.
|
||||
|
||||
// Memory Allocators
|
||||
@ -952,10 +972,7 @@ enum ImGuiInputTextFlags_
|
||||
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)
|
||||
ImGuiInputTextFlags_CallbackResize = 1 << 18, // Callback on buffer capacity changes request (beyond 'buf_size' parameter value), allowing the string to grow. Notify when the string wants to be resized (for string types which hold a cache of their Size). You will be provided a new BufSize in the callback and NEED to honor it. (see misc/cpp/imgui_stdlib.h for an example of using this)
|
||||
ImGuiInputTextFlags_CallbackEdit = 1 << 19, // Callback on any edit (note that InputText() already returns true on edit, the callback is useful mainly to manipulate the underlying buffer while focus is active)
|
||||
// [Internal]
|
||||
ImGuiInputTextFlags_Multiline = 1 << 20, // For internal use by InputTextMultiline()
|
||||
ImGuiInputTextFlags_NoMarkEdited = 1 << 21 // For internal use by functions using InputText() before reformatting data
|
||||
ImGuiInputTextFlags_CallbackEdit = 1 << 19 // Callback on any edit (note that InputText() already returns true on edit, the callback is useful mainly to manipulate the underlying buffer while focus is active)
|
||||
|
||||
// Obsolete names (will be removed soon)
|
||||
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
|
||||
@ -1631,6 +1648,7 @@ template<typename T> void IM_DELETE(T* p) { if (p) { p->~T(); ImGui::MemFree(p
|
||||
// Do NOT use this class as a std::vector replacement in your own code! Many of the structures used by dear imgui can be safely initialized by a zero-memset.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
IM_MSVC_RUNTIME_CHECKS_OFF
|
||||
template<typename T>
|
||||
struct ImVector
|
||||
{
|
||||
@ -1689,6 +1707,7 @@ struct ImVector
|
||||
inline bool find_erase_unsorted(const T& v) { const T* it = find(v); if (it < Data + Size) { erase_unsorted(it); return true; } return false; }
|
||||
inline int index_from_ptr(const T* it) const { IM_ASSERT(it >= Data && it < Data + Size); const ptrdiff_t off = it - Data; return (int)off; }
|
||||
};
|
||||
IM_MSVC_RUNTIME_CHECKS_RESTORE
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// [SECTION] ImGuiStyle
|
||||
@ -1845,7 +1864,7 @@ struct ImGuiIO
|
||||
bool WantSaveIniSettings; // When manual .ini load/save is active (io.IniFilename == NULL), this will be set to notify your application that you can call SaveIniSettingsToMemory() and save yourself. Important: clear io.WantSaveIniSettings yourself after saving!
|
||||
bool NavActive; // Keyboard/Gamepad navigation is currently allowed (will handle ImGuiKey_NavXXX events) = a window is focused and it doesn't use the ImGuiWindowFlags_NoNavInputs flag.
|
||||
bool NavVisible; // Keyboard/Gamepad navigation is visible and allowed (will handle ImGuiKey_NavXXX events).
|
||||
float Framerate; // Application framerate estimate, in frame per second. Solely for convenience. Rolling average estimation based on io.DeltaTime over 120 frames.
|
||||
float Framerate; // Rough estimate of application framerate, in frame per second. Solely for convenience. Rolling average estimation based on io.DeltaTime over 120 frames.
|
||||
int MetricsRenderVertices; // Vertices output during last call to Render()
|
||||
int MetricsRenderIndices; // Indices output during last call to Render() = number of triangles * 3
|
||||
int MetricsRenderWindows; // Number of visible windows
|
||||
@ -2224,6 +2243,9 @@ struct ImDrawCmd
|
||||
void* UserCallbackData; // 4-8 // The draw callback code can access this.
|
||||
|
||||
ImDrawCmd() { memset(this, 0, sizeof(*this)); } // Also ensure our padding fields are zeroed
|
||||
|
||||
// Since 1.83: returns ImTextureID associated with this draw call. Warning: DO NOT assume this is always same as 'TextureId' (we will change this function for an upcoming feature)
|
||||
inline ImTextureID GetTexID() const { return TextureId; }
|
||||
};
|
||||
|
||||
// Vertex index, default to 16-bit
|
||||
@ -2818,6 +2840,10 @@ enum ImDrawCornerFlags_
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning (pop)
|
||||
#endif
|
||||
|
||||
// Include imgui_user.h at the end of imgui.h (convenient for user to only explicitly include vanilla imgui.h)
|
||||
#ifdef IMGUI_INCLUDE_IMGUI_USER_H
|
||||
#include "imgui_user.h"
|
||||
|
240
imgui_demo.cpp
240
imgui_demo.cpp
@ -1,4 +1,4 @@
|
||||
// dear imgui, v1.82 WIP
|
||||
// dear imgui, v1.83
|
||||
// (demo code)
|
||||
|
||||
// Help:
|
||||
@ -6,9 +6,9 @@
|
||||
// - Newcomers, read 'Programmer guide' in imgui.cpp for notes on how to setup Dear ImGui in your codebase.
|
||||
// - Call and read ImGui::ShowDemoWindow() in imgui_demo.cpp. All applications in examples/ are doing that.
|
||||
// Read imgui.cpp for more details, documentation and comments.
|
||||
// Get latest version at https://github.com/ocornut/imgui
|
||||
// Get the latest version at https://github.com/ocornut/imgui
|
||||
|
||||
// Message to the person tempted to delete this file when integrating Dear ImGui into their code base:
|
||||
// Message to the person tempted to delete this file when integrating Dear ImGui into their codebase:
|
||||
// Do NOT remove this file from your project! Think again! It is the most useful reference code that you and other
|
||||
// coders will want to refer to and call. Have the ImGui::ShowDemoWindow() function wired in an always-available
|
||||
// debug menu of your game/app! Removing this file from your project is hindering access to documentation for everyone
|
||||
@ -16,19 +16,19 @@
|
||||
// Everything in this file will be stripped out by the linker if you don't call ImGui::ShowDemoWindow().
|
||||
// If you want to link core Dear ImGui in your shipped builds but want a thorough guarantee that the demo will not be
|
||||
// linked, you can setup your imconfig.h with #define IMGUI_DISABLE_DEMO_WINDOWS and those functions will be empty.
|
||||
// In other situation, whenever you have Dear ImGui available you probably want this to be available for reference.
|
||||
// In another situation, whenever you have Dear ImGui available you probably want this to be available for reference.
|
||||
// Thank you,
|
||||
// -Your beloved friend, imgui_demo.cpp (which you won't delete)
|
||||
|
||||
// Message to beginner C/C++ programmers about the meaning of the 'static' keyword:
|
||||
// In this demo code, we frequently we use 'static' variables inside functions. A static variable persist across calls,
|
||||
// In this demo code, we frequently use 'static' variables inside functions. A static variable persists across calls,
|
||||
// so it is essentially like a global variable but declared inside the scope of the function. We do this as a way to
|
||||
// gather code and data in the same place, to make the demo source code faster to read, faster to write, and smaller
|
||||
// in size. 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 multiple threads. This might be a pattern you will want to use in your code,
|
||||
// but most of the real data you would be editing is likely going to be stored outside your functions.
|
||||
|
||||
// The Demo code in this file is designed to be easy to copy-and-paste in into your application!
|
||||
// The Demo code in this file is designed to be easy to copy-and-paste into your application!
|
||||
// Because of this:
|
||||
// - We never omit the ImGui:: prefix when calling functions, even though most code here is in the same namespace.
|
||||
// - We try to declare static variables in the local scope, as close as possible to the code using them.
|
||||
@ -54,6 +54,7 @@ Index of this file:
|
||||
// - sub section: ShowDemoWindowTables()
|
||||
// - sub section: ShowDemoWindowMisc()
|
||||
// [SECTION] About Window / ShowAboutWindow()
|
||||
// [SECTION] Font Viewer / ShowFontAtlas()
|
||||
// [SECTION] Style Editor / ShowStyleEditor()
|
||||
// [SECTION] Example App: Main Menu Bar / ShowExampleAppMainMenuBar()
|
||||
// [SECTION] Example App: Debug Console / ShowExampleAppConsole()
|
||||
@ -92,7 +93,8 @@ Index of this file:
|
||||
|
||||
// Visual Studio warnings
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning (disable: 4996) // 'This function or variable may be unsafe': strcpy, strdup, sprintf, vsnprintf, sscanf, fopen
|
||||
#pragma warning (disable: 4996) // 'This function or variable may be unsafe': strcpy, strdup, sprintf, vsnprintf, sscanf, fopen
|
||||
#pragma warning (disable: 26451) // [Static Analyzer] Arithmetic overflow : Using operator 'xxx' on a 4 byte value and then casting the result to a 8 byte value. Cast the value to the wider type before calling operator 'xxx' to avoid overflow(io.2).
|
||||
#endif
|
||||
|
||||
// Clang/GCC warnings with -Weverything
|
||||
@ -1553,7 +1555,7 @@ static void ShowDemoWindowWidgets()
|
||||
// Plot/Graph widgets are not very good.
|
||||
// Consider writing your own, or using a third-party one, see:
|
||||
// - ImPlot https://github.com/epezent/implot
|
||||
// - others https://github.com/ocornut/imgui/wiki/Useful-Widgets
|
||||
// - others https://github.com/ocornut/imgui/wiki/Useful-Extensions
|
||||
if (ImGui::TreeNode("Plots Widgets"))
|
||||
{
|
||||
static bool animate = true;
|
||||
@ -1602,7 +1604,7 @@ static void ShowDemoWindowWidgets()
|
||||
};
|
||||
static int func_type = 0, display_count = 70;
|
||||
ImGui::Separator();
|
||||
ImGui::SetNextItemWidth(100);
|
||||
ImGui::SetNextItemWidth(ImGui::GetFontSize() * 8);
|
||||
ImGui::Combo("func", &func_type, "Sin\0Saw\0");
|
||||
ImGui::SameLine();
|
||||
ImGui::SliderInt("Sample count", &display_count, 1, 400);
|
||||
@ -2392,7 +2394,7 @@ static void ShowDemoWindowLayout()
|
||||
// the POV of the parent window). See 'Demo->Querying Status (Active/Focused/Hovered etc.)' for details.
|
||||
{
|
||||
static int offset_x = 0;
|
||||
ImGui::SetNextItemWidth(100);
|
||||
ImGui::SetNextItemWidth(ImGui::GetFontSize() * 8);
|
||||
ImGui::DragInt("Offset X", &offset_x, 1.0f, -1000, 1000);
|
||||
|
||||
ImGui::SetCursorPosX(ImGui::GetCursorPosX() + (float)offset_x);
|
||||
@ -2414,15 +2416,15 @@ static void ShowDemoWindowLayout()
|
||||
|
||||
if (ImGui::TreeNode("Widgets Width"))
|
||||
{
|
||||
static float f = 0.0f;
|
||||
static bool show_indented_items = true;
|
||||
ImGui::Checkbox("Show indented items", &show_indented_items);
|
||||
|
||||
// Use SetNextItemWidth() to set the width of a single upcoming item.
|
||||
// Use PushItemWidth()/PopItemWidth() to set the width of a group of items.
|
||||
// In real code use you'll probably want to choose width values that are proportional to your font size
|
||||
// e.g. Using '20.0f * GetFontSize()' as width instead of '200.0f', etc.
|
||||
|
||||
static float f = 0.0f;
|
||||
static bool show_indented_items = true;
|
||||
ImGui::Checkbox("Show indented items", &show_indented_items);
|
||||
|
||||
ImGui::Text("SetNextItemWidth/PushItemWidth(100)");
|
||||
ImGui::SameLine(); HelpMarker("Fixed width.");
|
||||
ImGui::PushItemWidth(100);
|
||||
@ -2838,6 +2840,8 @@ static void ShowDemoWindowLayout()
|
||||
{
|
||||
for (int item = 0; item < 100; item++)
|
||||
{
|
||||
if (item > 0)
|
||||
ImGui::SameLine();
|
||||
if (enable_track && item == track_item)
|
||||
{
|
||||
ImGui::TextColored(ImVec4(1, 1, 0, 1), "Item %d", item);
|
||||
@ -2847,7 +2851,6 @@ static void ShowDemoWindowLayout()
|
||||
{
|
||||
ImGui::Text("Item %d", item);
|
||||
}
|
||||
ImGui::SameLine();
|
||||
}
|
||||
}
|
||||
float scroll_x = ImGui::GetScrollX();
|
||||
@ -3191,46 +3194,84 @@ static void ShowDemoWindowPopups()
|
||||
|
||||
if (ImGui::TreeNode("Context menus"))
|
||||
{
|
||||
HelpMarker("\"Context\" functions are simple helpers to associate a Popup to a given Item or Window identifier.");
|
||||
|
||||
// BeginPopupContextItem() is a helper to provide common/simple popup behavior of essentially doing:
|
||||
// if (IsItemHovered() && IsMouseReleased(ImGuiMouseButton_Right))
|
||||
// OpenPopup(id);
|
||||
// return BeginPopup(id);
|
||||
// For more advanced uses you may want to replicate and customize this code.
|
||||
// See details in BeginPopupContextItem().
|
||||
static float value = 0.5f;
|
||||
ImGui::Text("Value = %.3f (<-- right-click here)", value);
|
||||
if (ImGui::BeginPopupContextItem("item context menu"))
|
||||
// if (id == 0)
|
||||
// id = GetItemID(); // Use last item id
|
||||
// if (IsItemHovered() && IsMouseReleased(ImGuiMouseButton_Right))
|
||||
// OpenPopup(id);
|
||||
// return BeginPopup(id);
|
||||
// For advanced advanced uses you may want to replicate and customize this code.
|
||||
// See more details in BeginPopupContextItem().
|
||||
|
||||
// Example 1
|
||||
// When used after an item that has an ID (e.g. Button), we can skip providing an ID to BeginPopupContextItem(),
|
||||
// and BeginPopupContextItem() will use the last item ID as the popup ID.
|
||||
{
|
||||
if (ImGui::Selectable("Set to zero")) value = 0.0f;
|
||||
if (ImGui::Selectable("Set to PI")) value = 3.1415f;
|
||||
ImGui::SetNextItemWidth(-FLT_MIN);
|
||||
ImGui::DragFloat("##Value", &value, 0.1f, 0.0f, 0.0f);
|
||||
ImGui::EndPopup();
|
||||
const char* names[5] = { "Label1", "Label2", "Label3", "Label4", "Label5" };
|
||||
for (int n = 0; n < 5; n++)
|
||||
{
|
||||
ImGui::Selectable(names[n]);
|
||||
if (ImGui::BeginPopupContextItem()) // <-- use last item id as popup id
|
||||
{
|
||||
ImGui::Text("This a popup for \"%s\"!", names[n]);
|
||||
if (ImGui::Button("Close"))
|
||||
ImGui::CloseCurrentPopup();
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
if (ImGui::IsItemHovered())
|
||||
ImGui::SetTooltip("Right-click to open popup");
|
||||
}
|
||||
}
|
||||
|
||||
// We can also use OpenPopupOnItemClick() which is the same as BeginPopupContextItem() but without the
|
||||
// Begin() call. So here we will make it that clicking on the text field with the right mouse button (1)
|
||||
// will toggle the visibility of the popup above.
|
||||
ImGui::Text("(You can also right-click me to open the same popup as above.)");
|
||||
ImGui::OpenPopupOnItemClick("item context menu", 1);
|
||||
|
||||
// When used after an item that has an ID (e.g.Button), we can skip providing an ID to BeginPopupContextItem().
|
||||
// BeginPopupContextItem() will use the last item ID as the popup ID.
|
||||
// In addition here, we want to include your editable label inside the button label.
|
||||
// We use the ### operator to override the ID (read FAQ about ID for details)
|
||||
static char name[32] = "Label1";
|
||||
char buf[64];
|
||||
sprintf(buf, "Button: %s###Button", name); // ### operator override ID ignoring the preceding label
|
||||
ImGui::Button(buf);
|
||||
if (ImGui::BeginPopupContextItem())
|
||||
// Example 2
|
||||
// Popup on a Text() element which doesn't have an identifier: we need to provide an identifier to BeginPopupContextItem().
|
||||
// Using an explicit identifier is also convenient if you want to activate the popups from different locations.
|
||||
{
|
||||
ImGui::Text("Edit name:");
|
||||
ImGui::InputText("##edit", name, IM_ARRAYSIZE(name));
|
||||
if (ImGui::Button("Close"))
|
||||
ImGui::CloseCurrentPopup();
|
||||
ImGui::EndPopup();
|
||||
HelpMarker("Text() elements don't have stable identifiers so we need to provide one.");
|
||||
static float value = 0.5f;
|
||||
ImGui::Text("Value = %.3f <-- (1) right-click this value", value);
|
||||
if (ImGui::BeginPopupContextItem("my popup"))
|
||||
{
|
||||
if (ImGui::Selectable("Set to zero")) value = 0.0f;
|
||||
if (ImGui::Selectable("Set to PI")) value = 3.1415f;
|
||||
ImGui::SetNextItemWidth(-FLT_MIN);
|
||||
ImGui::DragFloat("##Value", &value, 0.1f, 0.0f, 0.0f);
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
|
||||
// We can also use OpenPopupOnItemClick() to toggle the visibility of a given popup.
|
||||
// Here we make it that right-clicking this other text element opens the same popup as above.
|
||||
// The popup itself will be submitted by the code above.
|
||||
ImGui::Text("(2) Or right-click this text");
|
||||
ImGui::OpenPopupOnItemClick("my popup", ImGuiPopupFlags_MouseButtonRight);
|
||||
|
||||
// Back to square one: manually open the same popup.
|
||||
if (ImGui::Button("(3) Or click this button"))
|
||||
ImGui::OpenPopup("my popup");
|
||||
}
|
||||
|
||||
// Example 3
|
||||
// When using BeginPopupContextItem() with an implicit identifier (NULL == use last item ID),
|
||||
// we need to make sure your item identifier is stable.
|
||||
// In this example we showcase altering the item label while preserving its identifier, using the ### operator (see FAQ).
|
||||
{
|
||||
HelpMarker("Showcase using a popup ID linked to item ID, with the item having a changing label + stable ID using the ### operator.");
|
||||
static char name[32] = "Label1";
|
||||
char buf[64];
|
||||
sprintf(buf, "Button: %s###Button", name); // ### operator override ID ignoring the preceding label
|
||||
ImGui::Button(buf);
|
||||
if (ImGui::BeginPopupContextItem())
|
||||
{
|
||||
ImGui::Text("Edit name:");
|
||||
ImGui::InputText("##edit", name, IM_ARRAYSIZE(name));
|
||||
if (ImGui::Button("Close"))
|
||||
ImGui::CloseCurrentPopup();
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
ImGui::SameLine(); ImGui::Text("(<-- right-click here)");
|
||||
}
|
||||
ImGui::SameLine(); ImGui::Text("(<-- right-click here)");
|
||||
|
||||
ImGui::TreePop();
|
||||
}
|
||||
@ -5461,7 +5502,7 @@ static void ShowDemoWindowMisc()
|
||||
ImGui::InputText("3", buf, IM_ARRAYSIZE(buf));
|
||||
ImGui::PushAllowKeyboardFocus(false);
|
||||
ImGui::InputText("4 (tab skip)", buf, IM_ARRAYSIZE(buf));
|
||||
//ImGui::SameLine(); HelpMarker("Use ImGui::PushAllowKeyboardFocus(bool) to disable tabbing through certain widgets.");
|
||||
ImGui::SameLine(); HelpMarker("Item won't be cycled through when using TAB or Shift+Tab.");
|
||||
ImGui::PopAllowKeyboardFocus();
|
||||
ImGui::InputText("5", buf, IM_ARRAYSIZE(buf));
|
||||
ImGui::TreePop();
|
||||
@ -5487,6 +5528,7 @@ static void ShowDemoWindowMisc()
|
||||
if (focus_3) ImGui::SetKeyboardFocusHere();
|
||||
ImGui::InputText("3 (tab skip)", buf, IM_ARRAYSIZE(buf));
|
||||
if (ImGui::IsItemActive()) has_focus = 3;
|
||||
ImGui::SameLine(); HelpMarker("Item won't be cycled through when using TAB or Shift+Tab.");
|
||||
ImGui::PopAllowKeyboardFocus();
|
||||
|
||||
if (has_focus)
|
||||
@ -5702,31 +5744,15 @@ void ImGui::ShowAboutWindow(bool* p_open)
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// [SECTION] Style Editor / ShowStyleEditor()
|
||||
// [SECTION] Font viewer / ShowFontAtlas()
|
||||
//-----------------------------------------------------------------------------
|
||||
// - ShowStyleSelector()
|
||||
// - ShowFontSelector()
|
||||
// - ShowStyleEditor()
|
||||
// - ShowFont()
|
||||
// - ShowFontAtlas()
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
// 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 = -1;
|
||||
if (ImGui::Combo(label, &style_idx, "Dark\0Light\0Classic\0"))
|
||||
{
|
||||
switch (style_idx)
|
||||
{
|
||||
case 0: ImGui::StyleColorsDark(); break;
|
||||
case 1: ImGui::StyleColorsLight(); break;
|
||||
case 2: ImGui::StyleColorsClassic(); break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
// This isn't worth putting in public API but we want Metrics to use it
|
||||
namespace ImGui { void ShowFontAtlas(ImFontAtlas* atlas); }
|
||||
|
||||
// Demo helper function to select among loaded fonts.
|
||||
// Here we use the regular BeginCombo()/EndCombo() api which is more the more flexible one.
|
||||
@ -5755,7 +5781,7 @@ void ImGui::ShowFontSelector(const char* label)
|
||||
}
|
||||
|
||||
// [Internal] Display details for a single font, called by ShowStyleEditor().
|
||||
static void NodeFont(ImFont* font)
|
||||
static void ShowFont(ImFont* font)
|
||||
{
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
ImGuiStyle& style = ImGui::GetStyle();
|
||||
@ -5765,9 +5791,13 @@ static void NodeFont(ImFont* font)
|
||||
if (!font_details_opened)
|
||||
return;
|
||||
|
||||
// Display preview text
|
||||
ImGui::PushFont(font);
|
||||
ImGui::Text("The quick brown fox jumps over the lazy dog");
|
||||
ImGui::PopFont();
|
||||
|
||||
// Display details
|
||||
ImGui::SetNextItemWidth(ImGui::GetFontSize() * 8);
|
||||
ImGui::DragFloat("Font scale", &font->Scale, 0.005f, 0.3f, 2.0f, "%.1f"); // Scale only this font
|
||||
ImGui::SameLine(); HelpMarker(
|
||||
"Note than the default embedded font is NOT meant to be scaled.\n\n"
|
||||
@ -5785,9 +5815,10 @@ static void NodeFont(ImFont* font)
|
||||
if (const ImFontConfig* cfg = &font->ConfigData[config_i])
|
||||
ImGui::BulletText("Input %d: \'%s\', Oversample: (%d,%d), PixelSnapH: %d, Offset: (%.1f,%.1f)",
|
||||
config_i, cfg->Name, cfg->OversampleH, cfg->OversampleV, cfg->PixelSnapH, cfg->GlyphOffset.x, cfg->GlyphOffset.y);
|
||||
|
||||
// Display all glyphs of the fonts in separate pages of 256 characters
|
||||
if (ImGui::TreeNode("Glyphs", "Glyphs (%d)", font->Glyphs.Size))
|
||||
{
|
||||
// Display all glyphs of the fonts in separate pages of 256 characters
|
||||
const ImU32 glyph_col = ImGui::GetColorU32(ImGuiCol_Text);
|
||||
for (unsigned int base = 0; base <= IM_UNICODE_CODEPOINT_MAX; base += 256)
|
||||
{
|
||||
@ -5842,6 +5873,50 @@ static void NodeFont(ImFont* font)
|
||||
ImGui::TreePop();
|
||||
}
|
||||
|
||||
void ImGui::ShowFontAtlas(ImFontAtlas* atlas)
|
||||
{
|
||||
for (int i = 0; i < atlas->Fonts.Size; i++)
|
||||
{
|
||||
ImFont* font = atlas->Fonts[i];
|
||||
ImGui::PushID(font);
|
||||
ShowFont(font);
|
||||
ImGui::PopID();
|
||||
}
|
||||
if (ImGui::TreeNode("Atlas texture", "Atlas texture (%dx%d pixels)", atlas->TexWidth, atlas->TexHeight))
|
||||
{
|
||||
ImVec4 tint_col = ImVec4(1.0f, 1.0f, 1.0f, 1.0f);
|
||||
ImVec4 border_col = ImVec4(1.0f, 1.0f, 1.0f, 0.5f);
|
||||
ImGui::Image(atlas->TexID, ImVec2((float)atlas->TexWidth, (float)atlas->TexHeight), ImVec2(0, 0), ImVec2(1, 1), tint_col, border_col);
|
||||
ImGui::TreePop();
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// [SECTION] Style Editor / ShowStyleEditor()
|
||||
//-----------------------------------------------------------------------------
|
||||
// - ShowStyleSelector()
|
||||
// - ShowStyleEditor()
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
// 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 = -1;
|
||||
if (ImGui::Combo(label, &style_idx, "Dark\0Light\0Classic\0"))
|
||||
{
|
||||
switch (style_idx)
|
||||
{
|
||||
case 0: ImGui::StyleColorsDark(); break;
|
||||
case 1: ImGui::StyleColorsLight(); break;
|
||||
case 2: ImGui::StyleColorsClassic(); break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void ImGui::ShowStyleEditor(ImGuiStyle* ref)
|
||||
{
|
||||
// You can pass in a reference ImGuiStyle structure to compare to, revert to and save to
|
||||
@ -5998,21 +6073,7 @@ void ImGui::ShowStyleEditor(ImGuiStyle* ref)
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
ImFontAtlas* atlas = io.Fonts;
|
||||
HelpMarker("Read FAQ and docs/FONTS.md for details on font loading.");
|
||||
ImGui::PushItemWidth(120);
|
||||
for (int i = 0; i < atlas->Fonts.Size; i++)
|
||||
{
|
||||
ImFont* font = atlas->Fonts[i];
|
||||
ImGui::PushID(font);
|
||||
NodeFont(font);
|
||||
ImGui::PopID();
|
||||
}
|
||||
if (ImGui::TreeNode("Atlas texture", "Atlas texture (%dx%d pixels)", atlas->TexWidth, atlas->TexHeight))
|
||||
{
|
||||
ImVec4 tint_col = ImVec4(1.0f, 1.0f, 1.0f, 1.0f);
|
||||
ImVec4 border_col = ImVec4(1.0f, 1.0f, 1.0f, 0.5f);
|
||||
ImGui::Image(atlas->TexID, ImVec2((float)atlas->TexWidth, (float)atlas->TexHeight), ImVec2(0, 0), ImVec2(1, 1), tint_col, border_col);
|
||||
ImGui::TreePop();
|
||||
}
|
||||
ImGui::ShowFontAtlas(atlas);
|
||||
|
||||
// Post-baking font scaling. Note that this is NOT the nice way of scaling fonts, read below.
|
||||
// (we enforce hard clamping manually as by default DragFloat/SliderFloat allows CTRL+Click text to get out of bounds).
|
||||
@ -6024,6 +6085,7 @@ void ImGui::ShowStyleEditor(ImGuiStyle* ref)
|
||||
"rebuild the font atlas, and call style.ScaleAllSizes() on a reference ImGuiStyle structure.\n"
|
||||
"Using those settings here will give you poor quality results.");
|
||||
static float window_scale = 1.0f;
|
||||
ImGui::PushItemWidth(ImGui::GetFontSize() * 8);
|
||||
if (ImGui::DragFloat("window scale", &window_scale, 0.005f, MIN_SCALE, MAX_SCALE, "%.2f", ImGuiSliderFlags_AlwaysClamp)) // Scale only this window
|
||||
ImGui::SetWindowFontScale(window_scale);
|
||||
ImGui::DragFloat("global scale", &io.FontGlobalScale, 0.005f, MIN_SCALE, MAX_SCALE, "%.2f", ImGuiSliderFlags_AlwaysClamp); // Scale everything
|
||||
@ -6043,7 +6105,7 @@ void ImGui::ShowStyleEditor(ImGuiStyle* ref)
|
||||
HelpMarker("Faster lines using texture data. Require backend to render with bilinear filtering (not point/nearest filtering).");
|
||||
|
||||
ImGui::Checkbox("Anti-aliased fill", &style.AntiAliasedFill);
|
||||
ImGui::PushItemWidth(100);
|
||||
ImGui::PushItemWidth(ImGui::GetFontSize() * 8);
|
||||
ImGui::DragFloat("Curve Tessellation Tolerance", &style.CurveTessellationTol, 0.02f, 0.10f, 10.0f, "%.2f");
|
||||
if (style.CurveTessellationTol < 0.10f) style.CurveTessellationTol = 0.10f;
|
||||
|
||||
|
100
imgui_draw.cpp
100
imgui_draw.cpp
@ -1,4 +1,4 @@
|
||||
// dear imgui, v1.82 WIP
|
||||
// dear imgui, v1.83
|
||||
// (drawing and font code)
|
||||
|
||||
/*
|
||||
@ -54,9 +54,12 @@ Index of this file:
|
||||
|
||||
// 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
|
||||
#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
|
||||
#pragma warning (disable: 6255) // [Static Analyzer] _alloca indicates failure by raising a stack overflow exception. Consider using _malloca instead.
|
||||
#pragma warning (disable: 26451) // [Static Analyzer] Arithmetic overflow : Using operator 'xxx' on a 4 byte value and then casting the result to a 8 byte value. Cast the value to the wider type before calling operator 'xxx' to avoid overflow(io.2).
|
||||
#pragma warning (disable: 26812) // [Static Analyzer] The enum type 'xxx' is unscoped. Prefer 'enum class' over 'enum' (Enum.3). [MSVC Static Analyzer)
|
||||
#endif
|
||||
|
||||
// Clang/GCC warnings with -Weverything
|
||||
@ -105,6 +108,9 @@ namespace IMGUI_STB_NAMESPACE
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning (push)
|
||||
#pragma warning (disable: 4456) // declaration of 'xx' hides previous local declaration
|
||||
#pragma warning (disable: 6011) // (stb_rectpack) Dereferencing NULL pointer 'cur->next'.
|
||||
#pragma warning (disable: 6385) // (stb_truetype) Reading invalid data from 'buffer': the readable size is '_Old_3`kernel_width' bytes, but '3' bytes may be read.
|
||||
#pragma warning (disable: 28182) // (stb_rectpack) Dereferencing NULL pointer. 'cur' contains the same NULL value as 'cur->next' did.
|
||||
#endif
|
||||
|
||||
#if defined(__clang__)
|
||||
@ -145,7 +151,7 @@ namespace IMGUI_STB_NAMESPACE
|
||||
#define STBTT_sqrt(x) ImSqrt(x)
|
||||
#define STBTT_pow(x,y) ImPow(x,y)
|
||||
#define STBTT_fabs(x) ImFabs(x)
|
||||
#define STBTT_ifloor(x) ((int)ImFloorStd(x))
|
||||
#define STBTT_ifloor(x) ((int)ImFloorSigned(x))
|
||||
#define STBTT_iceil(x) ((int)ImCeil(x))
|
||||
#define STBTT_STATIC
|
||||
#define STB_TRUETYPE_IMPLEMENTATION
|
||||
@ -688,8 +694,9 @@ void ImDrawList::PrimQuadUV(const ImVec2& a, const ImVec2& b, const ImVec2& c, c
|
||||
|
||||
// On AddPolyline() and AddConvexPolyFilled() we intentionally avoid using ImVec2 and superfluous function calls to optimize debug/non-inlined builds.
|
||||
// Those macros expects l-values.
|
||||
#define IM_NORMALIZE2F_OVER_ZERO(VX,VY) do { float d2 = VX*VX + VY*VY; if (d2 > 0.0f) { float inv_len = 1.0f / ImSqrt(d2); VX *= inv_len; VY *= inv_len; } } while (0)
|
||||
#define IM_FIXNORMAL2F(VX,VY) do { float d2 = VX*VX + VY*VY; if (d2 < 0.5f) d2 = 0.5f; float inv_lensq = 1.0f / d2; VX *= inv_lensq; VY *= inv_lensq; } while (0)
|
||||
#define IM_NORMALIZE2F_OVER_ZERO(VX,VY) do { float d2 = VX*VX + VY*VY; if (d2 > 0.0f) { float inv_len = ImRsqrt(d2); VX *= inv_len; VY *= inv_len; } } while (0)
|
||||
#define IM_FIXNORMAL2F_MAX_INVLEN2 100.0f // 500.0f (see #4053, #3366)
|
||||
#define IM_FIXNORMAL2F(VX,VY) do { float d2 = VX*VX + VY*VY; if (d2 > 0.000001f) { float inv_len2 = 1.0f / d2; if (inv_len2 > IM_FIXNORMAL2F_MAX_INVLEN2) inv_len2 = IM_FIXNORMAL2F_MAX_INVLEN2; VX *= inv_len2; VY *= inv_len2; } } while (0)
|
||||
|
||||
// TODO: Thickness anti-aliased lines cap are missing their AA fringe.
|
||||
// We avoid using the ImVec2 math operators here to reduce cost to a minimum for debug/non-inlined builds.
|
||||
@ -1037,7 +1044,6 @@ void ImDrawList::_PathArcToFastEx(const ImVec2& center, float radius, int a_min_
|
||||
_Path.push_back(center);
|
||||
return;
|
||||
}
|
||||
IM_ASSERT(a_min_sample <= a_max_sample);
|
||||
|
||||
// Calculate arc auto segment step size
|
||||
if (a_step <= 0)
|
||||
@ -1046,17 +1052,7 @@ void ImDrawList::_PathArcToFastEx(const ImVec2& center, float radius, int a_min_
|
||||
// Make sure we never do steps larger than one quarter of the circle
|
||||
a_step = ImClamp(a_step, 1, IM_DRAWLIST_ARCFAST_TABLE_SIZE / 4);
|
||||
|
||||
// Normalize a_min_sample to always start lie in [0..IM_DRAWLIST_ARCFAST_SAMPLE_MAX] range.
|
||||
if (a_min_sample < 0)
|
||||
{
|
||||
int normalized_sample = a_min_sample % IM_DRAWLIST_ARCFAST_SAMPLE_MAX;
|
||||
if (normalized_sample < 0)
|
||||
normalized_sample += IM_DRAWLIST_ARCFAST_SAMPLE_MAX;
|
||||
a_max_sample += (normalized_sample - a_min_sample);
|
||||
a_min_sample = normalized_sample;
|
||||
}
|
||||
|
||||
const int sample_range = a_max_sample - a_min_sample;
|
||||
const int sample_range = ImAbs(a_max_sample - a_min_sample);
|
||||
const int a_next_step = a_step;
|
||||
|
||||
int samples = sample_range + 1;
|
||||
@ -1082,16 +1078,40 @@ void ImDrawList::_PathArcToFastEx(const ImVec2& center, float radius, int a_min_
|
||||
ImVec2* out_ptr = _Path.Data + (_Path.Size - samples);
|
||||
|
||||
int sample_index = a_min_sample;
|
||||
for (int a = a_min_sample; a <= a_max_sample; a += a_step, sample_index += a_step, a_step = a_next_step)
|
||||
if (sample_index < 0 || sample_index >= IM_DRAWLIST_ARCFAST_SAMPLE_MAX)
|
||||
{
|
||||
// a_step is clamped to IM_DRAWLIST_ARCFAST_SAMPLE_MAX, so we have guaranteed that it will not wrap over range twice or more
|
||||
if (sample_index >= IM_DRAWLIST_ARCFAST_SAMPLE_MAX)
|
||||
sample_index -= IM_DRAWLIST_ARCFAST_SAMPLE_MAX;
|
||||
sample_index = sample_index % IM_DRAWLIST_ARCFAST_SAMPLE_MAX;
|
||||
if (sample_index < 0)
|
||||
sample_index += IM_DRAWLIST_ARCFAST_SAMPLE_MAX;
|
||||
}
|
||||
|
||||
const ImVec2 s = _Data->ArcFastVtx[sample_index];
|
||||
out_ptr->x = center.x + s.x * radius;
|
||||
out_ptr->y = center.y + s.y * radius;
|
||||
out_ptr++;
|
||||
if (a_max_sample >= a_min_sample)
|
||||
{
|
||||
for (int a = a_min_sample; a <= a_max_sample; a += a_step, sample_index += a_step, a_step = a_next_step)
|
||||
{
|
||||
// a_step is clamped to IM_DRAWLIST_ARCFAST_SAMPLE_MAX, so we have guaranteed that it will not wrap over range twice or more
|
||||
if (sample_index >= IM_DRAWLIST_ARCFAST_SAMPLE_MAX)
|
||||
sample_index -= IM_DRAWLIST_ARCFAST_SAMPLE_MAX;
|
||||
|
||||
const ImVec2 s = _Data->ArcFastVtx[sample_index];
|
||||
out_ptr->x = center.x + s.x * radius;
|
||||
out_ptr->y = center.y + s.y * radius;
|
||||
out_ptr++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int a = a_min_sample; a >= a_max_sample; a -= a_step, sample_index -= a_step, a_step = a_next_step)
|
||||
{
|
||||
// a_step is clamped to IM_DRAWLIST_ARCFAST_SAMPLE_MAX, so we have guaranteed that it will not wrap over range twice or more
|
||||
if (sample_index < 0)
|
||||
sample_index += IM_DRAWLIST_ARCFAST_SAMPLE_MAX;
|
||||
|
||||
const ImVec2 s = _Data->ArcFastVtx[sample_index];
|
||||
out_ptr->x = center.x + s.x * radius;
|
||||
out_ptr->y = center.y + s.y * radius;
|
||||
out_ptr++;
|
||||
}
|
||||
}
|
||||
|
||||
if (extra_max_sample)
|
||||
@ -1116,7 +1136,6 @@ void ImDrawList::_PathArcToN(const ImVec2& center, float radius, float a_min, fl
|
||||
_Path.push_back(center);
|
||||
return;
|
||||
}
|
||||
IM_ASSERT(a_min <= a_max);
|
||||
|
||||
// Note that we are adding a point at both a_min and a_max.
|
||||
// If you are trying to draw a full closed circle you don't want the overlapping points!
|
||||
@ -1136,7 +1155,6 @@ void ImDrawList::PathArcToFast(const ImVec2& center, float radius, int a_min_of_
|
||||
_Path.push_back(center);
|
||||
return;
|
||||
}
|
||||
IM_ASSERT(a_min_of_12 <= a_max_of_12);
|
||||
_PathArcToFastEx(center, radius, a_min_of_12 * IM_DRAWLIST_ARCFAST_SAMPLE_MAX / 12, a_max_of_12 * IM_DRAWLIST_ARCFAST_SAMPLE_MAX / 12, 0);
|
||||
}
|
||||
|
||||
@ -1147,7 +1165,6 @@ void ImDrawList::PathArcTo(const ImVec2& center, float radius, float a_min, floa
|
||||
_Path.push_back(center);
|
||||
return;
|
||||
}
|
||||
IM_ASSERT(a_min <= a_max);
|
||||
|
||||
if (num_segments > 0)
|
||||
{
|
||||
@ -1158,28 +1175,33 @@ void ImDrawList::PathArcTo(const ImVec2& center, float radius, float a_min, floa
|
||||
// Automatic segment count
|
||||
if (radius <= _Data->ArcFastRadiusCutoff)
|
||||
{
|
||||
const bool a_is_reverse = a_max < a_min;
|
||||
|
||||
// We are going to use precomputed values for mid samples.
|
||||
// Determine first and last sample in lookup table that belong to the arc.
|
||||
const int a_min_sample = (int)ImCeil(IM_DRAWLIST_ARCFAST_SAMPLE_MAX * a_min / (IM_PI * 2.0f));
|
||||
const int a_max_sample = (int)( IM_DRAWLIST_ARCFAST_SAMPLE_MAX * a_max / (IM_PI * 2.0f));
|
||||
const int a_mid_samples = ImMax(a_max_sample - a_min_sample, 0);
|
||||
const float a_min_sample_f = IM_DRAWLIST_ARCFAST_SAMPLE_MAX * a_min / (IM_PI * 2.0f);
|
||||
const float a_max_sample_f = IM_DRAWLIST_ARCFAST_SAMPLE_MAX * a_max / (IM_PI * 2.0f);
|
||||
|
||||
const int a_min_sample = a_is_reverse ? (int)ImFloorSigned(a_min_sample_f) : (int)ImCeil(a_min_sample_f);
|
||||
const int a_max_sample = a_is_reverse ? (int)ImCeil(a_max_sample_f) : (int)ImFloorSigned(a_max_sample_f);
|
||||
const int a_mid_samples = a_is_reverse ? ImMax(a_min_sample - a_max_sample, 0) : ImMax(a_max_sample - a_min_sample, 0);
|
||||
|
||||
const float a_min_segment_angle = a_min_sample * IM_PI * 2.0f / IM_DRAWLIST_ARCFAST_SAMPLE_MAX;
|
||||
const float a_max_segment_angle = a_max_sample * IM_PI * 2.0f / IM_DRAWLIST_ARCFAST_SAMPLE_MAX;
|
||||
const bool a_emit_start = (a_min_segment_angle - a_min) > 0.0f;
|
||||
const bool a_emit_end = (a_max - a_max_segment_angle) > 0.0f;
|
||||
const bool a_emit_start = (a_min_segment_angle - a_min) != 0.0f;
|
||||
const bool a_emit_end = (a_max - a_max_segment_angle) != 0.0f;
|
||||
|
||||
_Path.reserve(_Path.Size + (a_mid_samples + 1 + (a_emit_start ? 1 : 0) + (a_emit_end ? 1 : 0)));
|
||||
if (a_emit_start)
|
||||
_Path.push_back(ImVec2(center.x + ImCos(a_min) * radius, center.y + ImSin(a_min) * radius));
|
||||
if (a_max_sample >= a_min_sample)
|
||||
if (a_mid_samples > 0)
|
||||
_PathArcToFastEx(center, radius, a_min_sample, a_max_sample, 0);
|
||||
if (a_emit_end)
|
||||
_Path.push_back(ImVec2(center.x + ImCos(a_max) * radius, center.y + ImSin(a_max) * radius));
|
||||
}
|
||||
else
|
||||
{
|
||||
const float arc_length = a_max - a_min;
|
||||
const float arc_length = ImAbs(a_max - a_min);
|
||||
const int circle_segment_count = _CalcCircleAutoSegmentCount(radius);
|
||||
const int arc_segment_count = ImMax((int)ImCeil(circle_segment_count * arc_length / (IM_PI * 2.0f)), (int)(2.0f * IM_PI / arc_length));
|
||||
_PathArcToN(center, radius, a_min, a_max, arc_segment_count);
|
||||
@ -3469,6 +3491,7 @@ ImVec2 ImFont::CalcTextSizeA(float size, float max_width, float wrap_width, cons
|
||||
return text_size;
|
||||
}
|
||||
|
||||
// Note: as with every ImDrawList drawing function, this expects that the font atlas texture is bound.
|
||||
void ImFont::RenderChar(ImDrawList* draw_list, float size, ImVec2 pos, ImU32 col, ImWchar c) const
|
||||
{
|
||||
const ImFontGlyph* glyph = FindGlyph(c);
|
||||
@ -3483,6 +3506,7 @@ void ImFont::RenderChar(ImDrawList* draw_list, float size, ImVec2 pos, ImU32 col
|
||||
draw_list->PrimRectUV(ImVec2(pos.x + glyph->X0 * scale, pos.y + glyph->Y0 * scale), ImVec2(pos.x + glyph->X1 * scale, pos.y + glyph->Y1 * scale), ImVec2(glyph->U0, glyph->V0), ImVec2(glyph->U1, glyph->V1), col);
|
||||
}
|
||||
|
||||
// Note: as with every ImDrawList drawing function, this expects that the font atlas texture is bound.
|
||||
void ImFont::RenderText(ImDrawList* draw_list, float size, ImVec2 pos, ImU32 col, const ImVec4& clip_rect, const char* text_begin, const char* text_end, float wrap_width, bool cpu_fine_clip) const
|
||||
{
|
||||
if (!text_end)
|
||||
@ -3752,7 +3776,7 @@ void ImGui::RenderMouseCursor(ImDrawList* draw_list, ImVec2 pos, float scale, Im
|
||||
if (font_atlas->GetMouseCursorTexData(mouse_cursor, &offset, &size, &uv[0], &uv[2]))
|
||||
{
|
||||
pos -= offset;
|
||||
const ImTextureID tex_id = font_atlas->TexID;
|
||||
ImTextureID tex_id = font_atlas->TexID;
|
||||
draw_list->PushTextureID(tex_id);
|
||||
draw_list->AddImage(tex_id, pos + ImVec2(1, 0) * scale, pos + (ImVec2(1, 0) + size) * scale, uv[2], uv[3], col_shadow);
|
||||
draw_list->AddImage(tex_id, pos + ImVec2(2, 0) * scale, pos + (ImVec2(2, 0) + size) * scale, uv[2], uv[3], col_shadow);
|
||||
|
259
imgui_internal.h
259
imgui_internal.h
@ -1,4 +1,4 @@
|
||||
// dear imgui, v1.82 WIP
|
||||
// dear imgui, v1.83
|
||||
// (internal structures/api)
|
||||
|
||||
// You may use this file to debug, understand or extend ImGui features but we don't provide any guarantee of forward compatibility!
|
||||
@ -51,10 +51,19 @@ Index of this file:
|
||||
#include <math.h> // sqrtf, fabsf, fmodf, powf, floorf, ceilf, cosf, sinf
|
||||
#include <limits.h> // INT_MIN, INT_MAX
|
||||
|
||||
// Enable SSE intrinsics if available
|
||||
#if defined __SSE__ || defined __x86_64__ || defined _M_X64
|
||||
#define IMGUI_ENABLE_SSE
|
||||
#include <immintrin.h>
|
||||
#endif
|
||||
|
||||
// Visual Studio warnings
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning (push)
|
||||
#pragma warning (disable: 4251) // class 'xxx' needs to have dll-interface to be used by clients of struct 'xxx' // when IMGUI_API is set to__declspec(dllexport)
|
||||
#pragma warning (disable: 4251) // class 'xxx' needs to have dll-interface to be used by clients of struct 'xxx' // when IMGUI_API is set to__declspec(dllexport)
|
||||
#pragma warning (disable: 26812) // The enum type 'xxx' is unscoped. Prefer 'enum class' over 'enum' (Enum.3). [MSVC Static Analyzer)
|
||||
#pragma warning (disable: 26495) // [Static Analyzer] Variable 'XXX' is uninitialized. Always initialize a member variable (type.6).
|
||||
|
||||
#endif
|
||||
|
||||
// Clang/GCC warnings with -Weverything
|
||||
@ -64,6 +73,7 @@ Index of this file:
|
||||
#pragma clang diagnostic ignored "-Wunknown-warning-option" // warning: unknown warning group 'xxx'
|
||||
#endif
|
||||
#pragma clang diagnostic ignored "-Wunknown-pragmas" // warning: unknown warning group 'xxx'
|
||||
#pragma clang diagnostic ignored "-Wfloat-equal" // warning: comparing floating point with == or != is unsafe // storing and comparing against same constants ok, for ImFloorSigned()
|
||||
#pragma clang diagnostic ignored "-Wunused-function" // for stb_textedit.h
|
||||
#pragma clang diagnostic ignored "-Wmissing-prototypes" // for stb_textedit.h
|
||||
#pragma clang diagnostic ignored "-Wold-style-cast"
|
||||
@ -106,7 +116,7 @@ struct ImGuiGroupData; // Stacked storage data for BeginGroup()/End
|
||||
struct ImGuiInputTextState; // Internal state of the currently focused/edited text input box
|
||||
struct ImGuiLastItemDataBackup; // Backup and restore IsItemHovered() internal data
|
||||
struct ImGuiMenuColumns; // Simple column measurement, currently used for MenuItem() only
|
||||
struct ImGuiNavMoveResult; // Result of a gamepad/keyboard directional navigation move query result
|
||||
struct ImGuiNavItemData; // Result of a gamepad/keyboard directional navigation move query result
|
||||
struct ImGuiMetricsConfig; // Storage for ShowMetricsWindow() and DebugNodeXXX() functions
|
||||
struct ImGuiNextWindowData; // Storage for SetNextWindow** functions
|
||||
struct ImGuiNextItemData; // Storage for SetNextItem** functions
|
||||
@ -120,15 +130,17 @@ struct ImGuiTabBar; // Storage for a tab bar
|
||||
struct ImGuiTabItem; // Storage for a tab item (within a tab bar)
|
||||
struct ImGuiTable; // Storage for a table
|
||||
struct ImGuiTableColumn; // Storage for one column of a table
|
||||
struct ImGuiTableTempData; // Temporary storage for one table (one per table in the stack), shared between tables.
|
||||
struct ImGuiTableSettings; // Storage for a table .ini settings
|
||||
struct ImGuiTableColumnsSettings; // Storage for a column .ini settings
|
||||
struct ImGuiWindow; // Storage for one window
|
||||
struct ImGuiWindowTempData; // Temporary storage for one window (that's the data which in theory we could ditch at the end of the frame)
|
||||
struct ImGuiWindowTempData; // Temporary storage for one window (that's the data which in theory we could ditch at the end of the frame, in practice we currently keep it for each window)
|
||||
struct ImGuiWindowSettings; // Storage for a window .ini settings (we keep one of those even if the actual window wasn't instanced during this session)
|
||||
|
||||
// Use your programming IDE "Go to definition" facility on the names of the center columns to find the actual flags/enum lists.
|
||||
typedef int ImGuiLayoutType; // -> enum ImGuiLayoutType_ // Enum: Horizontal or vertical
|
||||
typedef int ImGuiItemFlags; // -> enum ImGuiItemFlags_ // Flags: for PushItemFlag()
|
||||
typedef int ImGuiItemAddFlags; // -> enum ImGuiItemAddFlags_ // Flags: for ItemAdd()
|
||||
typedef int ImGuiItemStatusFlags; // -> enum ImGuiItemStatusFlags_ // Flags: for DC.LastItemStatusFlags
|
||||
typedef int ImGuiOldColumnFlags; // -> enum ImGuiOldColumnFlags_ // Flags: for BeginColumns()
|
||||
typedef int ImGuiNavHighlightFlags; // -> enum ImGuiNavHighlightFlags_ // Flags: for RenderNavHighlight()
|
||||
@ -227,6 +239,13 @@ namespace ImStb
|
||||
#define IMGUI_CDECL
|
||||
#endif
|
||||
|
||||
// Warnings
|
||||
#if defined(_MSC_VER) && !defined(__clang__)
|
||||
#define IM_MSVC_WARNING_SUPPRESS(XXXX) __pragma(warning(suppress: XXXX))
|
||||
#else
|
||||
#define IM_MSVC_WARNING_SUPPRESS(XXXX)
|
||||
#endif
|
||||
|
||||
// Debug Tools
|
||||
// Use 'Metrics->Tools->Item Picker' to break into the call-stack of a specific item.
|
||||
#ifndef IM_DEBUG_BREAK
|
||||
@ -314,6 +333,7 @@ IMGUI_API int ImTextCountUtf8BytesFromStr(const ImWchar* in_text, cons
|
||||
// We are keeping those disabled by default so they don't leak in user space, to allow user enabling implicit cast operators between ImVec2 and their own types (using IM_VEC2_CLASS_EXTRA etc.)
|
||||
// We unfortunately don't have a unary- operator for ImVec2 because this would needs to be defined inside the class itself.
|
||||
#ifdef IMGUI_DEFINE_MATH_OPERATORS
|
||||
IM_MSVC_RUNTIME_CHECKS_OFF
|
||||
static inline ImVec2 operator*(const ImVec2& lhs, const float rhs) { return ImVec2(lhs.x * rhs, lhs.y * rhs); }
|
||||
static inline ImVec2 operator/(const ImVec2& lhs, const float rhs) { return ImVec2(lhs.x / rhs, lhs.y / rhs); }
|
||||
static inline ImVec2 operator+(const ImVec2& lhs, const ImVec2& rhs) { return ImVec2(lhs.x + rhs.x, lhs.y + rhs.y); }
|
||||
@ -329,6 +349,7 @@ static inline ImVec2& operator/=(ImVec2& lhs, const ImVec2& rhs)
|
||||
static inline ImVec4 operator+(const ImVec4& lhs, const ImVec4& rhs) { return ImVec4(lhs.x + rhs.x, lhs.y + rhs.y, lhs.z + rhs.z, lhs.w + rhs.w); }
|
||||
static inline ImVec4 operator-(const ImVec4& lhs, const ImVec4& rhs) { return ImVec4(lhs.x - rhs.x, lhs.y - rhs.y, lhs.z - rhs.z, lhs.w - rhs.w); }
|
||||
static inline ImVec4 operator*(const ImVec4& lhs, const ImVec4& rhs) { return ImVec4(lhs.x * rhs.x, lhs.y * rhs.y, lhs.z * rhs.z, lhs.w * rhs.w); }
|
||||
IM_MSVC_RUNTIME_CHECKS_RESTORE
|
||||
#endif
|
||||
|
||||
// Helpers: File System
|
||||
@ -354,6 +375,7 @@ IMGUI_API ImU64 ImFileWrite(const void* data, ImU64 size, ImU64 coun
|
||||
IMGUI_API void* ImFileLoadToMemory(const char* filename, const char* mode, size_t* out_file_size = NULL, int padding_bytes = 0);
|
||||
|
||||
// Helpers: Maths
|
||||
IM_MSVC_RUNTIME_CHECKS_OFF
|
||||
// - Wrapper for standard libs functions. (Note that imgui_demo.cpp does _not_ use them to keep the code easy to copy)
|
||||
#ifndef IMGUI_DISABLE_DEFAULT_MATH_FUNCTIONS
|
||||
#define ImFabs(X) fabsf(X)
|
||||
@ -364,16 +386,23 @@ IMGUI_API void* ImFileLoadToMemory(const char* filename, const char*
|
||||
#define ImAcos(X) acosf(X)
|
||||
#define ImAtan2(Y, X) atan2f((Y), (X))
|
||||
#define ImAtof(STR) atof(STR)
|
||||
#define ImFloorStd(X) floorf(X) // We already uses our own ImFloor() { return (float)(int)v } internally so the standard one wrapper is named differently (it's used by e.g. stb_truetype)
|
||||
//#define ImFloorStd(X) floorf(X) // We use our own, see ImFloor() and ImFloorSigned()
|
||||
#define ImCeil(X) ceilf(X)
|
||||
static inline float ImPow(float x, float y) { return powf(x, y); } // DragBehaviorT/SliderBehaviorT uses ImPow with either float/double and need the precision
|
||||
static inline double ImPow(double x, double y) { return pow(x, y); }
|
||||
static inline float ImLog(float x) { return logf(x); } // DragBehaviorT/SliderBehaviorT uses ImLog with either float/double and need the precision
|
||||
static inline double ImLog(double x) { return log(x); }
|
||||
static inline int ImAbs(int x) { return x < 0 ? -x : x; }
|
||||
static inline float ImAbs(float x) { return fabsf(x); }
|
||||
static inline double ImAbs(double x) { return fabs(x); }
|
||||
static inline float ImSign(float x) { return (x < 0.0f) ? -1.0f : ((x > 0.0f) ? 1.0f : 0.0f); } // Sign operator - returns -1, 0 or 1 based on sign of argument
|
||||
static inline double ImSign(double x) { return (x < 0.0) ? -1.0 : ((x > 0.0) ? 1.0 : 0.0); }
|
||||
#ifdef IMGUI_ENABLE_SSE
|
||||
static inline float ImRsqrt(float x) { return _mm_cvtss_f32(_mm_rsqrt_ss(_mm_set_ss(x))); }
|
||||
#else
|
||||
static inline float ImRsqrt(float x) { return 1.0f / sqrtf(x); }
|
||||
#endif
|
||||
static inline double ImRsqrt(double x) { return 1.0 / sqrt(x); }
|
||||
#endif
|
||||
// - ImMin/ImMax/ImClamp/ImLerp/ImSwap are used by widgets which support variety of types: signed/unsigned int/long long float/double
|
||||
// (Exceptionally using templates here but we could also redefine them for those types)
|
||||
@ -394,14 +423,16 @@ static inline ImVec4 ImLerp(const ImVec4& a, const ImVec4& b, float t)
|
||||
static inline float ImSaturate(float f) { return (f < 0.0f) ? 0.0f : (f > 1.0f) ? 1.0f : f; }
|
||||
static inline float ImLengthSqr(const ImVec2& lhs) { return (lhs.x * lhs.x) + (lhs.y * lhs.y); }
|
||||
static inline float ImLengthSqr(const ImVec4& lhs) { return (lhs.x * lhs.x) + (lhs.y * lhs.y) + (lhs.z * lhs.z) + (lhs.w * lhs.w); }
|
||||
static inline float ImInvLength(const ImVec2& lhs, float fail_value) { float d = (lhs.x * lhs.x) + (lhs.y * lhs.y); if (d > 0.0f) return 1.0f / ImSqrt(d); return fail_value; }
|
||||
static inline float ImInvLength(const ImVec2& lhs, float fail_value) { float d = (lhs.x * lhs.x) + (lhs.y * lhs.y); if (d > 0.0f) return ImRsqrt(d); return fail_value; }
|
||||
static inline float ImFloor(float f) { return (float)(int)(f); }
|
||||
static inline float ImFloorSigned(float f) { return (float)((f >= 0 || (int)f == f) ? (int)f : (int)f - 1); } // Decent replacement for floorf()
|
||||
static inline ImVec2 ImFloor(const ImVec2& v) { return ImVec2((float)(int)(v.x), (float)(int)(v.y)); }
|
||||
static inline int ImModPositive(int a, int b) { return (a + b) % b; }
|
||||
static inline float ImDot(const ImVec2& a, const ImVec2& b) { return a.x * b.x + a.y * b.y; }
|
||||
static inline ImVec2 ImRotate(const ImVec2& v, float cos_a, float sin_a) { return ImVec2(v.x * cos_a - v.y * sin_a, v.x * sin_a + v.y * cos_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); }
|
||||
IM_MSVC_RUNTIME_CHECKS_RESTORE
|
||||
|
||||
// Helpers: Geometry
|
||||
IMGUI_API ImVec2 ImBezierCubicCalc(const ImVec2& p1, const ImVec2& p2, const ImVec2& p3, const ImVec2& p4, float t);
|
||||
@ -417,6 +448,7 @@ IMGUI_API ImGuiDir ImGetDirQuadrantFromDelta(float dx, float dy);
|
||||
|
||||
// Helper: ImVec1 (1D vector)
|
||||
// (this odd construct is used to facilitate the transition between 1D and 2D, and the maintenance of some branches/patches)
|
||||
IM_MSVC_RUNTIME_CHECKS_OFF
|
||||
struct ImVec1
|
||||
{
|
||||
float x;
|
||||
@ -470,6 +502,7 @@ struct IMGUI_API ImRect
|
||||
bool IsInverted() const { return Min.x > Max.x || Min.y > Max.y; }
|
||||
ImVec4 ToVec4() const { return ImVec4(Min.x, Min.y, Max.x, Max.y); }
|
||||
};
|
||||
IM_MSVC_RUNTIME_CHECKS_RESTORE
|
||||
|
||||
// Helper: ImBitArray
|
||||
inline bool ImBitArrayTestBit(const ImU32* arr, int n) { ImU32 mask = (ImU32)1 << (n & 31); return (arr[n >> 5] & mask) != 0; }
|
||||
@ -489,12 +522,12 @@ inline void ImBitArraySetBitRange(ImU32* arr, int n, int n2) // Works on ran
|
||||
}
|
||||
|
||||
// Helper: ImBitArray class (wrapper over ImBitArray functions)
|
||||
// Store 1-bit per value. NOT CLEARED by constructor.
|
||||
// Store 1-bit per value.
|
||||
template<int BITCOUNT>
|
||||
struct IMGUI_API ImBitArray
|
||||
{
|
||||
ImU32 Storage[(BITCOUNT + 31) >> 5];
|
||||
ImBitArray() { }
|
||||
ImBitArray() { ClearAllBits(); }
|
||||
void ClearAllBits() { memset(Storage, 0, sizeof(Storage)); }
|
||||
void SetAllBits() { memset(Storage, 255, sizeof(Storage)); }
|
||||
bool TestBit(int n) const { IM_ASSERT(n < BITCOUNT); return ImBitArrayTestBit(Storage, n); }
|
||||
@ -694,32 +727,51 @@ enum ImGuiItemFlags_
|
||||
ImGuiItemFlags_NoNavDefaultFocus = 1 << 4, // false
|
||||
ImGuiItemFlags_SelectableDontClosePopup = 1 << 5, // false // MenuItem/Selectable() automatically closes current Popup window
|
||||
ImGuiItemFlags_MixedValue = 1 << 6, // false // [BETA] Represent a mixed/indeterminate value, generally multi-selection where values differ. Currently only supported by Checkbox() (later should support all sorts of widgets)
|
||||
ImGuiItemFlags_ReadOnly = 1 << 7, // false // [ALPHA] Allow hovering interactions but underlying value is not changed.
|
||||
ImGuiItemFlags_Default_ = 0
|
||||
ImGuiItemFlags_ReadOnly = 1 << 7 // false // [ALPHA] Allow hovering interactions but underlying value is not changed.
|
||||
};
|
||||
|
||||
// Flags for ItemAdd()
|
||||
// FIXME-NAV: _Focusable is _ALMOST_ what you would expect to be called '_TabStop' but because SetKeyboardFocusHere() works on items with no TabStop we distinguish Focusable from TabStop.
|
||||
enum ImGuiItemAddFlags_
|
||||
{
|
||||
ImGuiItemAddFlags_None = 0,
|
||||
ImGuiItemAddFlags_Focusable = 1 << 0 // FIXME-NAV: In current/legacy scheme, Focusable+TabStop support are opt-in by widgets. We will transition it toward being opt-out, so this flag is expected to eventually disappear.
|
||||
};
|
||||
|
||||
// Storage for LastItem data
|
||||
enum ImGuiItemStatusFlags_
|
||||
{
|
||||
ImGuiItemStatusFlags_None = 0,
|
||||
ImGuiItemStatusFlags_HoveredRect = 1 << 0,
|
||||
ImGuiItemStatusFlags_HasDisplayRect = 1 << 1, // LastItemDisplayRect is valid
|
||||
ImGuiItemStatusFlags_HoveredRect = 1 << 0, // Mouse position is within item rectangle (does NOT mean that the window is in correct z-order and can be hovered!, this is only one part of the most-common IsItemHovered test)
|
||||
ImGuiItemStatusFlags_HasDisplayRect = 1 << 1, // window->DC.LastItemDisplayRect is valid
|
||||
ImGuiItemStatusFlags_Edited = 1 << 2, // Value exposed by item was edited in the current frame (should match the bool return value of most widgets)
|
||||
ImGuiItemStatusFlags_ToggledSelection = 1 << 3, // Set when Selectable(), TreeNode() reports toggling a selection. We can't report "Selected" because reporting the change allows us to handle clipping with less issues.
|
||||
ImGuiItemStatusFlags_ToggledSelection = 1 << 3, // Set when Selectable(), TreeNode() reports toggling a selection. We can't report "Selected", only state changes, in order to easily handle clipping with less issues.
|
||||
ImGuiItemStatusFlags_ToggledOpen = 1 << 4, // Set when TreeNode() reports toggling their open state.
|
||||
ImGuiItemStatusFlags_HasDeactivated = 1 << 5, // Set if the widget/group is able to provide data for the ImGuiItemStatusFlags_Deactivated flag.
|
||||
ImGuiItemStatusFlags_Deactivated = 1 << 6, // Only valid if ImGuiItemStatusFlags_HasDeactivated is set.
|
||||
ImGuiItemStatusFlags_HoveredWindow = 1 << 7 // Override the HoveredWindow test to allow cross-window hover testing.
|
||||
ImGuiItemStatusFlags_HoveredWindow = 1 << 7, // Override the HoveredWindow test to allow cross-window hover testing.
|
||||
ImGuiItemStatusFlags_FocusedByCode = 1 << 8, // Set when the Focusable item just got focused from code.
|
||||
ImGuiItemStatusFlags_FocusedByTabbing = 1 << 9, // Set when the Focusable item just got focused by Tabbing.
|
||||
ImGuiItemStatusFlags_Focused = ImGuiItemStatusFlags_FocusedByCode | ImGuiItemStatusFlags_FocusedByTabbing
|
||||
|
||||
#ifdef IMGUI_ENABLE_TEST_ENGINE
|
||||
, // [imgui_tests only]
|
||||
ImGuiItemStatusFlags_Openable = 1 << 10, //
|
||||
ImGuiItemStatusFlags_Opened = 1 << 11, //
|
||||
ImGuiItemStatusFlags_Checkable = 1 << 12, //
|
||||
ImGuiItemStatusFlags_Checked = 1 << 13 //
|
||||
ImGuiItemStatusFlags_Openable = 1 << 20, //
|
||||
ImGuiItemStatusFlags_Opened = 1 << 21, //
|
||||
ImGuiItemStatusFlags_Checkable = 1 << 22, //
|
||||
ImGuiItemStatusFlags_Checked = 1 << 23 //
|
||||
#endif
|
||||
};
|
||||
|
||||
// Extend ImGuiInputTextFlags_
|
||||
enum ImGuiInputTextFlagsPrivate_
|
||||
{
|
||||
// [Internal]
|
||||
ImGuiInputTextFlags_Multiline = 1 << 26, // For internal use by InputTextMultiline()
|
||||
ImGuiInputTextFlags_NoMarkEdited = 1 << 27, // For internal use by functions using InputText() before reformatting data
|
||||
ImGuiInputTextFlags_MergedItem = 1 << 28 // For internal use by TempInputText(), will skip calling ItemAdd(). Require bounding-box to strictly match.
|
||||
};
|
||||
|
||||
// Extend ImGuiButtonFlags_
|
||||
enum ImGuiButtonFlagsPrivate_
|
||||
{
|
||||
@ -827,6 +879,7 @@ enum ImGuiInputSource
|
||||
ImGuiInputSource_Keyboard,
|
||||
ImGuiInputSource_Gamepad,
|
||||
ImGuiInputSource_Nav, // Stored in g.ActiveIdSource only
|
||||
ImGuiInputSource_Clipboard, // Currently only used by InputText()
|
||||
ImGuiInputSource_COUNT
|
||||
};
|
||||
|
||||
@ -976,7 +1029,7 @@ struct IMGUI_API ImGuiInputTextState
|
||||
bool CursorFollow; // set when we want scrolling to follow the current cursor position (not always!)
|
||||
bool SelectedAllMouseLock; // after a double-click to select all, we ignore further mouse drags to update selection
|
||||
bool Edited; // edited this frame
|
||||
ImGuiInputTextFlags UserFlags; // Temporarily set while we call user's callback
|
||||
ImGuiInputTextFlags Flags; // copy of InputText() flags
|
||||
ImGuiInputTextCallback UserCallback; // "
|
||||
void* UserCallbackData; // "
|
||||
|
||||
@ -1009,18 +1062,18 @@ struct ImGuiPopupData
|
||||
ImGuiPopupData() { memset(this, 0, sizeof(*this)); OpenFrameCount = -1; }
|
||||
};
|
||||
|
||||
struct ImGuiNavMoveResult
|
||||
struct ImGuiNavItemData
|
||||
{
|
||||
ImGuiWindow* Window; // Best candidate window
|
||||
ImGuiID ID; // Best candidate ID
|
||||
ImGuiID FocusScopeId; // Best candidate focus scope ID
|
||||
float DistBox; // Best candidate box distance to current NavId
|
||||
float DistCenter; // Best candidate center distance to current NavId
|
||||
float DistAxial;
|
||||
ImRect RectRel; // Best candidate bounding box in window relative space
|
||||
ImGuiWindow* Window; // Init,Move // Best candidate window (result->ItemWindow->RootWindowForNav == request->Window)
|
||||
ImGuiID ID; // Init,Move // Best candidate item ID
|
||||
ImGuiID FocusScopeId; // Init,Move // Best candidate focus scope ID
|
||||
ImRect RectRel; // Init,Move // Best candidate bounding box in window relative space
|
||||
float DistBox; // Move // Best candidate box distance to current NavId
|
||||
float DistCenter; // Move // Best candidate center distance to current NavId
|
||||
float DistAxial; // Move // Best candidate axial distance to current NavId
|
||||
|
||||
ImGuiNavMoveResult() { Clear(); }
|
||||
void Clear() { Window = NULL; ID = FocusScopeId = 0; DistBox = DistCenter = DistAxial = FLT_MAX; RectRel = ImRect(); }
|
||||
ImGuiNavItemData() { Clear(); }
|
||||
void Clear() { Window = NULL; ID = FocusScopeId = 0; RectRel = ImRect(); DistBox = DistCenter = DistAxial = FLT_MAX; }
|
||||
};
|
||||
|
||||
enum ImGuiNextWindowDataFlags_
|
||||
@ -1180,14 +1233,21 @@ struct ImGuiViewportP : public ImGuiViewport
|
||||
|
||||
ImVec2 WorkOffsetMin; // Work Area: Offset from Pos to top-left corner of Work Area. Generally (0,0) or (0,+main_menu_bar_height). Work Area is Full Area but without menu-bars/status-bars (so WorkArea always fit inside Pos/Size!)
|
||||
ImVec2 WorkOffsetMax; // Work Area: Offset from Pos+Size to bottom-right corner of Work Area. Generally (0,0) or (0,-status_bar_height).
|
||||
ImVec2 CurrWorkOffsetMin; // Work Area: Offset being built/increased during current frame
|
||||
ImVec2 CurrWorkOffsetMax; // Work Area: Offset being built/decreased during current frame
|
||||
ImVec2 BuildWorkOffsetMin; // Work Area: Offset being built during current frame. Generally >= 0.0f.
|
||||
ImVec2 BuildWorkOffsetMax; // Work Area: Offset being built during current frame. Generally <= 0.0f.
|
||||
|
||||
ImGuiViewportP() { DrawListsLastFrame[0] = DrawListsLastFrame[1] = -1; DrawLists[0] = DrawLists[1] = NULL; }
|
||||
~ImGuiViewportP() { if (DrawLists[0]) IM_DELETE(DrawLists[0]); if (DrawLists[1]) IM_DELETE(DrawLists[1]); }
|
||||
ImRect GetMainRect() const { return ImRect(Pos.x, Pos.y, Pos.x + Size.x, Pos.y + Size.y); }
|
||||
ImRect GetWorkRect() const { return ImRect(WorkPos.x, WorkPos.y, WorkPos.x + WorkSize.x, WorkPos.y + WorkSize.y); }
|
||||
void UpdateWorkRect() { WorkPos = ImVec2(Pos.x + WorkOffsetMin.x, Pos.y + WorkOffsetMin.y); WorkSize = ImVec2(ImMax(0.0f, Size.x - WorkOffsetMin.x + WorkOffsetMax.x), ImMax(0.0f, Size.y - WorkOffsetMin.y + WorkOffsetMax.y)); }
|
||||
ImGuiViewportP() { DrawListsLastFrame[0] = DrawListsLastFrame[1] = -1; DrawLists[0] = DrawLists[1] = NULL; }
|
||||
~ImGuiViewportP() { if (DrawLists[0]) IM_DELETE(DrawLists[0]); if (DrawLists[1]) IM_DELETE(DrawLists[1]); }
|
||||
|
||||
// Calculate work rect pos/size given a set of offset (we have 1 pair of offset for rect locked from last frame data, and 1 pair for currently building rect)
|
||||
ImVec2 CalcWorkRectPos(const ImVec2& off_min) const { return ImVec2(Pos.x + off_min.x, Pos.y + off_min.y); }
|
||||
ImVec2 CalcWorkRectSize(const ImVec2& off_min, const ImVec2& off_max) const { return ImVec2(ImMax(0.0f, Size.x - off_min.x + off_max.x), ImMax(0.0f, Size.y - off_min.y + off_max.y)); }
|
||||
void UpdateWorkRect() { WorkPos = CalcWorkRectPos(WorkOffsetMin); WorkSize = CalcWorkRectSize(WorkOffsetMin, WorkOffsetMax); } // Update public fields
|
||||
|
||||
// Helpers to retrieve ImRect (we don't need to store BuildWorkRect as every access tend to change it, hence the code asymmetry)
|
||||
ImRect GetMainRect() const { return ImRect(Pos.x, Pos.y, Pos.x + Size.x, Pos.y + Size.y); }
|
||||
ImRect GetWorkRect() const { return ImRect(WorkPos.x, WorkPos.y, WorkPos.x + WorkSize.x, WorkPos.y + WorkSize.y); }
|
||||
ImRect GetBuildWorkRect() const { ImVec2 pos = CalcWorkRectPos(BuildWorkOffsetMin); ImVec2 size = CalcWorkRectSize(BuildWorkOffsetMin, BuildWorkOffsetMax); return ImRect(pos.x, pos.y, pos.x + size.x, pos.y + size.y); }
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -1311,11 +1371,12 @@ struct ImGuiContext
|
||||
|
||||
// Windows state
|
||||
ImVector<ImGuiWindow*> Windows; // Windows, sorted in display order, back to front
|
||||
ImVector<ImGuiWindow*> WindowsFocusOrder; // Windows, sorted in focus order, back to front. (FIXME: We could only store root windows here! Need to sort out the Docking equivalent which is RootWindowDockStop and is unfortunately a little more dynamic)
|
||||
ImVector<ImGuiWindow*> WindowsFocusOrder; // Root windows, sorted in focus order, back to front.
|
||||
ImVector<ImGuiWindow*> WindowsTempSortBuffer; // Temporary buffer used in EndFrame() to reorder windows so parents are kept before their child
|
||||
ImVector<ImGuiWindow*> CurrentWindowStack;
|
||||
ImGuiStorage WindowsById; // Map window's ImGuiID to ImGuiWindow*
|
||||
int WindowsActiveCount; // Number of unique windows submitted by frame
|
||||
ImVec2 WindowsHoverPadding; // Padding around resizable windows for which hovering on counts as hovering the window == ImMax(style.TouchExtraPadding, WINDOWS_HOVER_PADDING)
|
||||
ImGuiWindow* CurrentWindow; // Window being drawn into
|
||||
ImGuiWindow* HoveredWindow; // Window the mouse is hovering. Will typically catch mouse inputs.
|
||||
ImGuiWindow* HoveredWindowUnderMovingWindow; // Hovered window ignoring MovingWindow. Only set if MovingWindow is set.
|
||||
@ -1325,6 +1386,7 @@ struct ImGuiContext
|
||||
float WheelingWindowTimer;
|
||||
|
||||
// Item/widgets state and tracking information
|
||||
ImGuiItemFlags CurrentItemFlags; // == g.ItemFlagsStack.back()
|
||||
ImGuiID HoveredId; // Hovered widget, filled during the frame
|
||||
ImGuiID HoveredIdPreviousFrame;
|
||||
bool HoveredIdAllowOverlap;
|
||||
@ -1407,9 +1469,9 @@ struct ImGuiContext
|
||||
ImGuiKeyModFlags NavMoveRequestKeyMods;
|
||||
ImGuiDir NavMoveDir, NavMoveDirLast; // Direction of the move request (left/right/up/down), direction of the previous move request
|
||||
ImGuiDir NavMoveClipDir; // FIXME-NAV: Describe the purpose of this better. Might want to rename?
|
||||
ImGuiNavMoveResult NavMoveResultLocal; // Best move request candidate within NavWindow
|
||||
ImGuiNavMoveResult NavMoveResultLocalVisibleSet; // Best move request candidate within NavWindow that are mostly visible (when using ImGuiNavMoveFlags_AlsoScoreVisibleSet flag)
|
||||
ImGuiNavMoveResult NavMoveResultOther; // Best move request candidate within NavWindow's flattened hierarchy (when using ImGuiWindowFlags_NavFlattened flag)
|
||||
ImGuiNavItemData NavMoveResultLocal; // Best move request candidate within NavWindow
|
||||
ImGuiNavItemData NavMoveResultLocalVisibleSet; // Best move request candidate within NavWindow that are mostly visible (when using ImGuiNavMoveFlags_AlsoScoreVisibleSet flag)
|
||||
ImGuiNavItemData NavMoveResultOther; // Best move request candidate within NavWindow's flattened hierarchy (when using ImGuiWindowFlags_NavFlattened flag)
|
||||
ImGuiWindow* NavWrapRequestWindow; // Window which requested trying nav wrap-around.
|
||||
ImGuiNavMoveFlags NavWrapRequestFlags; // Wrap-around operation flags.
|
||||
|
||||
@ -1422,13 +1484,13 @@ struct ImGuiContext
|
||||
bool NavWindowingToggleLayer;
|
||||
|
||||
// Legacy Focus/Tabbing system (older than Nav, active even if Nav is disabled, misnamed. FIXME-NAV: This needs a redesign!)
|
||||
ImGuiWindow* FocusRequestCurrWindow; //
|
||||
ImGuiWindow* FocusRequestNextWindow; //
|
||||
int FocusRequestCurrCounterRegular; // Any item being requested for focus, stored as an index (we on layout to be stable between the frame pressing TAB and the next frame, semi-ouch)
|
||||
int FocusRequestCurrCounterTabStop; // Tab item being requested for focus, stored as an index
|
||||
int FocusRequestNextCounterRegular; // Stored for next frame
|
||||
int FocusRequestNextCounterTabStop; // "
|
||||
bool FocusTabPressed; //
|
||||
ImGuiWindow* TabFocusRequestCurrWindow; //
|
||||
ImGuiWindow* TabFocusRequestNextWindow; //
|
||||
int TabFocusRequestCurrCounterRegular; // Any item being requested for focus, stored as an index (we on layout to be stable between the frame pressing TAB and the next frame, semi-ouch)
|
||||
int TabFocusRequestCurrCounterTabStop; // Tab item being requested for focus, stored as an index
|
||||
int TabFocusRequestNextCounterRegular; // Stored for next frame
|
||||
int TabFocusRequestNextCounterTabStop; // "
|
||||
bool TabFocusPressed; // Set in NewFrame() when user pressed Tab
|
||||
|
||||
// Render
|
||||
float DimBgRatio; // 0.0..1.0 animation when fading in a dimming background (for modal window and CTRL+TAB list)
|
||||
@ -1455,8 +1517,9 @@ struct ImGuiContext
|
||||
|
||||
// Table
|
||||
ImGuiTable* CurrentTable;
|
||||
int CurrentTableStackIdx;
|
||||
ImPool<ImGuiTable> Tables;
|
||||
ImVector<ImGuiPtrOrIndex> CurrentTableStack;
|
||||
ImVector<ImGuiTableTempData> TablesTempDataStack;
|
||||
ImVector<float> TablesLastTimeActive; // Last used timestamp of each tables (SOA, for efficient GC)
|
||||
ImVector<ImDrawChannel> DrawChannelsTempMergeBuffer;
|
||||
|
||||
@ -1523,6 +1586,7 @@ struct ImGuiContext
|
||||
// Misc
|
||||
float FramerateSecPerFrame[120]; // Calculate estimate of framerate for user over the last 2 seconds.
|
||||
int FramerateSecPerFrameIdx;
|
||||
int FramerateSecPerFrameCount;
|
||||
float FramerateSecPerFrameAccum;
|
||||
int WantCaptureMouseNextFrame; // Explicit capture via CaptureKeyboardFromApp()/CaptureMouseFromApp() sets those flags
|
||||
int WantCaptureKeyboardNextFrame;
|
||||
@ -1553,6 +1617,7 @@ struct ImGuiContext
|
||||
WheelingWindow = NULL;
|
||||
WheelingWindowTimer = 0.0f;
|
||||
|
||||
CurrentItemFlags = ImGuiItemFlags_None;
|
||||
HoveredId = HoveredIdPreviousFrame = 0;
|
||||
HoveredIdAllowOverlap = false;
|
||||
HoveredIdUsingMouseWheel = HoveredIdPreviousFrameUsingMouseWheel = false;
|
||||
@ -1611,10 +1676,10 @@ struct ImGuiContext
|
||||
NavWindowingTimer = NavWindowingHighlightAlpha = 0.0f;
|
||||
NavWindowingToggleLayer = false;
|
||||
|
||||
FocusRequestCurrWindow = FocusRequestNextWindow = NULL;
|
||||
FocusRequestCurrCounterRegular = FocusRequestCurrCounterTabStop = INT_MAX;
|
||||
FocusRequestNextCounterRegular = FocusRequestNextCounterTabStop = INT_MAX;
|
||||
FocusTabPressed = false;
|
||||
TabFocusRequestCurrWindow = TabFocusRequestNextWindow = NULL;
|
||||
TabFocusRequestCurrCounterRegular = TabFocusRequestCurrCounterTabStop = INT_MAX;
|
||||
TabFocusRequestNextCounterRegular = TabFocusRequestNextCounterTabStop = INT_MAX;
|
||||
TabFocusPressed = false;
|
||||
|
||||
DimBgRatio = 0.0f;
|
||||
MouseCursor = ImGuiMouseCursor_Arrow;
|
||||
@ -1632,6 +1697,7 @@ struct ImGuiContext
|
||||
memset(DragDropPayloadBufLocal, 0, sizeof(DragDropPayloadBufLocal));
|
||||
|
||||
CurrentTable = NULL;
|
||||
CurrentTableStackIdx = -1;
|
||||
CurrentTabBar = NULL;
|
||||
|
||||
LastValidMousePos = ImVec2(0.0f, 0.0f);
|
||||
@ -1668,7 +1734,7 @@ struct ImGuiContext
|
||||
DebugItemPickerBreakId = 0;
|
||||
|
||||
memset(FramerateSecPerFrame, 0, sizeof(FramerateSecPerFrame));
|
||||
FramerateSecPerFrameIdx = 0;
|
||||
FramerateSecPerFrameIdx = FramerateSecPerFrameCount = 0;
|
||||
FramerateSecPerFrameAccum = 0.0f;
|
||||
WantCaptureMouseNextFrame = WantCaptureKeyboardNextFrame = WantTextInputNextFrame = -1;
|
||||
memset(TempBuffer, 0, sizeof(TempBuffer));
|
||||
@ -1706,8 +1772,8 @@ struct IMGUI_API ImGuiWindowTempData
|
||||
|
||||
// Keyboard/Gamepad navigation
|
||||
ImGuiNavLayer NavLayerCurrent; // Current layer, 0..31 (we currently only use 0..1)
|
||||
int NavLayerActiveMask; // Which layers have been written to (result from previous frame)
|
||||
int NavLayerActiveMaskNext; // Which layers have been written to (accumulator for current frame)
|
||||
short NavLayersActiveMask; // Which layers have been written to (result from previous frame)
|
||||
short NavLayersActiveMaskNext;// Which layers have been written to (accumulator for current frame)
|
||||
ImGuiID NavFocusScopeIdCurrent; // Current focus scope ID while appending
|
||||
bool NavHideHighlightOneFrame;
|
||||
bool NavHasScroll; // Set when scrolling can be used (ScrollMax > 0.0f)
|
||||
@ -1729,7 +1795,6 @@ struct IMGUI_API ImGuiWindowTempData
|
||||
|
||||
// Local parameters stacks
|
||||
// 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; // == g.ItemFlagsStack.back()
|
||||
float ItemWidth; // Current item width (>0.0: width in pixels, <0.0: align xx pixels to the right of window).
|
||||
float TextWrapPos; // Current text wrap pos.
|
||||
ImVector<float> ItemWidthStack; // Store item widths to restore (attention: .back() is not == ItemWidth)
|
||||
@ -1774,8 +1839,9 @@ struct IMGUI_API ImGuiWindow
|
||||
bool HasCloseButton; // Set when the window has a close button (p_open != NULL)
|
||||
signed char ResizeBorderHeld; // Current border being held for resize (-1: none, otherwise 0-3)
|
||||
short BeginCount; // Number of Begin() during the current frame (generally 0 or 1, 1+ if appending via multiple Begin/End pairs)
|
||||
short BeginOrderWithinParent; // Order within immediate parent window, if we are a child window. Otherwise 0.
|
||||
short BeginOrderWithinContext; // Order within entire imgui context. This is mostly used for debugging submission order related issues.
|
||||
short BeginOrderWithinParent; // Begin() order within immediate parent window, if we are a child window. Otherwise 0.
|
||||
short BeginOrderWithinContext; // Begin() order within entire imgui context. This is mostly used for debugging submission order related issues.
|
||||
short FocusOrder; // Order within WindowsFocusOrder[], altered when windows are focused.
|
||||
ImGuiID PopupId; // ID in the popup stack when this window is used as a popup/menu (because we use generic Name/ID for recycling)
|
||||
ImS8 AutoFitFramesX, AutoFitFramesY;
|
||||
ImS8 AutoFitChildAxises;
|
||||
@ -1784,6 +1850,7 @@ struct IMGUI_API ImGuiWindow
|
||||
ImS8 HiddenFramesCanSkipItems; // Hide the window for N frames
|
||||
ImS8 HiddenFramesCannotSkipItems; // Hide the window for N frames while allowing items to be submitted so we can measure their size
|
||||
ImS8 HiddenFramesForRenderOnly; // Hide the window until frame N at Render() time only
|
||||
ImS8 DisableInputsFrames; // Disable window interactions for N frames
|
||||
ImGuiCond SetWindowPosAllowFlags : 8; // store acceptable condition flags for SetNextWindowPos() use.
|
||||
ImGuiCond SetWindowSizeAllowFlags : 8; // store acceptable condition flags for SetNextWindowSize() use.
|
||||
ImGuiCond SetWindowCollapsedAllowFlags : 8; // store acceptable condition flags for SetNextWindowCollapsed() use.
|
||||
@ -1877,6 +1944,7 @@ enum ImGuiTabBarFlagsPrivate_
|
||||
// Extend ImGuiTabItemFlags_
|
||||
enum ImGuiTabItemFlagsPrivate_
|
||||
{
|
||||
ImGuiTabItemFlags_SectionMask_ = ImGuiTabItemFlags_Leading | ImGuiTabItemFlags_Trailing,
|
||||
ImGuiTabItemFlags_NoCloseButton = 1 << 20, // Track whether p_open was set or not (we'll need this info on the next frame to recompute ContentWidth during layout)
|
||||
ImGuiTabItemFlags_Button = 1 << 21 // Used by TabItemButton, change the tab item behavior to mimic a button
|
||||
};
|
||||
@ -1922,7 +1990,7 @@ struct ImGuiTabBar
|
||||
float ScrollingRectMinX;
|
||||
float ScrollingRectMaxX;
|
||||
ImGuiID ReorderRequestTabId;
|
||||
ImS8 ReorderRequestDir;
|
||||
ImS16 ReorderRequestOffset;
|
||||
ImS8 BeginCount;
|
||||
bool WantLayout;
|
||||
bool VisibleTabWasSubmitted;
|
||||
@ -1947,8 +2015,6 @@ struct ImGuiTabBar
|
||||
// [SECTION] Table support
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifdef IMGUI_HAS_TABLE
|
||||
|
||||
#define IM_COL32_DISABLE IM_COL32(0,0,0,1) // Special sentinel code which cannot be used as a regular color.
|
||||
#define IMGUI_TABLE_MAX_COLUMNS 64 // sizeof(ImU64) * 8. This is solely because we frequently encode columns set in a ImU64.
|
||||
#define IMGUI_TABLE_MAX_DRAW_CHANNELS (4 + 64 * 2) // See TableSetupDrawChannels()
|
||||
@ -2025,12 +2091,13 @@ struct ImGuiTableCellData
|
||||
ImGuiTableColumnIdx Column; // Column number
|
||||
};
|
||||
|
||||
// FIXME-TABLE: transient data could be stored in a per-stacked table structure: DrawSplitter, SortSpecs, incoming RowData
|
||||
// FIXME-TABLE: more transient data could be stored in a per-stacked table structure: DrawSplitter, SortSpecs, incoming RowData
|
||||
struct ImGuiTable
|
||||
{
|
||||
ImGuiID ID;
|
||||
ImGuiTableFlags Flags;
|
||||
void* RawData; // Single allocation to hold Columns[], DisplayOrderToIndex[] and RowCellData[]
|
||||
ImGuiTableTempData* TempData; // Transient data while table is active. Point within g.CurrentTableStack[]
|
||||
ImSpan<ImGuiTableColumn> Columns; // Point within RawData[]
|
||||
ImSpan<ImGuiTableColumnIdx> DisplayOrderToIndex; // Point within RawData[]. Store display order of columns (when not reordered, the values are 0...Count-1)
|
||||
ImSpan<ImGuiTableCellData> RowCellData; // Point within RawData[]. Store cells background requests for current row.
|
||||
@ -2082,22 +2149,11 @@ struct ImGuiTable
|
||||
ImRect Bg0ClipRectForDrawCmd; // Actual ImDrawCmd clip rect for BG0/1 channel. This tends to be == OuterWindow->ClipRect at BeginTable() because output in BG0/BG1 is cpu-clipped
|
||||
ImRect Bg2ClipRectForDrawCmd; // Actual ImDrawCmd clip rect for BG2 channel. This tends to be a correct, tight-fit, because output to BG2 are done by widgets relying on regular ClipRect.
|
||||
ImRect HostClipRect; // This is used to check if we can eventually merge our columns draw calls into the current draw call of the current window.
|
||||
ImRect HostBackupWorkRect; // Backup of InnerWindow->WorkRect at the end of BeginTable()
|
||||
ImRect HostBackupParentWorkRect; // Backup of InnerWindow->ParentWorkRect at the end of BeginTable()
|
||||
ImRect HostBackupInnerClipRect; // Backup of InnerWindow->ClipRect during PushTableBackground()/PopTableBackground()
|
||||
ImVec2 HostBackupPrevLineSize; // Backup of InnerWindow->DC.PrevLineSize at the end of BeginTable()
|
||||
ImVec2 HostBackupCurrLineSize; // Backup of InnerWindow->DC.CurrLineSize at the end of BeginTable()
|
||||
ImVec2 HostBackupCursorMaxPos; // Backup of InnerWindow->DC.CursorMaxPos at the end of BeginTable()
|
||||
ImVec2 UserOuterSize; // outer_size.x passed to BeginTable()
|
||||
ImVec1 HostBackupColumnsOffset; // Backup of OuterWindow->DC.ColumnsOffset at the end of BeginTable()
|
||||
float HostBackupItemWidth; // Backup of OuterWindow->DC.ItemWidth at the end of BeginTable()
|
||||
int HostBackupItemWidthStackSize;// Backup of OuterWindow->DC.ItemWidthStack.Size at the end of BeginTable()
|
||||
ImGuiWindow* OuterWindow; // Parent window for the table
|
||||
ImGuiWindow* InnerWindow; // Window holding the table data (== OuterWindow or a child window)
|
||||
ImGuiTextBuffer ColumnsNames; // Contiguous buffer holding columns names
|
||||
ImDrawListSplitter DrawSplitter; // We carry our own ImDrawList splitter to allow recursion (FIXME: could be stored outside, worst case we need 1 splitter per recursing table)
|
||||
ImGuiTableColumnSortSpecs SortSpecsSingle;
|
||||
ImVector<ImGuiTableColumnSortSpecs> SortSpecsMulti; // FIXME-OPT: Using a small-vector pattern would work be good.
|
||||
ImDrawListSplitter* DrawSplitter; // Shortcut to TempData->DrawSplitter while in table. Isolate draw commands per columns to avoid switching clip rect constantly
|
||||
ImGuiTableSortSpecs SortSpecs; // Public facing sorts specs, this is what we return in TableGetSortSpecs()
|
||||
ImGuiTableColumnIdx SortSpecsCount;
|
||||
ImGuiTableColumnIdx ColumnsEnabledCount; // Number of enabled columns (<= ColumnsCount)
|
||||
@ -2144,6 +2200,32 @@ struct ImGuiTable
|
||||
IMGUI_API ~ImGuiTable() { IM_FREE(RawData); }
|
||||
};
|
||||
|
||||
// Transient data that are only needed between BeginTable() and EndTable(), those buffers are shared (1 per level of stacked table).
|
||||
// - Accessing those requires chasing an extra pointer so for very frequently used data we leave them in the main table structure.
|
||||
// - We also leave out of this structure data that tend to be particularly useful for debugging/metrics.
|
||||
// FIXME-TABLE: more transient data could be stored here: DrawSplitter, incoming RowData?
|
||||
struct ImGuiTableTempData
|
||||
{
|
||||
int TableIndex; // Index in g.Tables.Buf[] pool
|
||||
float LastTimeActive; // Last timestamp this structure was used
|
||||
|
||||
ImVec2 UserOuterSize; // outer_size.x passed to BeginTable()
|
||||
ImDrawListSplitter DrawSplitter;
|
||||
ImGuiTableColumnSortSpecs SortSpecsSingle;
|
||||
ImVector<ImGuiTableColumnSortSpecs> SortSpecsMulti; // FIXME-OPT: Using a small-vector pattern would be good.
|
||||
|
||||
ImRect HostBackupWorkRect; // Backup of InnerWindow->WorkRect at the end of BeginTable()
|
||||
ImRect HostBackupParentWorkRect; // Backup of InnerWindow->ParentWorkRect at the end of BeginTable()
|
||||
ImVec2 HostBackupPrevLineSize; // Backup of InnerWindow->DC.PrevLineSize at the end of BeginTable()
|
||||
ImVec2 HostBackupCurrLineSize; // Backup of InnerWindow->DC.CurrLineSize at the end of BeginTable()
|
||||
ImVec2 HostBackupCursorMaxPos; // Backup of InnerWindow->DC.CursorMaxPos at the end of BeginTable()
|
||||
ImVec1 HostBackupColumnsOffset; // Backup of OuterWindow->DC.ColumnsOffset at the end of BeginTable()
|
||||
float HostBackupItemWidth; // Backup of OuterWindow->DC.ItemWidth at the end of BeginTable()
|
||||
int HostBackupItemWidthStackSize;//Backup of OuterWindow->DC.ItemWidthStack.Size at the end of BeginTable()
|
||||
|
||||
IMGUI_API ImGuiTableTempData() { memset(this, 0, sizeof(*this)); LastTimeActive = -1.0f; }
|
||||
};
|
||||
|
||||
// sizeof() ~ 12
|
||||
struct ImGuiTableColumnSettings
|
||||
{
|
||||
@ -2182,8 +2264,6 @@ struct ImGuiTableSettings
|
||||
ImGuiTableColumnSettings* GetColumnSettings() { return (ImGuiTableColumnSettings*)(this + 1); }
|
||||
};
|
||||
|
||||
#endif // #ifdef IMGUI_HAS_TABLE
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// [SECTION] ImGui internal API
|
||||
// No guarantee of forward compatibility here!
|
||||
@ -2262,7 +2342,7 @@ namespace ImGui
|
||||
inline ImGuiItemStatusFlags GetItemStatusFlags() { ImGuiContext& g = *GImGui; return g.CurrentWindow->DC.LastItemStatusFlags; }
|
||||
inline ImGuiID GetActiveID() { ImGuiContext& g = *GImGui; return g.ActiveId; }
|
||||
inline ImGuiID GetFocusID() { ImGuiContext& g = *GImGui; return g.NavId; }
|
||||
inline ImGuiItemFlags GetItemsFlags() { ImGuiContext& g = *GImGui; return g.CurrentWindow->DC.ItemFlags; }
|
||||
inline ImGuiItemFlags GetItemFlags() { ImGuiContext& g = *GImGui; return g.CurrentItemFlags; }
|
||||
IMGUI_API void SetActiveID(ImGuiID id, ImGuiWindow* window);
|
||||
IMGUI_API void SetFocusID(ImGuiID id, ImGuiWindow* window);
|
||||
IMGUI_API void ClearActiveID();
|
||||
@ -2276,12 +2356,11 @@ namespace ImGui
|
||||
// Basic Helpers for widget code
|
||||
IMGUI_API void ItemSize(const ImVec2& size, float text_baseline_y = -1.0f);
|
||||
IMGUI_API void ItemSize(const ImRect& bb, float text_baseline_y = -1.0f);
|
||||
IMGUI_API bool ItemAdd(const ImRect& bb, ImGuiID id, const ImRect* nav_bb = NULL);
|
||||
IMGUI_API bool ItemAdd(const ImRect& bb, ImGuiID id, const ImRect* nav_bb = NULL, ImGuiItemAddFlags flags = 0);
|
||||
IMGUI_API bool ItemHoverable(const ImRect& bb, ImGuiID id);
|
||||
IMGUI_API void ItemFocusable(ImGuiWindow* window, ImGuiID id);
|
||||
IMGUI_API bool IsClippedEx(const ImRect& bb, ImGuiID id, bool clip_even_when_logged);
|
||||
IMGUI_API void SetLastItemData(ImGuiWindow* window, ImGuiID item_id, ImGuiItemStatusFlags status_flags, const ImRect& item_rect);
|
||||
IMGUI_API bool FocusableItemRegister(ImGuiWindow* window, ImGuiID id); // Return true if focus is requested
|
||||
IMGUI_API void FocusableItemUnregister(ImGuiWindow* window);
|
||||
IMGUI_API ImVec2 CalcItemSize(ImVec2 size, float default_w, float default_h);
|
||||
IMGUI_API float CalcWrapWidthForPos(const ImVec2& pos, float wrap_pos_x);
|
||||
IMGUI_API void PushMultiItemsWidths(int components, float width_full);
|
||||
@ -2291,6 +2370,15 @@ namespace ImGui
|
||||
IMGUI_API ImVec2 GetContentRegionMaxAbs();
|
||||
IMGUI_API void ShrinkWidths(ImGuiShrinkWidthItem* items, int count, float width_excess);
|
||||
|
||||
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
|
||||
// If you have old/custom copy-and-pasted widgets that used FocusableItemRegister():
|
||||
// (Old) IMGUI_VERSION_NUM < 18209: using 'ItemAdd(....)' and 'bool focused = FocusableItemRegister(...)'
|
||||
// (New) IMGUI_VERSION_NUM >= 18209: using 'ItemAdd(..., ImGuiItemAddFlags_Focusable)' and 'bool focused = (GetItemStatusFlags() & ImGuiItemStatusFlags_Focused) != 0'
|
||||
// Widget code are simplified as there's no need to call FocusableItemUnregister() while managing the transition from regular widget to TempInputText()
|
||||
inline bool FocusableItemRegister(ImGuiWindow* window, ImGuiID id) { IM_ASSERT(0); IM_UNUSED(window); IM_UNUSED(id); return false; } // -> pass ImGuiItemAddFlags_Focusable flag to ItemAdd()
|
||||
inline void FocusableItemUnregister(ImGuiWindow* window) { IM_ASSERT(0); IM_UNUSED(window); } // -> unnecessary: TempInputText() uses ImGuiInputTextFlags_MergedItem
|
||||
#endif
|
||||
|
||||
// Logging/Capture
|
||||
IMGUI_API void LogBegin(ImGuiLogType type, int auto_open_depth); // -> BeginCapture() when we design v2 api, for now stay under the radar by using the old name.
|
||||
IMGUI_API void LogToBuffer(int auto_open_depth = -1); // Start logging/capturing to internal buffer
|
||||
@ -2308,6 +2396,7 @@ namespace ImGui
|
||||
IMGUI_API ImGuiWindow* GetTopMostPopupModal();
|
||||
IMGUI_API ImVec2 FindBestWindowPosForPopup(ImGuiWindow* window);
|
||||
IMGUI_API ImVec2 FindBestWindowPosForPopupEx(const ImVec2& ref_pos, const ImVec2& size, ImGuiDir* last_dir, const ImRect& r_outer, const ImRect& r_avoid, ImGuiPopupPositionPolicy policy);
|
||||
IMGUI_API bool BeginViewportSideBar(const char* name, ImGuiViewport* viewport, ImGuiDir dir, float size, ImGuiWindowFlags window_flags);
|
||||
|
||||
// Gamepad/Keyboard Navigation
|
||||
IMGUI_API void NavInitWindow(ImGuiWindow* window, bool force_reinit);
|
||||
@ -2319,7 +2408,7 @@ namespace ImGui
|
||||
IMGUI_API ImVec2 GetNavInputAmount2d(ImGuiNavDirSourceFlags dir_sources, ImGuiInputReadMode mode, float slow_factor = 0.0f, float fast_factor = 0.0f);
|
||||
IMGUI_API int CalcTypematicRepeatAmount(float t0, float t1, float repeat_delay, float repeat_rate);
|
||||
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 void SetNavID(ImGuiID id, int nav_layer, ImGuiID focus_scope_id, const ImRect& rect_rel);
|
||||
IMGUI_API void SetNavID(ImGuiID id, ImGuiNavLayer nav_layer, ImGuiID focus_scope_id, const ImRect& rect_rel);
|
||||
|
||||
// Focus Scope (WIP)
|
||||
// This is generally used to identify a selection set (multiple of which may be in the same window), as selection
|
||||
@ -2360,7 +2449,6 @@ namespace ImGui
|
||||
|
||||
// Tables: Candidates for public API
|
||||
IMGUI_API void TableOpenContextMenu(int column_n = -1);
|
||||
IMGUI_API void TableSetColumnEnabled(int column_n, bool enabled);
|
||||
IMGUI_API void TableSetColumnWidth(int column_n, float width);
|
||||
IMGUI_API void TableSetColumnSortDirection(int column_n, ImGuiSortDirection sort_direction, bool append_to_sort_specs);
|
||||
IMGUI_API int TableGetHoveredColumn(); // May use (TableGetColumnFlags() & ImGuiTableColumnFlags_IsHovered) instead. Return hovered column. return -1 when table is not hovered. return columns_count if the unused space at the right of visible columns is hovered.
|
||||
@ -2398,6 +2486,7 @@ namespace ImGui
|
||||
IMGUI_API void TableSetColumnWidthAutoAll(ImGuiTable* table);
|
||||
IMGUI_API void TableRemove(ImGuiTable* table);
|
||||
IMGUI_API void TableGcCompactTransientBuffers(ImGuiTable* table);
|
||||
IMGUI_API void TableGcCompactTransientBuffers(ImGuiTableTempData* table);
|
||||
IMGUI_API void TableGcCompactSettings();
|
||||
|
||||
// Tables: Settings
|
||||
@ -2414,7 +2503,8 @@ namespace ImGui
|
||||
IMGUI_API ImGuiTabItem* TabBarFindTabByID(ImGuiTabBar* tab_bar, ImGuiID tab_id);
|
||||
IMGUI_API void TabBarRemoveTab(ImGuiTabBar* tab_bar, ImGuiID tab_id);
|
||||
IMGUI_API void TabBarCloseTab(ImGuiTabBar* tab_bar, ImGuiTabItem* tab);
|
||||
IMGUI_API void TabBarQueueReorder(ImGuiTabBar* tab_bar, const ImGuiTabItem* tab, int dir);
|
||||
IMGUI_API void TabBarQueueReorder(ImGuiTabBar* tab_bar, const ImGuiTabItem* tab, int offset);
|
||||
IMGUI_API void TabBarQueueReorderFromMousePos(ImGuiTabBar* tab_bar, const ImGuiTabItem* tab, ImVec2 mouse_pos);
|
||||
IMGUI_API bool TabBarProcessReorder(ImGuiTabBar* tab_bar);
|
||||
IMGUI_API bool TabItemEx(ImGuiTabBar* tab_bar, const char* label, bool* p_open, ImGuiTabItemFlags flags);
|
||||
IMGUI_API ImVec2 TabItemCalcSize(const char* label, bool has_close_button);
|
||||
@ -2461,7 +2551,8 @@ namespace ImGui
|
||||
IMGUI_API bool ImageButtonEx(ImGuiID id, ImTextureID texture_id, const ImVec2& size, const ImVec2& uv0, const ImVec2& uv1, const ImVec2& padding, const ImVec4& bg_col, const ImVec4& tint_col);
|
||||
IMGUI_API ImRect GetWindowScrollbarRect(ImGuiWindow* window, ImGuiAxis axis);
|
||||
IMGUI_API ImGuiID GetWindowScrollbarID(ImGuiWindow* window, ImGuiAxis axis);
|
||||
IMGUI_API ImGuiID GetWindowResizeID(ImGuiWindow* window, int n); // 0..3: corners, 4..7: borders
|
||||
IMGUI_API ImGuiID GetWindowResizeCornerID(ImGuiWindow* window, int n); // 0..3: corners
|
||||
IMGUI_API ImGuiID GetWindowResizeBorderID(ImGuiWindow* window, ImGuiDir dir);
|
||||
IMGUI_API void SeparatorEx(ImGuiSeparatorFlags flags);
|
||||
IMGUI_API bool CheckboxFlags(const char* label, ImS64* flags, ImS64 flags_value);
|
||||
IMGUI_API bool CheckboxFlags(const char* label, ImU64* flags, ImU64 flags_value);
|
||||
|
225
imgui_tables.cpp
225
imgui_tables.cpp
@ -1,4 +1,4 @@
|
||||
// dear imgui, v1.82 WIP
|
||||
// dear imgui, v1.83
|
||||
// (tables and columns code)
|
||||
|
||||
/*
|
||||
@ -8,6 +8,7 @@ Index of this file:
|
||||
// [SECTION] Commentary
|
||||
// [SECTION] Header mess
|
||||
// [SECTION] Tables: Main code
|
||||
// [SECTION] Tables: Simple accessors
|
||||
// [SECTION] Tables: Row changes
|
||||
// [SECTION] Tables: Columns changes
|
||||
// [SECTION] Tables: Columns width management
|
||||
@ -73,7 +74,7 @@ Index of this file:
|
||||
// (Read carefully because this is subtle but it does make sense!)
|
||||
//-----------------------------------------------------------------------------
|
||||
// About 'outer_size':
|
||||
// Its meaning needs to differ slightly depending of if we are using ScrollX/ScrollY flags.
|
||||
// Its meaning needs to differ slightly depending on if we are using ScrollX/ScrollY flags.
|
||||
// Default value is ImVec2(0.0f, 0.0f).
|
||||
// X
|
||||
// - outer_size.x <= 0.0f -> Right-align from window/work-rect right-most edge. With -FLT_MIN or 0.0f will align exactly on right-most edge.
|
||||
@ -90,7 +91,7 @@ Index of this file:
|
||||
// Outer size is also affected by the NoHostExtendX/NoHostExtendY flags.
|
||||
// Important to that note how the two flags have slightly different behaviors!
|
||||
// - ImGuiTableFlags_NoHostExtendX -> Make outer width auto-fit to columns (overriding outer_size.x value). Only available when ScrollX/ScrollY are disabled and Stretch columns are not used.
|
||||
// - ImGuiTableFlags_NoHostExtendY -> Make outer height stop exactly at outer_size.y (prevent auto-extending table past the limit). Only available when ScrollX/ScrollY are disabled. Data below the limit will be clipped and not visible.
|
||||
// - ImGuiTableFlags_NoHostExtendY -> Make outer height stop exactly at outer_size.y (prevent auto-extending table past the limit). Only available when ScrollX/ScrollY is disabled. Data below the limit will be clipped and not visible.
|
||||
// In theory ImGuiTableFlags_NoHostExtendY could be the default and any non-scrolling tables with outer_size.y != 0.0f would use exact height.
|
||||
// This would be consistent but perhaps less useful and more confusing (as vertically clipped items are not easily noticeable)
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -132,7 +133,7 @@ Index of this file:
|
||||
// - the typical use of mixing sizing policies is: any number of LEADING Fixed columns, followed by one or two TRAILING Stretch columns.
|
||||
// - using mixed policies with ScrollX does not make much sense, as using Stretch columns with ScrollX does not make much sense in the first place!
|
||||
// that is, unless 'inner_width' is passed to BeginTable() to explicitly provide a total width to layout columns in.
|
||||
// - when using ImGuiTableFlags_SizingFixedSame with mixed columns, only the Fixed/Auto columns will match their widths to the maximum contents width.
|
||||
// - when using ImGuiTableFlags_SizingFixedSame with mixed columns, only the Fixed/Auto columns will match their widths to the width of the maximum contents.
|
||||
// - when using ImGuiTableFlags_SizingStretchSame with mixed columns, only the Stretch columns will match their weight/widths.
|
||||
//-----------------------------------------------------------------------------
|
||||
// About using column width:
|
||||
@ -140,9 +141,9 @@ Index of this file:
|
||||
// - you may use GetContentRegionAvail().x to query the width available in a given column.
|
||||
// - right-side alignment features such as SetNextItemWidth(-x) or PushItemWidth(-x) will rely on this width.
|
||||
// If the column is not resizable and has no width specified with TableSetupColumn():
|
||||
// - its width will be automatic and be the set to the max of items submitted.
|
||||
// - its width will be automatic and be set to the max of items submitted.
|
||||
// - therefore you generally cannot have ALL items of the columns use e.g. SetNextItemWidth(-FLT_MIN).
|
||||
// - but if the column has one or more item of known/fixed size, this will become the reference width used by SetNextItemWidth(-FLT_MIN).
|
||||
// - but if the column has one or more items of known/fixed size, this will become the reference width used by SetNextItemWidth(-FLT_MIN).
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
|
||||
@ -161,18 +162,18 @@ Index of this file:
|
||||
// - Both TableSetColumnIndex() and TableNextColumn() return true when the column is visible or performing
|
||||
// width measurements. Otherwise, you may skip submitting the contents of a cell/column, BUT ONLY if you know
|
||||
// it is not going to contribute to row height.
|
||||
// In many situations, you may skip submitting contents for every columns but one (e.g. the first one).
|
||||
// In many situations, you may skip submitting contents for every column but one (e.g. the first one).
|
||||
// - Case A: column is not hidden by user, and at least partially in sight (most common case).
|
||||
// - Case B: column is clipped / out of sight (because of scrolling or parent ClipRect): TableNextColumn() return false as a hint but we still allow layout output.
|
||||
// - Case C: column is hidden explicitly by the user (e.g. via the context menu, or _DefaultHide column flag, etc.).
|
||||
//
|
||||
// [A] [B] [C]
|
||||
// [A] [B] [C]
|
||||
// TableNextColumn(): true false false -> [userland] when TableNextColumn() / TableSetColumnIndex() return false, user can skip submitting items but only if the column doesn't contribute to row height.
|
||||
// SkipItems: false false true -> [internal] when SkipItems is true, most widgets will early out if submitted, resulting is no layout output.
|
||||
// ClipRect: normal zero-width zero-width -> [internal] when ClipRect is zero, ItemAdd() will return false and most widgets will early out mid-way.
|
||||
// ImDrawList output: normal dummy dummy -> [internal] when using the dummy channel, ImDrawList submissions (if any) will be wasted (because cliprect is zero-width anyway).
|
||||
//
|
||||
// - We need distinguish those cases because non-hidden columns that are clipped outside of scrolling bounds should still contribute their height to the row.
|
||||
// - We need to distinguish those cases because non-hidden columns that are clipped outside of scrolling bounds should still contribute their height to the row.
|
||||
// However, in the majority of cases, the contribution to row height is the same for all columns, or the tallest cells are known by the programmer.
|
||||
//-----------------------------------------------------------------------------
|
||||
// About clipping/culling of whole Tables:
|
||||
@ -209,6 +210,8 @@ Index of this file:
|
||||
#if defined(_MSC_VER) && _MSC_VER >= 1922 // MSVC 2019 16.2 or later
|
||||
#pragma warning (disable: 5054) // operator '|': deprecated between enumerations of different types
|
||||
#endif
|
||||
#pragma warning (disable: 26451) // [Static Analyzer] Arithmetic overflow : Using operator 'xxx' on a 4 byte value and then casting the result to a 8 byte value. Cast the value to the wider type before calling operator 'xxx' to avoid overflow(io.2).
|
||||
#pragma warning (disable: 26812) // [Static Analyzer] The enum type 'xxx' is unscoped. Prefer 'enum class' over 'enum' (Enum.3).
|
||||
#endif
|
||||
|
||||
// Clang/GCC warnings with -Weverything
|
||||
@ -235,6 +238,19 @@ Index of this file:
|
||||
//-----------------------------------------------------------------------------
|
||||
// [SECTION] Tables: Main code
|
||||
//-----------------------------------------------------------------------------
|
||||
// - TableFixFlags() [Internal]
|
||||
// - TableFindByID() [Internal]
|
||||
// - BeginTable()
|
||||
// - BeginTableEx() [Internal]
|
||||
// - TableBeginInitMemory() [Internal]
|
||||
// - TableBeginApplyRequests() [Internal]
|
||||
// - TableSetupColumnFlags() [Internal]
|
||||
// - TableUpdateLayout() [Internal]
|
||||
// - TableUpdateBorders() [Internal]
|
||||
// - EndTable()
|
||||
// - TableSetupColumn()
|
||||
// - TableSetupScrollFreeze()
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
// Configuration
|
||||
static const int TABLE_DRAW_CHANNEL_BG0 = 0;
|
||||
@ -327,6 +343,16 @@ bool ImGui::BeginTableEx(const char* name, ImGuiID id, int columns_count, ImG
|
||||
if (instance_no > 0)
|
||||
IM_ASSERT(table->ColumnsCount == columns_count && "BeginTable(): Cannot change columns count mid-frame while preserving same ID");
|
||||
|
||||
// Acquire temporary buffers
|
||||
const int table_idx = g.Tables.GetIndex(table);
|
||||
g.CurrentTableStackIdx++;
|
||||
if (g.CurrentTableStackIdx + 1 > g.TablesTempDataStack.Size)
|
||||
g.TablesTempDataStack.resize(g.CurrentTableStackIdx + 1, ImGuiTableTempData());
|
||||
ImGuiTableTempData* temp_data = table->TempData = &g.TablesTempDataStack[g.CurrentTableStackIdx];
|
||||
temp_data->TableIndex = table_idx;
|
||||
table->DrawSplitter = &table->TempData->DrawSplitter;
|
||||
table->DrawSplitter->Clear();
|
||||
|
||||
// Fix flags
|
||||
table->IsDefaultSizingPolicy = (flags & ImGuiTableFlags_SizingMask_) == 0;
|
||||
flags = TableFixFlags(flags, outer_window);
|
||||
@ -340,7 +366,7 @@ bool ImGui::BeginTableEx(const char* name, ImGuiID id, int columns_count, ImG
|
||||
table->ColumnsCount = columns_count;
|
||||
table->IsLayoutLocked = false;
|
||||
table->InnerWidth = inner_width;
|
||||
table->UserOuterSize = outer_size;
|
||||
temp_data->UserOuterSize = outer_size;
|
||||
|
||||
// When not using a child window, WorkRect.Max will grow as we append contents.
|
||||
if (use_child_window)
|
||||
@ -389,14 +415,14 @@ bool ImGui::BeginTableEx(const char* name, ImGuiID id, int columns_count, ImG
|
||||
table->HostIndentX = inner_window->DC.Indent.x;
|
||||
table->HostClipRect = inner_window->ClipRect;
|
||||
table->HostSkipItems = inner_window->SkipItems;
|
||||
table->HostBackupWorkRect = inner_window->WorkRect;
|
||||
table->HostBackupParentWorkRect = inner_window->ParentWorkRect;
|
||||
table->HostBackupColumnsOffset = outer_window->DC.ColumnsOffset;
|
||||
table->HostBackupPrevLineSize = inner_window->DC.PrevLineSize;
|
||||
table->HostBackupCurrLineSize = inner_window->DC.CurrLineSize;
|
||||
table->HostBackupCursorMaxPos = inner_window->DC.CursorMaxPos;
|
||||
table->HostBackupItemWidth = outer_window->DC.ItemWidth;
|
||||
table->HostBackupItemWidthStackSize = outer_window->DC.ItemWidthStack.Size;
|
||||
temp_data->HostBackupWorkRect = inner_window->WorkRect;
|
||||
temp_data->HostBackupParentWorkRect = inner_window->ParentWorkRect;
|
||||
temp_data->HostBackupColumnsOffset = outer_window->DC.ColumnsOffset;
|
||||
temp_data->HostBackupPrevLineSize = inner_window->DC.PrevLineSize;
|
||||
temp_data->HostBackupCurrLineSize = inner_window->DC.CurrLineSize;
|
||||
temp_data->HostBackupCursorMaxPos = inner_window->DC.CursorMaxPos;
|
||||
temp_data->HostBackupItemWidth = outer_window->DC.ItemWidth;
|
||||
temp_data->HostBackupItemWidthStackSize = outer_window->DC.ItemWidthStack.Size;
|
||||
inner_window->DC.PrevLineSize = inner_window->DC.CurrLineSize = ImVec2(0.0f, 0.0f);
|
||||
|
||||
// Padding and Spacing
|
||||
@ -439,8 +465,6 @@ bool ImGui::BeginTableEx(const char* name, ImGuiID id, int columns_count, ImG
|
||||
table->BorderColorLight = GetColorU32(ImGuiCol_TableBorderLight);
|
||||
|
||||
// Make table current
|
||||
const int table_idx = g.Tables.GetIndex(table);
|
||||
g.CurrentTableStack.push_back(ImGuiPtrOrIndex(table_idx));
|
||||
g.CurrentTable = table;
|
||||
outer_window->DC.CurrentTableIdx = table_idx;
|
||||
if (inner_window != outer_window) // So EndChild() within the inner window can restore the table properly.
|
||||
@ -453,13 +477,18 @@ bool ImGui::BeginTableEx(const char* name, ImGuiID id, int columns_count, ImG
|
||||
if (table_idx >= g.TablesLastTimeActive.Size)
|
||||
g.TablesLastTimeActive.resize(table_idx + 1, -1.0f);
|
||||
g.TablesLastTimeActive[table_idx] = (float)g.Time;
|
||||
temp_data->LastTimeActive = (float)g.Time;
|
||||
table->MemoryCompacted = false;
|
||||
|
||||
// Setup memory buffer (clear data if columns count changed)
|
||||
const int stored_size = table->Columns.size();
|
||||
if (stored_size != 0 && stored_size != columns_count)
|
||||
ImGuiTableColumn* old_columns_to_preserve = NULL;
|
||||
void* old_columns_raw_data = NULL;
|
||||
const int old_columns_count = table->Columns.size();
|
||||
if (old_columns_count != 0 && old_columns_count != columns_count)
|
||||
{
|
||||
IM_FREE(table->RawData);
|
||||
// Attempt to preserve width on column count change (#4046)
|
||||
old_columns_to_preserve = table->Columns.Data;
|
||||
old_columns_raw_data = table->RawData;
|
||||
table->RawData = NULL;
|
||||
}
|
||||
if (table->RawData == NULL)
|
||||
@ -482,14 +511,24 @@ bool ImGui::BeginTableEx(const char* name, ImGuiID id, int columns_count, ImG
|
||||
for (int n = 0; n < columns_count; n++)
|
||||
{
|
||||
ImGuiTableColumn* column = &table->Columns[n];
|
||||
float width_auto = column->WidthAuto;
|
||||
*column = ImGuiTableColumn();
|
||||
column->WidthAuto = width_auto;
|
||||
column->IsPreserveWidthAuto = true; // Preserve WidthAuto when reinitializing a live table: not technically necessary but remove a visible flicker
|
||||
if (old_columns_to_preserve && n < old_columns_count)
|
||||
{
|
||||
// FIXME: We don't attempt to preserve column order in this path.
|
||||
*column = old_columns_to_preserve[n];
|
||||
}
|
||||
else
|
||||
{
|
||||
float width_auto = column->WidthAuto;
|
||||
*column = ImGuiTableColumn();
|
||||
column->WidthAuto = width_auto;
|
||||
column->IsPreserveWidthAuto = true; // Preserve WidthAuto when reinitializing a live table: not technically necessary but remove a visible flicker
|
||||
column->IsEnabled = column->IsEnabledNextFrame = true;
|
||||
}
|
||||
column->DisplayOrder = table->DisplayOrderToIndex[n] = (ImGuiTableColumnIdx)n;
|
||||
column->IsEnabled = column->IsEnabledNextFrame = true;
|
||||
}
|
||||
}
|
||||
if (old_columns_raw_data)
|
||||
IM_FREE(old_columns_raw_data);
|
||||
|
||||
// Load settings
|
||||
if (table->IsSettingsRequestLoad)
|
||||
@ -635,7 +674,7 @@ static void TableSetupColumnFlags(ImGuiTable* table, ImGuiTableColumn* column, I
|
||||
{
|
||||
IM_ASSERT(ImIsPowerOfTwo(flags & ImGuiTableColumnFlags_WidthMask_)); // Check that only 1 of each set is used.
|
||||
}
|
||||
|
||||
|
||||
// Resize
|
||||
if ((table->Flags & ImGuiTableFlags_Resizable) == 0)
|
||||
flags |= ImGuiTableColumnFlags_NoResize;
|
||||
@ -808,7 +847,7 @@ void ImGui::TableUpdateLayout(ImGuiTable* table)
|
||||
// Apply same widths policy
|
||||
float width_auto = column->WidthAuto;
|
||||
if (table_sizing_policy == ImGuiTableFlags_SizingFixedSame && (column->AutoFitQueue != 0x00 || !column_is_resizable))
|
||||
width_auto = fixed_max_width_auto;
|
||||
width_auto = fixed_max_width_auto;
|
||||
|
||||
// Apply automatic width
|
||||
// Latch initial size for fixed columns and update it constantly for auto-resizing column (unless clipped!)
|
||||
@ -1087,7 +1126,7 @@ void ImGui::TableUpdateLayout(ImGuiTable* table)
|
||||
// Initial state
|
||||
ImGuiWindow* inner_window = table->InnerWindow;
|
||||
if (table->Flags & ImGuiTableFlags_NoClip)
|
||||
table->DrawSplitter.SetCurrentChannel(inner_window->DrawList, TABLE_DRAW_CHANNEL_NOCLIP);
|
||||
table->DrawSplitter->SetCurrentChannel(inner_window->DrawList, TABLE_DRAW_CHANNEL_NOCLIP);
|
||||
else
|
||||
inner_window->DrawList->PushClipRect(inner_window->ClipRect.Min, inner_window->ClipRect.Max, false);
|
||||
}
|
||||
@ -1175,6 +1214,7 @@ void ImGui::EndTable()
|
||||
const ImGuiTableFlags flags = table->Flags;
|
||||
ImGuiWindow* inner_window = table->InnerWindow;
|
||||
ImGuiWindow* outer_window = table->OuterWindow;
|
||||
ImGuiTableTempData* temp_data = table->TempData;
|
||||
IM_ASSERT(inner_window == g.CurrentWindow);
|
||||
IM_ASSERT(outer_window == inner_window || outer_window == inner_window->ParentWindow);
|
||||
|
||||
@ -1187,9 +1227,9 @@ void ImGui::EndTable()
|
||||
TableOpenContextMenu((int)table->HoveredColumnBody);
|
||||
|
||||
// Finalize table height
|
||||
inner_window->DC.PrevLineSize = table->HostBackupPrevLineSize;
|
||||
inner_window->DC.CurrLineSize = table->HostBackupCurrLineSize;
|
||||
inner_window->DC.CursorMaxPos = table->HostBackupCursorMaxPos;
|
||||
inner_window->DC.PrevLineSize = temp_data->HostBackupPrevLineSize;
|
||||
inner_window->DC.CurrLineSize = temp_data->HostBackupCurrLineSize;
|
||||
inner_window->DC.CursorMaxPos = temp_data->HostBackupCursorMaxPos;
|
||||
const float inner_content_max_y = table->RowPosY2;
|
||||
IM_ASSERT(table->RowPosY2 == inner_window->DC.CursorPos.y);
|
||||
if (inner_window != outer_window)
|
||||
@ -1236,10 +1276,11 @@ void ImGui::EndTable()
|
||||
#endif
|
||||
|
||||
// Flatten channels and merge draw calls
|
||||
table->DrawSplitter.SetCurrentChannel(inner_window->DrawList, 0);
|
||||
ImDrawListSplitter* splitter = table->DrawSplitter;
|
||||
splitter->SetCurrentChannel(inner_window->DrawList, 0);
|
||||
if ((table->Flags & ImGuiTableFlags_NoClip) == 0)
|
||||
TableMergeDrawChannels(table);
|
||||
table->DrawSplitter.Merge(inner_window->DrawList);
|
||||
splitter->Merge(inner_window->DrawList);
|
||||
|
||||
// Update ColumnsAutoFitWidth to get us ahead for host using our size to auto-resize without waiting for next BeginTable()
|
||||
const float width_spacings = (table->OuterPaddingX * 2.0f) + (table->CellSpacingX1 + table->CellSpacingX2) * (table->ColumnsEnabledCount - 1);
|
||||
@ -1281,18 +1322,18 @@ void ImGui::EndTable()
|
||||
|
||||
// Pop from id stack
|
||||
IM_ASSERT_USER_ERROR(inner_window->IDStack.back() == table->ID + table->InstanceCurrent, "Mismatching PushID/PopID!");
|
||||
IM_ASSERT_USER_ERROR(outer_window->DC.ItemWidthStack.Size >= table->HostBackupItemWidthStackSize, "Too many PopItemWidth!");
|
||||
IM_ASSERT_USER_ERROR(outer_window->DC.ItemWidthStack.Size >= temp_data->HostBackupItemWidthStackSize, "Too many PopItemWidth!");
|
||||
PopID();
|
||||
|
||||
// Restore window data that we modified
|
||||
const ImVec2 backup_outer_max_pos = outer_window->DC.CursorMaxPos;
|
||||
inner_window->WorkRect = table->HostBackupWorkRect;
|
||||
inner_window->ParentWorkRect = table->HostBackupParentWorkRect;
|
||||
inner_window->WorkRect = temp_data->HostBackupWorkRect;
|
||||
inner_window->ParentWorkRect = temp_data->HostBackupParentWorkRect;
|
||||
inner_window->SkipItems = table->HostSkipItems;
|
||||
outer_window->DC.CursorPos = table->OuterRect.Min;
|
||||
outer_window->DC.ItemWidth = table->HostBackupItemWidth;
|
||||
outer_window->DC.ItemWidthStack.Size = table->HostBackupItemWidthStackSize;
|
||||
outer_window->DC.ColumnsOffset = table->HostBackupColumnsOffset;
|
||||
outer_window->DC.ItemWidth = temp_data->HostBackupItemWidth;
|
||||
outer_window->DC.ItemWidthStack.Size = temp_data->HostBackupItemWidthStackSize;
|
||||
outer_window->DC.ColumnsOffset = temp_data->HostBackupColumnsOffset;
|
||||
|
||||
// Layout in outer window
|
||||
// (FIXME: To allow auto-fit and allow desirable effect of SameLine() we dissociate 'used' vs 'ideal' size by overriding
|
||||
@ -1315,20 +1356,20 @@ void ImGui::EndTable()
|
||||
IM_ASSERT((table->Flags & ImGuiTableFlags_ScrollX) == 0);
|
||||
outer_window->DC.CursorMaxPos.x = ImMax(backup_outer_max_pos.x, table->OuterRect.Min.x + table->ColumnsAutoFitWidth);
|
||||
}
|
||||
else if (table->UserOuterSize.x <= 0.0f)
|
||||
else if (temp_data->UserOuterSize.x <= 0.0f)
|
||||
{
|
||||
const float decoration_size = (table->Flags & ImGuiTableFlags_ScrollX) ? inner_window->ScrollbarSizes.x : 0.0f;
|
||||
outer_window->DC.IdealMaxPos.x = ImMax(outer_window->DC.IdealMaxPos.x, table->OuterRect.Min.x + table->ColumnsAutoFitWidth + decoration_size - table->UserOuterSize.x);
|
||||
outer_window->DC.IdealMaxPos.x = ImMax(outer_window->DC.IdealMaxPos.x, table->OuterRect.Min.x + table->ColumnsAutoFitWidth + decoration_size - temp_data->UserOuterSize.x);
|
||||
outer_window->DC.CursorMaxPos.x = ImMax(backup_outer_max_pos.x, ImMin(table->OuterRect.Max.x, table->OuterRect.Min.x + table->ColumnsAutoFitWidth));
|
||||
}
|
||||
else
|
||||
{
|
||||
outer_window->DC.CursorMaxPos.x = ImMax(backup_outer_max_pos.x, table->OuterRect.Max.x);
|
||||
}
|
||||
if (table->UserOuterSize.y <= 0.0f)
|
||||
if (temp_data->UserOuterSize.y <= 0.0f)
|
||||
{
|
||||
const float decoration_size = (table->Flags & ImGuiTableFlags_ScrollY) ? inner_window->ScrollbarSizes.y : 0.0f;
|
||||
outer_window->DC.IdealMaxPos.y = ImMax(outer_window->DC.IdealMaxPos.y, inner_content_max_y + decoration_size - table->UserOuterSize.y);
|
||||
outer_window->DC.IdealMaxPos.y = ImMax(outer_window->DC.IdealMaxPos.y, inner_content_max_y + decoration_size - temp_data->UserOuterSize.y);
|
||||
outer_window->DC.CursorMaxPos.y = ImMax(backup_outer_max_pos.y, ImMin(table->OuterRect.Max.y, inner_content_max_y));
|
||||
}
|
||||
else
|
||||
@ -1344,8 +1385,15 @@ void ImGui::EndTable()
|
||||
|
||||
// Clear or restore current table, if any
|
||||
IM_ASSERT(g.CurrentWindow == outer_window && g.CurrentTable == table);
|
||||
g.CurrentTableStack.pop_back();
|
||||
g.CurrentTable = g.CurrentTableStack.Size ? g.Tables.GetByIndex(g.CurrentTableStack.back().Index) : NULL;
|
||||
IM_ASSERT(g.CurrentTableStackIdx >= 0);
|
||||
g.CurrentTableStackIdx--;
|
||||
temp_data = g.CurrentTableStackIdx >= 0 ? &g.TablesTempDataStack[g.CurrentTableStackIdx] : NULL;
|
||||
g.CurrentTable = temp_data ? g.Tables.GetByIndex(temp_data->TableIndex) : NULL;
|
||||
if (g.CurrentTable)
|
||||
{
|
||||
g.CurrentTable->TempData = temp_data;
|
||||
g.CurrentTable->DrawSplitter = &temp_data->DrawSplitter;
|
||||
}
|
||||
outer_window->DC.CurrentTableIdx = g.CurrentTable ? g.Tables.GetIndex(g.CurrentTable) : -1;
|
||||
}
|
||||
|
||||
@ -1435,6 +1483,20 @@ void ImGui::TableSetupScrollFreeze(int columns, int rows)
|
||||
table->IsUnfrozenRows = (table->FreezeRowsCount == 0); // Make sure this is set before TableUpdateLayout() so ImGuiListClipper can benefit from it.b
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// [SECTION] Tables: Simple accessors
|
||||
//-----------------------------------------------------------------------------
|
||||
// - TableGetColumnCount()
|
||||
// - TableGetColumnName()
|
||||
// - TableGetColumnName() [Internal]
|
||||
// - TableSetColumnEnabled() [Internal]
|
||||
// - TableGetColumnFlags()
|
||||
// - TableGetCellBgRect() [Internal]
|
||||
// - TableGetColumnResizeID() [Internal]
|
||||
// - TableGetHoveredColumn() [Internal]
|
||||
// - TableSetBgColor()
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
int ImGui::TableGetColumnCount()
|
||||
{
|
||||
ImGuiContext& g = *GImGui;
|
||||
@ -1463,6 +1525,9 @@ const char* ImGui::TableGetColumnName(const ImGuiTable* table, int column_n)
|
||||
return &table->ColumnsNames.Buf[column->NameOffset];
|
||||
}
|
||||
|
||||
// Request enabling/disabling a column (often perceived as "showing/hiding" from users point of view)
|
||||
// Note that end-user can use the context menu to change this themselves (right-click in headers, or right-click in columns body with ImGuiTableFlags_ContextMenuInBody)
|
||||
// Request will be applied during next layout, which happens on the first call to TableNextRow() after BeginTable()
|
||||
// For the getter you can use (TableGetColumnFlags() & ImGuiTableColumnFlags_IsEnabled)
|
||||
void ImGui::TableSetColumnEnabled(int column_n, bool enabled)
|
||||
{
|
||||
@ -1701,7 +1766,7 @@ void ImGui::TableEndRow(ImGuiTable* table)
|
||||
// always followed by a change of clipping rectangle we perform the smallest overwrite possible here.
|
||||
if ((table->Flags & ImGuiTableFlags_NoClip) == 0)
|
||||
window->DrawList->_CmdHeader.ClipRect = table->Bg0ClipRectForDrawCmd.ToVec4();
|
||||
table->DrawSplitter.SetCurrentChannel(window->DrawList, TABLE_DRAW_CHANNEL_BG0);
|
||||
table->DrawSplitter->SetCurrentChannel(window->DrawList, TABLE_DRAW_CHANNEL_BG0);
|
||||
}
|
||||
|
||||
// Draw row background
|
||||
@ -1773,7 +1838,7 @@ void ImGui::TableEndRow(ImGuiTable* table)
|
||||
|
||||
// Update cliprect ahead of TableBeginCell() so clipper can access to new ClipRect->Min.y
|
||||
SetWindowClipRectBeforeSetChannel(window, table->Columns[0].ClipRect);
|
||||
table->DrawSplitter.SetCurrentChannel(window->DrawList, table->Columns[0].DrawChannelCurrent);
|
||||
table->DrawSplitter->SetCurrentChannel(window->DrawList, table->Columns[0].DrawChannelCurrent);
|
||||
}
|
||||
|
||||
if (!(table->RowFlags & ImGuiTableRowFlags_Headers))
|
||||
@ -1888,14 +1953,14 @@ void ImGui::TableBeginCell(ImGuiTable* table, int column_n)
|
||||
if (table->Flags & ImGuiTableFlags_NoClip)
|
||||
{
|
||||
// FIXME: if we end up drawing all borders/bg in EndTable, could remove this and just assert that channel hasn't changed.
|
||||
table->DrawSplitter.SetCurrentChannel(window->DrawList, TABLE_DRAW_CHANNEL_NOCLIP);
|
||||
table->DrawSplitter->SetCurrentChannel(window->DrawList, TABLE_DRAW_CHANNEL_NOCLIP);
|
||||
//IM_ASSERT(table->DrawSplitter._Current == TABLE_DRAW_CHANNEL_NOCLIP);
|
||||
}
|
||||
else
|
||||
{
|
||||
// FIXME-TABLE: Could avoid this if draw channel is dummy channel?
|
||||
SetWindowClipRectBeforeSetChannel(window, column->ClipRect);
|
||||
table->DrawSplitter.SetCurrentChannel(window->DrawList, column->DrawChannelCurrent);
|
||||
table->DrawSplitter->SetCurrentChannel(window->DrawList, column->DrawChannelCurrent);
|
||||
}
|
||||
|
||||
// Logging
|
||||
@ -2143,7 +2208,7 @@ void ImGui::TablePushBackgroundChannel()
|
||||
// Optimization: avoid SetCurrentChannel() + PushClipRect()
|
||||
table->HostBackupInnerClipRect = window->ClipRect;
|
||||
SetWindowClipRectBeforeSetChannel(window, table->Bg2ClipRectForDrawCmd);
|
||||
table->DrawSplitter.SetCurrentChannel(window->DrawList, table->Bg2DrawChannelCurrent);
|
||||
table->DrawSplitter->SetCurrentChannel(window->DrawList, table->Bg2DrawChannelCurrent);
|
||||
}
|
||||
|
||||
void ImGui::TablePopBackgroundChannel()
|
||||
@ -2155,7 +2220,7 @@ void ImGui::TablePopBackgroundChannel()
|
||||
|
||||
// Optimization: avoid PopClipRect() + SetCurrentChannel()
|
||||
SetWindowClipRectBeforeSetChannel(window, table->HostBackupInnerClipRect);
|
||||
table->DrawSplitter.SetCurrentChannel(window->DrawList, column->DrawChannelCurrent);
|
||||
table->DrawSplitter->SetCurrentChannel(window->DrawList, column->DrawChannelCurrent);
|
||||
}
|
||||
|
||||
// Allocate draw channels. Called by TableUpdateLayout()
|
||||
@ -2181,7 +2246,7 @@ void ImGui::TableSetupDrawChannels(ImGuiTable* table)
|
||||
const int channels_for_bg = 1 + 1 * freeze_row_multiplier;
|
||||
const int channels_for_dummy = (table->ColumnsEnabledCount < table->ColumnsCount || table->VisibleMaskByIndex != table->EnabledMaskByIndex) ? +1 : 0;
|
||||
const int channels_total = channels_for_bg + (channels_for_row * freeze_row_multiplier) + channels_for_dummy;
|
||||
table->DrawSplitter.Split(table->InnerWindow->DrawList, channels_total);
|
||||
table->DrawSplitter->Split(table->InnerWindow->DrawList, channels_total);
|
||||
table->DummyDrawChannel = (ImGuiTableDrawChannelIdx)((channels_for_dummy > 0) ? channels_total - 1 : -1);
|
||||
table->Bg2DrawChannelCurrent = TABLE_DRAW_CHANNEL_BG2_FROZEN;
|
||||
table->Bg2DrawChannelUnfrozen = (ImGuiTableDrawChannelIdx)((table->FreezeRowsCount > 0) ? 2 + channels_for_row : TABLE_DRAW_CHANNEL_BG2_FROZEN);
|
||||
@ -2245,7 +2310,7 @@ void ImGui::TableSetupDrawChannels(ImGuiTable* table)
|
||||
void ImGui::TableMergeDrawChannels(ImGuiTable* table)
|
||||
{
|
||||
ImGuiContext& g = *GImGui;
|
||||
ImDrawListSplitter* splitter = &table->DrawSplitter;
|
||||
ImDrawListSplitter* splitter = table->DrawSplitter;
|
||||
const bool has_freeze_v = (table->FreezeRowsCount > 0);
|
||||
const bool has_freeze_h = (table->FreezeColumnsCount > 0);
|
||||
IM_ASSERT(splitter->_Current == 0);
|
||||
@ -2256,10 +2321,11 @@ void ImGui::TableMergeDrawChannels(ImGuiTable* table)
|
||||
ImRect ClipRect;
|
||||
int ChannelsCount;
|
||||
ImBitArray<IMGUI_TABLE_MAX_DRAW_CHANNELS> ChannelsMask;
|
||||
|
||||
MergeGroup() { ChannelsCount = 0; }
|
||||
};
|
||||
int merge_group_mask = 0x00;
|
||||
MergeGroup merge_groups[4];
|
||||
memset(merge_groups, 0, sizeof(merge_groups));
|
||||
|
||||
// 1. Scan channels and take note of those which can be merged
|
||||
for (int column_n = 0; column_n < table->ColumnsCount; column_n++)
|
||||
@ -2337,7 +2403,6 @@ void ImGui::TableMergeDrawChannels(ImGuiTable* table)
|
||||
g.DrawChannelsTempMergeBuffer.resize(splitter->_Count - LEADING_DRAW_CHANNELS); // Use shared temporary storage so the allocation gets amortized
|
||||
ImDrawChannel* dst_tmp = g.DrawChannelsTempMergeBuffer.Data;
|
||||
ImBitArray<IMGUI_TABLE_MAX_DRAW_CHANNELS> remaining_mask; // We need 132-bit of storage
|
||||
remaining_mask.ClearAllBits();
|
||||
remaining_mask.SetBitRange(LEADING_DRAW_CHANNELS, splitter->_Count);
|
||||
remaining_mask.ClearBit(table->Bg2DrawChannelUnfrozen);
|
||||
IM_ASSERT(has_freeze_v == false || table->Bg2DrawChannelUnfrozen != TABLE_DRAW_CHANNEL_BG2_FROZEN);
|
||||
@ -2416,7 +2481,7 @@ void ImGui::TableDrawBorders(ImGuiTable* table)
|
||||
return;
|
||||
|
||||
ImDrawList* inner_drawlist = inner_window->DrawList;
|
||||
table->DrawSplitter.SetCurrentChannel(inner_drawlist, TABLE_DRAW_CHANNEL_BG0);
|
||||
table->DrawSplitter->SetCurrentChannel(inner_drawlist, TABLE_DRAW_CHANNEL_BG0);
|
||||
inner_drawlist->PushClipRect(table->Bg0ClipRectForDrawCmd.Min, table->Bg0ClipRectForDrawCmd.Max, false);
|
||||
|
||||
// Draw inner border and resizing feedback
|
||||
@ -2676,20 +2741,22 @@ void ImGui::TableSortSpecsBuild(ImGuiTable* table)
|
||||
TableSortSpecsSanitize(table);
|
||||
|
||||
// Write output
|
||||
table->SortSpecsMulti.resize(table->SortSpecsCount <= 1 ? 0 : table->SortSpecsCount);
|
||||
ImGuiTableColumnSortSpecs* sort_specs = (table->SortSpecsCount == 0) ? NULL : (table->SortSpecsCount == 1) ? &table->SortSpecsSingle : table->SortSpecsMulti.Data;
|
||||
for (int column_n = 0; column_n < table->ColumnsCount; column_n++)
|
||||
{
|
||||
ImGuiTableColumn* column = &table->Columns[column_n];
|
||||
if (column->SortOrder == -1)
|
||||
continue;
|
||||
IM_ASSERT(column->SortOrder < table->SortSpecsCount);
|
||||
ImGuiTableColumnSortSpecs* sort_spec = &sort_specs[column->SortOrder];
|
||||
sort_spec->ColumnUserID = column->UserID;
|
||||
sort_spec->ColumnIndex = (ImGuiTableColumnIdx)column_n;
|
||||
sort_spec->SortOrder = (ImGuiTableColumnIdx)column->SortOrder;
|
||||
sort_spec->SortDirection = column->SortDirection;
|
||||
}
|
||||
ImGuiTableTempData* temp_data = table->TempData;
|
||||
temp_data->SortSpecsMulti.resize(table->SortSpecsCount <= 1 ? 0 : table->SortSpecsCount);
|
||||
ImGuiTableColumnSortSpecs* sort_specs = (table->SortSpecsCount == 0) ? NULL : (table->SortSpecsCount == 1) ? &temp_data->SortSpecsSingle : temp_data->SortSpecsMulti.Data;
|
||||
if (sort_specs != NULL)
|
||||
for (int column_n = 0; column_n < table->ColumnsCount; column_n++)
|
||||
{
|
||||
ImGuiTableColumn* column = &table->Columns[column_n];
|
||||
if (column->SortOrder == -1)
|
||||
continue;
|
||||
IM_ASSERT(column->SortOrder < table->SortSpecsCount);
|
||||
ImGuiTableColumnSortSpecs* sort_spec = &sort_specs[column->SortOrder];
|
||||
sort_spec->ColumnUserID = column->UserID;
|
||||
sort_spec->ColumnIndex = (ImGuiTableColumnIdx)column_n;
|
||||
sort_spec->SortOrder = (ImGuiTableColumnIdx)column->SortOrder;
|
||||
sort_spec->SortDirection = column->SortDirection;
|
||||
}
|
||||
table->SortSpecs.Specs = sort_specs;
|
||||
table->SortSpecs.SpecsCount = table->SortSpecsCount;
|
||||
table->SortSpecs.SpecsDirty = true; // Mark as dirty for user
|
||||
@ -3318,6 +3385,9 @@ static void TableSettingsHandler_WriteAll(ImGuiContext* ctx, ImGuiSettingsHandle
|
||||
for (int column_n = 0; column_n < settings->ColumnsCount; column_n++, column++)
|
||||
{
|
||||
// "Column 0 UserID=0x42AD2D21 Width=100 Visible=1 Order=0 Sort=0v"
|
||||
bool save_column = column->UserID != 0 || save_size || save_visible || save_order || (save_sort && column->SortOrder != -1);
|
||||
if (!save_column)
|
||||
continue;
|
||||
buf->appendf("Column %-2d", column_n);
|
||||
if (column->UserID != 0) buf->appendf(" UserID=%08X", column->UserID);
|
||||
if (save_size && column->IsStretch) buf->appendf(" Weight=%.4f", column->WidthOrWeight);
|
||||
@ -3371,8 +3441,6 @@ void ImGui::TableGcCompactTransientBuffers(ImGuiTable* table)
|
||||
//IMGUI_DEBUG_LOG("TableGcCompactTransientBuffers() id=0x%08X\n", table->ID);
|
||||
ImGuiContext& g = *GImGui;
|
||||
IM_ASSERT(table->MemoryCompacted == false);
|
||||
table->DrawSplitter.ClearFreeMemory();
|
||||
table->SortSpecsMulti.clear();
|
||||
table->SortSpecs.Specs = NULL;
|
||||
table->IsSortSpecsDirty = true;
|
||||
table->ColumnsNames.clear();
|
||||
@ -3382,6 +3450,13 @@ void ImGui::TableGcCompactTransientBuffers(ImGuiTable* table)
|
||||
g.TablesLastTimeActive[g.Tables.GetIndex(table)] = -1.0f;
|
||||
}
|
||||
|
||||
void ImGui::TableGcCompactTransientBuffers(ImGuiTableTempData* temp_data)
|
||||
{
|
||||
temp_data->DrawSplitter.ClearFreeMemory();
|
||||
temp_data->SortSpecsMulti.clear();
|
||||
temp_data->LastTimeActive = -1.0f;
|
||||
}
|
||||
|
||||
// Compact and remove unused settings data (currently only used by TestEngine)
|
||||
void ImGui::TableGcCompactSettings()
|
||||
{
|
||||
|
@ -1,4 +1,4 @@
|
||||
// dear imgui, v1.82 WIP
|
||||
// dear imgui, v1.83
|
||||
// (widgets code)
|
||||
|
||||
/*
|
||||
@ -59,6 +59,8 @@ Index of this file:
|
||||
#if defined(_MSC_VER) && _MSC_VER >= 1922 // MSVC 2019 16.2 or later
|
||||
#pragma warning (disable: 5054) // operator '|': deprecated between enumerations of different types
|
||||
#endif
|
||||
#pragma warning (disable: 26451) // [Static Analyzer] Arithmetic overflow : Using operator 'xxx' on a 4 byte value and then casting the result to a 8 byte value. Cast the value to the wider type before calling operator 'xxx' to avoid overflow(io.2).
|
||||
#pragma warning (disable: 26812) // [Static Analyzer] The enum type 'xxx' is unscoped. Prefer 'enum class' over 'enum' (Enum.3).
|
||||
#endif
|
||||
|
||||
// Clang/GCC warnings with -Weverything
|
||||
@ -122,7 +124,7 @@ static const ImU64 IM_U64_MAX = (2ULL * 9223372036854775807LL + 1);
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
// For InputTextEx()
|
||||
static bool InputTextFilterCharacter(unsigned int* p_char, ImGuiInputTextFlags flags, ImGuiInputTextCallback callback, void* user_data);
|
||||
static bool InputTextFilterCharacter(unsigned int* p_char, ImGuiInputTextFlags flags, ImGuiInputTextCallback callback, void* user_data, ImGuiInputSource input_source);
|
||||
static int InputTextCalcTextLenAndLineCount(const char* text_begin, const char** out_text_end);
|
||||
static ImVec2 InputTextCalcTextSizeW(const ImWchar* text_begin, const ImWchar* text_end, const ImWchar** remaining = NULL, ImVec2* out_offset = NULL, bool stop_on_new_line = false);
|
||||
|
||||
@ -350,17 +352,20 @@ void ImGui::LabelTextV(const char* label, const char* fmt, va_list args)
|
||||
const ImGuiStyle& style = g.Style;
|
||||
const float w = CalcItemWidth();
|
||||
|
||||
const char* value_text_begin = &g.TempBuffer[0];
|
||||
const char* value_text_end = value_text_begin + ImFormatStringV(g.TempBuffer, IM_ARRAYSIZE(g.TempBuffer), fmt, args);
|
||||
const ImVec2 value_size = CalcTextSize(value_text_begin, value_text_end, false);
|
||||
const ImVec2 label_size = CalcTextSize(label, NULL, true);
|
||||
const ImRect value_bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(w, label_size.y + style.FramePadding.y * 2));
|
||||
const ImRect total_bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(w + (label_size.x > 0.0f ? style.ItemInnerSpacing.x : 0.0f), style.FramePadding.y * 2) + label_size);
|
||||
|
||||
const ImVec2 pos = window->DC.CursorPos;
|
||||
const ImRect value_bb(pos, pos + ImVec2(w, value_size.y + style.FramePadding.y * 2));
|
||||
const ImRect total_bb(pos, pos + ImVec2(w + (label_size.x > 0.0f ? style.ItemInnerSpacing.x + label_size.x : 0.0f), ImMax(value_size.y, label_size.y) + style.FramePadding.y * 2));
|
||||
ItemSize(total_bb, style.FramePadding.y);
|
||||
if (!ItemAdd(total_bb, 0))
|
||||
return;
|
||||
|
||||
// Render
|
||||
const char* value_text_begin = &g.TempBuffer[0];
|
||||
const char* value_text_end = value_text_begin + ImFormatStringV(g.TempBuffer, IM_ARRAYSIZE(g.TempBuffer), fmt, args);
|
||||
RenderTextClipped(value_bb.Min, value_bb.Max, value_text_begin, value_text_end, NULL, ImVec2(0.0f, 0.5f));
|
||||
RenderTextClipped(value_bb.Min + style.FramePadding, value_bb.Max, value_text_begin, value_text_end, &value_size, ImVec2(0.0f, 0.0f));
|
||||
if (label_size.x > 0.0f)
|
||||
RenderText(ImVec2(value_bb.Max.x + style.ItemInnerSpacing.x, value_bb.Min.y + style.FramePadding.y), label);
|
||||
}
|
||||
@ -683,7 +688,7 @@ bool ImGui::ButtonEx(const char* label, const ImVec2& size_arg, ImGuiButtonFlags
|
||||
if (!ItemAdd(bb, id))
|
||||
return false;
|
||||
|
||||
if (window->DC.ItemFlags & ImGuiItemFlags_ButtonRepeat)
|
||||
if (g.CurrentItemFlags & ImGuiItemFlags_ButtonRepeat)
|
||||
flags |= ImGuiButtonFlags_Repeat;
|
||||
bool hovered, held;
|
||||
bool pressed = ButtonBehavior(bb, id, &hovered, &held, flags);
|
||||
@ -759,7 +764,7 @@ bool ImGui::ArrowButtonEx(const char* str_id, ImGuiDir dir, ImVec2 size, ImGuiBu
|
||||
if (!ItemAdd(bb, id))
|
||||
return false;
|
||||
|
||||
if (window->DC.ItemFlags & ImGuiItemFlags_ButtonRepeat)
|
||||
if (g.CurrentItemFlags & ImGuiItemFlags_ButtonRepeat)
|
||||
flags |= ImGuiButtonFlags_Repeat;
|
||||
|
||||
bool hovered, held;
|
||||
@ -1078,7 +1083,7 @@ bool ImGui::Checkbox(const char* label, bool* v)
|
||||
ItemSize(total_bb, style.FramePadding.y);
|
||||
if (!ItemAdd(total_bb, id))
|
||||
{
|
||||
IMGUI_TEST_ENGINE_ITEM_INFO(id, label, window->DC.ItemFlags | ImGuiItemStatusFlags_Checkable | (*v ? ImGuiItemStatusFlags_Checked : 0));
|
||||
IMGUI_TEST_ENGINE_ITEM_INFO(id, label, window->DC.LastItemStatusFlags | ImGuiItemStatusFlags_Checkable | (*v ? ImGuiItemStatusFlags_Checked : 0));
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -1094,7 +1099,7 @@ bool ImGui::Checkbox(const char* label, bool* v)
|
||||
RenderNavHighlight(total_bb, id);
|
||||
RenderFrame(check_bb.Min, check_bb.Max, GetColorU32((held && hovered) ? ImGuiCol_FrameBgActive : hovered ? ImGuiCol_FrameBgHovered : ImGuiCol_FrameBg), true, style.FrameRounding);
|
||||
ImU32 check_col = GetColorU32(ImGuiCol_CheckMark);
|
||||
bool mixed_value = (window->DC.ItemFlags & ImGuiItemFlags_MixedValue) != 0;
|
||||
bool mixed_value = (g.CurrentItemFlags & ImGuiItemFlags_MixedValue) != 0;
|
||||
if (mixed_value)
|
||||
{
|
||||
// Undocumented tristate/mixed/indeterminate checkbox (#2644)
|
||||
@ -1114,7 +1119,7 @@ bool ImGui::Checkbox(const char* label, bool* v)
|
||||
if (label_size.x > 0.0f)
|
||||
RenderText(label_pos, label);
|
||||
|
||||
IMGUI_TEST_ENGINE_ITEM_INFO(id, label, window->DC.ItemFlags | ImGuiItemStatusFlags_Checkable | (*v ? ImGuiItemStatusFlags_Checked : 0));
|
||||
IMGUI_TEST_ENGINE_ITEM_INFO(id, label, window->DC.LastItemStatusFlags | ImGuiItemStatusFlags_Checkable | (*v ? ImGuiItemStatusFlags_Checked : 0));
|
||||
return pressed;
|
||||
}
|
||||
|
||||
@ -1126,11 +1131,11 @@ bool ImGui::CheckboxFlagsT(const char* label, T* flags, T flags_value)
|
||||
bool pressed;
|
||||
if (!all_on && any_on)
|
||||
{
|
||||
ImGuiWindow* window = GetCurrentWindow();
|
||||
ImGuiItemFlags backup_item_flags = window->DC.ItemFlags;
|
||||
window->DC.ItemFlags |= ImGuiItemFlags_MixedValue;
|
||||
ImGuiContext& g = *GImGui;
|
||||
ImGuiItemFlags backup_item_flags = g.CurrentItemFlags;
|
||||
g.CurrentItemFlags |= ImGuiItemFlags_MixedValue;
|
||||
pressed = Checkbox(label, &all_on);
|
||||
window->DC.ItemFlags = backup_item_flags;
|
||||
g.CurrentItemFlags = backup_item_flags;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -1216,7 +1221,7 @@ bool ImGui::RadioButton(const char* label, bool active)
|
||||
if (label_size.x > 0.0f)
|
||||
RenderText(label_pos, label);
|
||||
|
||||
IMGUI_TEST_ENGINE_ITEM_INFO(id, label, window->DC.ItemFlags);
|
||||
IMGUI_TEST_ENGINE_ITEM_INFO(id, label, window->DC.LastItemStatusFlags);
|
||||
return pressed;
|
||||
}
|
||||
|
||||
@ -1428,10 +1433,10 @@ bool ImGui::SplitterBehavior(const ImRect& bb, ImGuiID id, ImGuiAxis axis, float
|
||||
ImGuiContext& g = *GImGui;
|
||||
ImGuiWindow* window = g.CurrentWindow;
|
||||
|
||||
const ImGuiItemFlags item_flags_backup = window->DC.ItemFlags;
|
||||
window->DC.ItemFlags |= ImGuiItemFlags_NoNav | ImGuiItemFlags_NoNavDefaultFocus;
|
||||
const ImGuiItemFlags item_flags_backup = g.CurrentItemFlags;
|
||||
g.CurrentItemFlags |= ImGuiItemFlags_NoNav | ImGuiItemFlags_NoNavDefaultFocus;
|
||||
bool item_add = ItemAdd(bb, id);
|
||||
window->DC.ItemFlags = item_flags_backup;
|
||||
g.CurrentItemFlags = item_flags_backup;
|
||||
if (!item_add)
|
||||
return false;
|
||||
|
||||
@ -1573,7 +1578,9 @@ bool ImGui::BeginCombo(const char* label, const char* preview_value, ImGuiComboF
|
||||
|
||||
bool hovered, held;
|
||||
bool pressed = ButtonBehavior(frame_bb, id, &hovered, &held);
|
||||
bool popup_open = IsPopupOpen(id, ImGuiPopupFlags_None);
|
||||
|
||||
const ImGuiID popup_id = ImHashStr("##ComboPopup", 0, id);
|
||||
bool popup_open = IsPopupOpen(popup_id, ImGuiPopupFlags_None);
|
||||
|
||||
const ImU32 frame_col = GetColorU32(hovered ? ImGuiCol_FrameBgHovered : ImGuiCol_FrameBg);
|
||||
const float value_x2 = ImMax(frame_bb.Min.x, frame_bb.Max.x - arrow_size);
|
||||
@ -1603,7 +1610,7 @@ bool ImGui::BeginCombo(const char* label, const char* preview_value, ImGuiComboF
|
||||
{
|
||||
if (window->DC.NavLayerCurrent == 0)
|
||||
window->NavLastIds[0] = id;
|
||||
OpenPopupEx(id, ImGuiPopupFlags_None);
|
||||
OpenPopupEx(popup_id, ImGuiPopupFlags_None);
|
||||
popup_open = true;
|
||||
}
|
||||
|
||||
@ -1790,7 +1797,7 @@ static const ImGuiDataTypeInfo GDataTypeInfo[] =
|
||||
{ sizeof(ImS64), "S64", "%lld", "%lld" }, // ImGuiDataType_S64
|
||||
{ sizeof(ImU64), "U64", "%llu", "%llu" },
|
||||
#endif
|
||||
{ sizeof(float), "float", "%f", "%f" }, // ImGuiDataType_Float (float are promoted to double in va_arg)
|
||||
{ sizeof(float), "float", "%.3f","%f" }, // ImGuiDataType_Float (float are promoted to double in va_arg)
|
||||
{ sizeof(double), "double","%f", "%lf" }, // ImGuiDataType_Double
|
||||
};
|
||||
IM_STATIC_ASSERT(IM_ARRAYSIZE(GDataTypeInfo) == ImGuiDataType_COUNT);
|
||||
@ -1977,13 +1984,15 @@ bool ImGui::DataTypeApplyOpFromText(const char* buf, const char* initial_value_b
|
||||
{
|
||||
// All other types assign constant
|
||||
// We don't bother handling support for legacy operators since they are a little too crappy. Instead we will later implement a proper expression evaluator in the future.
|
||||
sscanf(buf, format, p_data);
|
||||
if (sscanf(buf, format, p_data) < 1)
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Small types need a 32-bit buffer to receive the result from scanf()
|
||||
int v32;
|
||||
sscanf(buf, format, &v32);
|
||||
if (sscanf(buf, format, &v32) < 1)
|
||||
return false;
|
||||
if (data_type == ImGuiDataType_S8)
|
||||
*(ImS8*)p_data = (ImS8)ImClamp(v32, (int)IM_S8_MIN, (int)IM_S8_MAX);
|
||||
else if (data_type == ImGuiDataType_U8)
|
||||
@ -2082,6 +2091,7 @@ static const char* ImAtoi(const char* src, TYPE* output)
|
||||
// - stb_sprintf.h supports several new modifiers which format numbers in a way that also makes them incompatible atof/atoi.
|
||||
static void SanitizeFormatString(const char* fmt, char* fmt_out, size_t fmt_out_size)
|
||||
{
|
||||
IM_UNUSED(fmt_out_size);
|
||||
const char* fmt_end = ImParseFormatFindEnd(fmt);
|
||||
IM_ASSERT((size_t)(fmt_end - fmt + 1) < fmt_out_size); // Format is too long, let us know if this happens to you!
|
||||
while (fmt < fmt_end)
|
||||
@ -2143,9 +2153,9 @@ bool ImGui::DragBehaviorT(ImGuiDataType data_type, TYPE* v, float v_speed, const
|
||||
{
|
||||
ImGuiContext& g = *GImGui;
|
||||
const ImGuiAxis axis = (flags & ImGuiSliderFlags_Vertical) ? ImGuiAxis_Y : ImGuiAxis_X;
|
||||
const bool is_decimal = (data_type == ImGuiDataType_Float) || (data_type == ImGuiDataType_Double);
|
||||
const bool is_clamped = (v_min < v_max);
|
||||
const bool is_logarithmic = (flags & ImGuiSliderFlags_Logarithmic) && is_decimal;
|
||||
const bool is_logarithmic = (flags & ImGuiSliderFlags_Logarithmic) != 0;
|
||||
const bool is_floating_point = (data_type == ImGuiDataType_Float) || (data_type == ImGuiDataType_Double);
|
||||
|
||||
// Default tweak speed
|
||||
if (v_speed == 0.0f && is_clamped && (v_max - v_min < FLT_MAX))
|
||||
@ -2163,7 +2173,7 @@ bool ImGui::DragBehaviorT(ImGuiDataType data_type, TYPE* v, float v_speed, const
|
||||
}
|
||||
else if (g.ActiveIdSource == ImGuiInputSource_Nav)
|
||||
{
|
||||
int decimal_precision = is_decimal ? ImParseFormatPrecision(format, 3) : 0;
|
||||
const int decimal_precision = is_floating_point ? ImParseFormatPrecision(format, 3) : 0;
|
||||
adjust_delta = GetNavInputAmount2d(ImGuiNavDirSourceFlags_Keyboard | ImGuiNavDirSourceFlags_PadDPad, ImGuiInputReadMode_RepeatFast, 1.0f / 10.0f, 10.0f)[axis];
|
||||
v_speed = ImMax(v_speed, GetMinimumStepAtDecimalPrecision(decimal_precision));
|
||||
}
|
||||
@ -2203,7 +2213,7 @@ bool ImGui::DragBehaviorT(ImGuiDataType data_type, TYPE* v, float v_speed, const
|
||||
if (is_logarithmic)
|
||||
{
|
||||
// When using logarithmic sliders, we need to clamp to avoid hitting zero, but our choice of clamp value greatly affects slider precision. We attempt to use the specified precision to estimate a good lower bound.
|
||||
const int decimal_precision = is_decimal ? ImParseFormatPrecision(format, 3) : 1;
|
||||
const int decimal_precision = is_floating_point ? ImParseFormatPrecision(format, 3) : 1;
|
||||
logarithmic_zero_epsilon = ImPow(0.1f, (float)decimal_precision);
|
||||
|
||||
// Convert to parametric space, apply delta, convert back
|
||||
@ -2241,9 +2251,9 @@ bool ImGui::DragBehaviorT(ImGuiDataType data_type, TYPE* v, float v_speed, const
|
||||
// Clamp values (+ handle overflow/wrap-around for integer types)
|
||||
if (*v != v_cur && is_clamped)
|
||||
{
|
||||
if (v_cur < v_min || (v_cur > *v && adjust_delta < 0.0f && !is_decimal))
|
||||
if (v_cur < v_min || (v_cur > *v && adjust_delta < 0.0f && !is_floating_point))
|
||||
v_cur = v_min;
|
||||
if (v_cur > v_max || (v_cur < *v && adjust_delta > 0.0f && !is_decimal))
|
||||
if (v_cur > v_max || (v_cur < *v && adjust_delta > 0.0f && !is_floating_point))
|
||||
v_cur = v_max;
|
||||
}
|
||||
|
||||
@ -2269,7 +2279,7 @@ bool ImGui::DragBehavior(ImGuiID id, ImGuiDataType data_type, void* p_v, float v
|
||||
}
|
||||
if (g.ActiveId != id)
|
||||
return false;
|
||||
if ((g.CurrentWindow->DC.ItemFlags & ImGuiItemFlags_ReadOnly) || (flags & ImGuiSliderFlags_ReadOnly))
|
||||
if ((g.CurrentItemFlags & ImGuiItemFlags_ReadOnly) || (flags & ImGuiSliderFlags_ReadOnly))
|
||||
return false;
|
||||
|
||||
switch (data_type)
|
||||
@ -2302,12 +2312,14 @@ bool ImGui::DragScalar(const char* label, ImGuiDataType data_type, void* p_data,
|
||||
const ImGuiStyle& style = g.Style;
|
||||
const ImGuiID id = window->GetID(label);
|
||||
const float w = CalcItemWidth();
|
||||
|
||||
const ImVec2 label_size = CalcTextSize(label, NULL, true);
|
||||
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));
|
||||
|
||||
const bool temp_input_allowed = (flags & ImGuiSliderFlags_NoInput) == 0;
|
||||
ItemSize(total_bb, style.FramePadding.y);
|
||||
if (!ItemAdd(total_bb, id, &frame_bb))
|
||||
if (!ItemAdd(total_bb, id, &frame_bb, temp_input_allowed ? ImGuiItemAddFlags_Focusable : 0))
|
||||
return false;
|
||||
|
||||
// Default format string when passing NULL
|
||||
@ -2318,11 +2330,10 @@ bool ImGui::DragScalar(const char* label, ImGuiDataType data_type, void* p_data,
|
||||
|
||||
// Tabbing or CTRL-clicking on Drag turns it into an InputText
|
||||
const bool hovered = ItemHoverable(frame_bb, id);
|
||||
const bool temp_input_allowed = (flags & ImGuiSliderFlags_NoInput) == 0;
|
||||
bool temp_input_is_active = temp_input_allowed && TempInputIsActive(id);
|
||||
if (!temp_input_is_active)
|
||||
{
|
||||
const bool focus_requested = temp_input_allowed && FocusableItemRegister(window, id);
|
||||
const bool focus_requested = temp_input_allowed && (window->DC.LastItemStatusFlags & ImGuiItemStatusFlags_Focused) != 0;
|
||||
const bool clicked = (hovered && g.IO.MouseClicked[0]);
|
||||
const bool double_clicked = (hovered && g.IO.MouseDoubleClicked[0]);
|
||||
if (focus_requested || clicked || double_clicked || g.NavActivateId == id || g.NavInputId == id)
|
||||
@ -2332,10 +2343,7 @@ bool ImGui::DragScalar(const char* label, ImGuiDataType data_type, void* p_data,
|
||||
FocusWindow(window);
|
||||
g.ActiveIdUsingNavDirMask = (1 << ImGuiDir_Left) | (1 << ImGuiDir_Right);
|
||||
if (temp_input_allowed && (focus_requested || (clicked && g.IO.KeyCtrl) || double_clicked || g.NavInputId == id))
|
||||
{
|
||||
temp_input_is_active = true;
|
||||
FocusableItemUnregister(window);
|
||||
}
|
||||
}
|
||||
// Experimental: simple click (without moving) turns Drag into an InputText
|
||||
// FIXME: Currently polling ImGuiConfigFlags_IsTouchScreen, may either poll an hypothetical ImGuiBackendFlags_HasKeyboard and/or an explicit drag settings.
|
||||
@ -2344,7 +2352,6 @@ bool ImGui::DragScalar(const char* label, ImGuiDataType data_type, void* p_data,
|
||||
{
|
||||
g.NavInputId = id;
|
||||
temp_input_is_active = true;
|
||||
FocusableItemUnregister(window);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2375,7 +2382,7 @@ bool ImGui::DragScalar(const char* label, ImGuiDataType data_type, void* p_data,
|
||||
if (label_size.x > 0.0f)
|
||||
RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, frame_bb.Min.y + style.FramePadding.y), label);
|
||||
|
||||
IMGUI_TEST_ENGINE_ITEM_INFO(id, label, window->DC.ItemFlags);
|
||||
IMGUI_TEST_ENGINE_ITEM_INFO(id, label, window->DC.LastItemStatusFlags);
|
||||
return value_changed;
|
||||
}
|
||||
|
||||
@ -2634,7 +2641,7 @@ TYPE ImGui::ScaleValueFromRatioT(ImGuiDataType data_type, float t, TYPE v_min, T
|
||||
{
|
||||
if (v_min == v_max)
|
||||
return v_min;
|
||||
const bool is_decimal = (data_type == ImGuiDataType_Float) || (data_type == ImGuiDataType_Double);
|
||||
const bool is_floating_point = (data_type == ImGuiDataType_Float) || (data_type == ImGuiDataType_Double);
|
||||
|
||||
TYPE result;
|
||||
if (is_logarithmic)
|
||||
@ -2682,7 +2689,7 @@ TYPE ImGui::ScaleValueFromRatioT(ImGuiDataType data_type, float t, TYPE v_min, T
|
||||
else
|
||||
{
|
||||
// Linear slider
|
||||
if (is_decimal)
|
||||
if (is_floating_point)
|
||||
{
|
||||
result = ImLerp(v_min, v_max, t);
|
||||
}
|
||||
@ -2715,14 +2722,14 @@ bool ImGui::SliderBehaviorT(const ImRect& bb, ImGuiID id, ImGuiDataType data_typ
|
||||
const ImGuiStyle& style = g.Style;
|
||||
|
||||
const ImGuiAxis axis = (flags & ImGuiSliderFlags_Vertical) ? ImGuiAxis_Y : ImGuiAxis_X;
|
||||
const bool is_decimal = (data_type == ImGuiDataType_Float) || (data_type == ImGuiDataType_Double);
|
||||
const bool is_logarithmic = (flags & ImGuiSliderFlags_Logarithmic) && is_decimal;
|
||||
const bool is_logarithmic = (flags & ImGuiSliderFlags_Logarithmic) != 0;
|
||||
const bool is_floating_point = (data_type == ImGuiDataType_Float) || (data_type == ImGuiDataType_Double);
|
||||
|
||||
const float grab_padding = 2.0f;
|
||||
const float slider_sz = (bb.Max[axis] - bb.Min[axis]) - grab_padding * 2.0f;
|
||||
float grab_sz = style.GrabMinSize;
|
||||
SIGNEDTYPE v_range = (v_min < v_max ? v_max - v_min : v_min - v_max);
|
||||
if (!is_decimal && v_range >= 0) // v_range < 0 may happen on integer overflows
|
||||
if (!is_floating_point && v_range >= 0) // v_range < 0 may happen on integer overflows
|
||||
grab_sz = ImMax((float)(slider_sz / (v_range + 1)), style.GrabMinSize); // For integer sliders: if possible have the grab size represent 1 unit
|
||||
grab_sz = ImMin(grab_sz, slider_sz);
|
||||
const float slider_usable_sz = slider_sz - grab_sz;
|
||||
@ -2734,7 +2741,7 @@ bool ImGui::SliderBehaviorT(const ImRect& bb, ImGuiID id, ImGuiDataType data_typ
|
||||
if (is_logarithmic)
|
||||
{
|
||||
// When using logarithmic sliders, we need to clamp to avoid hitting zero, but our choice of clamp value greatly affects slider precision. We attempt to use the specified precision to estimate a good lower bound.
|
||||
const int decimal_precision = is_decimal ? ImParseFormatPrecision(format, 3) : 1;
|
||||
const int decimal_precision = is_floating_point ? ImParseFormatPrecision(format, 3) : 1;
|
||||
logarithmic_zero_epsilon = ImPow(0.1f, (float)decimal_precision);
|
||||
zero_deadzone_halfsize = (style.LogSliderDeadzone * 0.5f) / ImMax(slider_usable_sz, 1.0f);
|
||||
}
|
||||
@ -2772,7 +2779,7 @@ bool ImGui::SliderBehaviorT(const ImRect& bb, ImGuiID id, ImGuiDataType data_typ
|
||||
float input_delta = (axis == ImGuiAxis_X) ? input_delta2.x : -input_delta2.y;
|
||||
if (input_delta != 0.0f)
|
||||
{
|
||||
const int decimal_precision = is_decimal ? ImParseFormatPrecision(format, 3) : 0;
|
||||
const int decimal_precision = is_floating_point ? ImParseFormatPrecision(format, 3) : 0;
|
||||
if (decimal_precision > 0)
|
||||
{
|
||||
input_delta /= 100.0f; // Gamepad/keyboard tweak speeds in % of slider bounds
|
||||
@ -2875,7 +2882,7 @@ bool ImGui::SliderBehavior(const ImRect& bb, ImGuiID id, ImGuiDataType data_type
|
||||
IM_ASSERT((flags == 1 || (flags & ImGuiSliderFlags_InvalidMask_) == 0) && "Invalid ImGuiSliderFlags flag! Has the 'float power' argument been mistakenly cast to flags? Call function with ImGuiSliderFlags_Logarithmic flags instead.");
|
||||
|
||||
ImGuiContext& g = *GImGui;
|
||||
if ((g.CurrentWindow->DC.ItemFlags & ImGuiItemFlags_ReadOnly) || (flags & ImGuiSliderFlags_ReadOnly))
|
||||
if ((g.CurrentItemFlags & ImGuiItemFlags_ReadOnly) || (flags & ImGuiSliderFlags_ReadOnly))
|
||||
return false;
|
||||
|
||||
switch (data_type)
|
||||
@ -2925,8 +2932,9 @@ bool ImGui::SliderScalar(const char* label, ImGuiDataType data_type, void* p_dat
|
||||
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));
|
||||
|
||||
const bool temp_input_allowed = (flags & ImGuiSliderFlags_NoInput) == 0;
|
||||
ItemSize(total_bb, style.FramePadding.y);
|
||||
if (!ItemAdd(total_bb, id, &frame_bb))
|
||||
if (!ItemAdd(total_bb, id, &frame_bb, temp_input_allowed ? ImGuiItemAddFlags_Focusable : 0))
|
||||
return false;
|
||||
|
||||
// Default format string when passing NULL
|
||||
@ -2937,11 +2945,10 @@ bool ImGui::SliderScalar(const char* label, ImGuiDataType data_type, void* p_dat
|
||||
|
||||
// Tabbing or CTRL-clicking on Slider turns it into an input box
|
||||
const bool hovered = ItemHoverable(frame_bb, id);
|
||||
const bool temp_input_allowed = (flags & ImGuiSliderFlags_NoInput) == 0;
|
||||
bool temp_input_is_active = temp_input_allowed && TempInputIsActive(id);
|
||||
if (!temp_input_is_active)
|
||||
{
|
||||
const bool focus_requested = temp_input_allowed && FocusableItemRegister(window, id);
|
||||
const bool focus_requested = temp_input_allowed && (window->DC.LastItemStatusFlags & ImGuiItemStatusFlags_Focused) != 0;
|
||||
const bool clicked = (hovered && g.IO.MouseClicked[0]);
|
||||
if (focus_requested || clicked || g.NavActivateId == id || g.NavInputId == id)
|
||||
{
|
||||
@ -2950,10 +2957,7 @@ bool ImGui::SliderScalar(const char* label, ImGuiDataType data_type, void* p_dat
|
||||
FocusWindow(window);
|
||||
g.ActiveIdUsingNavDirMask |= (1 << ImGuiDir_Left) | (1 << ImGuiDir_Right);
|
||||
if (temp_input_allowed && (focus_requested || (clicked && g.IO.KeyCtrl) || g.NavInputId == id))
|
||||
{
|
||||
temp_input_is_active = true;
|
||||
FocusableItemUnregister(window);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -2989,7 +2993,7 @@ bool ImGui::SliderScalar(const char* label, ImGuiDataType data_type, void* p_dat
|
||||
if (label_size.x > 0.0f)
|
||||
RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, frame_bb.Min.y + style.FramePadding.y), label);
|
||||
|
||||
IMGUI_TEST_ENGINE_ITEM_INFO(id, label, window->DC.ItemFlags);
|
||||
IMGUI_TEST_ENGINE_ITEM_INFO(id, label, window->DC.LastItemStatusFlags);
|
||||
return value_changed;
|
||||
}
|
||||
|
||||
@ -3280,7 +3284,7 @@ bool ImGui::TempInputText(const ImRect& bb, ImGuiID id, const char* label, char*
|
||||
ClearActiveID();
|
||||
|
||||
g.CurrentWindow->DC.CursorPos = bb.Min;
|
||||
bool value_changed = InputTextEx(label, NULL, buf, buf_size, bb.GetSize(), flags);
|
||||
bool value_changed = InputTextEx(label, NULL, buf, buf_size, bb.GetSize(), flags | ImGuiInputTextFlags_MergedItem);
|
||||
if (init)
|
||||
{
|
||||
// First frame we started displaying the InputText widget, we expect it to take the active id.
|
||||
@ -3577,12 +3581,12 @@ static ImVec2 InputTextCalcTextSizeW(const ImWchar* text_begin, const ImWchar* t
|
||||
namespace ImStb
|
||||
{
|
||||
|
||||
static int STB_TEXTEDIT_STRINGLEN(const STB_TEXTEDIT_STRING* obj) { return obj->CurLenW; }
|
||||
static ImWchar STB_TEXTEDIT_GETCHAR(const STB_TEXTEDIT_STRING* obj, int idx) { return obj->TextW[idx]; }
|
||||
static float STB_TEXTEDIT_GETWIDTH(STB_TEXTEDIT_STRING* obj, int line_start_idx, int char_idx) { ImWchar c = obj->TextW[line_start_idx + char_idx]; if (c == '\n') return STB_TEXTEDIT_GETWIDTH_NEWLINE; ImGuiContext& g = *GImGui; return g.Font->GetCharAdvance(c) * (g.FontSize / g.Font->FontSize); }
|
||||
static int STB_TEXTEDIT_STRINGLEN(const ImGuiInputTextState* obj) { return obj->CurLenW; }
|
||||
static ImWchar STB_TEXTEDIT_GETCHAR(const ImGuiInputTextState* obj, int idx) { return obj->TextW[idx]; }
|
||||
static float STB_TEXTEDIT_GETWIDTH(ImGuiInputTextState* obj, int line_start_idx, int char_idx) { ImWchar c = obj->TextW[line_start_idx + char_idx]; if (c == '\n') return STB_TEXTEDIT_GETWIDTH_NEWLINE; ImGuiContext& g = *GImGui; return g.Font->GetCharAdvance(c) * (g.FontSize / g.Font->FontSize); }
|
||||
static int STB_TEXTEDIT_KEYTOTEXT(int key) { return key >= 0x200000 ? 0 : key; }
|
||||
static ImWchar STB_TEXTEDIT_NEWLINE = '\n';
|
||||
static void STB_TEXTEDIT_LAYOUTROW(StbTexteditRow* r, STB_TEXTEDIT_STRING* obj, int line_start_idx)
|
||||
static void STB_TEXTEDIT_LAYOUTROW(StbTexteditRow* r, ImGuiInputTextState* obj, int line_start_idx)
|
||||
{
|
||||
const ImWchar* text = obj->TextW.Data;
|
||||
const ImWchar* text_remaining = NULL;
|
||||
@ -3595,19 +3599,20 @@ static void STB_TEXTEDIT_LAYOUTROW(StbTexteditRow* r, STB_TEXTEDIT_STRING* ob
|
||||
r->num_chars = (int)(text_remaining - (text + line_start_idx));
|
||||
}
|
||||
|
||||
// When ImGuiInputTextFlags_Password is set, we don't want actions such as CTRL+Arrow to leak the fact that underlying data are blanks or separators.
|
||||
static bool is_separator(unsigned int c) { return ImCharIsBlankW(c) || c==',' || c==';' || c=='(' || c==')' || c=='{' || c=='}' || c=='[' || c==']' || c=='|'; }
|
||||
static int is_word_boundary_from_right(STB_TEXTEDIT_STRING* obj, int idx) { return idx > 0 ? (is_separator(obj->TextW[idx - 1]) && !is_separator(obj->TextW[idx]) ) : 1; }
|
||||
static int STB_TEXTEDIT_MOVEWORDLEFT_IMPL(STB_TEXTEDIT_STRING* obj, int idx) { idx--; while (idx >= 0 && !is_word_boundary_from_right(obj, idx)) idx--; return idx < 0 ? 0 : idx; }
|
||||
static int is_word_boundary_from_right(ImGuiInputTextState* obj, int idx) { if (obj->Flags & ImGuiInputTextFlags_Password) return 0; return idx > 0 ? (is_separator(obj->TextW[idx - 1]) && !is_separator(obj->TextW[idx]) ) : 1; }
|
||||
static int STB_TEXTEDIT_MOVEWORDLEFT_IMPL(ImGuiInputTextState* obj, int idx) { idx--; while (idx >= 0 && !is_word_boundary_from_right(obj, idx)) idx--; return idx < 0 ? 0 : idx; }
|
||||
#ifdef __APPLE__ // FIXME: Move setting to IO structure
|
||||
static int is_word_boundary_from_left(STB_TEXTEDIT_STRING* obj, int idx) { return idx > 0 ? (!is_separator(obj->TextW[idx - 1]) && is_separator(obj->TextW[idx]) ) : 1; }
|
||||
static int STB_TEXTEDIT_MOVEWORDRIGHT_IMPL(STB_TEXTEDIT_STRING* obj, int idx) { idx++; int len = obj->CurLenW; while (idx < len && !is_word_boundary_from_left(obj, idx)) idx++; return idx > len ? len : idx; }
|
||||
static int is_word_boundary_from_left(ImGuiInputTextState* obj, int idx) { if (obj->Flags & ImGuiInputTextFlags_Password) return 0; return idx > 0 ? (!is_separator(obj->TextW[idx - 1]) && is_separator(obj->TextW[idx]) ) : 1; }
|
||||
static int STB_TEXTEDIT_MOVEWORDRIGHT_IMPL(ImGuiInputTextState* obj, int idx) { idx++; int len = obj->CurLenW; while (idx < len && !is_word_boundary_from_left(obj, idx)) idx++; return idx > len ? len : idx; }
|
||||
#else
|
||||
static int STB_TEXTEDIT_MOVEWORDRIGHT_IMPL(STB_TEXTEDIT_STRING* obj, int idx) { idx++; int len = obj->CurLenW; while (idx < len && !is_word_boundary_from_right(obj, idx)) idx++; return idx > len ? len : idx; }
|
||||
static int STB_TEXTEDIT_MOVEWORDRIGHT_IMPL(ImGuiInputTextState* obj, int idx) { idx++; int len = obj->CurLenW; while (idx < len && !is_word_boundary_from_right(obj, idx)) idx++; return idx > len ? len : idx; }
|
||||
#endif
|
||||
#define STB_TEXTEDIT_MOVEWORDLEFT STB_TEXTEDIT_MOVEWORDLEFT_IMPL // They need to be #define for stb_textedit.h
|
||||
#define STB_TEXTEDIT_MOVEWORDRIGHT STB_TEXTEDIT_MOVEWORDRIGHT_IMPL
|
||||
|
||||
static void STB_TEXTEDIT_DELETECHARS(STB_TEXTEDIT_STRING* obj, int pos, int n)
|
||||
static void STB_TEXTEDIT_DELETECHARS(ImGuiInputTextState* obj, int pos, int n)
|
||||
{
|
||||
ImWchar* dst = obj->TextW.Data + pos;
|
||||
|
||||
@ -3623,9 +3628,9 @@ static void STB_TEXTEDIT_DELETECHARS(STB_TEXTEDIT_STRING* obj, int pos, int n)
|
||||
*dst = '\0';
|
||||
}
|
||||
|
||||
static bool STB_TEXTEDIT_INSERTCHARS(STB_TEXTEDIT_STRING* obj, int pos, const ImWchar* new_text, int new_text_len)
|
||||
static bool STB_TEXTEDIT_INSERTCHARS(ImGuiInputTextState* obj, int pos, const ImWchar* new_text, int new_text_len)
|
||||
{
|
||||
const bool is_resizable = (obj->UserFlags & ImGuiInputTextFlags_CallbackResize) != 0;
|
||||
const bool is_resizable = (obj->Flags & ImGuiInputTextFlags_CallbackResize) != 0;
|
||||
const int text_len = obj->CurLenW;
|
||||
IM_ASSERT(pos <= text_len);
|
||||
|
||||
@ -3679,7 +3684,7 @@ static bool STB_TEXTEDIT_INSERTCHARS(STB_TEXTEDIT_STRING* obj, int pos, const Im
|
||||
|
||||
// stb_textedit internally allows for a single undo record to do addition and deletion, but somehow, calling
|
||||
// the stb_textedit_paste() function creates two separate records, so we perform it manually. (FIXME: Report to nothings/stb?)
|
||||
static void stb_textedit_replace(STB_TEXTEDIT_STRING* str, STB_TexteditState* state, const STB_TEXTEDIT_CHARTYPE* text, int text_len)
|
||||
static void stb_textedit_replace(ImGuiInputTextState* str, STB_TexteditState* state, const STB_TEXTEDIT_CHARTYPE* text, int text_len)
|
||||
{
|
||||
stb_text_makeundo_replace(str, state, 0, str->CurLenW, text_len);
|
||||
ImStb::STB_TEXTEDIT_DELETECHARS(str, 0, str->CurLenW);
|
||||
@ -3762,8 +3767,9 @@ void ImGuiInputTextCallbackData::InsertChars(int pos, const char* new_text, cons
|
||||
}
|
||||
|
||||
// Return false to discard a character.
|
||||
static bool InputTextFilterCharacter(unsigned int* p_char, ImGuiInputTextFlags flags, ImGuiInputTextCallback callback, void* user_data)
|
||||
static bool InputTextFilterCharacter(unsigned int* p_char, ImGuiInputTextFlags flags, ImGuiInputTextCallback callback, void* user_data, ImGuiInputSource input_source)
|
||||
{
|
||||
IM_ASSERT(input_source == ImGuiInputSource_Keyboard || input_source == ImGuiInputSource_Clipboard);
|
||||
unsigned int c = *p_char;
|
||||
|
||||
// Filter non-printable (NB: isprint is unreliable! see #2467)
|
||||
@ -3776,15 +3782,18 @@ static bool InputTextFilterCharacter(unsigned int* p_char, ImGuiInputTextFlags f
|
||||
return false;
|
||||
}
|
||||
|
||||
// We ignore Ascii representation of delete (emitted from Backspace on OSX, see #2578, #2817)
|
||||
if (c == 127)
|
||||
return false;
|
||||
if (input_source != ImGuiInputSource_Clipboard)
|
||||
{
|
||||
// We ignore Ascii representation of delete (emitted from Backspace on OSX, see #2578, #2817)
|
||||
if (c == 127)
|
||||
return false;
|
||||
|
||||
// Filter private Unicode range. GLFW on OSX seems to send private characters for special keys like arrow keys (FIXME)
|
||||
if (c >= 0xE000 && c <= 0xF8FF)
|
||||
return false;
|
||||
// Filter private Unicode range. GLFW on OSX seems to send private characters for special keys like arrow keys (FIXME)
|
||||
if (c >= 0xE000 && c <= 0xF8FF)
|
||||
return false;
|
||||
}
|
||||
|
||||
// Filter Unicode ranges we are not handling in this build.
|
||||
// Filter Unicode ranges we are not handling in this build
|
||||
if (c > IM_UNICODE_CODEPOINT_MAX)
|
||||
return false;
|
||||
|
||||
@ -3888,7 +3897,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
|
||||
ImVec2 inner_size = frame_size;
|
||||
if (is_multiline)
|
||||
{
|
||||
if (!ItemAdd(total_bb, id, &frame_bb))
|
||||
if (!ItemAdd(total_bb, id, &frame_bb, ImGuiItemAddFlags_Focusable))
|
||||
{
|
||||
ItemSize(total_bb, style.FramePadding.y);
|
||||
EndGroup();
|
||||
@ -3909,15 +3918,17 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
|
||||
return false;
|
||||
}
|
||||
draw_window = g.CurrentWindow; // Child window
|
||||
draw_window->DC.NavLayerActiveMaskNext |= (1 << draw_window->DC.NavLayerCurrent); // This is to ensure that EndChild() will display a navigation highlight so we can "enter" into it.
|
||||
draw_window->DC.NavLayersActiveMaskNext |= (1 << draw_window->DC.NavLayerCurrent); // This is to ensure that EndChild() will display a navigation highlight so we can "enter" into it.
|
||||
draw_window->DC.CursorPos += style.FramePadding;
|
||||
inner_size.x -= draw_window->ScrollbarSizes.x;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Support for internal ImGuiInputTextFlags_MergedItem flag, which could be redesigned as an ItemFlags if needed (with test performed in ItemAdd)
|
||||
ItemSize(total_bb, style.FramePadding.y);
|
||||
if (!ItemAdd(total_bb, id, &frame_bb))
|
||||
return false;
|
||||
if (!(flags & ImGuiInputTextFlags_MergedItem))
|
||||
if (!ItemAdd(total_bb, id, &frame_bb, ImGuiItemAddFlags_Focusable))
|
||||
return false;
|
||||
}
|
||||
const bool hovered = ItemHoverable(frame_bb, id);
|
||||
if (hovered)
|
||||
@ -3926,9 +3937,8 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
|
||||
// We are only allowed to access the state if we are already the active widget.
|
||||
ImGuiInputTextState* state = GetInputTextState(id);
|
||||
|
||||
const bool focus_requested = FocusableItemRegister(window, id);
|
||||
const bool focus_requested_by_code = focus_requested && (g.FocusRequestCurrWindow == window && g.FocusRequestCurrCounterRegular == window->DC.FocusCounterRegular);
|
||||
const bool focus_requested_by_tab = focus_requested && !focus_requested_by_code;
|
||||
const bool focus_requested_by_code = (window->DC.LastItemStatusFlags & ImGuiItemStatusFlags_FocusedByCode) != 0;
|
||||
const bool focus_requested_by_tabbing = (window->DC.LastItemStatusFlags & ImGuiItemStatusFlags_FocusedByTabbing) != 0;
|
||||
|
||||
const bool user_clicked = hovered && io.MouseClicked[0];
|
||||
const bool user_nav_input_start = (g.ActiveId != id) && ((g.NavInputId == id) || (g.NavActivateId == id && g.NavInputSource == ImGuiInputSource_Keyboard));
|
||||
@ -3941,7 +3951,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
|
||||
float scroll_y = is_multiline ? draw_window->Scroll.y : FLT_MAX;
|
||||
|
||||
const bool init_changed_specs = (state != NULL && state->Stb.single_line != !is_multiline);
|
||||
const bool init_make_active = (focus_requested || user_clicked || user_scroll_finish || user_nav_input_start);
|
||||
const bool init_make_active = (user_clicked || user_scroll_finish || user_nav_input_start || focus_requested_by_code || focus_requested_by_tabbing);
|
||||
const bool init_state = (init_make_active || user_scroll_active);
|
||||
if ((init_state && g.ActiveId != id) || init_changed_specs)
|
||||
{
|
||||
@ -3982,7 +3992,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
|
||||
}
|
||||
if (flags & ImGuiInputTextFlags_AlwaysOverwrite)
|
||||
state->Stb.insert_mode = 1; // stb field name is indeed incorrect (see #2863)
|
||||
if (!is_multiline && (focus_requested_by_tab || (user_clicked && io.KeyCtrl)))
|
||||
if (!is_multiline && (focus_requested_by_tabbing || (user_clicked && io.KeyCtrl)))
|
||||
select_all = true;
|
||||
}
|
||||
|
||||
@ -4060,7 +4070,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
|
||||
backup_current_text_length = state->CurLenA;
|
||||
state->Edited = false;
|
||||
state->BufCapacityA = buf_size;
|
||||
state->UserFlags = flags;
|
||||
state->Flags = flags;
|
||||
state->UserCallback = callback;
|
||||
state->UserCallbackData = callback_user_data;
|
||||
|
||||
@ -4109,7 +4119,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
|
||||
if (!io.InputQueueCharacters.contains('\t'))
|
||||
{
|
||||
unsigned int c = '\t'; // Insert TAB
|
||||
if (InputTextFilterCharacter(&c, flags, callback, callback_user_data))
|
||||
if (InputTextFilterCharacter(&c, flags, callback, callback_user_data, ImGuiInputSource_Keyboard))
|
||||
state->OnKeyPressed((int)c);
|
||||
}
|
||||
|
||||
@ -4124,7 +4134,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
|
||||
unsigned int c = (unsigned int)io.InputQueueCharacters[n];
|
||||
if (c == '\t' && io.KeyShift)
|
||||
continue;
|
||||
if (InputTextFilterCharacter(&c, flags, callback, callback_user_data))
|
||||
if (InputTextFilterCharacter(&c, flags, callback, callback_user_data, ImGuiInputSource_Keyboard))
|
||||
state->OnKeyPressed((int)c);
|
||||
}
|
||||
|
||||
@ -4188,7 +4198,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
|
||||
else if (!is_readonly)
|
||||
{
|
||||
unsigned int c = '\n'; // Insert new line
|
||||
if (InputTextFilterCharacter(&c, flags, callback, callback_user_data))
|
||||
if (InputTextFilterCharacter(&c, flags, callback, callback_user_data, ImGuiInputSource_Keyboard))
|
||||
state->OnKeyPressed((int)c);
|
||||
}
|
||||
}
|
||||
@ -4241,7 +4251,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
|
||||
s += ImTextCharFromUtf8(&c, s, NULL);
|
||||
if (c == 0)
|
||||
break;
|
||||
if (!InputTextFilterCharacter(&c, flags, callback, callback_user_data))
|
||||
if (!InputTextFilterCharacter(&c, flags, callback, callback_user_data, ImGuiInputSource_Clipboard))
|
||||
continue;
|
||||
clipboard_filtered[clipboard_filtered_len++] = (ImWchar)c;
|
||||
}
|
||||
@ -4413,7 +4423,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
|
||||
}
|
||||
|
||||
// Clear temporary user storage
|
||||
state->UserFlags = 0;
|
||||
state->Flags = ImGuiInputTextFlags_None;
|
||||
state->UserCallback = NULL;
|
||||
state->UserCallbackData = NULL;
|
||||
}
|
||||
@ -4597,7 +4607,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
|
||||
{
|
||||
state->CursorAnim += io.DeltaTime;
|
||||
bool cursor_is_visible = (!g.IO.ConfigInputTextCursorBlink) || (state->CursorAnim <= 0.0f) || ImFmod(state->CursorAnim, 1.20f) <= 0.80f;
|
||||
ImVec2 cursor_screen_pos = draw_pos + cursor_offset - draw_scroll;
|
||||
ImVec2 cursor_screen_pos = ImFloor(draw_pos + cursor_offset - draw_scroll);
|
||||
ImRect cursor_screen_rect(cursor_screen_pos.x, cursor_screen_pos.y - g.FontSize + 0.5f, cursor_screen_pos.x + 1.0f, cursor_screen_pos.y - 1.5f);
|
||||
if (cursor_is_visible && cursor_screen_rect.Overlaps(clip_rect))
|
||||
draw_window->DrawList->AddLine(cursor_screen_rect.Min, cursor_screen_rect.GetBL(), GetColorU32(ImGuiCol_Text));
|
||||
@ -4647,7 +4657,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
|
||||
if (value_changed && !(flags & ImGuiInputTextFlags_NoMarkEdited))
|
||||
MarkItemEdited(id);
|
||||
|
||||
IMGUI_TEST_ENGINE_ITEM_INFO(id, label, window->DC.ItemFlags);
|
||||
IMGUI_TEST_ENGINE_ITEM_INFO(id, label, window->DC.LastItemStatusFlags);
|
||||
if ((flags & ImGuiInputTextFlags_EnterReturnsTrue) != 0)
|
||||
return enter_pressed;
|
||||
else
|
||||
@ -4803,11 +4813,14 @@ bool ImGui::ColorEdit4(const char* label, float col[4], ImGuiColorEditFlags flag
|
||||
char* p = buf;
|
||||
while (*p == '#' || ImCharIsBlankA(*p))
|
||||
p++;
|
||||
i[0] = i[1] = i[2] = i[3] = 0;
|
||||
i[0] = i[1] = i[2] = 0;
|
||||
i[3] = 0xFF; // alpha default to 255 is not parsed by scanf (e.g. inputting #FFFFFF omitting alpha)
|
||||
int r;
|
||||
if (alpha)
|
||||
sscanf(p, "%02X%02X%02X%02X", (unsigned int*)&i[0], (unsigned int*)&i[1], (unsigned int*)&i[2], (unsigned int*)&i[3]); // Treat at unsigned (%X is unsigned)
|
||||
r = sscanf(p, "%02X%02X%02X%02X", (unsigned int*)&i[0], (unsigned int*)&i[1], (unsigned int*)&i[2], (unsigned int*)&i[3]); // Treat at unsigned (%X is unsigned)
|
||||
else
|
||||
sscanf(p, "%02X%02X%02X", (unsigned int*)&i[0], (unsigned int*)&i[1], (unsigned int*)&i[2]);
|
||||
r = sscanf(p, "%02X%02X%02X", (unsigned int*)&i[0], (unsigned int*)&i[1], (unsigned int*)&i[2]);
|
||||
IM_UNUSED(r); // Fixes C6031: Return value ignored: 'sscanf'.
|
||||
}
|
||||
if (!(flags & ImGuiColorEditFlags_NoOptions))
|
||||
OpenPopupOnItemClick("context");
|
||||
@ -5745,7 +5758,7 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l
|
||||
{
|
||||
if (is_open && !(flags & ImGuiTreeNodeFlags_NoTreePushOnOpen))
|
||||
TreePushOverrideID(id);
|
||||
IMGUI_TEST_ENGINE_ITEM_INFO(window->DC.LastItemId, label, window->DC.ItemFlags | (is_leaf ? 0 : ImGuiItemStatusFlags_Openable) | (is_open ? ImGuiItemStatusFlags_Opened : 0));
|
||||
IMGUI_TEST_ENGINE_ITEM_INFO(window->DC.LastItemId, label, window->DC.LastItemStatusFlags | (is_leaf ? 0 : ImGuiItemStatusFlags_Openable) | (is_open ? ImGuiItemStatusFlags_Opened : 0));
|
||||
return is_open;
|
||||
}
|
||||
|
||||
@ -5871,7 +5884,7 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l
|
||||
|
||||
if (is_open && !(flags & ImGuiTreeNodeFlags_NoTreePushOnOpen))
|
||||
TreePushOverrideID(id);
|
||||
IMGUI_TEST_ENGINE_ITEM_INFO(id, label, window->DC.ItemFlags | (is_leaf ? 0 : ImGuiItemStatusFlags_Openable) | (is_open ? ImGuiItemStatusFlags_Opened : 0));
|
||||
IMGUI_TEST_ENGINE_ITEM_INFO(id, label, window->DC.LastItemStatusFlags | (is_leaf ? 0 : ImGuiItemStatusFlags_Openable) | (is_open ? ImGuiItemStatusFlags_Opened : 0));
|
||||
return is_open;
|
||||
}
|
||||
|
||||
@ -6054,10 +6067,10 @@ bool ImGui::Selectable(const char* label, bool selected, ImGuiSelectableFlags fl
|
||||
bool item_add;
|
||||
if (flags & ImGuiSelectableFlags_Disabled)
|
||||
{
|
||||
ImGuiItemFlags backup_item_flags = window->DC.ItemFlags;
|
||||
window->DC.ItemFlags |= ImGuiItemFlags_Disabled | ImGuiItemFlags_NoNavDefaultFocus;
|
||||
ImGuiItemFlags backup_item_flags = g.CurrentItemFlags;
|
||||
g.CurrentItemFlags |= ImGuiItemFlags_Disabled | ImGuiItemFlags_NoNavDefaultFocus;
|
||||
item_add = ItemAdd(bb, id);
|
||||
window->DC.ItemFlags = backup_item_flags;
|
||||
g.CurrentItemFlags = backup_item_flags;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -6135,10 +6148,10 @@ bool ImGui::Selectable(const char* label, bool selected, ImGuiSelectableFlags fl
|
||||
if (flags & ImGuiSelectableFlags_Disabled) PopStyleColor();
|
||||
|
||||
// Automatically close popups
|
||||
if (pressed && (window->Flags & ImGuiWindowFlags_Popup) && !(flags & ImGuiSelectableFlags_DontClosePopups) && !(window->DC.ItemFlags & ImGuiItemFlags_SelectableDontClosePopup))
|
||||
if (pressed && (window->Flags & ImGuiWindowFlags_Popup) && !(flags & ImGuiSelectableFlags_DontClosePopups) && !(g.CurrentItemFlags & ImGuiItemFlags_SelectableDontClosePopup))
|
||||
CloseCurrentPopup();
|
||||
|
||||
IMGUI_TEST_ENGINE_ITEM_INFO(id, label, window->DC.ItemFlags);
|
||||
IMGUI_TEST_ENGINE_ITEM_INFO(id, label, window->DC.LastItemStatusFlags);
|
||||
return pressed;
|
||||
}
|
||||
|
||||
@ -6287,7 +6300,7 @@ bool ImGui::ListBox(const char* label, int* current_item, bool (*items_getter)(v
|
||||
// Plot/Graph widgets are not very good.
|
||||
// Consider writing your own, or using a third-party one, see:
|
||||
// - ImPlot https://github.com/epezent/implot
|
||||
// - others https://github.com/ocornut/imgui/wiki/Useful-Widgets
|
||||
// - others https://github.com/ocornut/imgui/wiki/Useful-Extensions
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
int ImGui::PlotEx(ImGuiPlotType plot_type, const char* label, float (*values_getter)(void* data, int idx), void* data, int values_count, int values_offset, const char* overlay_text, float scale_min, float scale_max, ImVec2 frame_size)
|
||||
@ -6579,7 +6592,7 @@ void ImGui::EndMenuBar()
|
||||
// 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)
|
||||
const ImGuiNavLayer layer = ImGuiNavLayer_Menu;
|
||||
IM_ASSERT(window->DC.NavLayerActiveMaskNext & (1 << layer)); // Sanity check
|
||||
IM_ASSERT(window->DC.NavLayersActiveMaskNext & (1 << layer)); // Sanity check
|
||||
FocusWindow(window);
|
||||
SetNavID(window->NavLastIds[layer], layer, 0, window->NavRectRel[layer]);
|
||||
g.NavDisableHighlight = true; // Hide highlight for the current frame so we don't see the intermediary selection.
|
||||
@ -6589,11 +6602,12 @@ void ImGui::EndMenuBar()
|
||||
}
|
||||
}
|
||||
|
||||
IM_MSVC_WARNING_SUPPRESS(6011); // Static Analysis false positive "warning C6011: Dereferencing NULL pointer 'window'"
|
||||
IM_ASSERT(window->Flags & ImGuiWindowFlags_MenuBar);
|
||||
IM_ASSERT(window->DC.MenuBarAppending);
|
||||
PopClipRect();
|
||||
PopID();
|
||||
window->DC.MenuBarOffset.x = window->DC.CursorPos.x - window->MenuBarRect().Min.x; // Save horizontal position so next append can reuse it. This is kinda equivalent to a per-layer CursorPos.
|
||||
window->DC.MenuBarOffset.x = window->DC.CursorPos.x - window->Pos.x; // Save horizontal position so next append can reuse it. This is kinda equivalent to a per-layer CursorPos.
|
||||
g.GroupStack.back().EmitItem = false;
|
||||
EndGroup(); // Restore position on layer 0
|
||||
window->DC.LayoutType = ImGuiLayoutType_Vertical;
|
||||
@ -6601,46 +6615,63 @@ void ImGui::EndMenuBar()
|
||||
window->DC.MenuBarAppending = false;
|
||||
}
|
||||
|
||||
// Important: calling order matters!
|
||||
// FIXME: Somehow overlapping with docking tech.
|
||||
// FIXME: The "rect-cut" aspect of this could be formalized into a lower-level helper (rect-cut: https://halt.software/dead-simple-layouts)
|
||||
bool ImGui::BeginViewportSideBar(const char* name, ImGuiViewport* viewport_p, ImGuiDir dir, float axis_size, ImGuiWindowFlags window_flags)
|
||||
{
|
||||
IM_ASSERT(dir != ImGuiDir_None);
|
||||
|
||||
ImGuiWindow* bar_window = FindWindowByName(name);
|
||||
if (bar_window == NULL || bar_window->BeginCount == 0)
|
||||
{
|
||||
// Calculate and set window size/position
|
||||
ImGuiViewportP* viewport = (ImGuiViewportP*)(void*)(viewport_p ? viewport_p : GetMainViewport());
|
||||
ImRect avail_rect = viewport->GetBuildWorkRect();
|
||||
ImGuiAxis axis = (dir == ImGuiDir_Up || dir == ImGuiDir_Down) ? ImGuiAxis_Y : ImGuiAxis_X;
|
||||
ImVec2 pos = avail_rect.Min;
|
||||
if (dir == ImGuiDir_Right || dir == ImGuiDir_Down)
|
||||
pos[axis] = avail_rect.Max[axis] - axis_size;
|
||||
ImVec2 size = avail_rect.GetSize();
|
||||
size[axis] = axis_size;
|
||||
SetNextWindowPos(pos);
|
||||
SetNextWindowSize(size);
|
||||
|
||||
// Report our size into work area (for next frame) using actual window size
|
||||
if (dir == ImGuiDir_Up || dir == ImGuiDir_Left)
|
||||
viewport->BuildWorkOffsetMin[axis] += axis_size;
|
||||
else if (dir == ImGuiDir_Down || dir == ImGuiDir_Right)
|
||||
viewport->BuildWorkOffsetMax[axis] -= axis_size;
|
||||
}
|
||||
|
||||
window_flags |= ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove;
|
||||
PushStyleVar(ImGuiStyleVar_WindowRounding, 0.0f);
|
||||
PushStyleVar(ImGuiStyleVar_WindowMinSize, ImVec2(0, 0)); // Lift normal size constraint
|
||||
bool is_open = Begin(name, NULL, window_flags);
|
||||
PopStyleVar(2);
|
||||
|
||||
return is_open;
|
||||
}
|
||||
|
||||
bool ImGui::BeginMainMenuBar()
|
||||
{
|
||||
ImGuiContext& g = *GImGui;
|
||||
ImGuiViewportP* viewport = (ImGuiViewportP*)(void*)GetMainViewport();
|
||||
ImGuiWindow* menu_bar_window = FindWindowByName("##MainMenuBar");
|
||||
|
||||
// For the main menu bar, which cannot be moved, we honor g.Style.DisplaySafeAreaPadding to ensure text can be visible on a TV set.
|
||||
// FIXME: This could be generalized as an opt-in way to clamp window->DC.CursorStartPos to avoid SafeArea?
|
||||
// FIXME: Consider removing support for safe area down the line... it's messy. Nowadays consoles have support for TV calibration in OS settings.
|
||||
g.NextWindowData.MenuBarOffsetMinVal = ImVec2(g.Style.DisplaySafeAreaPadding.x, ImMax(g.Style.DisplaySafeAreaPadding.y - g.Style.FramePadding.y, 0.0f));
|
||||
|
||||
// Get our rectangle at the top of the work area
|
||||
if (menu_bar_window == NULL || menu_bar_window->BeginCount == 0)
|
||||
{
|
||||
// Set window position
|
||||
// We don't attempt to calculate our height ahead, as it depends on the per-viewport font size.
|
||||
// However menu-bar will affect the minimum window size so we'll get the right height.
|
||||
ImVec2 menu_bar_pos = viewport->Pos + viewport->CurrWorkOffsetMin;
|
||||
ImVec2 menu_bar_size = ImVec2(viewport->Size.x - viewport->CurrWorkOffsetMin.x + viewport->CurrWorkOffsetMax.x, 1.0f);
|
||||
SetNextWindowPos(menu_bar_pos);
|
||||
SetNextWindowSize(menu_bar_size);
|
||||
}
|
||||
|
||||
// Create window
|
||||
PushStyleVar(ImGuiStyleVar_WindowRounding, 0.0f);
|
||||
PushStyleVar(ImGuiStyleVar_WindowMinSize, ImVec2(0, 0)); // Lift normal size constraint, however the presence of a menu-bar will give us the minimum height we want.
|
||||
ImGuiWindowFlags window_flags = ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_MenuBar;
|
||||
bool is_open = Begin("##MainMenuBar", NULL, window_flags) && BeginMenuBar();
|
||||
PopStyleVar(2);
|
||||
|
||||
// Report our size into work area (for next frame) using actual window size
|
||||
menu_bar_window = GetCurrentWindow();
|
||||
if (menu_bar_window->BeginCount == 1)
|
||||
viewport->CurrWorkOffsetMin.y += menu_bar_window->Size.y;
|
||||
|
||||
ImGuiWindowFlags window_flags = ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_MenuBar;
|
||||
float height = GetFrameHeight();
|
||||
bool is_open = BeginViewportSideBar("##MainMenuBar", viewport, ImGuiDir_Up, height, window_flags);
|
||||
g.NextWindowData.MenuBarOffsetMinVal = ImVec2(0.0f, 0.0f);
|
||||
if (!is_open)
|
||||
{
|
||||
|
||||
if (is_open)
|
||||
BeginMenuBar();
|
||||
else
|
||||
End();
|
||||
return false;
|
||||
}
|
||||
return true; //-V1020
|
||||
return is_open;
|
||||
}
|
||||
|
||||
void ImGui::EndMainMenuBar()
|
||||
@ -6794,7 +6825,7 @@ bool ImGui::BeginMenu(const char* label, bool enabled)
|
||||
if (want_close && IsPopupOpen(id, ImGuiPopupFlags_None))
|
||||
ClosePopupToLevel(g.BeginPopupStack.Size, true);
|
||||
|
||||
IMGUI_TEST_ENGINE_ITEM_INFO(id, label, window->DC.ItemFlags | ImGuiItemStatusFlags_Openable | (menu_is_open ? ImGuiItemStatusFlags_Opened : 0));
|
||||
IMGUI_TEST_ENGINE_ITEM_INFO(id, label, window->DC.LastItemStatusFlags | ImGuiItemStatusFlags_Openable | (menu_is_open ? ImGuiItemStatusFlags_Opened : 0));
|
||||
|
||||
if (!menu_is_open && want_open && g.OpenPopupStack.Size > g.BeginPopupStack.Size)
|
||||
{
|
||||
@ -6854,11 +6885,11 @@ bool ImGui::MenuItem(const char* label, const char* shortcut, bool selected, boo
|
||||
if (window->DC.LayoutType == ImGuiLayoutType_Horizontal)
|
||||
{
|
||||
// Mimic the exact layout spacing of BeginMenu() to allow MenuItem() inside a menu bar, which is a little misleading but may be useful
|
||||
// Note that in this situation we render neither the shortcut neither the selected tick mark
|
||||
// Note that in this situation: we don't render the shortcut, we render a highlight instead of the selected tick mark.
|
||||
float w = label_size.x;
|
||||
window->DC.CursorPos.x += IM_FLOOR(style.ItemSpacing.x * 0.5f);
|
||||
PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(style.ItemSpacing.x * 2.0f, style.ItemSpacing.y));
|
||||
pressed = Selectable(label, false, flags, ImVec2(w, 0.0f));
|
||||
pressed = Selectable(label, selected, flags, ImVec2(w, 0.0f));
|
||||
PopStyleVar();
|
||||
window->DC.CursorPos.x += IM_FLOOR(style.ItemSpacing.x * (-1.0f + 0.5f)); // -1 spacing to compensate the spacing added when Selectable() did a SameLine(). It would also work to call SameLine() ourselves after the PopStyleVar().
|
||||
}
|
||||
@ -6881,7 +6912,7 @@ bool ImGui::MenuItem(const char* label, const char* shortcut, bool selected, boo
|
||||
RenderCheckMark(window->DrawList, pos + ImVec2(window->DC.MenuColumns.Pos[2] + extra_w + g.FontSize * 0.40f, g.FontSize * 0.134f * 0.5f), GetColorU32(enabled ? ImGuiCol_Text : ImGuiCol_TextDisabled), g.FontSize * 0.866f);
|
||||
}
|
||||
|
||||
IMGUI_TEST_ENGINE_ITEM_INFO(window->DC.LastItemId, label, window->DC.ItemFlags | ImGuiItemStatusFlags_Checkable | (selected ? ImGuiItemStatusFlags_Checked : 0));
|
||||
IMGUI_TEST_ENGINE_ITEM_INFO(window->DC.LastItemId, label, window->DC.LastItemStatusFlags | ImGuiItemStatusFlags_Checkable | (selected ? ImGuiItemStatusFlags_Checked : 0));
|
||||
return pressed;
|
||||
}
|
||||
|
||||
@ -6942,12 +6973,17 @@ ImGuiTabBar::ImGuiTabBar()
|
||||
LastTabItemIdx = -1;
|
||||
}
|
||||
|
||||
static inline int TabItemGetSectionIdx(const ImGuiTabItem* tab)
|
||||
{
|
||||
return (tab->Flags & ImGuiTabItemFlags_Leading) ? 0 : (tab->Flags & ImGuiTabItemFlags_Trailing) ? 2 : 1;
|
||||
}
|
||||
|
||||
static int IMGUI_CDECL TabItemComparerBySection(const void* lhs, const void* rhs)
|
||||
{
|
||||
const ImGuiTabItem* a = (const ImGuiTabItem*)lhs;
|
||||
const ImGuiTabItem* b = (const ImGuiTabItem*)rhs;
|
||||
const int a_section = (a->Flags & ImGuiTabItemFlags_Leading) ? 0 : (a->Flags & ImGuiTabItemFlags_Trailing) ? 2 : 1;
|
||||
const int b_section = (b->Flags & ImGuiTabItemFlags_Leading) ? 0 : (b->Flags & ImGuiTabItemFlags_Trailing) ? 2 : 1;
|
||||
const int a_section = TabItemGetSectionIdx(a);
|
||||
const int b_section = TabItemGetSectionIdx(b);
|
||||
if (a_section != b_section)
|
||||
return a_section - b_section;
|
||||
return (int)(a->IndexDuringLayout - b->IndexDuringLayout);
|
||||
@ -7116,11 +7152,11 @@ static void ImGui::TabBarLayout(ImGuiTabBar* tab_bar)
|
||||
tab->IndexDuringLayout = (ImS16)tab_dst_n;
|
||||
|
||||
// We will need sorting if tabs have changed section (e.g. moved from one of Leading/Central/Trailing to another)
|
||||
int curr_tab_section_n = (tab->Flags & ImGuiTabItemFlags_Leading) ? 0 : (tab->Flags & ImGuiTabItemFlags_Trailing) ? 2 : 1;
|
||||
int curr_tab_section_n = TabItemGetSectionIdx(tab);
|
||||
if (tab_dst_n > 0)
|
||||
{
|
||||
ImGuiTabItem* prev_tab = &tab_bar->Tabs[tab_dst_n - 1];
|
||||
int prev_tab_section_n = (prev_tab->Flags & ImGuiTabItemFlags_Leading) ? 0 : (prev_tab->Flags & ImGuiTabItemFlags_Trailing) ? 2 : 1;
|
||||
int prev_tab_section_n = TabItemGetSectionIdx(prev_tab);
|
||||
if (curr_tab_section_n == 0 && prev_tab_section_n != 0)
|
||||
need_sort_by_section = true;
|
||||
if (prev_tab_section_n == 2 && curr_tab_section_n != 2)
|
||||
@ -7192,12 +7228,13 @@ static void ImGui::TabBarLayout(ImGuiTabBar* tab_bar)
|
||||
const bool has_close_button = (tab->Flags & ImGuiTabItemFlags_NoCloseButton) ? false : true;
|
||||
tab->ContentWidth = TabItemCalcSize(tab_name, has_close_button).x;
|
||||
|
||||
int section_n = (tab->Flags & ImGuiTabItemFlags_Leading) ? 0 : (tab->Flags & ImGuiTabItemFlags_Trailing) ? 2 : 1;
|
||||
int section_n = TabItemGetSectionIdx(tab);
|
||||
ImGuiTabBarSection* section = §ions[section_n];
|
||||
section->Width += tab->ContentWidth + (section_n == curr_section_n ? g.Style.ItemInnerSpacing.x : 0.0f);
|
||||
curr_section_n = section_n;
|
||||
|
||||
// Store data so we can build an array sorted by width if we need to shrink tabs down
|
||||
IM_MSVC_WARNING_SUPPRESS(6385);
|
||||
int shrink_buffer_index = shrink_buffer_indexes[section_n]++;
|
||||
g.ShrinkWidthBuffer[shrink_buffer_index].Index = tab_n;
|
||||
g.ShrinkWidthBuffer[shrink_buffer_index].Width = tab->ContentWidth;
|
||||
@ -7247,7 +7284,7 @@ static void ImGui::TabBarLayout(ImGuiTabBar* tab_bar)
|
||||
if (shrinked_width < 0.0f)
|
||||
continue;
|
||||
|
||||
int section_n = (tab->Flags & ImGuiTabItemFlags_Leading) ? 0 : (tab->Flags & ImGuiTabItemFlags_Trailing) ? 2 : 1;
|
||||
int section_n = TabItemGetSectionIdx(tab);
|
||||
sections[section_n].Width -= (tab->Width - shrinked_width);
|
||||
tab->Width = shrinked_width;
|
||||
}
|
||||
@ -7392,7 +7429,7 @@ static void ImGui::TabBarScrollToTab(ImGuiTabBar* tab_bar, ImGuiID tab_id, ImGui
|
||||
ImGuiTabItem* tab = TabBarFindTabByID(tab_bar, tab_id);
|
||||
if (tab == NULL)
|
||||
return;
|
||||
if (tab->Flags & (ImGuiTabItemFlags_Leading | ImGuiTabItemFlags_Trailing))
|
||||
if (tab->Flags & ImGuiTabItemFlags_SectionMask_)
|
||||
return;
|
||||
|
||||
ImGuiContext& g = *GImGui;
|
||||
@ -7421,12 +7458,48 @@ static void ImGui::TabBarScrollToTab(ImGuiTabBar* tab_bar, ImGuiID tab_id, ImGui
|
||||
}
|
||||
}
|
||||
|
||||
void ImGui::TabBarQueueReorder(ImGuiTabBar* tab_bar, const ImGuiTabItem* tab, int dir)
|
||||
void ImGui::TabBarQueueReorder(ImGuiTabBar* tab_bar, const ImGuiTabItem* tab, int offset)
|
||||
{
|
||||
IM_ASSERT(dir == -1 || dir == +1);
|
||||
IM_ASSERT(offset != 0);
|
||||
IM_ASSERT(tab_bar->ReorderRequestTabId == 0);
|
||||
tab_bar->ReorderRequestTabId = tab->ID;
|
||||
tab_bar->ReorderRequestDir = (ImS8)dir;
|
||||
tab_bar->ReorderRequestOffset = (ImS16)offset;
|
||||
}
|
||||
|
||||
void ImGui::TabBarQueueReorderFromMousePos(ImGuiTabBar* tab_bar, const ImGuiTabItem* src_tab, ImVec2 mouse_pos)
|
||||
{
|
||||
ImGuiContext& g = *GImGui;
|
||||
IM_ASSERT(tab_bar->ReorderRequestTabId == 0);
|
||||
if ((tab_bar->Flags & ImGuiTabBarFlags_Reorderable) == 0)
|
||||
return;
|
||||
|
||||
const bool is_central_section = (src_tab->Flags & ImGuiTabItemFlags_SectionMask_) == 0;
|
||||
const float bar_offset = tab_bar->BarRect.Min.x - (is_central_section ? tab_bar->ScrollingTarget : 0);
|
||||
|
||||
// Count number of contiguous tabs we are crossing over
|
||||
const int dir = (bar_offset + src_tab->Offset) > mouse_pos.x ? -1 : +1;
|
||||
const int src_idx = tab_bar->Tabs.index_from_ptr(src_tab);
|
||||
int dst_idx = src_idx;
|
||||
for (int i = src_idx; i >= 0 && i < tab_bar->Tabs.Size; i += dir)
|
||||
{
|
||||
// Reordered tabs must share the same section
|
||||
const ImGuiTabItem* dst_tab = &tab_bar->Tabs[i];
|
||||
if (dst_tab->Flags & ImGuiTabItemFlags_NoReorder)
|
||||
break;
|
||||
if ((dst_tab->Flags & ImGuiTabItemFlags_SectionMask_) != (src_tab->Flags & ImGuiTabItemFlags_SectionMask_))
|
||||
break;
|
||||
dst_idx = i;
|
||||
|
||||
// Include spacing after tab, so when mouse cursor is between tabs we would not continue checking further tabs that are not hovered.
|
||||
const float x1 = bar_offset + dst_tab->Offset - g.Style.ItemInnerSpacing.x;
|
||||
const float x2 = bar_offset + dst_tab->Offset + dst_tab->Width + g.Style.ItemInnerSpacing.x;
|
||||
//GetForegroundDrawList()->AddRect(ImVec2(x1, tab_bar->BarRect.Min.y), ImVec2(x2, tab_bar->BarRect.Max.y), IM_COL32(255, 0, 0, 255));
|
||||
if ((dir < 0 && mouse_pos.x > x1) || (dir > 0 && mouse_pos.x < x2))
|
||||
break;
|
||||
}
|
||||
|
||||
if (dst_idx != src_idx)
|
||||
TabBarQueueReorder(tab_bar, src_tab, dst_idx - src_idx);
|
||||
}
|
||||
|
||||
bool ImGui::TabBarProcessReorder(ImGuiTabBar* tab_bar)
|
||||
@ -7436,19 +7509,23 @@ bool ImGui::TabBarProcessReorder(ImGuiTabBar* tab_bar)
|
||||
return false;
|
||||
|
||||
//IM_ASSERT(tab_bar->Flags & ImGuiTabBarFlags_Reorderable); // <- this may happen when using debug tools
|
||||
int tab2_order = tab_bar->GetTabOrder(tab1) + tab_bar->ReorderRequestDir;
|
||||
int tab2_order = tab_bar->GetTabOrder(tab1) + tab_bar->ReorderRequestOffset;
|
||||
if (tab2_order < 0 || tab2_order >= tab_bar->Tabs.Size)
|
||||
return false;
|
||||
|
||||
// Reordered TabItem must share the same position flags than target
|
||||
// Reordered tabs must share the same section
|
||||
// (Note: TabBarQueueReorderFromMousePos() also has a similar test but since we allow direct calls to TabBarQueueReorder() we do it here too)
|
||||
ImGuiTabItem* tab2 = &tab_bar->Tabs[tab2_order];
|
||||
if (tab2->Flags & ImGuiTabItemFlags_NoReorder)
|
||||
return false;
|
||||
if ((tab1->Flags & (ImGuiTabItemFlags_Leading | ImGuiTabItemFlags_Trailing)) != (tab2->Flags & (ImGuiTabItemFlags_Leading | ImGuiTabItemFlags_Trailing)))
|
||||
if ((tab1->Flags & ImGuiTabItemFlags_SectionMask_) != (tab2->Flags & ImGuiTabItemFlags_SectionMask_))
|
||||
return false;
|
||||
|
||||
ImGuiTabItem item_tmp = *tab1;
|
||||
*tab1 = *tab2;
|
||||
ImGuiTabItem* src_tab = (tab_bar->ReorderRequestOffset > 0) ? tab1 + 1 : tab2;
|
||||
ImGuiTabItem* dst_tab = (tab_bar->ReorderRequestOffset > 0) ? tab1 : tab2 + 1;
|
||||
const int move_count = (tab_bar->ReorderRequestOffset > 0) ? tab_bar->ReorderRequestOffset : -tab_bar->ReorderRequestOffset;
|
||||
memmove(dst_tab, src_tab, move_count * sizeof(ImGuiTabItem));
|
||||
*tab2 = item_tmp;
|
||||
|
||||
if (tab_bar->Flags & ImGuiTabBarFlags_SaveSettings)
|
||||
@ -7730,7 +7807,7 @@ bool ImGui::TabItemEx(ImGuiTabBar* tab_bar, const char* label, bool* p_open,
|
||||
const ImVec2 backup_main_cursor_pos = window->DC.CursorPos;
|
||||
|
||||
// Layout
|
||||
const bool is_central_section = (tab->Flags & (ImGuiTabItemFlags_Leading | ImGuiTabItemFlags_Trailing)) == 0;
|
||||
const bool is_central_section = (tab->Flags & ImGuiTabItemFlags_SectionMask_) == 0;
|
||||
size.x = tab->Width;
|
||||
if (is_central_section)
|
||||
window->DC.CursorPos = tab_bar->BarRect.Min + ImVec2(IM_FLOOR(tab->Offset - tab_bar->ScrollingAnim), 0.0f);
|
||||
@ -7778,13 +7855,11 @@ bool ImGui::TabItemEx(ImGuiTabBar* tab_bar, const char* label, bool* p_open,
|
||||
// While moving a tab it will jump on the other side of the mouse, so we also test for MouseDelta.x
|
||||
if (g.IO.MouseDelta.x < 0.0f && g.IO.MousePos.x < bb.Min.x)
|
||||
{
|
||||
if (tab_bar->Flags & ImGuiTabBarFlags_Reorderable)
|
||||
TabBarQueueReorder(tab_bar, tab, -1);
|
||||
TabBarQueueReorderFromMousePos(tab_bar, tab, g.IO.MousePos);
|
||||
}
|
||||
else if (g.IO.MouseDelta.x > 0.0f && g.IO.MousePos.x > bb.Max.x)
|
||||
{
|
||||
if (tab_bar->Flags & ImGuiTabBarFlags_Reorderable)
|
||||
TabBarQueueReorder(tab_bar, tab, +1);
|
||||
TabBarQueueReorderFromMousePos(tab_bar, tab, g.IO.MousePos);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -28,3 +28,10 @@ See https://gist.github.com/ocornut/b3a9ecf13502fd818799a452969649ad
|
||||
|
||||
Small, thin anti-aliased fonts are typically benefiting a lots from Freetype's hinting:
|
||||

|
||||
|
||||
### Colorful glyphs/emojis
|
||||
|
||||
You can use the `ImGuiFreeTypeBuilderFlags_LoadColor` flag to load certain colorful glyphs. See
|
||||
["Using Colorful Glyphs/Emojis"](https://github.com/ocornut/imgui/edit/master/docs/FONTS.md#using-colorful-glyphsemojis) section of FONTS.md.
|
||||
|
||||

|
||||
|
@ -1,7 +1,7 @@
|
||||
// dear imgui: FreeType font builder (used as a replacement for the stb_truetype builder)
|
||||
// (code)
|
||||
|
||||
// Get latest version at https://github.com/ocornut/imgui/tree/master/misc/freetype
|
||||
// Get the latest version at https://github.com/ocornut/imgui/tree/master/misc/freetype
|
||||
// Original code by @vuhdo (Aleksei Skriabin). Improvements by @mikesart. Maintained since 2019 by @ocornut.
|
||||
|
||||
// CHANGELOG
|
||||
|
Reference in New Issue
Block a user