mirror of
https://github.com/Drezil/imgui.git
synced 2025-07-15 09:13:13 +02:00
Compare commits
94 Commits
Author | SHA1 | Date | |
---|---|---|---|
512c54bbc0 | |||
612b787b0d | |||
4bad852a78 | |||
0636f9adac | |||
d9bc1e44af | |||
0cdc4a9565 | |||
4a43dcb940 | |||
1c4066cd9e | |||
389982eb5a | |||
48f263336b | |||
a528398c77 | |||
11638fdf7d | |||
0e8c199e87 | |||
d7350668d1 | |||
1b6b8602c1 | |||
f71ee5203e | |||
b720f1f03c | |||
8a9fe26866 | |||
c801799218 | |||
a8e1dde357 | |||
e03383d088 | |||
bdd2a94315 | |||
072caa4a90 | |||
270d4d0855 | |||
a19815dc6b | |||
c80e8b964c | |||
b38af0f522 | |||
657073a650 | |||
20e040c858 | |||
926addbfe2 | |||
027a7ba3eb | |||
a76bc52da5 | |||
6e141a9cae | |||
eea836135a | |||
aa41f16589 | |||
23ef6c149e | |||
da3a36eefd | |||
78c6435dbb | |||
5c388c39f4 | |||
5b1a70aa2d | |||
440824d431 | |||
f087a5b856 | |||
c5db276521 | |||
9d704d99d3 | |||
66f0fb986c | |||
5ccb66794b | |||
cb5c73f64a | |||
65f4be1a10 | |||
5ac25e7c7a | |||
4d9a3b19d5 | |||
764f9e606d | |||
a3667f462a | |||
3fde445b91 | |||
d80a9123b7 | |||
2c29e391dd | |||
f8a806ad9f | |||
7cd3cfa58a | |||
cad790d43b | |||
e790fc0e79 | |||
a9ea1ae854 | |||
eb02dcf87f | |||
8ce23b3ccd | |||
bce1ba400f | |||
ebac375791 | |||
1a7526dcd4 | |||
f01a6d3e8f | |||
32779c5b64 | |||
64daeddf6f | |||
6a7e2c74fb | |||
93cccd27f6 | |||
cd1b5f7883 | |||
b409df34db | |||
14466a6d19 | |||
978598b174 | |||
d1eb7b5757 | |||
eb654f1bad | |||
b1a68d899c | |||
a67f7dce31 | |||
8d361c47fb | |||
8361ed1f54 | |||
19c72cd52a | |||
c363b6df2b | |||
0f2898ea88 | |||
99552420a2 | |||
126a6f894f | |||
9c78fc928a | |||
2318c764cf | |||
39b99072fb | |||
ad3f54ff1a | |||
19c3773cc0 | |||
bbd5119a26 | |||
e3bd9434b1 | |||
13cdf2ff0e | |||
be03b8ff93 |
55
.github/workflows/build.yml
vendored
55
.github/workflows/build.yml
vendored
@ -37,20 +37,30 @@ jobs:
|
||||
- name: Fix Projects
|
||||
shell: powershell
|
||||
run: |
|
||||
# WARNING: This will need updating if toolset/sdk change in project files!
|
||||
# CI workers do not supporter older Visual Studio versions. Fix projects to target newer available version.
|
||||
gci -recurse -filter "*.vcxproj" | ForEach-Object {
|
||||
# Fix SDK and toolset for most samples.
|
||||
(Get-Content $_.FullName) -Replace "<PlatformToolset>v110</PlatformToolset>","<PlatformToolset>v142</PlatformToolset>" | Set-Content -Path $_.FullName
|
||||
(Get-Content $_.FullName) -Replace "<WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>","<WindowsTargetPlatformVersion>10.0.18362.0</WindowsTargetPlatformVersion>" | Set-Content -Path $_.FullName
|
||||
# Fix SDK and toolset for samples that require newer SDK/toolset. At the moment it is only dx12.
|
||||
(Get-Content $_.FullName) -Replace "<PlatformToolset>v140</PlatformToolset>","<PlatformToolset>v142</PlatformToolset>" | Set-Content -Path $_.FullName
|
||||
(Get-Content $_.FullName) -Replace "<WindowsTargetPlatformVersion>10.0.14393.0</WindowsTargetPlatformVersion>","<WindowsTargetPlatformVersion>10.0.18362.0</WindowsTargetPlatformVersion>" | Set-Content -Path $_.FullName
|
||||
(Get-Content $_.FullName) -Replace "<PlatformToolset>v\d{3}</PlatformToolset>","<PlatformToolset>v142</PlatformToolset>" | Set-Content -Path $_.FullName
|
||||
(Get-Content $_.FullName) -Replace "<WindowsTargetPlatformVersion>[\d\.]+</WindowsTargetPlatformVersion>","<WindowsTargetPlatformVersion>10.0.18362.0</WindowsTargetPlatformVersion>" | Set-Content -Path $_.FullName
|
||||
}
|
||||
|
||||
# Not using matrix here because it would inflate job count too much. Check out and setup is done for every job and that makes build times way too long.
|
||||
- name: Build example_null (extra warnings, mingw 64-bit)
|
||||
run: mingw32-make -C examples/example_null WITH_EXTRA_WARNINGS=1
|
||||
|
||||
- name: Build example_null (mingw 64-bit, as DLL)
|
||||
shell: bash
|
||||
run: |
|
||||
echo '#ifdef _EXPORT' > example_single_file.cpp
|
||||
echo '# define IMGUI_API __declspec(dllexport)' >> example_single_file.cpp
|
||||
echo '#else' >> example_single_file.cpp
|
||||
echo '# define IMGUI_API __declspec(dllimport)' >> example_single_file.cpp
|
||||
echo '#endif' >> example_single_file.cpp
|
||||
echo '#define IMGUI_IMPLEMENTATION' >> example_single_file.cpp
|
||||
echo '#include "misc/single_file/imgui_single_file.h"' >> example_single_file.cpp
|
||||
g++ -I. -Wall -Wformat -D_EXPORT -shared -o libimgui.dll -Wl,--out-implib,libimgui.a example_single_file.cpp -limm32
|
||||
g++ -I. -Wall -Wformat -o example_null.exe examples/example_null/main.cpp -L. -limgui
|
||||
rm -f example_null.exe libimgui.* example_single_file.*
|
||||
|
||||
- name: Build example_null (extra warnings, msvc 64-bit)
|
||||
shell: cmd
|
||||
run: |
|
||||
@ -483,34 +493,3 @@ jobs:
|
||||
run: |
|
||||
cd examples/example_android_opengl3/android
|
||||
gradle assembleDebug
|
||||
|
||||
Discord-CI:
|
||||
runs-on: ubuntu-18.04
|
||||
if: always()
|
||||
needs: [Windows, Linux, MacOS, iOS, Emscripten, Android]
|
||||
steps:
|
||||
- uses: dearimgui/github_discord_notifier@latest
|
||||
with:
|
||||
discord-webhook: ${{ secrets.DISCORD_CI_WEBHOOK }}
|
||||
github-token: ${{ github.token }}
|
||||
action-task: discord-jobs
|
||||
discord-filter: "'{{ github.branch }}'.match(/master|docking/g) != null && '{{ run.conclusion }}' != '{{ last_run.conclusion }}'"
|
||||
discord-username: GitHub Actions
|
||||
discord-job-new-failure-message: ''
|
||||
discord-job-fixed-failure-message: ''
|
||||
discord-job-new-failure-embed: |
|
||||
{
|
||||
"title": "`{{ job.name }}` job is failing on `{{ github.branch }}`!",
|
||||
"description": "Commit [{{ github.context.payload.head_commit.title }}]({{ github.context.payload.head_commit.url }}) pushed to [{{ github.branch }}]({{ github.branch_url }}) broke [{{ job.name }}]({{ job.url }}) build job.\nFailing steps: {{ failing_steps }}",
|
||||
"url": "{{ job.url }}",
|
||||
"color": "0xFF0000",
|
||||
"timestamp": "{{ run.updated_at }}"
|
||||
}
|
||||
discord-job-fixed-failure-embed: |
|
||||
{
|
||||
"title": "`{{ github.branch }}` branch is no longer failing!",
|
||||
"description": "Build failures were fixed on [{{ github.branch }}]({{ github.branch_url }}) branch.",
|
||||
"color": "0x00FF00",
|
||||
"url": "{{ github.context.payload.head_commit.url }}",
|
||||
"timestamp": "{{ run.completed_at }}"
|
||||
}
|
||||
|
@ -16,6 +16,7 @@
|
||||
|
||||
// CHANGELOG
|
||||
// (minor and older changes stripped away, please see git history for details)
|
||||
// 2021-12-08: Renderer: Fixed mishandling of the the ImDrawCmd::IdxOffset field! This is an old bug but it never had an effect until some internal rendering changes in 1.86.
|
||||
// 2021-08-17: Calling io.AddFocusEvent() on ALLEGRO_EVENT_DISPLAY_SWITCH_OUT/ALLEGRO_EVENT_DISPLAY_SWITCH_IN events.
|
||||
// 2021-06-29: Reorganized backend to pull data from a single structure to facilitate usage with multiple-contexts (all g_XXXX access changed to bd->XXXX).
|
||||
// 2021-05-19: Renderer: Replaced direct access to ImDrawCmd::TextureId with a call to ImDrawCmd::GetTexID(). (will become a requirement)
|
||||
@ -155,7 +156,6 @@ void ImGui_ImplAllegro5_RenderDrawData(ImDrawData* draw_data)
|
||||
}
|
||||
|
||||
// Render command lists
|
||||
int idx_offset = 0;
|
||||
ImVec2 clip_off = draw_data->DisplayPos;
|
||||
for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++)
|
||||
{
|
||||
@ -174,15 +174,14 @@ void ImGui_ImplAllegro5_RenderDrawData(ImDrawData* draw_data)
|
||||
// Project scissor/clipping rectangles into framebuffer space
|
||||
ImVec2 clip_min(pcmd->ClipRect.x - clip_off.x, pcmd->ClipRect.y - clip_off.y);
|
||||
ImVec2 clip_max(pcmd->ClipRect.z - clip_off.x, pcmd->ClipRect.w - clip_off.y);
|
||||
if (clip_max.x < clip_min.x || clip_max.y < clip_min.y)
|
||||
if (clip_max.x <= clip_min.x || clip_max.y <= clip_min.y)
|
||||
continue;
|
||||
|
||||
// Apply scissor/clipping rectangle, Draw
|
||||
ALLEGRO_BITMAP* texture = (ALLEGRO_BITMAP*)pcmd->GetTexID();
|
||||
al_set_clipping_rectangle(clip_min.x, clip_min.y, clip_max.x - clip_min.x, clip_max.y - clip_min.y);
|
||||
al_draw_prim(&vertices[0], bd->VertexDecl, texture, idx_offset, idx_offset + pcmd->ElemCount, ALLEGRO_PRIM_TRIANGLE_LIST);
|
||||
al_draw_prim(&vertices[0], bd->VertexDecl, texture, pcmd->IdxOffset, pcmd->IdxOffset + pcmd->ElemCount, ALLEGRO_PRIM_TRIANGLE_LIST);
|
||||
}
|
||||
idx_offset += pcmd->ElemCount;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -256,7 +256,7 @@ void ImGui_ImplDX10_RenderDrawData(ImDrawData* draw_data)
|
||||
// Project scissor/clipping rectangles into framebuffer space
|
||||
ImVec2 clip_min(pcmd->ClipRect.x - clip_off.x, pcmd->ClipRect.y - clip_off.y);
|
||||
ImVec2 clip_max(pcmd->ClipRect.z - clip_off.x, pcmd->ClipRect.w - clip_off.y);
|
||||
if (clip_max.x < clip_min.x || clip_max.y < clip_min.y)
|
||||
if (clip_max.x <= clip_min.x || clip_max.y <= clip_min.y)
|
||||
continue;
|
||||
|
||||
// Apply scissor/clipping rectangle
|
||||
|
@ -266,7 +266,7 @@ void ImGui_ImplDX11_RenderDrawData(ImDrawData* draw_data)
|
||||
// Project scissor/clipping rectangles into framebuffer space
|
||||
ImVec2 clip_min(pcmd->ClipRect.x - clip_off.x, pcmd->ClipRect.y - clip_off.y);
|
||||
ImVec2 clip_max(pcmd->ClipRect.z - clip_off.x, pcmd->ClipRect.w - clip_off.y);
|
||||
if (clip_max.x < clip_min.x || clip_max.y < clip_min.y)
|
||||
if (clip_max.x <= clip_min.x || clip_max.y <= clip_min.y)
|
||||
continue;
|
||||
|
||||
// Apply scissor/clipping rectangle
|
||||
|
@ -262,7 +262,7 @@ void ImGui_ImplDX12_RenderDrawData(ImDrawData* draw_data, ID3D12GraphicsCommandL
|
||||
// Project scissor/clipping rectangles into framebuffer space
|
||||
ImVec2 clip_min(pcmd->ClipRect.x - clip_off.x, pcmd->ClipRect.y - clip_off.y);
|
||||
ImVec2 clip_max(pcmd->ClipRect.z - clip_off.x, pcmd->ClipRect.w - clip_off.y);
|
||||
if (clip_max.x < clip_min.x || clip_max.y < clip_min.y)
|
||||
if (clip_max.x <= clip_min.x || clip_max.y <= clip_min.y)
|
||||
continue;
|
||||
|
||||
// Apply Scissor/clipping rectangle, Bind texture, Draw
|
||||
|
@ -251,7 +251,7 @@ void ImGui_ImplDX9_RenderDrawData(ImDrawData* draw_data)
|
||||
// Project scissor/clipping rectangles into framebuffer space
|
||||
ImVec2 clip_min(pcmd->ClipRect.x - clip_off.x, pcmd->ClipRect.y - clip_off.y);
|
||||
ImVec2 clip_max(pcmd->ClipRect.z - clip_off.x, pcmd->ClipRect.w - clip_off.y);
|
||||
if (clip_max.x < clip_min.x || clip_max.y < clip_min.y)
|
||||
if (clip_max.x <= clip_min.x || clip_max.y <= clip_min.y)
|
||||
continue;
|
||||
|
||||
// Apply Scissor/clipping rectangle, Bind texture, Draw
|
||||
|
@ -270,6 +270,7 @@ static bool ImGui_ImplGlfw_Init(GLFWwindow* window, bool install_callbacks, Glfw
|
||||
|
||||
// Chain GLFW callbacks: our callbacks will call the user's previously installed callbacks, if any.
|
||||
bd->PrevUserCallbackWindowFocus = NULL;
|
||||
bd->PrevUserCallbackCursorEnter = NULL;
|
||||
bd->PrevUserCallbackMousebutton = NULL;
|
||||
bd->PrevUserCallbackScroll = NULL;
|
||||
bd->PrevUserCallbackKey = NULL;
|
||||
|
@ -1,318 +0,0 @@
|
||||
// dear imgui: Renderer + Platform Backend for Marmalade + IwGx
|
||||
// Marmalade code: Copyright (C) 2015 by Giovanni Zito (this file is part of Dear ImGui)
|
||||
|
||||
// Implemented features:
|
||||
// [X] Renderer: User texture binding. Use 'CIwTexture*' as ImTextureID. Read the FAQ about ImTextureID!
|
||||
// Missing features:
|
||||
// [ ] Renderer: Clipping rectangles are not honored.
|
||||
|
||||
// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
|
||||
// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
|
||||
// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
|
||||
// Read online: https://github.com/ocornut/imgui/tree/master/docs
|
||||
|
||||
// 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.
|
||||
// 2018-02-16: Misc: Obsoleted the io.RenderDrawListsFn callback and exposed ImGui_Marmalade_RenderDrawData() in the .h file so you can call it yourself.
|
||||
// 2018-02-06: Misc: Removed call to ImGui::Shutdown() which is not available from 1.60 WIP, user needs to call CreateContext/DestroyContext themselves.
|
||||
// 2018-02-06: Inputs: Added mapping for ImGuiKey_Space.
|
||||
|
||||
#include "imgui.h"
|
||||
#include "imgui_impl_marmalade.h"
|
||||
|
||||
#include <s3eClipboard.h>
|
||||
#include <s3ePointer.h>
|
||||
#include <s3eKeyboard.h>
|
||||
#include <IwTexture.h>
|
||||
#include <IwGx.h>
|
||||
|
||||
// Data
|
||||
static double g_Time = 0.0f;
|
||||
static bool g_MousePressed[3] = { false, false, false };
|
||||
static CIwTexture* g_FontTexture = NULL;
|
||||
static char* g_ClipboardText = NULL;
|
||||
static bool g_osdKeyboardEnabled = false;
|
||||
|
||||
// use this setting to scale the interface - e.g. on device you could use 2 or 3 scale factor
|
||||
static ImVec2 g_RenderScale = ImVec2(1.0f, 1.0f);
|
||||
|
||||
// Render function.
|
||||
void ImGui_Marmalade_RenderDrawData(ImDrawData* draw_data)
|
||||
{
|
||||
// Avoid rendering when minimized
|
||||
if (draw_data->DisplaySize.x <= 0.0f || draw_data->DisplaySize.y <= 0.0f)
|
||||
return;
|
||||
|
||||
// Render command lists
|
||||
for (int n = 0; n < draw_data->CmdListsCount; n++)
|
||||
{
|
||||
const ImDrawList* cmd_list = draw_data->CmdLists[n];
|
||||
const ImDrawIdx* idx_buffer = cmd_list->IdxBuffer.Data;
|
||||
const int nVert = cmd_list->VtxBuffer.Size;
|
||||
CIwFVec2* pVertStream = IW_GX_ALLOC(CIwFVec2, nVert);
|
||||
CIwFVec2* pUVStream = IW_GX_ALLOC(CIwFVec2, nVert);
|
||||
CIwColour* pColStream = IW_GX_ALLOC(CIwColour, nVert);
|
||||
|
||||
for (int i = 0; i < nVert; i++)
|
||||
{
|
||||
// FIXME-OPT: optimize multiplication on GPU using vertex shader/projection matrix.
|
||||
pVertStream[i].x = cmd_list->VtxBuffer[i].pos.x * g_RenderScale.x;
|
||||
pVertStream[i].y = cmd_list->VtxBuffer[i].pos.y * g_RenderScale.y;
|
||||
pUVStream[i].x = cmd_list->VtxBuffer[i].uv.x;
|
||||
pUVStream[i].y = cmd_list->VtxBuffer[i].uv.y;
|
||||
pColStream[i] = cmd_list->VtxBuffer[i].col;
|
||||
}
|
||||
|
||||
IwGxSetVertStreamScreenSpace(pVertStream, nVert);
|
||||
IwGxSetUVStream(pUVStream);
|
||||
IwGxSetColStream(pColStream, nVert);
|
||||
IwGxSetNormStream(0);
|
||||
|
||||
for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++)
|
||||
{
|
||||
const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i];
|
||||
if (pcmd->UserCallback)
|
||||
{
|
||||
pcmd->UserCallback(cmd_list, pcmd);
|
||||
}
|
||||
else
|
||||
{
|
||||
// FIXME: Not honoring ClipRect fields.
|
||||
CIwMaterial* pCurrentMaterial = IW_GX_ALLOC_MATERIAL();
|
||||
pCurrentMaterial->SetShadeMode(CIwMaterial::SHADE_FLAT);
|
||||
pCurrentMaterial->SetCullMode(CIwMaterial::CULL_NONE);
|
||||
pCurrentMaterial->SetFiltering(false);
|
||||
pCurrentMaterial->SetAlphaMode(CIwMaterial::ALPHA_BLEND);
|
||||
pCurrentMaterial->SetDepthWriteMode(CIwMaterial::DEPTH_WRITE_NORMAL);
|
||||
pCurrentMaterial->SetAlphaTestMode(CIwMaterial::ALPHATEST_DISABLED);
|
||||
pCurrentMaterial->SetTexture((CIwTexture*)pcmd->GetTexID());
|
||||
IwGxSetMaterial(pCurrentMaterial);
|
||||
IwGxDrawPrims(IW_GX_TRI_LIST, (uint16*)idx_buffer, pcmd->ElemCount);
|
||||
}
|
||||
idx_buffer += pcmd->ElemCount;
|
||||
}
|
||||
IwGxFlush();
|
||||
}
|
||||
|
||||
// TODO: restore modified state (i.e. mvp matrix)
|
||||
}
|
||||
|
||||
static const char* ImGui_Marmalade_GetClipboardText(void* /*user_data*/)
|
||||
{
|
||||
if (!s3eClipboardAvailable())
|
||||
return NULL;
|
||||
|
||||
if (int size = s3eClipboardGetText(NULL, 0))
|
||||
{
|
||||
if (g_ClipboardText)
|
||||
delete[] g_ClipboardText;
|
||||
g_ClipboardText = new char[size];
|
||||
g_ClipboardText[0] = '\0';
|
||||
s3eClipboardGetText(g_ClipboardText, size);
|
||||
}
|
||||
|
||||
return g_ClipboardText;
|
||||
}
|
||||
|
||||
static void ImGui_Marmalade_SetClipboardText(void* /*user_data*/, const char* text)
|
||||
{
|
||||
if (s3eClipboardAvailable())
|
||||
s3eClipboardSetText(text);
|
||||
}
|
||||
|
||||
int32 ImGui_Marmalade_PointerButtonEventCallback(void* system_data, void* user_data)
|
||||
{
|
||||
// pEvent->m_Button is of type s3ePointerButton and indicates which mouse
|
||||
// button was pressed. For touchscreen this should always have the value
|
||||
// S3E_POINTER_BUTTON_SELECT
|
||||
s3ePointerEvent* pEvent = (s3ePointerEvent*)system_data;
|
||||
|
||||
if (pEvent->m_Pressed == 1)
|
||||
{
|
||||
if (pEvent->m_Button == S3E_POINTER_BUTTON_LEFTMOUSE)
|
||||
g_MousePressed[0] = true;
|
||||
if (pEvent->m_Button == S3E_POINTER_BUTTON_RIGHTMOUSE)
|
||||
g_MousePressed[1] = true;
|
||||
if (pEvent->m_Button == S3E_POINTER_BUTTON_MIDDLEMOUSE)
|
||||
g_MousePressed[2] = true;
|
||||
if (pEvent->m_Button == S3E_POINTER_BUTTON_MOUSEWHEELUP)
|
||||
io.MouseWheel += pEvent->m_y;
|
||||
if (pEvent->m_Button == S3E_POINTER_BUTTON_MOUSEWHEELDOWN)
|
||||
io.MouseWheel += pEvent->m_y;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32 ImGui_Marmalade_KeyCallback(void* system_data, void* user_data)
|
||||
{
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
s3eKeyboardEvent* e = (s3eKeyboardEvent*)system_data;
|
||||
if (e->m_Pressed == 1)
|
||||
io.KeysDown[e->m_Key] = true;
|
||||
if (e->m_Pressed == 0)
|
||||
io.KeysDown[e->m_Key] = false;
|
||||
|
||||
io.KeyCtrl = s3eKeyboardGetState(s3eKeyLeftControl) == S3E_KEY_STATE_DOWN || s3eKeyboardGetState(s3eKeyRightControl) == S3E_KEY_STATE_DOWN;
|
||||
io.KeyShift = s3eKeyboardGetState(s3eKeyLeftShift) == S3E_KEY_STATE_DOWN || s3eKeyboardGetState(s3eKeyRightShift) == S3E_KEY_STATE_DOWN;
|
||||
io.KeyAlt = s3eKeyboardGetState(s3eKeyLeftAlt) == S3E_KEY_STATE_DOWN || s3eKeyboardGetState(s3eKeyRightAlt) == S3E_KEY_STATE_DOWN;
|
||||
io.KeySuper = s3eKeyboardGetState(s3eKeyLeftWindows) == S3E_KEY_STATE_DOWN || s3eKeyboardGetState(s3eKeyRightWindows) == S3E_KEY_STATE_DOWN;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32 ImGui_Marmalade_CharCallback(void* system_data, void* user_data)
|
||||
{
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
s3eKeyboardCharEvent* e = (s3eKeyboardCharEvent*)system_data;
|
||||
io.AddInputCharacter((unsigned int)e->m_Char);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool ImGui_Marmalade_CreateDeviceObjects()
|
||||
{
|
||||
// Build texture atlas
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
unsigned char* pixels;
|
||||
int width, height;
|
||||
io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height);
|
||||
|
||||
// Upload texture to graphics system
|
||||
g_FontTexture = new CIwTexture();
|
||||
g_FontTexture->SetModifiable(true);
|
||||
CIwImage& image = g_FontTexture->GetImage();
|
||||
image.SetFormat(CIwImage::ARGB_8888);
|
||||
image.SetWidth(width);
|
||||
image.SetHeight(height);
|
||||
image.SetBuffers(); // allocates and own buffers
|
||||
image.ReadTexels(pixels);
|
||||
g_FontTexture->SetMipMapping(false);
|
||||
g_FontTexture->SetFiltering(false);
|
||||
g_FontTexture->Upload();
|
||||
|
||||
// Store our identifier
|
||||
io.Fonts->SetTexID((ImTextureID)g_FontTexture);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ImGui_Marmalade_InvalidateDeviceObjects()
|
||||
{
|
||||
if (g_ClipboardText)
|
||||
{
|
||||
delete[] g_ClipboardText;
|
||||
g_ClipboardText = NULL;
|
||||
}
|
||||
|
||||
if (g_FontTexture)
|
||||
{
|
||||
ImGui::GetIO().Fonts->SetTexID(0);
|
||||
delete g_FontTexture;
|
||||
g_FontTexture = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
bool ImGui_Marmalade_Init(bool install_callbacks)
|
||||
{
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
io.BackendPlatformName = io.BackendRendererName = "imgui_impl_marmalade";
|
||||
|
||||
// Keyboard mapping. Dear ImGui will use those indices to peek into the io.KeysDown[] array.
|
||||
io.KeyMap[ImGuiKey_Tab] = s3eKeyTab
|
||||
io.KeyMap[ImGuiKey_LeftArrow] = s3eKeyLeft;
|
||||
io.KeyMap[ImGuiKey_RightArrow] = s3eKeyRight;
|
||||
io.KeyMap[ImGuiKey_UpArrow] = s3eKeyUp;
|
||||
io.KeyMap[ImGuiKey_DownArrow] = s3eKeyDown;
|
||||
io.KeyMap[ImGuiKey_PageUp] = s3eKeyPageUp;
|
||||
io.KeyMap[ImGuiKey_PageDown] = s3eKeyPageDown;
|
||||
io.KeyMap[ImGuiKey_Home] = s3eKeyHome;
|
||||
io.KeyMap[ImGuiKey_End] = s3eKeyEnd;
|
||||
io.KeyMap[ImGuiKey_Insert] = s3eKeyInsert;
|
||||
io.KeyMap[ImGuiKey_Delete] = s3eKeyDelete;
|
||||
io.KeyMap[ImGuiKey_Backspace] = s3eKeyBackspace;
|
||||
io.KeyMap[ImGuiKey_Space] = s3eKeySpace;
|
||||
io.KeyMap[ImGuiKey_Enter] = s3eKeyEnter;
|
||||
io.KeyMap[ImGuiKey_Escape] = s3eKeyEsc;
|
||||
io.KeyMap[ImGuiKey_KeyPadEnter] = s3eKeyNumPadEnter;
|
||||
io.KeyMap[ImGuiKey_A] = s3eKeyA;
|
||||
io.KeyMap[ImGuiKey_C] = s3eKeyC;
|
||||
io.KeyMap[ImGuiKey_V] = s3eKeyV;
|
||||
io.KeyMap[ImGuiKey_X] = s3eKeyX;
|
||||
io.KeyMap[ImGuiKey_Y] = s3eKeyY;
|
||||
io.KeyMap[ImGuiKey_Z] = s3eKeyZ;
|
||||
|
||||
io.SetClipboardTextFn = ImGui_Marmalade_SetClipboardText;
|
||||
io.GetClipboardTextFn = ImGui_Marmalade_GetClipboardText;
|
||||
|
||||
if (install_callbacks)
|
||||
{
|
||||
s3ePointerRegister(S3E_POINTER_BUTTON_EVENT, ImGui_Marmalade_PointerButtonEventCallback, 0);
|
||||
s3eKeyboardRegister(S3E_KEYBOARD_KEY_EVENT, ImGui_Marmalade_KeyCallback, 0);
|
||||
s3eKeyboardRegister(S3E_KEYBOARD_CHAR_EVENT, ImGui_Marmalade_CharCallback, 0);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ImGui_Marmalade_Shutdown()
|
||||
{
|
||||
ImGui_Marmalade_InvalidateDeviceObjects();
|
||||
}
|
||||
|
||||
void ImGui_Marmalade_NewFrame()
|
||||
{
|
||||
if (!g_FontTexture)
|
||||
ImGui_Marmalade_CreateDeviceObjects();
|
||||
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
|
||||
// Setup display size (every frame to accommodate for window resizing)
|
||||
int w = IwGxGetScreenWidth(), h = IwGxGetScreenHeight();
|
||||
io.DisplaySize = ImVec2((float)w, (float)h);
|
||||
// For retina display or other situations where window coordinates are different from framebuffer coordinates. User storage only, presently not used by ImGui.
|
||||
io.DisplayFramebufferScale = g_scale;
|
||||
|
||||
// Setup time step
|
||||
double current_time = s3eTimerGetUST() / 1000.0f;
|
||||
io.DeltaTime = g_Time > 0.0 ? (float)(current_time - g_Time) : (float)(1.0f / 60.0f);
|
||||
g_Time = current_time;
|
||||
|
||||
double mouse_x, mouse_y;
|
||||
mouse_x = s3ePointerGetX();
|
||||
mouse_y = s3ePointerGetY();
|
||||
io.MousePos = ImVec2((float)mouse_x / g_scale.x, (float)mouse_y / g_scale.y); // Mouse position (set to -FLT_MAX,-FLT_MAX if no mouse / on another screen, etc.)
|
||||
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
io.MouseDown[i] = g_MousePressed[i] || s3ePointerGetState((s3ePointerButton)i) != S3E_POINTER_STATE_UP; // If a mouse press event came, always pass it as "mouse held this frame", so we don't miss click-release events that are shorter than 1 frame.
|
||||
g_MousePressed[i] = false;
|
||||
}
|
||||
|
||||
// TODO: Hide OS mouse cursor if ImGui is drawing it
|
||||
// s3ePointerSetInt(S3E_POINTER_HIDE_CURSOR,(io.MouseDrawCursor ? 0 : 1));
|
||||
|
||||
// Show/hide OSD keyboard
|
||||
if (io.WantTextInput)
|
||||
{
|
||||
// Some text input widget is active?
|
||||
if (!g_osdKeyboardEnabled)
|
||||
{
|
||||
g_osdKeyboardEnabled = true;
|
||||
s3eKeyboardSetInt(S3E_KEYBOARD_GET_CHAR, 1); // show OSD keyboard
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// No text input widget is active
|
||||
if (g_osdKeyboardEnabled)
|
||||
{
|
||||
g_osdKeyboardEnabled = false;
|
||||
s3eKeyboardSetInt(S3E_KEYBOARD_GET_CHAR, 0); // hide OSD keyboard
|
||||
}
|
||||
}
|
||||
}
|
@ -1,28 +0,0 @@
|
||||
// dear imgui: Renderer + Platform Backend for Marmalade + IwGx
|
||||
// Marmalade code: Copyright (C) 2015 by Giovanni Zito (this file is part of Dear ImGui)
|
||||
|
||||
// Implemented features:
|
||||
// [X] Renderer: User texture binding. Use 'CIwTexture*' as ImTextureID. Read the FAQ about ImTextureID!
|
||||
|
||||
// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
|
||||
// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
|
||||
// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
|
||||
// Read online: https://github.com/ocornut/imgui/tree/master/docs
|
||||
|
||||
#pragma once
|
||||
#include "imgui.h" // IMGUI_IMPL_API
|
||||
|
||||
IMGUI_IMPL_API bool ImGui_Marmalade_Init(bool install_callbacks);
|
||||
IMGUI_IMPL_API void ImGui_Marmalade_Shutdown();
|
||||
IMGUI_IMPL_API void ImGui_Marmalade_NewFrame();
|
||||
IMGUI_IMPL_API void ImGui_Marmalade_RenderDrawData(ImDrawData* draw_data);
|
||||
|
||||
// Use if you want to reset your rendering device without losing Dear ImGui state.
|
||||
IMGUI_IMPL_API void ImGui_Marmalade_InvalidateDeviceObjects();
|
||||
IMGUI_IMPL_API bool ImGui_Marmalade_CreateDeviceObjects();
|
||||
|
||||
// Callbacks (installed by default if you enable 'install_callbacks' during initialization)
|
||||
// You can also handle inputs yourself and use those as a reference.
|
||||
IMGUI_IMPL_API int32 ImGui_Marmalade_PointerButtonEventCallback(void* system_data, void* user_data);
|
||||
IMGUI_IMPL_API int32 ImGui_Marmalade_KeyCallback(void* system_data, void* user_data);
|
||||
IMGUI_IMPL_API int32 ImGui_Marmalade_CharCallback(void* system_data, void* user_data);
|
@ -513,7 +513,7 @@ void ImGui_ImplMetal_DestroyDeviceObjects()
|
||||
if (clip_min.y < 0.0f) { clip_min.y = 0.0f; }
|
||||
if (clip_max.x > fb_width) { clip_max.x = (float)fb_width; }
|
||||
if (clip_max.y > fb_height) { clip_max.y = (float)fb_height; }
|
||||
if (clip_max.x < clip_min.x || clip_max.y < clip_min.y)
|
||||
if (clip_max.x <= clip_min.x || clip_max.y <= clip_min.y)
|
||||
continue;
|
||||
|
||||
// Apply scissor/clipping rectangle
|
||||
|
@ -19,6 +19,7 @@
|
||||
|
||||
// CHANGELOG
|
||||
// (minor and older changes stripped away, please see git history for details)
|
||||
// 2021-12-08: OpenGL: Fixed mishandling of the the ImDrawCmd::IdxOffset field! This is an old bug but it never had an effect until some internal rendering changes in 1.86.
|
||||
// 2021-06-29: Reorganized backend to pull data from a single structure to facilitate usage with multiple-contexts (all g_XXXX access changed to bd->XXXX).
|
||||
// 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.
|
||||
@ -203,7 +204,7 @@ void ImGui_ImplOpenGL2_RenderDrawData(ImDrawData* draw_data)
|
||||
// Project scissor/clipping rectangles into framebuffer space
|
||||
ImVec2 clip_min((pcmd->ClipRect.x - clip_off.x) * clip_scale.x, (pcmd->ClipRect.y - clip_off.y) * clip_scale.y);
|
||||
ImVec2 clip_max((pcmd->ClipRect.z - clip_off.x) * clip_scale.x, (pcmd->ClipRect.w - clip_off.y) * clip_scale.y);
|
||||
if (clip_max.x < clip_min.x || clip_max.y < clip_min.y)
|
||||
if (clip_max.x <= clip_min.x || clip_max.y <= clip_min.y)
|
||||
continue;
|
||||
|
||||
// Apply scissor/clipping rectangle (Y is inverted in OpenGL)
|
||||
@ -211,9 +212,8 @@ void ImGui_ImplOpenGL2_RenderDrawData(ImDrawData* draw_data)
|
||||
|
||||
// Bind texture, Draw
|
||||
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);
|
||||
glDrawElements(GL_TRIANGLES, (GLsizei)pcmd->ElemCount, sizeof(ImDrawIdx) == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, idx_buffer + pcmd->IdxOffset);
|
||||
}
|
||||
idx_buffer += pcmd->ElemCount;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -14,6 +14,7 @@
|
||||
|
||||
// CHANGELOG
|
||||
// (minor and older changes stripped away, please see git history for details)
|
||||
// 2021-12-15: OpenGL: Using buffer orphaning + glBufferSubData(), seems to fix leaks with multi-viewports with some Intel HD drivers.
|
||||
// 2021-08-23: OpenGL: Fixed ES 3.0 shader ("#version 300 es") use normal precision floats to avoid wobbly rendering at HD resolutions.
|
||||
// 2021-08-19: OpenGL: Embed and use our own minimal GL loader (imgui_impl_opengl3_loader.h), removing requirement and support for third-party loader.
|
||||
// 2021-06-29: Reorganized backend to pull data from a single structure to facilitate usage with multiple-contexts (all g_XXXX access changed to bd->XXXX).
|
||||
@ -174,6 +175,8 @@ struct ImGui_ImplOpenGL3_Data
|
||||
GLuint AttribLocationVtxUV;
|
||||
GLuint AttribLocationVtxColor;
|
||||
unsigned int VboHandle, ElementsHandle;
|
||||
GLsizeiptr VertexBufferSize;
|
||||
GLsizeiptr IndexBufferSize;
|
||||
bool HasClipOrigin;
|
||||
|
||||
ImGui_ImplOpenGL3_Data() { memset(this, 0, sizeof(*this)); }
|
||||
@ -425,8 +428,20 @@ void ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data)
|
||||
const ImDrawList* cmd_list = draw_data->CmdLists[n];
|
||||
|
||||
// Upload vertex/index buffers
|
||||
glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)cmd_list->VtxBuffer.Size * (int)sizeof(ImDrawVert), (const GLvoid*)cmd_list->VtxBuffer.Data, GL_STREAM_DRAW);
|
||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, (GLsizeiptr)cmd_list->IdxBuffer.Size * (int)sizeof(ImDrawIdx), (const GLvoid*)cmd_list->IdxBuffer.Data, GL_STREAM_DRAW);
|
||||
GLsizeiptr vtx_buffer_size = (GLsizeiptr)cmd_list->VtxBuffer.Size * (int)sizeof(ImDrawVert);
|
||||
GLsizeiptr idx_buffer_size = (GLsizeiptr)cmd_list->IdxBuffer.Size * (int)sizeof(ImDrawIdx);
|
||||
if (bd->VertexBufferSize < vtx_buffer_size)
|
||||
{
|
||||
bd->VertexBufferSize = vtx_buffer_size;
|
||||
glBufferData(GL_ARRAY_BUFFER, bd->VertexBufferSize, NULL, GL_STREAM_DRAW);
|
||||
}
|
||||
if (bd->IndexBufferSize < idx_buffer_size)
|
||||
{
|
||||
bd->IndexBufferSize = idx_buffer_size;
|
||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, bd->IndexBufferSize, NULL, GL_STREAM_DRAW);
|
||||
}
|
||||
glBufferSubData(GL_ARRAY_BUFFER, 0, vtx_buffer_size, (const GLvoid*)cmd_list->VtxBuffer.Data);
|
||||
glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, idx_buffer_size, (const GLvoid*)cmd_list->IdxBuffer.Data);
|
||||
|
||||
for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++)
|
||||
{
|
||||
@ -445,7 +460,7 @@ void ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data)
|
||||
// Project scissor/clipping rectangles into framebuffer space
|
||||
ImVec2 clip_min((pcmd->ClipRect.x - clip_off.x) * clip_scale.x, (pcmd->ClipRect.y - clip_off.y) * clip_scale.y);
|
||||
ImVec2 clip_max((pcmd->ClipRect.z - clip_off.x) * clip_scale.x, (pcmd->ClipRect.w - clip_off.y) * clip_scale.y);
|
||||
if (clip_max.x < clip_min.x || clip_max.y < clip_min.y)
|
||||
if (clip_max.x <= clip_min.x || clip_max.y <= clip_min.y)
|
||||
continue;
|
||||
|
||||
// Apply scissor/clipping rectangle (Y is inverted in OpenGL)
|
||||
|
@ -249,11 +249,13 @@ typedef void (APIENTRYP PFNGLBINDBUFFERPROC) (GLenum target, GLuint buffer);
|
||||
typedef void (APIENTRYP PFNGLDELETEBUFFERSPROC) (GLsizei n, const GLuint *buffers);
|
||||
typedef void (APIENTRYP PFNGLGENBUFFERSPROC) (GLsizei n, GLuint *buffers);
|
||||
typedef void (APIENTRYP PFNGLBUFFERDATAPROC) (GLenum target, GLsizeiptr size, const void *data, GLenum usage);
|
||||
typedef void (APIENTRYP PFNGLBUFFERSUBDATAPROC) (GLenum target, GLintptr offset, GLsizeiptr size, const void *data);
|
||||
#ifdef GL_GLEXT_PROTOTYPES
|
||||
GLAPI void APIENTRY glBindBuffer (GLenum target, GLuint buffer);
|
||||
GLAPI void APIENTRY glDeleteBuffers (GLsizei n, const GLuint *buffers);
|
||||
GLAPI void APIENTRY glGenBuffers (GLsizei n, GLuint *buffers);
|
||||
GLAPI void APIENTRY glBufferData (GLenum target, GLsizeiptr size, const void *data, GLenum usage);
|
||||
GLAPI void APIENTRY glBufferSubData (GLenum target, GLintptr offset, GLsizeiptr size, const void *data);
|
||||
#endif
|
||||
#endif /* GL_VERSION_1_5 */
|
||||
#ifndef GL_VERSION_2_0
|
||||
@ -447,6 +449,7 @@ union GL3WProcs {
|
||||
PFNGLBLENDEQUATIONSEPARATEPROC BlendEquationSeparate;
|
||||
PFNGLBLENDFUNCSEPARATEPROC BlendFuncSeparate;
|
||||
PFNGLBUFFERDATAPROC BufferData;
|
||||
PFNGLBUFFERSUBDATAPROC BufferSubData;
|
||||
PFNGLCLEARPROC Clear;
|
||||
PFNGLCLEARCOLORPROC ClearColor;
|
||||
PFNGLCOMPILESHADERPROC CompileShader;
|
||||
@ -506,6 +509,7 @@ GL3W_API extern union GL3WProcs imgl3wProcs;
|
||||
#define glBlendEquationSeparate imgl3wProcs.gl.BlendEquationSeparate
|
||||
#define glBlendFuncSeparate imgl3wProcs.gl.BlendFuncSeparate
|
||||
#define glBufferData imgl3wProcs.gl.BufferData
|
||||
#define glBufferSubData imgl3wProcs.gl.BufferSubData
|
||||
#define glClear imgl3wProcs.gl.Clear
|
||||
#define glClearColor imgl3wProcs.gl.ClearColor
|
||||
#define glCompileShader imgl3wProcs.gl.CompileShader
|
||||
@ -692,6 +696,7 @@ static const char *proc_names[] = {
|
||||
"glBlendEquationSeparate",
|
||||
"glBlendFuncSeparate",
|
||||
"glBufferData",
|
||||
"glBufferSubData",
|
||||
"glClear",
|
||||
"glClearColor",
|
||||
"glCompileShader",
|
||||
|
@ -5,10 +5,10 @@
|
||||
// Implemented features:
|
||||
// [X] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'.
|
||||
// [X] Platform: OSX clipboard is supported within core Dear ImGui (no specific code in this backend).
|
||||
// Issues:
|
||||
// [ ] Platform: Keys are all generally very broken. Best using [event keycode] and not [event characters]..
|
||||
// [X] Platform: Gamepad support. Enabled with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'.
|
||||
// [X] Platform: Keyboard arrays indexed using kVK_* codes, e.g. ImGui::IsKeyPressed(kVK_Space).
|
||||
|
||||
// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
|
||||
// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
|
||||
// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
|
||||
// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
|
||||
// Read online: https://github.com/ocornut/imgui/tree/master/docs
|
||||
@ -18,7 +18,7 @@
|
||||
@class NSEvent;
|
||||
@class NSView;
|
||||
|
||||
IMGUI_IMPL_API bool ImGui_ImplOSX_Init();
|
||||
IMGUI_IMPL_API bool ImGui_ImplOSX_Init(NSView* _Nonnull view);
|
||||
IMGUI_IMPL_API void ImGui_ImplOSX_Shutdown();
|
||||
IMGUI_IMPL_API void ImGui_ImplOSX_NewFrame(NSView* _Nullable view);
|
||||
IMGUI_IMPL_API bool ImGui_ImplOSX_HandleEvent(NSEvent* _Nonnull event, NSView* _Nullable view);
|
||||
|
@ -5,21 +5,25 @@
|
||||
// Implemented features:
|
||||
// [X] Platform: Mouse cursor shape and visibility. Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'.
|
||||
// [X] Platform: OSX clipboard is supported within core Dear ImGui (no specific code in this backend).
|
||||
// Issues:
|
||||
// [ ] Platform: Keys are all generally very broken. Best using [event keycode] and not [event characters]..
|
||||
// [X] Platform: Gamepad support. Enabled with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'.
|
||||
// [X] Platform: Keyboard arrays indexed using kVK_* codes, e.g. ImGui::IsKeyPressed(kVK_Space).
|
||||
|
||||
// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
|
||||
// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
|
||||
// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
|
||||
// Read online: https://github.com/ocornut/imgui/tree/master/docs
|
||||
|
||||
#include "imgui.h"
|
||||
#include "imgui_impl_osx.h"
|
||||
#import "imgui.h"
|
||||
#import "imgui_impl_osx.h"
|
||||
#import <Cocoa/Cocoa.h>
|
||||
#include <mach/mach_time.h>
|
||||
#import <mach/mach_time.h>
|
||||
#import <Carbon/Carbon.h>
|
||||
#import <GameController/GameController.h>
|
||||
|
||||
// CHANGELOG
|
||||
// (minor and older changes stripped away, please see git history for details)
|
||||
// 2021-12-13: *BREAKING CHANGE* Add NSView parameter to ImGui_ImplOSX_Init(). Generally fix keyboard support. Using kVK_* codes for keyboard keys.
|
||||
// 2021-12-13: Add game controller support.
|
||||
// 2021-09-21: Use mach_absolute_time as CFAbsoluteTimeGetCurrent can jump backwards.
|
||||
// 2021-08-17: Calling io.AddFocusEvent() on NSApplicationDidBecomeActiveNotification/NSApplicationDidResignActiveNotification events.
|
||||
// 2021-06-23: Inputs: Added a fix for shortcuts using CTRL key instead of CMD key.
|
||||
@ -37,15 +41,17 @@
|
||||
// 2018-07-07: Initial version.
|
||||
|
||||
@class ImFocusObserver;
|
||||
@class KeyEventResponder;
|
||||
|
||||
// Data
|
||||
static double g_HostClockPeriod = 0.0;
|
||||
static double 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;
|
||||
static double g_HostClockPeriod = 0.0;
|
||||
static double 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 = nil;
|
||||
static KeyEventResponder* g_KeyEventResponder = nil;
|
||||
|
||||
// Undocumented methods for creating cursors.
|
||||
@interface NSCursor()
|
||||
@ -74,6 +80,102 @@ static void resetKeys()
|
||||
io.KeyCtrl = io.KeyShift = io.KeyAlt = io.KeySuper = false;
|
||||
}
|
||||
|
||||
/**
|
||||
KeyEventResponder implements the NSTextInputClient protocol as is required by the macOS text input manager.
|
||||
|
||||
The macOS text input manager is invoked by calling the interpretKeyEvents method from the keyDown method.
|
||||
Keyboard events are then evaluated by the macOS input manager and valid text input is passed back via the
|
||||
insertText:replacementRange method.
|
||||
|
||||
This is the same approach employed by other cross-platform libraries such as SDL2:
|
||||
https://github.com/spurious/SDL-mirror/blob/e17aacbd09e65a4fd1e166621e011e581fb017a8/src/video/cocoa/SDL_cocoakeyboard.m#L53
|
||||
and GLFW:
|
||||
https://github.com/glfw/glfw/blob/b55a517ae0c7b5127dffa79a64f5406021bf9076/src/cocoa_window.m#L722-L723
|
||||
*/
|
||||
@interface KeyEventResponder: NSView<NSTextInputClient>
|
||||
@end
|
||||
|
||||
@implementation KeyEventResponder
|
||||
|
||||
- (void)viewDidMoveToWindow
|
||||
{
|
||||
// Ensure self is a first responder to receive the input events.
|
||||
[self.window makeFirstResponder:self];
|
||||
}
|
||||
|
||||
- (void)keyDown:(NSEvent*)event
|
||||
{
|
||||
// Call to the macOS input manager system.
|
||||
[self interpretKeyEvents:@[event]];
|
||||
}
|
||||
|
||||
- (void)insertText:(id)aString replacementRange:(NSRange)replacementRange
|
||||
{
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
|
||||
NSString* characters;
|
||||
if ([aString isKindOfClass:[NSAttributedString class]])
|
||||
characters = [aString string];
|
||||
else
|
||||
characters = (NSString*)aString;
|
||||
|
||||
io.AddInputCharactersUTF8(characters.UTF8String);
|
||||
}
|
||||
|
||||
- (BOOL)acceptsFirstResponder
|
||||
{
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (void)doCommandBySelector:(SEL)myselector
|
||||
{
|
||||
}
|
||||
|
||||
- (nullable NSAttributedString*)attributedSubstringForProposedRange:(NSRange)range actualRange:(nullable NSRangePointer)actualRange
|
||||
{
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (NSUInteger)characterIndexForPoint:(NSPoint)point
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
- (NSRect)firstRectForCharacterRange:(NSRange)range actualRange:(nullable NSRangePointer)actualRange
|
||||
{
|
||||
return NSZeroRect;
|
||||
}
|
||||
|
||||
- (BOOL)hasMarkedText
|
||||
{
|
||||
return NO;
|
||||
}
|
||||
|
||||
- (NSRange)markedRange
|
||||
{
|
||||
return NSMakeRange(NSNotFound, 0);
|
||||
}
|
||||
|
||||
- (NSRange)selectedRange
|
||||
{
|
||||
return NSMakeRange(NSNotFound, 0);
|
||||
}
|
||||
|
||||
- (void)setMarkedText:(nonnull id)string selectedRange:(NSRange)selectedRange replacementRange:(NSRange)replacementRange
|
||||
{
|
||||
}
|
||||
|
||||
- (void)unmarkText
|
||||
{
|
||||
}
|
||||
|
||||
- (nonnull NSArray<NSAttributedStringKey>*)validAttributesForMarkedText
|
||||
{
|
||||
return @[];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@interface ImFocusObserver : NSObject
|
||||
|
||||
- (void)onApplicationBecomeActive:(NSNotification*)aNotification;
|
||||
@ -103,7 +205,7 @@ static void resetKeys()
|
||||
@end
|
||||
|
||||
// Functions
|
||||
bool ImGui_ImplOSX_Init()
|
||||
bool ImGui_ImplOSX_Init(NSView* view)
|
||||
{
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
|
||||
@ -115,29 +217,28 @@ bool ImGui_ImplOSX_Init()
|
||||
io.BackendPlatformName = "imgui_impl_osx";
|
||||
|
||||
// Keyboard mapping. Dear ImGui will use those indices to peek into the io.KeyDown[] array.
|
||||
const int offset_for_function_keys = 256 - 0xF700;
|
||||
io.KeyMap[ImGuiKey_Tab] = '\t';
|
||||
io.KeyMap[ImGuiKey_LeftArrow] = NSLeftArrowFunctionKey + offset_for_function_keys;
|
||||
io.KeyMap[ImGuiKey_RightArrow] = NSRightArrowFunctionKey + offset_for_function_keys;
|
||||
io.KeyMap[ImGuiKey_UpArrow] = NSUpArrowFunctionKey + offset_for_function_keys;
|
||||
io.KeyMap[ImGuiKey_DownArrow] = NSDownArrowFunctionKey + offset_for_function_keys;
|
||||
io.KeyMap[ImGuiKey_PageUp] = NSPageUpFunctionKey + offset_for_function_keys;
|
||||
io.KeyMap[ImGuiKey_PageDown] = NSPageDownFunctionKey + offset_for_function_keys;
|
||||
io.KeyMap[ImGuiKey_Home] = NSHomeFunctionKey + offset_for_function_keys;
|
||||
io.KeyMap[ImGuiKey_End] = NSEndFunctionKey + offset_for_function_keys;
|
||||
io.KeyMap[ImGuiKey_Insert] = NSInsertFunctionKey + offset_for_function_keys;
|
||||
io.KeyMap[ImGuiKey_Delete] = NSDeleteFunctionKey + offset_for_function_keys;
|
||||
io.KeyMap[ImGuiKey_Backspace] = 127;
|
||||
io.KeyMap[ImGuiKey_Space] = 32;
|
||||
io.KeyMap[ImGuiKey_Enter] = 13;
|
||||
io.KeyMap[ImGuiKey_Escape] = 27;
|
||||
io.KeyMap[ImGuiKey_KeyPadEnter] = 3;
|
||||
io.KeyMap[ImGuiKey_A] = 'A';
|
||||
io.KeyMap[ImGuiKey_C] = 'C';
|
||||
io.KeyMap[ImGuiKey_V] = 'V';
|
||||
io.KeyMap[ImGuiKey_X] = 'X';
|
||||
io.KeyMap[ImGuiKey_Y] = 'Y';
|
||||
io.KeyMap[ImGuiKey_Z] = 'Z';
|
||||
io.KeyMap[ImGuiKey_Tab] = kVK_Tab;
|
||||
io.KeyMap[ImGuiKey_LeftArrow] = kVK_LeftArrow;
|
||||
io.KeyMap[ImGuiKey_RightArrow] = kVK_RightArrow;
|
||||
io.KeyMap[ImGuiKey_UpArrow] = kVK_UpArrow;
|
||||
io.KeyMap[ImGuiKey_DownArrow] = kVK_DownArrow;
|
||||
io.KeyMap[ImGuiKey_PageUp] = kVK_PageUp;
|
||||
io.KeyMap[ImGuiKey_PageDown] = kVK_PageDown;
|
||||
io.KeyMap[ImGuiKey_Home] = kVK_Home;
|
||||
io.KeyMap[ImGuiKey_End] = kVK_End;
|
||||
io.KeyMap[ImGuiKey_Insert] = kVK_F13;
|
||||
io.KeyMap[ImGuiKey_Delete] = kVK_ForwardDelete;
|
||||
io.KeyMap[ImGuiKey_Backspace] = kVK_Delete;
|
||||
io.KeyMap[ImGuiKey_Space] = kVK_Space;
|
||||
io.KeyMap[ImGuiKey_Enter] = kVK_Return;
|
||||
io.KeyMap[ImGuiKey_Escape] = kVK_Escape;
|
||||
io.KeyMap[ImGuiKey_KeyPadEnter] = kVK_ANSI_KeypadEnter;
|
||||
io.KeyMap[ImGuiKey_A] = kVK_ANSI_A;
|
||||
io.KeyMap[ImGuiKey_C] = kVK_ANSI_C;
|
||||
io.KeyMap[ImGuiKey_V] = kVK_ANSI_V;
|
||||
io.KeyMap[ImGuiKey_X] = kVK_ANSI_X;
|
||||
io.KeyMap[ImGuiKey_Y] = kVK_ANSI_Y;
|
||||
io.KeyMap[ImGuiKey_Z] = kVK_ANSI_Z;
|
||||
|
||||
// Load cursors. Some of them are undocumented.
|
||||
g_MouseCursorHidden = false;
|
||||
@ -190,6 +291,11 @@ bool ImGui_ImplOSX_Init()
|
||||
name:NSApplicationDidResignActiveNotification
|
||||
object:nil];
|
||||
|
||||
// Add the NSTextInputClient to the view hierarchy,
|
||||
// to receive keyboard events and translate them to input text.
|
||||
g_KeyEventResponder = [[KeyEventResponder alloc] initWithFrame:NSZeroRect];
|
||||
[view addSubview:g_KeyEventResponder];
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -224,8 +330,12 @@ static void ImGui_ImplOSX_UpdateMouseCursorAndButtons()
|
||||
}
|
||||
else
|
||||
{
|
||||
// Show OS mouse cursor
|
||||
[g_MouseCursors[g_MouseCursors[imgui_cursor] ? imgui_cursor : ImGuiMouseCursor_Arrow] set];
|
||||
NSCursor* desired = g_MouseCursors[imgui_cursor] ?: g_MouseCursors[ImGuiMouseCursor_Arrow];
|
||||
// -[NSCursor set] generates measureable overhead if called unconditionally.
|
||||
if (desired != NSCursor.currentCursor)
|
||||
{
|
||||
[desired set];
|
||||
}
|
||||
if (g_MouseCursorHidden)
|
||||
{
|
||||
g_MouseCursorHidden = false;
|
||||
@ -234,6 +344,50 @@ static void ImGui_ImplOSX_UpdateMouseCursorAndButtons()
|
||||
}
|
||||
}
|
||||
|
||||
void ImGui_ImplOSX_UpdateGamepads()
|
||||
{
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
memset(io.NavInputs, 0, sizeof(io.NavInputs));
|
||||
if ((io.ConfigFlags & ImGuiConfigFlags_NavEnableGamepad) == 0)
|
||||
return;
|
||||
|
||||
GCController* controller;
|
||||
if (@available(macOS 11.0, *))
|
||||
controller = GCController.current;
|
||||
else
|
||||
controller = GCController.controllers.firstObject;
|
||||
|
||||
if (controller == nil || controller.extendedGamepad == nil)
|
||||
{
|
||||
io.BackendFlags &= ~ImGuiBackendFlags_HasGamepad;
|
||||
return;
|
||||
}
|
||||
|
||||
GCExtendedGamepad* gp = controller.extendedGamepad;
|
||||
|
||||
#define MAP_BUTTON(NAV_NO, NAME) { io.NavInputs[NAV_NO] = gp.NAME.isPressed ? 1.0 : 0.0; }
|
||||
MAP_BUTTON(ImGuiNavInput_Activate, buttonA);
|
||||
MAP_BUTTON(ImGuiNavInput_Cancel, buttonB);
|
||||
MAP_BUTTON(ImGuiNavInput_Menu, buttonX);
|
||||
MAP_BUTTON(ImGuiNavInput_Input, buttonY);
|
||||
MAP_BUTTON(ImGuiNavInput_DpadLeft, dpad.left);
|
||||
MAP_BUTTON(ImGuiNavInput_DpadRight, dpad.right);
|
||||
MAP_BUTTON(ImGuiNavInput_DpadUp, dpad.up);
|
||||
MAP_BUTTON(ImGuiNavInput_DpadDown, dpad.down);
|
||||
MAP_BUTTON(ImGuiNavInput_FocusPrev, leftShoulder);
|
||||
MAP_BUTTON(ImGuiNavInput_FocusNext, rightShoulder);
|
||||
MAP_BUTTON(ImGuiNavInput_TweakSlow, leftTrigger);
|
||||
MAP_BUTTON(ImGuiNavInput_TweakFast, rightTrigger);
|
||||
#undef MAP_BUTTON
|
||||
|
||||
io.NavInputs[ImGuiNavInput_LStickLeft] = gp.leftThumbstick.left.value;
|
||||
io.NavInputs[ImGuiNavInput_LStickRight] = gp.leftThumbstick.right.value;
|
||||
io.NavInputs[ImGuiNavInput_LStickUp] = gp.leftThumbstick.up.value;
|
||||
io.NavInputs[ImGuiNavInput_LStickDown] = gp.leftThumbstick.down.value;
|
||||
|
||||
io.BackendFlags |= ImGuiBackendFlags_HasGamepad;
|
||||
}
|
||||
|
||||
void ImGui_ImplOSX_NewFrame(NSView* view)
|
||||
{
|
||||
// Setup display size
|
||||
@ -256,19 +410,25 @@ void ImGui_ImplOSX_NewFrame(NSView* view)
|
||||
g_Time = current_time;
|
||||
|
||||
ImGui_ImplOSX_UpdateMouseCursorAndButtons();
|
||||
ImGui_ImplOSX_UpdateGamepads();
|
||||
}
|
||||
|
||||
static int mapCharacterToKey(int c)
|
||||
NSString* NSStringFromPhase(NSEventPhase phase)
|
||||
{
|
||||
if (c >= 'a' && c <= 'z')
|
||||
return c - 'a' + 'A';
|
||||
if (c == 25) // SHIFT+TAB -> TAB
|
||||
return 9;
|
||||
if (c >= 0 && c < 256)
|
||||
return c;
|
||||
if (c >= 0xF700 && c < 0xF700 + 256)
|
||||
return c - 0xF700 + 256;
|
||||
return -1;
|
||||
static NSString* strings[] =
|
||||
{
|
||||
@"none",
|
||||
@"began",
|
||||
@"stationary",
|
||||
@"changed",
|
||||
@"ended",
|
||||
@"cancelled",
|
||||
@"mayBegin",
|
||||
};
|
||||
|
||||
int pos = phase == NSEventPhaseNone ? 0 : __builtin_ctzl((NSUInteger)phase) + 1;
|
||||
|
||||
return strings[pos];
|
||||
}
|
||||
|
||||
bool ImGui_ImplOSX_HandleEvent(NSEvent* event, NSView* view)
|
||||
@ -301,6 +461,21 @@ bool ImGui_ImplOSX_HandleEvent(NSEvent* event, NSView* view)
|
||||
|
||||
if (event.type == NSEventTypeScrollWheel)
|
||||
{
|
||||
// Ignore canceled events.
|
||||
//
|
||||
// From macOS 12.1, scrolling with two fingers and then decelerating
|
||||
// by tapping two fingers results in two events appearing:
|
||||
//
|
||||
// 1. A scroll wheel NSEvent, with a phase == NSEventPhaseMayBegin, when the user taps
|
||||
// two fingers to decelerate or stop the scroll events.
|
||||
//
|
||||
// 2. A scroll wheel NSEvent, with a phase == NSEventPhaseCancelled, when the user releases the
|
||||
// two-finger tap. It is this event that sometimes contains large values for scrollingDeltaX and
|
||||
// scrollingDeltaY. When these are added to the current x and y positions of the scrolling view,
|
||||
// it appears to jump up or down. It can be observed in Preview, various JetBrains IDEs and here.
|
||||
if (event.phase == NSEventPhaseCancelled)
|
||||
return false;
|
||||
|
||||
double wheel_dx = 0.0;
|
||||
double wheel_dy = 0.0;
|
||||
|
||||
@ -322,6 +497,8 @@ bool ImGui_ImplOSX_HandleEvent(NSEvent* event, NSView* view)
|
||||
wheel_dy = [event deltaY];
|
||||
}
|
||||
|
||||
//NSLog(@"dx=%0.3ff, dy=%0.3f, phase=%@", wheel_dx, wheel_dy, NSStringFromPhase(event.phase));
|
||||
|
||||
if (fabs(wheel_dx) > 0.0)
|
||||
io.MouseWheelH += (float)wheel_dx * 0.1f;
|
||||
if (fabs(wheel_dy) > 0.0)
|
||||
@ -329,57 +506,37 @@ bool ImGui_ImplOSX_HandleEvent(NSEvent* event, NSView* view)
|
||||
return io.WantCaptureMouse;
|
||||
}
|
||||
|
||||
// FIXME: All the key handling is wrong and broken. Refer to GLFW's cocoa_init.mm and cocoa_window.mm.
|
||||
if (event.type == NSEventTypeKeyDown)
|
||||
if (event.type == NSEventTypeKeyDown || event.type == NSEventTypeKeyUp)
|
||||
{
|
||||
NSString* str = [event characters];
|
||||
NSUInteger len = [str length];
|
||||
for (NSUInteger i = 0; i < len; i++)
|
||||
{
|
||||
int c = [str characterAtIndex:i];
|
||||
if (!io.KeySuper && !(c >= 0xF700 && c <= 0xFFFF) && c != 127)
|
||||
io.AddInputCharacter((unsigned int)c);
|
||||
|
||||
// We must reset in case we're pressing a sequence of special keys while keeping the command pressed
|
||||
int key = mapCharacterToKey(c);
|
||||
if (key != -1 && key < 256 && !io.KeySuper)
|
||||
resetKeys();
|
||||
if (key != -1)
|
||||
io.KeysDown[key] = true;
|
||||
}
|
||||
return io.WantCaptureKeyboard;
|
||||
}
|
||||
|
||||
if (event.type == NSEventTypeKeyUp)
|
||||
{
|
||||
NSString* str = [event characters];
|
||||
NSUInteger len = [str length];
|
||||
for (NSUInteger i = 0; i < len; i++)
|
||||
{
|
||||
int c = [str characterAtIndex:i];
|
||||
int key = mapCharacterToKey(c);
|
||||
if (key != -1)
|
||||
io.KeysDown[key] = false;
|
||||
}
|
||||
unsigned short code = event.keyCode;
|
||||
IM_ASSERT(code >= 0 && code < IM_ARRAYSIZE(io.KeysDown));
|
||||
io.KeysDown[code] = event.type == NSEventTypeKeyDown;
|
||||
NSEventModifierFlags flags = event.modifierFlags;
|
||||
io.KeyCtrl = (flags & NSEventModifierFlagControl) != 0;
|
||||
io.KeyShift = (flags & NSEventModifierFlagShift) != 0;
|
||||
io.KeyAlt = (flags & NSEventModifierFlagOption) != 0;
|
||||
io.KeySuper = (flags & NSEventModifierFlagCommand) != 0;
|
||||
return io.WantCaptureKeyboard;
|
||||
}
|
||||
|
||||
if (event.type == NSEventTypeFlagsChanged)
|
||||
{
|
||||
unsigned int flags = [event modifierFlags] & NSEventModifierFlagDeviceIndependentFlagsMask;
|
||||
|
||||
bool oldKeyCtrl = io.KeyCtrl;
|
||||
bool oldKeyShift = io.KeyShift;
|
||||
bool oldKeyAlt = io.KeyAlt;
|
||||
bool oldKeySuper = io.KeySuper;
|
||||
io.KeyCtrl = flags & NSEventModifierFlagControl;
|
||||
io.KeyShift = flags & NSEventModifierFlagShift;
|
||||
io.KeyAlt = flags & NSEventModifierFlagOption;
|
||||
io.KeySuper = flags & NSEventModifierFlagCommand;
|
||||
|
||||
// We must reset them as we will not receive any keyUp event if they where pressed with a modifier
|
||||
if ((oldKeyShift && !io.KeyShift) || (oldKeyCtrl && !io.KeyCtrl) || (oldKeyAlt && !io.KeyAlt) || (oldKeySuper && !io.KeySuper))
|
||||
resetKeys();
|
||||
NSEventModifierFlags flags = event.modifierFlags;
|
||||
switch (event.keyCode)
|
||||
{
|
||||
case kVK_Control:
|
||||
io.KeyCtrl = (flags & NSEventModifierFlagControl) != 0;
|
||||
break;
|
||||
case kVK_Shift:
|
||||
io.KeyShift = (flags & NSEventModifierFlagShift) != 0;
|
||||
break;
|
||||
case kVK_Option:
|
||||
io.KeyAlt = (flags & NSEventModifierFlagOption) != 0;
|
||||
break;
|
||||
case kVK_Command:
|
||||
io.KeySuper = (flags & NSEventModifierFlagCommand) != 0;
|
||||
break;
|
||||
}
|
||||
return io.WantCaptureKeyboard;
|
||||
}
|
||||
|
||||
|
@ -1,20 +1,25 @@
|
||||
// dear imgui: Renderer Backend for SDL_Renderer
|
||||
// (Requires: SDL 2.0.17+)
|
||||
|
||||
// Important to understand: SDL_Renderer is an _optional_ component of SDL. We do not recommend you use SDL_Renderer
|
||||
// because it provide a rather limited API to the end-user. We provide this backend for the sake of completeness.
|
||||
// Important to understand: SDL_Renderer is an _optional_ component of SDL.
|
||||
// For a multi-platform app consider using e.g. SDL+DirectX on Windows and SDL+OpenGL on Linux/OSX.
|
||||
// If your application will want to render any non trivial amount of graphics other than UI,
|
||||
// please be aware that SDL_Renderer offers a limited graphic API to the end-user and it might
|
||||
// be difficult to step out of those boundaries.
|
||||
// However, we understand it is a convenient choice to get an app started easily.
|
||||
|
||||
// Implemented features:
|
||||
// [X] Renderer: User texture binding. Use 'SDL_Texture*' as ImTextureID. Read the FAQ about ImTextureID!
|
||||
// [X] Renderer: Support for large meshes (64k+ vertices) with 16-bit indices.
|
||||
// Missing features:
|
||||
// [ ] Renderer: Support for large meshes (64k+ vertices) with 16-bit indices.
|
||||
|
||||
// You can copy and use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
|
||||
// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
|
||||
// Read online: https://github.com/ocornut/imgui/tree/master/docs
|
||||
|
||||
// CHANGELOG
|
||||
// 2021-12-21: Update SDL_RenderGeometryRaw() format to work with SDL 2.0.19.
|
||||
// 2021-12-03: Added support for large mesh (64K+ vertices), enable ImGuiBackendFlags_RendererHasVtxOffset flag.
|
||||
// 2021-10-06: Backup and restore modified ClipRect/Viewport.
|
||||
// 2021-09-21: Initial version.
|
||||
|
||||
@ -58,6 +63,7 @@ bool ImGui_ImplSDLRenderer_Init(SDL_Renderer* renderer)
|
||||
ImGui_ImplSDLRenderer_Data* bd = IM_NEW(ImGui_ImplSDLRenderer_Data)();
|
||||
io.BackendRendererUserData = (void*)bd;
|
||||
io.BackendRendererName = "imgui_impl_sdlrenderer";
|
||||
io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset; // We can honor the ImDrawCmd::VtxOffset field, allowing for large meshes.
|
||||
|
||||
bd->SDLRenderer = renderer;
|
||||
|
||||
@ -124,7 +130,7 @@ void ImGui_ImplSDLRenderer_RenderDrawData(ImDrawData* draw_data)
|
||||
SDL_Rect ClipRect;
|
||||
};
|
||||
BackupSDLRendererState old = {};
|
||||
old.ClipEnabled = SDL_RenderIsClipEnabled(bd->SDLRenderer);
|
||||
old.ClipEnabled = SDL_RenderIsClipEnabled(bd->SDLRenderer) == SDL_TRUE;
|
||||
SDL_RenderGetViewport(bd->SDLRenderer, &old.Viewport);
|
||||
SDL_RenderGetClipRect(bd->SDLRenderer, &old.ClipRect);
|
||||
|
||||
@ -161,15 +167,19 @@ void ImGui_ImplSDLRenderer_RenderDrawData(ImDrawData* draw_data)
|
||||
if (clip_min.y < 0.0f) { clip_min.y = 0.0f; }
|
||||
if (clip_max.x > fb_width) { clip_max.x = (float)fb_width; }
|
||||
if (clip_max.y > fb_height) { clip_max.y = (float)fb_height; }
|
||||
if (clip_max.x < clip_min.x || clip_max.y < clip_min.y)
|
||||
if (clip_max.x <= clip_min.x || clip_max.y <= clip_min.y)
|
||||
continue;
|
||||
|
||||
SDL_Rect r = { (int)(clip_min.x), (int)(clip_min.y), (int)(clip_max.x - clip_min.x), (int)(clip_max.y - clip_min.y) };
|
||||
SDL_RenderSetClipRect(bd->SDLRenderer, &r);
|
||||
|
||||
const float* xy = (const float*)((const char*)vtx_buffer + IM_OFFSETOF(ImDrawVert, pos));
|
||||
const float* uv = (const float*)((const char*)vtx_buffer + IM_OFFSETOF(ImDrawVert, uv));
|
||||
const int* color = (const int*)((const char*)vtx_buffer + IM_OFFSETOF(ImDrawVert, col));
|
||||
const float* xy = (const float*)((const char*)(vtx_buffer + pcmd->VtxOffset) + IM_OFFSETOF(ImDrawVert, pos));
|
||||
const float* uv = (const float*)((const char*)(vtx_buffer + pcmd->VtxOffset) + IM_OFFSETOF(ImDrawVert, uv));
|
||||
#if SDL_VERSION_ATLEAST(2,0,19)
|
||||
const SDL_Color* color = (const SDL_Color*)((const char*)(vtx_buffer + pcmd->VtxOffset) + IM_OFFSETOF(ImDrawVert, col)); // SDL 2.0.19+
|
||||
#else
|
||||
const int* color = (const int*)((const char*)(vtx_buffer + pcmd->VtxOffset) + IM_OFFSETOF(ImDrawVert, col)); // SDL 2.0.17 and 2.0.18
|
||||
#endif
|
||||
|
||||
// Bind texture, Draw
|
||||
SDL_Texture* tex = (SDL_Texture*)pcmd->GetTexID();
|
||||
@ -177,7 +187,7 @@ void ImGui_ImplSDLRenderer_RenderDrawData(ImDrawData* draw_data)
|
||||
xy, (int)sizeof(ImDrawVert),
|
||||
color, (int)sizeof(ImDrawVert),
|
||||
uv, (int)sizeof(ImDrawVert),
|
||||
cmd_list->VtxBuffer.Size,
|
||||
cmd_list->VtxBuffer.Size - pcmd->VtxOffset,
|
||||
idx_buffer + pcmd->IdxOffset, pcmd->ElemCount, sizeof(ImDrawIdx));
|
||||
}
|
||||
}
|
||||
|
@ -1,14 +1,16 @@
|
||||
// dear imgui: Renderer Backend for SDL_Renderer
|
||||
// (Requires: SDL 2.0.17+)
|
||||
|
||||
// Important to understand: SDL_Renderer is an _optional_ component of SDL. We do not recommend you use SDL_Renderer
|
||||
// because it provide a rather limited API to the end-user. We provide this backend for the sake of completeness.
|
||||
// Important to understand: SDL_Renderer is an _optional_ component of SDL.
|
||||
// For a multi-platform app consider using e.g. SDL+DirectX on Windows and SDL+OpenGL on Linux/OSX.
|
||||
// If your application will want to render any non trivial amount of graphics other than UI,
|
||||
// please be aware that SDL_Renderer offers a limited graphic API to the end-user and it might
|
||||
// be difficult to step out of those boundaries.
|
||||
// However, we understand it is a convenient choice to get an app started easily.
|
||||
|
||||
// Implemented features:
|
||||
// [X] Renderer: User texture binding. Use 'SDL_Texture*' as ImTextureID. Read the FAQ about ImTextureID!
|
||||
// Missing features:
|
||||
// [ ] Renderer: Support for large meshes (64k+ vertices) with 16-bit indices.
|
||||
// [X] Renderer: Support for large meshes (64k+ vertices) with 16-bit indices.
|
||||
|
||||
#pragma once
|
||||
#include "imgui.h" // IMGUI_IMPL_API
|
||||
|
@ -23,6 +23,7 @@
|
||||
|
||||
// CHANGELOG
|
||||
// (minor and older changes stripped away, please see git history for details)
|
||||
// 2021-10-15: Vulkan: Call vkCmdSetScissor() at the end of render a full-viewport to reduce likehood of issues with people using VK_DYNAMIC_STATE_SCISSOR in their app without calling vkCmdSetScissor() explicitly every frame.
|
||||
// 2021-06-29: Reorganized backend to pull data from a single structure to facilitate usage with multiple-contexts (all g_XXXX access changed to bd->XXXX).
|
||||
// 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.
|
||||
@ -519,7 +520,7 @@ void ImGui_ImplVulkan_RenderDrawData(ImDrawData* draw_data, VkCommandBuffer comm
|
||||
if (clip_min.y < 0.0f) { clip_min.y = 0.0f; }
|
||||
if (clip_max.x > fb_width) { clip_max.x = (float)fb_width; }
|
||||
if (clip_max.y > fb_height) { clip_max.y = (float)fb_height; }
|
||||
if (clip_max.x < clip_min.x || clip_max.y < clip_min.y)
|
||||
if (clip_max.x <= clip_min.x || clip_max.y <= clip_min.y)
|
||||
continue;
|
||||
|
||||
// Apply scissor/clipping rectangle
|
||||
@ -537,6 +538,16 @@ void ImGui_ImplVulkan_RenderDrawData(ImDrawData* draw_data, VkCommandBuffer comm
|
||||
global_idx_offset += cmd_list->IdxBuffer.Size;
|
||||
global_vtx_offset += cmd_list->VtxBuffer.Size;
|
||||
}
|
||||
|
||||
// Note: at this point both vkCmdSetViewport() and vkCmdSetScissor() have been called.
|
||||
// Our last values will leak into user/application rendering IF:
|
||||
// - Your app uses a pipeline with VK_DYNAMIC_STATE_VIEWPORT or VK_DYNAMIC_STATE_SCISSOR dynamic state
|
||||
// - And you forgot to call vkCmdSetViewport() and vkCmdSetScissor() yourself to explicitely set that state.
|
||||
// If you use VK_DYNAMIC_STATE_VIEWPORT or VK_DYNAMIC_STATE_SCISSOR you are responsible for setting the values before rendering.
|
||||
// In theory we should aim to backup/restore those values but I am not sure this is possible.
|
||||
// We perform a call to vkCmdSetScissor() to set back a full viewport which is likely to fix things for 99% users but technically this is not perfect. (See github #4644)
|
||||
VkRect2D scissor = { { 0, 0 }, { (uint32_t)fb_width, (uint32_t)fb_height } };
|
||||
vkCmdSetScissor(command_buffer, 0, 1, &scissor);
|
||||
}
|
||||
|
||||
bool ImGui_ImplVulkan_CreateFontsTexture(VkCommandBuffer command_buffer)
|
||||
|
@ -13,6 +13,7 @@
|
||||
|
||||
// CHANGELOG
|
||||
// (minor and older changes stripped away, please see git history for details)
|
||||
// 2021-11-29: Passing explicit buffer sizes to wgpuRenderPassEncoderSetVertexBuffer()/wgpuRenderPassEncoderSetIndexBuffer().
|
||||
// 2021-08-24: Fix for latest specs.
|
||||
// 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)
|
||||
@ -313,8 +314,8 @@ static void ImGui_ImplWGPU_SetupRenderState(ImDrawData* draw_data, WGPURenderPas
|
||||
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
|
||||
wgpuRenderPassEncoderSetVertexBuffer(ctx, 0, fr->VertexBuffer, 0, 0);
|
||||
wgpuRenderPassEncoderSetIndexBuffer(ctx, fr->IndexBuffer, sizeof(ImDrawIdx) == 2 ? WGPUIndexFormat_Uint16 : WGPUIndexFormat_Uint32, 0, 0);
|
||||
wgpuRenderPassEncoderSetVertexBuffer(ctx, 0, fr->VertexBuffer, 0, fr->VertexBufferSize);
|
||||
wgpuRenderPassEncoderSetIndexBuffer(ctx, fr->IndexBuffer, sizeof(ImDrawIdx) == 2 ? WGPUIndexFormat_Uint16 : WGPUIndexFormat_Uint32, 0, fr->IndexBufferSize);
|
||||
wgpuRenderPassEncoderSetPipeline(ctx, g_pipelineState);
|
||||
wgpuRenderPassEncoderSetBindGroup(ctx, 0, g_resources.CommonBindGroup, 0, NULL);
|
||||
|
||||
@ -446,7 +447,7 @@ void ImGui_ImplWGPU_RenderDrawData(ImDrawData* draw_data, WGPURenderPassEncoder
|
||||
// Project scissor/clipping rectangles into framebuffer space
|
||||
ImVec2 clip_min((pcmd->ClipRect.x - clip_off.x) * clip_scale.x, (pcmd->ClipRect.y - clip_off.y) * clip_scale.y);
|
||||
ImVec2 clip_max((pcmd->ClipRect.z - clip_off.x) * clip_scale.x, (pcmd->ClipRect.w - clip_off.y) * clip_scale.y);
|
||||
if (clip_max.x < clip_min.x || clip_max.y < clip_min.y)
|
||||
if (clip_max.x <= clip_min.x || clip_max.y <= clip_min.y)
|
||||
continue;
|
||||
|
||||
// Apply scissor/clipping rectangle, Draw
|
||||
|
@ -33,8 +33,9 @@ typedef DWORD (WINAPI *PFN_XInputGetState)(DWORD, XINPUT_STATE*);
|
||||
|
||||
// CHANGELOG
|
||||
// (minor and older changes stripped away, please see git history for details)
|
||||
// 2021-12-16: Inputs: Fill VK_LCONTROL/VK_RCONTROL/VK_LSHIFT/VK_RSHIFT/VK_LMENU/VK_RMENU for completeness.
|
||||
// 2021-08-17: Calling io.AddFocusEvent() on WM_SETFOCUS/WM_KILLFOCUS messages.
|
||||
// 2021-08-02: Inputs: Fixed keyboard modifiers being reported when host windo doesn't have focus.
|
||||
// 2021-08-02: Inputs: Fixed keyboard modifiers being reported when host window doesn't have focus.
|
||||
// 2021-07-29: Inputs: MousePos is correctly reported when the host platform window is hovered but not focused (using TrackMouseEvent() to receive WM_MOUSELEAVE events).
|
||||
// 2021-06-29: Reorganized backend to pull data from a single structure to facilitate usage with multiple-contexts (all g_XXXX access changed to bd->XXXX).
|
||||
// 2021-06-08: Fixed ImGui_ImplWin32_EnableDpiAwareness() and ImGui_ImplWin32_GetDpiScaleForMonitor() to handle Windows 8.1/10 features without a manifest (per-monitor DPI, and properly calls SetProcessDpiAwareness() on 8.1).
|
||||
@ -426,11 +427,23 @@ IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hwnd, UINT msg, WPARA
|
||||
if (wParam < 256)
|
||||
io.KeysDown[wParam] = down;
|
||||
if (wParam == VK_CONTROL)
|
||||
io.KeyCtrl = down;
|
||||
{
|
||||
io.KeysDown[VK_LCONTROL] = ((::GetKeyState(VK_LCONTROL) & 0x8000) != 0);
|
||||
io.KeysDown[VK_RCONTROL] = ((::GetKeyState(VK_RCONTROL) & 0x8000) != 0);
|
||||
io.KeyCtrl = io.KeysDown[VK_LCONTROL] || io.KeysDown[VK_RCONTROL];
|
||||
}
|
||||
if (wParam == VK_SHIFT)
|
||||
io.KeyShift = down;
|
||||
{
|
||||
io.KeysDown[VK_LSHIFT] = ((::GetKeyState(VK_LSHIFT) & 0x8000) != 0);
|
||||
io.KeysDown[VK_RSHIFT] = ((::GetKeyState(VK_RSHIFT) & 0x8000) != 0);
|
||||
io.KeyShift = io.KeysDown[VK_LSHIFT] || io.KeysDown[VK_RSHIFT];
|
||||
}
|
||||
if (wParam == VK_MENU)
|
||||
io.KeyAlt = down;
|
||||
{
|
||||
io.KeysDown[VK_LMENU] = ((::GetKeyState(VK_LMENU) & 0x8000) != 0);
|
||||
io.KeysDown[VK_RMENU] = ((::GetKeyState(VK_RMENU) & 0x8000) != 0);
|
||||
io.KeyAlt = io.KeysDown[VK_LMENU] || io.KeysDown[VK_RMENU];
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
case WM_SETFOCUS:
|
||||
|
@ -12,7 +12,7 @@ your application or engine to easily integrate Dear ImGui.** Each backend is typ
|
||||
e.g. DirectX11 ([imgui_impl_dx11.cpp](https://github.com/ocornut/imgui/blob/master/backends/imgui_impl_dx11.cpp)), OpenGL/WebGL ([imgui_impl_opengl3.cpp](https://github.com/ocornut/imgui/blob/master/backends/imgui_impl_opengl3.cpp), Vulkan ([imgui_impl_vulkan.cpp](https://github.com/ocornut/imgui/blob/master/backends/imgui_impl_vulkan.cpp), etc.
|
||||
|
||||
- For some high-level frameworks, a single backend usually handle both 'Platform' and 'Renderer' parts.<BR>
|
||||
e.g. Allegro 5 ([imgui_impl_allegro5.cpp](https://github.com/ocornut/imgui/blob/master/backends/imgui_impl_allegro5.cpp)), Marmalade ([imgui_impl_marmalade.cpp](https://github.com/ocornut/imgui/blob/master/backends/imgui_impl_marmalade.cpp)). If you end up creating a custom backend for your engine, you may want to do the same.
|
||||
e.g. Allegro 5 ([imgui_impl_allegro5.cpp](https://github.com/ocornut/imgui/blob/master/backends/imgui_impl_allegro5.cpp)). If you end up creating a custom backend for your engine, you may want to do the same.
|
||||
|
||||
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.
|
||||
@ -82,14 +82,13 @@ List of Renderer Backends:
|
||||
List of high-level Frameworks Backends (combining Platform + Renderer):
|
||||
|
||||
imgui_impl_allegro5.cpp
|
||||
imgui_impl_marmalade.cpp
|
||||
|
||||
Emscripten is also supported.
|
||||
The [example_emscripten_opengl3](https://github.com/ocornut/imgui/tree/master/examples/example_emscripten_opengl3) app uses imgui_impl_sdl.cpp + imgui_impl_opengl3.cpp, but other combos are possible.
|
||||
|
||||
### Backends for third-party frameworks, graphics API or other languages
|
||||
|
||||
See https://github.com/ocornut/imgui/wiki/Bindings for the full list.
|
||||
See https://github.com/ocornut/imgui/wiki/Bindings for the full list (e.g. Adventure Game Studio, Cinder, Cocos2d-x, Game Maker Studio2, Godot, L<EFBFBD>VE+LUA, Magnum, Monogame, Ogre, openFrameworks, OpenSceneGraph, SFML, Sokol, Unity, Unreal Engine and many others).
|
||||
|
||||
### Recommended Backends
|
||||
|
||||
@ -128,7 +127,10 @@ Once it works, if you really need it you can replace parts of backends with your
|
||||
and you have high-level systems everywhere.<BR>
|
||||
Suggestion: try using a non-portable backend first (e.g. win32 + underlying graphics API) to get
|
||||
your desktop builds working first. This will get you running faster and get your acquainted with
|
||||
how Dear ImGui works and is setup. You can then rewrite a custom backend using your own engine API.
|
||||
how Dear ImGui works and is setup. You can then rewrite a custom backend using your own engine API...
|
||||
|
||||
Generally:
|
||||
It is unlikely you will add value to your project by creating your own backend.
|
||||
|
||||
Also:
|
||||
The [multi-viewports feature](https://github.com/ocornut/imgui/issues/1542) of the 'docking' branch allows
|
||||
|
@ -30,6 +30,102 @@ HOW TO UPDATE?
|
||||
and API updates have been a little more frequent lately. They are documented below and in imgui.cpp and should not affect all users.
|
||||
- Please report any issue!
|
||||
|
||||
-----------------------------------------------------------------------
|
||||
VERSION 1.86 (Released 2021-12-22)
|
||||
-----------------------------------------------------------------------
|
||||
|
||||
Breaking Changes:
|
||||
|
||||
- Removed CalcListClipping() function. Prefer using ImGuiListClipper which can return non-contiguous ranges.
|
||||
Please open an issue if you think you really need this function. (#3841)
|
||||
- Backends: OSX: Added NSView* parameter to ImGui_ImplOSX_Init(). (#4759) [@stuartcarnie]
|
||||
- Backends: Marmalade: Removed obsolete Marmalade backend (imgui_impl_marmalade.cpp) + example app. (#368, #375)
|
||||
Find last supported version at https://github.com/ocornut/imgui/wiki/Bindings
|
||||
|
||||
Other Changes:
|
||||
|
||||
- Added an assertion for the common user mistake of using "" as an identifier at the root level of a window
|
||||
instead of using "##something". Empty identifiers are valid and useful in a very small amount of cases,
|
||||
but 99.9% of the time if you need an empty label you should use "##something". (#1414, #2562, #2807, #4008,
|
||||
#4158, #4375, #4548, #4657, #4796). READ THE FAQ ABOUT HOW THE ID STACK WORKS -> https://dearimgui.org/faq
|
||||
- Added GetMouseClickedCount() function, returning the number of successive clicks. (#3229) [@kudaba]
|
||||
(so IsMouseDoubleClicked(ImGuiMouseButton_Left) is same as GetMouseClickedCount(ImGuiMouseButton_Left) == 2,
|
||||
but it allows testing for triple clicks and more).
|
||||
- Modals: fixed issue hovering popups inside a child windows inside a modal. (#4676, #4527)
|
||||
- Modals, Popups, Windows: changes how appearing windows are interrupting popups and modals. (#4317) [@rokups]
|
||||
- appearing windows created from within the begin stack of a popup/modal will no longer close it.
|
||||
- appearing windows created not within the begin stack of a modal will no longer close the modal,
|
||||
and automatically appear behind it.
|
||||
- Fixed IsWindowFocused()/IsWindowHovered() issues with child windows inside popups. (#4676)
|
||||
- Nav: Ctrl+tabbing to cycle through windows is now enabled regardless of using the _NavEnableKeyboard
|
||||
configuration flag. This is part of an effort to generalize the use of keyboard inputs. (#4023, #787).
|
||||
Note that while this is active you can also moving windows (with arrow) and resize (shift+arrows).
|
||||
- Nav: tabbing now cycles through clipped items and scroll accordingly. (#4449)
|
||||
- Nav: pressing PageUp/PageDown/Home/End when in Menu layer automatically moves back to Main layer.
|
||||
- Nav: fixed resizing window from borders setting navigation to Menu layer.
|
||||
- Nav: prevent child from clipping items when using _NavFlattened and parent has a pending request.
|
||||
- Nav: pressing Esc to exit a child window reactivates the Nav highlight if it was disabled by mouse.
|
||||
- Nav: with ImGuiConfigFlags_NavEnableSetMousePos enabled: Fixed absolute mouse position when using
|
||||
Home/End leads to scrolling. Fixed not setting mouse position when a failed move request (e.g. when
|
||||
already at edge) reactivates the navigation highlight.
|
||||
- Menus: fixed closing a menu inside a popup/modal by clicking on the popup/modal. (#3496, #4797)
|
||||
- Menus: fixed closing a menu by clicking on its menu-bar item when inside a popup. (#3496, #4797) [@xndcn]
|
||||
- Menus: fixed menu inside a popup/modal not inhibiting hovering of items in the popup/modal. (#3496, #4797)
|
||||
- Menus: fixed sub-menu items inside a popups from closing the popup.
|
||||
- Menus: fixed top-level menu from not consistently using style.PopupRounding. (#4788)
|
||||
- InputText, Nav: fixed repeated calls to SetKeyboardFocusHere() preventing to use InputText(). (#4682)
|
||||
- Inputtext, Nav: fixed using SetKeyboardFocusHere() on InputTextMultiline(). (#4761)
|
||||
- InputText: made double-click select word, triple-line select line. Word delimitation logic differs
|
||||
slightly from the one used by CTRL+arrows. (#2244)
|
||||
- InputText: fixed ReadOnly flag preventing callbacks from receiving the text buffer. (#4762) [@actondev]
|
||||
- InputText: fixed Shift+Delete from not cutting into clipboard. (#4818, #1541) [@corporateshark]
|
||||
- InputTextMultiline: fixed incorrect padding when FrameBorder > 0. (#3781, #4794)
|
||||
- InputTextMultiline: fixed vertical tracking with large values of FramePadding.y. (#3781, #4794)
|
||||
- Separator: fixed cover all columns while called inside a table. (#4787)
|
||||
- Clipper: currently focused item is automatically included in clipper range.
|
||||
Fixes issue where e.g. drag and dropping an item and scrolling ensure the item source location is
|
||||
still submitted. (#3841, #1725) [@GamingMinds-DanielC, @ocornut]
|
||||
- Clipper: added ForceDisplayRangeByIndices() to force a given item (or several) to be stepped out
|
||||
during a clipping operation. (#3841) [@@GamingMinds-DanielC]
|
||||
- Clipper: rework so gamepad/keyboard navigation doesn't create spikes in number of items requested
|
||||
by the clipper to display. (#3841)
|
||||
- Clipper: fixed content height declaration slightly mismatching the value of when not using a clipper.
|
||||
(an additional ItemSpacing.y was declared, affecting scrollbar range).
|
||||
- Clipper: various and incomplete changes to tame down scrolling and precision issues on very large ranges.
|
||||
Passing an explicit height to the clipper now allows larger ranges. (#3609, #3962).
|
||||
- Clipper: fixed invalid state when number of frozen table row is smaller than ItemCount.
|
||||
- Drag and Drop: BeginDragDropSource() with ImGuiDragDropFlags_SourceAllowNullID doesn't lose
|
||||
tooltip when scrolling. (#143)
|
||||
- Fonts: fixed infinite loop in ImFontGlyphRangesBuilder::AddRanges() when passing UINT16_MAX or UINT32_MAX
|
||||
without the IMGUI_USE_WCHAR32 compile-time option. (#4802) [@SlavicPotato]
|
||||
- Metrics: Added a node showing windows in submission order and showing the Begin() stack.
|
||||
- Misc: Added missing ImGuiMouseCursor_NotAllowed cursor for software rendering (when the
|
||||
io.MouseDrawCursor flag is enabled). (#4713) [@nobody-special666]
|
||||
- Misc: Fixed software mouse cursor being rendered multiple times if Render() is called more than once.
|
||||
- Misc: Fix MinGW DLL build issue (when IMGUI_API is defined). [@rokups]
|
||||
- CI: Add MinGW DLL build to test suite. [@rokups]
|
||||
- Backends: Vulkan: Call vkCmdSetScissor() at the end of render with a full-viewport to reduce
|
||||
likehood of issues with people using VK_DYNAMIC_STATE_SCISSOR in their app without calling
|
||||
vkCmdSetScissor() explicitly every frame. (#4644)
|
||||
- Backends: OpenGL3: Using buffer orphaning + glBufferSubData(), seems to fix leaks with multi-viewports
|
||||
with some Intel HD drivers, and perhaps improve performances. (#4468, #4504, #2981, #3381) [@parbo]
|
||||
- Backends: OpenGL2, Allegro5, Marmalade: Fixed mishandling of the ImDrawCmd::IdxOffset field.
|
||||
This is an old bug, but due to the way we created drawlists, it never had any visible side-effect before.
|
||||
The new code for handling Modal and CTRL+Tab dimming/whitening recently made the bug surface. (#4790)
|
||||
- Backends: Win32: Store left/right variants of Ctrl/Shift/Alt mods in KeysDown[] array. (#2625) [@thedmd]
|
||||
- Backends: DX12: Fixed DRAW_EMPTY_SCISSOR_RECTANGLE warnings. (#4775)
|
||||
- Backends: SDL_Renderer: Added support for large meshes (64k+ vertices) with 16-bit indices,
|
||||
enabling 'ImGuiBackendFlags_RendererHasVtxOffset' in the backend. (#3926) [@rokups]
|
||||
- Backends: SDL_Renderer: Fix for SDL 2.0.19+ RenderGeometryRaw() API signature change. (#4819) [@sridenour]
|
||||
- Backends: OSX: Generally fix keyboard support. Keyboard arrays indexed using kVK_* codes, e.g.
|
||||
ImGui::IsKeyPressed(kVK_Space). Don't set mouse cursor shape unconditionally. Handle two fingers scroll
|
||||
cancel event. (#4759, #4253, #1873) [@stuartcarnie]
|
||||
- Backends: OSX: Add Game Controller support (need linking GameController framework) (#4759) [@stuartcarnie]
|
||||
- Backends: WebGPU: Passing explicit buffer sizes to wgpuRenderPassEncoderSetVertexBuffer() and
|
||||
wgpuRenderPassEncoderSetIndexBuffer() functions as validation layers appears to not do what the
|
||||
in-flux specs says. (#4766) [@meshula]
|
||||
|
||||
|
||||
-----------------------------------------------------------------------
|
||||
VERSION 1.85 (Released 2021-10-12)
|
||||
-----------------------------------------------------------------------
|
||||
|
@ -141,10 +141,6 @@ GLUT (e.g., FreeGLUT on Linux/Windows, GLUT framework on OSX) + OpenGL2 example.
|
||||
= main.cpp + imgui_impl_glut.cpp + imgui_impl_opengl2.cpp <BR>
|
||||
Note that GLUT/FreeGLUT is largely obsolete software, prefer using GLFW or SDL.
|
||||
|
||||
[example_marmalade/](https://github.com/ocornut/imgui/blob/master/examples/example_marmalade/) <BR>
|
||||
Marmalade example using IwGx. <BR>
|
||||
= main.cpp + imgui_impl_marmalade.cpp
|
||||
|
||||
[example_null/](https://github.com/ocornut/imgui/blob/master/examples/example_null/) <BR>
|
||||
Null example, compile and link imgui, create context, run headless with no inputs and no graphics output. <BR>
|
||||
= main.cpp <BR>
|
||||
|
@ -23,7 +23,7 @@ or view this file with any Markdown viewer.
|
||||
| [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** |
|
||||
| **[About the ID Stack system..<br>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-about-the-id-stack-system)** |
|
||||
| **[About the ID Stack system..<br>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?<br>How can I have multiple windows with the same label?](#q-about-the-id-stack-system)** |
|
||||
| [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)|
|
||||
| [How can I use my own math types instead of ImVec2/ImVec4?](#q-how-can-i-use-my-own-math-types-instead-of-imvec2imvec4) |
|
||||
| [How can I interact with standard C++ types (such as std::string and std::vector)?](#q-how-can-i-interact-with-standard-c-types-such-as-stdstring-and-stdvector) |
|
||||
@ -190,6 +190,7 @@ Refer to rendering backends in the [examples/](https://github.com/ocornut/imgui/
|
||||
### Q: Why is my widget not reacting when I click on it?
|
||||
### Q: How can I have widgets with an empty label?
|
||||
### Q: How can I have multiple widgets with the same label?
|
||||
### Q: How can I have multiple windows with the same label?
|
||||
|
||||
A primer on labels and the ID Stack...
|
||||
|
||||
@ -474,7 +475,7 @@ ImGui::End();
|
||||
- Math operators: if you have setup `IM_VEC2_CLASS_EXTRA` in `imconfig.h` to bind your own math types, you can use your own math types and their natural operators instead of ImVec2. ImVec2 by default doesn't export any math operators in the public API. You may use `#define IMGUI_DEFINE_MATH_OPERATORS` `#include "imgui_internal.h"` to use the internally defined math operators, but instead prefer using your own math library and set it up in `imconfig.h`.
|
||||
- You can use `ImGui::GetBackgroundDrawList()` or `ImGui::GetForegroundDrawList()` to access draw lists which will be displayed behind and over every other dear imgui windows (one bg/fg drawlist per viewport). This is very convenient if you need to quickly display something on the screen that is not associated to a dear imgui window.
|
||||
- You can also create your own empty window and draw inside it. Call Begin() with the NoBackground | NoDecoration | NoSavedSettings | NoInputs flags (The `ImGuiWindowFlags_NoDecoration` flag itself is a shortcut for NoTitleBar | NoResize | NoScrollbar | NoCollapse). Then you can retrieve the ImDrawList* via `GetWindowDrawList()` and draw to it in any way you like.
|
||||
`- You can create your own ImDrawList instance. You'll need to initialize them with `ImGui::GetDrawListSharedData()`, or create your own instancing ImDrawListSharedData`, and then call your renderer function with your own ImDrawList or ImDrawData data.
|
||||
- You can create your own ImDrawList instance. You'll need to initialize them with `ImGui::GetDrawListSharedData()`, or create your own instancing `ImDrawListSharedData`, and then call your renderer function with your own ImDrawList or ImDrawData data.
|
||||
- Looking for fun? The [ImDrawList coding party 2020](https://github.com/ocornut/imgui/issues/3606) thread is full of "don't do this at home" extreme uses of the ImDrawList API.
|
||||
|
||||
##### [Return to Index](#index)
|
||||
|
@ -118,7 +118,7 @@ Integrating Dear ImGui within your custom engine is a matter of 1) wiring mouse/
|
||||
Officially maintained backends/bindings (in repository):
|
||||
- Renderers: DirectX9, DirectX10, DirectX11, DirectX12, Metal, OpenGL/ES/ES2, SDL_Renderer, Vulkan, WebGPU.
|
||||
- Platforms: GLFW, SDL2, Win32, Glut, OSX, Android.
|
||||
- Frameworks: Emscripten, Allegro5, Marmalade.
|
||||
- Frameworks: Allegro5, Emscripten.
|
||||
|
||||
[Third-party backends/bindings](https://github.com/ocornut/imgui/wiki/Bindings) wiki page:
|
||||
- Languages: C, C# and: Beef, ChaiScript, Crystal, D, Go, Haskell, Haxe/hxcpp, Java, JavaScript, Julia, Kotlin, Lobster, Lua, Odin, Pascal, PureBasic, Python, Ruby, Rust, Swift...
|
||||
@ -201,13 +201,13 @@ Ongoing Dear ImGui development is currently financially supported by users and p
|
||||
- [Blizzard](https://careers.blizzard.com/en-us/openings/engineering/all/all/all/1)
|
||||
|
||||
*Double-chocolate sponsors*
|
||||
- [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)
|
||||
- [Ubisoft](https://montreal.ubisoft.com/en/ubisoft-sponsors-user-interface-library-for-c-dear-imgui), [Supercell](https://supercell.com)
|
||||
|
||||
*Chocolate sponsors*
|
||||
- [Activision](https://careers.activision.com/c/programmingsoftware-engineering-jobs), [Adobe](https://www.adobe.com/products/medium.html), [Aras Pranckevičius](https://aras-p.info), [Arkane Studios](https://www.arkane-studios.com), [Epic](https://www.unrealengine.com/en-US/megagrants), [RAD Game Tools](http://www.radgametools.com/)
|
||||
- [Activision](https://careers.activision.com/c/programmingsoftware-engineering-jobs), [Adobe](https://www.adobe.com/products/medium.html), [Aras Pranckevičius](https://aras-p.info), [Arkane Studios](https://www.arkane-studios.com), [Epic](https://www.unrealengine.com/en-US/megagrants), [Google](https://github.com/google/filament), [Nvidia](https://developer.nvidia.com/nvidia-omniverse), [RAD Game Tools](http://www.radgametools.com/)
|
||||
|
||||
*Salty-caramel sponsors*
|
||||
- [Framefield](http://framefield.com), [Grinding Gear Games](https://www.grindinggear.com), [Kylotonn](https://www.kylotonn.com), [Next Level Games](https://www.nextlevelgames.com), [O-Net Communications (USA)](http://en.o-netcom.com), [Supercell](https://supercell.com).
|
||||
- [Framefield](http://framefield.com), [Grinding Gear Games](https://www.grindinggear.com), [Kylotonn](https://www.kylotonn.com), [Next Level Games](https://www.nextlevelgames.com), [O-Net Communications (USA)](http://en.o-netcom.com)
|
||||
|
||||
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.
|
||||
|
@ -142,7 +142,6 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i
|
||||
- plot: option/feature: draw unit
|
||||
- plot: add a helper e.g. Plot(char* label, float value, float time_span=2.0f) that stores values and Plot them for you - probably another function name. and/or automatically allow to plot ANY displayed value (more reliance on stable ID)
|
||||
|
||||
- clipper: ability to force display 1 item in the list would be convenient (for patterns where we need to set active id etc.)
|
||||
- clipper: ability to disable the clipping through a simple flag/bool.
|
||||
- clipper: ability to run without knowing full count in advance.
|
||||
- clipper: horizontal clipping support. (#2580)
|
||||
@ -341,7 +340,6 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i
|
||||
- nav: NavFlattened: broken: in typical usage scenario, the items of a fully clipped child are currently not considered to enter into a NavFlattened child.
|
||||
- nav: NavFlattened: cannot access menu-bar of a flattened child window with Alt/menu key (not a very common use case..).
|
||||
- nav: simulate right-click or context activation? (SHIFT+F10)
|
||||
- nav/tabbing: refactor old tabbing system and turn into navigation, should pass through all widgets (in submission order?).
|
||||
- nav/popup: esc/enter default behavior for popups, e.g. be able to mark an "ok" or "cancel" button that would get triggered by those keys, default validation button, etc.
|
||||
- nav/treenode: left within a tree node block as a fallback (ImGuiTreeNodeFlags_NavLeftJumpsBackHere by default?)
|
||||
- nav/menus: pressing left-right on a vertically clipped menu bar tends to jump to the collapse/close buttons.
|
||||
|
@ -7,6 +7,7 @@
|
||||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
05318E0F274C397200A8DE2E /* GameController.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 05318E0E274C397200A8DE2E /* GameController.framework */; };
|
||||
07A82ED82139413D0078D120 /* imgui_widgets.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 07A82ED72139413C0078D120 /* imgui_widgets.cpp */; };
|
||||
07A82ED92139418F0078D120 /* imgui_widgets.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 07A82ED72139413C0078D120 /* imgui_widgets.cpp */; };
|
||||
5079822E257677DB0038A28D /* imgui_tables.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5079822D257677DB0038A28D /* imgui_tables.cpp */; };
|
||||
@ -32,6 +33,7 @@
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
05318E0E274C397200A8DE2E /* GameController.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = GameController.framework; path = System/Library/Frameworks/GameController.framework; sourceTree = SDKROOT; };
|
||||
07A82ED62139413C0078D120 /* imgui_internal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = imgui_internal.h; path = ../../imgui_internal.h; sourceTree = "<group>"; };
|
||||
07A82ED72139413C0078D120 /* imgui_widgets.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_widgets.cpp; path = ../../imgui_widgets.cpp; sourceTree = "<group>"; };
|
||||
5079822D257677DB0038A28D /* imgui_tables.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_tables.cpp; path = ../../imgui_tables.cpp; sourceTree = "<group>"; };
|
||||
@ -76,6 +78,7 @@
|
||||
files = (
|
||||
8309BDC6253CCCFE0045E2A1 /* AppKit.framework in Frameworks */,
|
||||
83BBE9EC20EB471700295997 /* MetalKit.framework in Frameworks */,
|
||||
05318E0F274C397200A8DE2E /* GameController.framework in Frameworks */,
|
||||
83BBE9ED20EB471700295997 /* Metal.framework in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
@ -133,6 +136,7 @@
|
||||
83BBE9E320EB46B800295997 /* Frameworks */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
05318E0E274C397200A8DE2E /* GameController.framework */,
|
||||
8309BDC5253CCCFE0045E2A1 /* AppKit.framework */,
|
||||
8309BD8E253CCAAA0045E2A1 /* UIKit.framework */,
|
||||
83BBE9EE20EB471C00295997 /* ModelIO.framework */,
|
||||
|
@ -119,7 +119,7 @@
|
||||
return event;
|
||||
}];
|
||||
|
||||
ImGui_ImplOSX_Init();
|
||||
ImGui_ImplOSX_Init(self.view);
|
||||
|
||||
#endif
|
||||
}
|
||||
|
@ -7,6 +7,7 @@
|
||||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
05E31B59274EF0700083FCB6 /* GameController.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 05E31B57274EF0360083FCB6 /* GameController.framework */; };
|
||||
07A82EDB213941D00078D120 /* imgui_widgets.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 07A82EDA213941D00078D120 /* imgui_widgets.cpp */; };
|
||||
4080A99820B02D340036BA46 /* main.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4080A98A20B02CD90036BA46 /* main.mm */; };
|
||||
4080A9A220B034280036BA46 /* imgui_impl_opengl2.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4080A99E20B034280036BA46 /* imgui_impl_opengl2.cpp */; };
|
||||
@ -32,6 +33,7 @@
|
||||
/* End PBXCopyFilesBuildPhase section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
05E31B57274EF0360083FCB6 /* GameController.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = GameController.framework; path = System/Library/Frameworks/GameController.framework; sourceTree = SDKROOT; };
|
||||
07A82EDA213941D00078D120 /* imgui_widgets.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imgui_widgets.cpp; path = ../../imgui_widgets.cpp; sourceTree = "<group>"; };
|
||||
4080A96B20B029B00036BA46 /* example_osx_opengl2 */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = example_osx_opengl2; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
4080A98A20B02CD90036BA46 /* main.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = main.mm; sourceTree = SOURCE_ROOT; };
|
||||
@ -57,6 +59,7 @@
|
||||
files = (
|
||||
4080A9B520B034EA0036BA46 /* OpenGL.framework in Frameworks */,
|
||||
4080A9B320B034E40036BA46 /* Cocoa.framework in Frameworks */,
|
||||
05E31B59274EF0700083FCB6 /* GameController.framework in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
@ -95,6 +98,7 @@
|
||||
4080A9B120B034E40036BA46 /* Frameworks */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
05E31B57274EF0360083FCB6 /* GameController.framework */,
|
||||
4080A9B420B034EA0036BA46 /* OpenGL.framework */,
|
||||
4080A9B220B034E40036BA46 /* Cocoa.framework */,
|
||||
);
|
||||
|
@ -58,7 +58,7 @@
|
||||
//ImGui::StyleColorsClassic();
|
||||
|
||||
// Setup Platform/Renderer backends
|
||||
ImGui_ImplOSX_Init();
|
||||
ImGui_ImplOSX_Init(self);
|
||||
ImGui_ImplOpenGL2_Init();
|
||||
|
||||
// Load Fonts
|
||||
@ -146,12 +146,9 @@
|
||||
animationTimer = [NSTimer scheduledTimerWithTimeInterval:0.017 target:self selector:@selector(animationTimerFired:) userInfo:nil repeats:YES];
|
||||
}
|
||||
|
||||
-(void)reshape { [[self openGLContext] update]; [self updateAndDrawDemoView]; }
|
||||
-(void)reshape { [super reshape]; [[self openGLContext] update]; [self updateAndDrawDemoView]; }
|
||||
-(void)drawRect:(NSRect)bounds { [self updateAndDrawDemoView]; }
|
||||
-(void)animationTimerFired:(NSTimer*)timer { [self setNeedsDisplay:YES]; }
|
||||
-(BOOL)acceptsFirstResponder { return (YES); }
|
||||
-(BOOL)becomeFirstResponder { return (YES); }
|
||||
-(BOOL)resignFirstResponder { return (YES); }
|
||||
-(void)dealloc { animationTimer = nil; }
|
||||
|
||||
//-----------------------------------------------------------------------------------
|
||||
|
@ -1,8 +1,11 @@
|
||||
## How to Build
|
||||
|
||||
- You need to install Emscripten from https://emscripten.org/docs/getting_started/downloads.html, and have the environment variables set, as described in https://emscripten.org/docs/getting_started/downloads.html#installation-instructions
|
||||
- You may also refer to our [Continuous Integration setup](https://github.com/ocornut/imgui/tree/master/.github/workflows) for Emscripten setup.
|
||||
|
||||
- Depending on your configuration, in Windows you may need to run `emsdk/emsdk_env.bat` in your console to access the Emscripten command-line tools.
|
||||
|
||||
- You may also refer to our [Continuous Integration setup](https://github.com/ocornut/imgui/tree/master/.github/workflows) for Emscripten setup.
|
||||
|
||||
- Then build using `make` while in the `example_emscripten_opengl3/` directory.
|
||||
|
||||
## How to Run
|
||||
@ -15,6 +18,7 @@ _"Unfortunately several browsers (including Chrome, Safari, and Internet Explore
|
||||
- Emscripten SDK has a handy `emrun` command: `emrun web/example_emscripten_opengl3.html --browser firefox` which will spawn a temporary local webserver (in Firefox). See https://emscripten.org/docs/compiling/Running-html-files-with-emrun.html for details.
|
||||
- You may use Python 3 builtin webserver: `python -m http.server -d web` (this is what `make serve` uses).
|
||||
- You may use Python 2 builtin webserver: `cd web && python -m SimpleHTTPServer`.
|
||||
- If you are accessing the files over a network, certain browsers, such as Firefox, will restrict Gamepad API access to secure contexts only (e.g. https only).
|
||||
|
||||
## Obsolete features:
|
||||
|
||||
|
@ -1,10 +1,24 @@
|
||||
|
||||
# How to Build
|
||||
## How to Build
|
||||
|
||||
- You need to install Emscripten from https://emscripten.org/docs/getting_started/downloads.html, and have the environment variables set, as described in https://emscripten.org/docs/getting_started/downloads.html#installation-instructions
|
||||
|
||||
- Depending on your configuration, in Windows you may need to run `emsdk/emsdk_env.bat` in your console to access the Emscripten command-line tools.
|
||||
|
||||
- You may also refer to our [Continuous Integration setup](https://github.com/ocornut/imgui/tree/master/.github/workflows) for Emscripten setup.
|
||||
|
||||
- Then build using `make` while in the `example_emscripten_wgpu/` directory.
|
||||
|
||||
- Requires Emscripten 2.0.10 (December 2020) due to GLFW adaptations
|
||||
- Requires recent Emscripten as WGPU is still a work-in-progress API.
|
||||
|
||||
## How to Run
|
||||
|
||||
To run on a local machine:
|
||||
- Make sure your browse supports WGPU and it is enabled. WGPU is still WIP not enabled by default in most browser.
|
||||
- `make serve` will use Python3 to spawn a local webserver, you can then browse http://localhost:8000 to access your build.
|
||||
- Otherwise, generally you will need a local webserver:
|
||||
- Quoting [https://emscripten.org/docs/getting_started](https://emscripten.org/docs/getting_started/Tutorial.html#generating-html):<br>
|
||||
_"Unfortunately several browsers (including Chrome, Safari, and Internet Explorer) do not support file:// [XHR](https://emscripten.org/docs/site/glossary.html#term-xhr) requests, and can’t load extra files needed by the HTML (like a .wasm file, or packaged file data as mentioned lower down). For these browsers you’ll need to serve the files using a [local webserver](https://emscripten.org/docs/getting_started/FAQ.html#faq-local-webserver) and then open http://localhost:8000/hello.html."_
|
||||
- Emscripten SDK has a handy `emrun` command: `emrun web/example_emscripten_opengl3.html --browser firefox` which will spawn a temporary local webserver (in Firefox). See https://emscripten.org/docs/compiling/Running-html-files-with-emrun.html for details.
|
||||
- You may use Python 3 builtin webserver: `python -m http.server -d web` (this is what `make serve` uses).
|
||||
- You may use Python 2 builtin webserver: `cd web && python -m SimpleHTTPServer`.
|
||||
- If you are accessing the files over a network, certain browsers, such as Firefox, will restrict Gamepad API access to secure contexts only (e.g. https only).
|
||||
|
@ -1,32 +0,0 @@
|
||||
# This file is for configuration settings for your
|
||||
# application.
|
||||
#
|
||||
# The syntax is similar to windows .ini files ie
|
||||
#
|
||||
# [GroupName]
|
||||
# Setting = Value
|
||||
#
|
||||
# Which can be read by your application using
|
||||
# e.g s3eConfigGetString("GroupName", "Setting", string)
|
||||
#
|
||||
# All settings must be documented in .config.txt files.
|
||||
# New settings specific to this application should be
|
||||
# documented in app.config.txt
|
||||
#
|
||||
# Some conditional operations are also permitted, see the
|
||||
# S3E documentation for details.
|
||||
|
||||
[S3E]
|
||||
MemSize=6000000
|
||||
MemSizeDebug=6000000
|
||||
DispFixRot=FixedLandscape
|
||||
|
||||
# emulate iphone 5 resolution, change these settings to emulate other display resolution
|
||||
WinWidth=1136
|
||||
WinHeight=640
|
||||
|
||||
[GX]
|
||||
DataCacheSize=131070
|
||||
|
||||
[Util]
|
||||
#MemoryBreakpoint=1282
|
@ -1,124 +0,0 @@
|
||||
// Dear ImGui: standalone example application for Marmalade
|
||||
// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
|
||||
// Read online: https://github.com/ocornut/imgui/tree/master/docs
|
||||
|
||||
// Copyright (C) 2015 by Giovanni Zito
|
||||
// This file is part of Dear ImGui
|
||||
|
||||
#include "imgui.h"
|
||||
#include "imgui_impl_marmalade.h"
|
||||
#include <stdio.h>
|
||||
|
||||
#include <s3eKeyboard.h>
|
||||
#include <s3ePointer.h>
|
||||
#include <IwGx.h>
|
||||
|
||||
int main(int, char**)
|
||||
{
|
||||
IwGxInit();
|
||||
|
||||
// Setup Dear ImGui context
|
||||
IMGUI_CHECKVERSION();
|
||||
ImGui::CreateContext();
|
||||
ImGuiIO& io = ImGui::GetIO(); (void)io;
|
||||
//io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls
|
||||
|
||||
// Setup Dear ImGui style
|
||||
ImGui::StyleColorsDark();
|
||||
//ImGui::StyleColorsClassic();
|
||||
|
||||
// Setup Platform/Renderer backends
|
||||
ImGui_Marmalade_Init(true);
|
||||
|
||||
// Load Fonts
|
||||
// - If no fonts are loaded, dear imgui will use the default font. You can also load multiple fonts and use ImGui::PushFont()/PopFont() to select them.
|
||||
// - AddFontFromFileTTF() will return the ImFont* so you can store it if you need to select the font among multiple.
|
||||
// - If the file cannot be loaded, the function will return NULL. Please handle those errors in your application (e.g. use an assertion, or display an error and quit).
|
||||
// - The fonts will be rasterized at a given size (w/ oversampling) and stored into a texture when calling ImFontAtlas::Build()/GetTexDataAsXXXX(), which ImGui_ImplXXXX_NewFrame below will call.
|
||||
// - Read 'docs/FONTS.md' for more instructions and details.
|
||||
// - Remember that in C/C++ if you want to include a backslash \ in a string literal you need to write a double backslash \\ !
|
||||
//io.Fonts->AddFontDefault();
|
||||
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/Roboto-Medium.ttf", 16.0f);
|
||||
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/Cousine-Regular.ttf", 15.0f);
|
||||
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/DroidSans.ttf", 16.0f);
|
||||
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/ProggyTiny.ttf", 10.0f);
|
||||
//ImFont* font = io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf", 18.0f, NULL, io.Fonts->GetGlyphRangesJapanese());
|
||||
//IM_ASSERT(font != NULL);
|
||||
|
||||
// Our state
|
||||
bool show_demo_window = true;
|
||||
bool show_another_window = false;
|
||||
ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f);
|
||||
|
||||
// Main loop
|
||||
while (true)
|
||||
{
|
||||
if (s3eDeviceCheckQuitRequest())
|
||||
break;
|
||||
|
||||
// Poll and handle inputs
|
||||
// You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs.
|
||||
// - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application.
|
||||
// - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application.
|
||||
// Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags.
|
||||
s3eKeyboardUpdate();
|
||||
s3ePointerUpdate();
|
||||
|
||||
// Start the Dear ImGui frame
|
||||
ImGui_Marmalade_NewFrame();
|
||||
ImGui::NewFrame();
|
||||
|
||||
// 1. Show the big demo window (Most of the sample code is in ImGui::ShowDemoWindow()! You can browse its code to learn more about Dear ImGui!).
|
||||
if (show_demo_window)
|
||||
ImGui::ShowDemoWindow(&show_demo_window);
|
||||
|
||||
// 2. Show a simple window that we create ourselves. We use a Begin/End pair to created a named window.
|
||||
{
|
||||
static float f = 0.0f;
|
||||
static int counter = 0;
|
||||
|
||||
ImGui::Begin("Hello, world!"); // Create a window called "Hello, world!" and append into it.
|
||||
|
||||
ImGui::Text("This is some useful text."); // Display some text (you can use a format strings too)
|
||||
ImGui::Checkbox("Demo Window", &show_demo_window); // Edit bools storing our window open/close state
|
||||
ImGui::Checkbox("Another Window", &show_another_window);
|
||||
|
||||
ImGui::SliderFloat("float", &f, 0.0f, 1.0f); // Edit 1 float using a slider from 0.0f to 1.0f
|
||||
ImGui::ColorEdit3("clear color", (float*)&clear_color); // Edit 3 floats representing a color
|
||||
|
||||
if (ImGui::Button("Button")) // Buttons return true when clicked (most widgets return true when edited/activated)
|
||||
counter++;
|
||||
ImGui::SameLine();
|
||||
ImGui::Text("counter = %d", counter);
|
||||
|
||||
ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate);
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
// 3. Show another simple window.
|
||||
if (show_another_window)
|
||||
{
|
||||
ImGui::Begin("Another Window", &show_another_window); // Pass a pointer to our bool variable (the window will have a closing button that will clear the bool when clicked)
|
||||
ImGui::Text("Hello from another window!");
|
||||
if (ImGui::Button("Close Me"))
|
||||
show_another_window = false;
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
// Rendering
|
||||
ImGui::Render();
|
||||
IwGxSetColClear(clear_color.x * 255, clear_color.y * 255, clear_color.z * 255, clear_color.w * 255);
|
||||
IwGxClear();
|
||||
ImGui_Marmalade_RenderDrawData(ImGui::GetDrawData());
|
||||
IwGxSwapBuffers();
|
||||
|
||||
s3eDeviceYield(0);
|
||||
}
|
||||
|
||||
// Cleanup
|
||||
ImGui_Marmalade_Shutdown();
|
||||
ImGui::DestroyContext();
|
||||
IwGxTerminate();
|
||||
|
||||
return 0;
|
||||
}
|
@ -1,47 +0,0 @@
|
||||
#!/usr/bin/env mkb
|
||||
|
||||
# ImGui - standalone example application for Marmalade
|
||||
# Copyright (C) 2015 by Giovanni Zito
|
||||
# This file is part of ImGui
|
||||
# https://github.com/ocornut/imgui
|
||||
|
||||
define IMGUI_DISABLE_INCLUDE_IMCONFIG_H
|
||||
define IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCS
|
||||
define IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCS
|
||||
define _snprintf=snprintf
|
||||
|
||||
options
|
||||
{
|
||||
optimise-speed=1
|
||||
}
|
||||
|
||||
includepaths
|
||||
{
|
||||
../..
|
||||
../../backends
|
||||
}
|
||||
|
||||
subprojects
|
||||
{
|
||||
iwgx
|
||||
}
|
||||
|
||||
files
|
||||
{
|
||||
(.)
|
||||
["imgui"]
|
||||
../../imgui.cpp
|
||||
../../imgui_demo.cpp
|
||||
../../imgui_draw.cpp
|
||||
../../imgui_tables.cpp
|
||||
../../imgui_widgets.cpp
|
||||
../../imconfig.h
|
||||
../../imgui.h
|
||||
../../imgui_internal.h
|
||||
|
||||
["imgui","Marmalade backend"]
|
||||
../../backends/imgui_impl_marmalade.h
|
||||
../../backends/imgui_impl_marmalade.cpp
|
||||
main.cpp
|
||||
|
||||
}
|
69
imgui.h
69
imgui.h
@ -1,4 +1,4 @@
|
||||
// dear imgui, v1.85
|
||||
// dear imgui, v1.86
|
||||
// (headers)
|
||||
|
||||
// Help:
|
||||
@ -63,8 +63,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.85"
|
||||
#define IMGUI_VERSION_NUM 18500
|
||||
#define IMGUI_VERSION "1.86"
|
||||
#define IMGUI_VERSION_NUM 18600
|
||||
#define IMGUI_CHECKVERSION() ImGui::DebugCheckVersionAndDataLayout(IMGUI_VERSION, sizeof(ImGuiIO), sizeof(ImGuiStyle), sizeof(ImVec2), sizeof(ImVec4), sizeof(ImDrawVert), sizeof(ImDrawIdx))
|
||||
#define IMGUI_HAS_TABLE
|
||||
|
||||
@ -152,7 +152,7 @@ struct ImGuiContext; // Dear ImGui context (opaque structure, unl
|
||||
struct ImGuiIO; // Main configuration and I/O between your application and ImGui
|
||||
struct ImGuiInputTextCallbackData; // Shared state of InputText() when using custom ImGuiInputTextCallback (rare/advanced use)
|
||||
struct ImGuiListClipper; // Helper to manually clip large list of items
|
||||
struct ImGuiOnceUponAFrame; // Helper for running a block of code not more than once a frame, used by IMGUI_ONCE_UPON_A_FRAME macro
|
||||
struct ImGuiOnceUponAFrame; // Helper for running a block of code not more than once a frame
|
||||
struct ImGuiPayload; // User data payload for drag and drop operations
|
||||
struct ImGuiSizeCallbackData; // Callback data when using SetNextWindowSizeConstraints() (rare/advanced use)
|
||||
struct ImGuiStorage; // Helper for key->value storage
|
||||
@ -869,7 +869,6 @@ namespace ImGui
|
||||
IMGUI_API const char* GetStyleColorName(ImGuiCol idx); // get a string corresponding to the enum value (for display, saving, etc.).
|
||||
IMGUI_API void SetStateStorage(ImGuiStorage* storage); // replace current window storage with our own (if you want to manipulate it yourself, typically clear subsection of it)
|
||||
IMGUI_API ImGuiStorage* GetStateStorage();
|
||||
IMGUI_API void CalcListClipping(int items_count, float items_height, int* out_items_display_start, int* out_items_display_end); // calculate coarse clipping for large list of evenly sized items. Prefer using the ImGuiListClipper higher-level helper if you can.
|
||||
IMGUI_API bool BeginChildFrame(ImGuiID id, const ImVec2& size, ImGuiWindowFlags flags = 0); // helper to create a child window / scrolling region that looks like a normal widget frame
|
||||
IMGUI_API void EndChildFrame(); // always call EndChildFrame() regardless of BeginChildFrame() return values (which indicates a collapsed/clipped window)
|
||||
|
||||
@ -897,9 +896,10 @@ namespace ImGui
|
||||
// - You can also use regular integer: it is forever guaranteed that 0=Left, 1=Right, 2=Middle.
|
||||
// - Dragging operations are only reported after mouse has moved a certain distance away from the initial clicking position (see 'lock_threshold' and 'io.MouseDraggingThreshold')
|
||||
IMGUI_API bool IsMouseDown(ImGuiMouseButton button); // is mouse button held?
|
||||
IMGUI_API bool IsMouseClicked(ImGuiMouseButton button, bool repeat = false); // did mouse button clicked? (went from !Down to Down)
|
||||
IMGUI_API bool IsMouseClicked(ImGuiMouseButton button, bool repeat = false); // did mouse button clicked? (went from !Down to Down). Same as GetMouseClickedCount() == 1.
|
||||
IMGUI_API bool IsMouseReleased(ImGuiMouseButton button); // did mouse button released? (went from Down to !Down)
|
||||
IMGUI_API bool IsMouseDoubleClicked(ImGuiMouseButton button); // did mouse button double-clicked? (note that a double-click will also report IsMouseClicked() == true)
|
||||
IMGUI_API bool IsMouseDoubleClicked(ImGuiMouseButton button); // did mouse button double-clicked? Same as GetMouseClickedCount() == 2. (note that a double-click will also report IsMouseClicked() == true)
|
||||
IMGUI_API int GetMouseClickedCount(ImGuiMouseButton button); // return the number of successive mouse-clicks at the time where a click happen (otherwise 0).
|
||||
IMGUI_API bool IsMouseHoveringRect(const ImVec2& r_min, const ImVec2& r_max, bool clip = true);// is mouse hovering given bounding rect (in screen space). clipped by current clipping settings, but disregarding of other consideration of focus/window ordering/popup-block.
|
||||
IMGUI_API bool IsMousePosValid(const ImVec2* mouse_pos = NULL); // by convention we use (-FLT_MAX,-FLT_MAX) to denote that there is no mouse available
|
||||
IMGUI_API bool IsAnyMouseDown(); // is any mouse button held?
|
||||
@ -954,7 +954,7 @@ enum ImGuiWindowFlags_
|
||||
ImGuiWindowFlags_NoMove = 1 << 2, // Disable user moving the window
|
||||
ImGuiWindowFlags_NoScrollbar = 1 << 3, // Disable scrollbars (window can still scroll with mouse or programmatically)
|
||||
ImGuiWindowFlags_NoScrollWithMouse = 1 << 4, // Disable user vertically scrolling with mouse wheel. On child window, mouse wheel will be forwarded to the parent unless NoScrollbar is also set.
|
||||
ImGuiWindowFlags_NoCollapse = 1 << 5, // Disable user collapsing window by double-clicking on it
|
||||
ImGuiWindowFlags_NoCollapse = 1 << 5, // Disable user collapsing window by double-clicking on it. Also referred to as Window Menu Button (e.g. within a docking node).
|
||||
ImGuiWindowFlags_AlwaysAutoResize = 1 << 6, // Resize every window to its content every frame
|
||||
ImGuiWindowFlags_NoBackground = 1 << 7, // Disable drawing background color (WindowBg, etc.) and outside border. Similar as using SetNextWindowBgAlpha(0.0f).
|
||||
ImGuiWindowFlags_NoSavedSettings = 1 << 8, // Never load/save settings in .ini file
|
||||
@ -974,7 +974,7 @@ enum ImGuiWindowFlags_
|
||||
ImGuiWindowFlags_NoInputs = ImGuiWindowFlags_NoMouseInputs | ImGuiWindowFlags_NoNavInputs | ImGuiWindowFlags_NoNavFocus,
|
||||
|
||||
// [Internal]
|
||||
ImGuiWindowFlags_NavFlattened = 1 << 23, // [BETA] Allow gamepad/keyboard navigation to cross over parent border to this child (only use on child that have no scrolling!)
|
||||
ImGuiWindowFlags_NavFlattened = 1 << 23, // [BETA] On child window: allow gamepad/keyboard navigation to cross over parent border to this child or between sibling child windows.
|
||||
ImGuiWindowFlags_ChildWindow = 1 << 24, // Don't use! For internal use by BeginChild()
|
||||
ImGuiWindowFlags_Tooltip = 1 << 25, // Don't use! For internal use by BeginTooltip()
|
||||
ImGuiWindowFlags_Popup = 1 << 26, // Don't use! For internal use by BeginPopup()
|
||||
@ -1742,7 +1742,7 @@ struct ImVector
|
||||
inline void pop_back() { IM_ASSERT(Size > 0); Size--; }
|
||||
inline void push_front(const T& v) { if (Size == 0) push_back(v); else insert(Data, v); }
|
||||
inline T* erase(const T* it) { IM_ASSERT(it >= Data && it < Data + Size); const ptrdiff_t off = it - Data; memmove(Data + off, Data + off + 1, ((size_t)Size - (size_t)off - 1) * sizeof(T)); Size--; return Data + off; }
|
||||
inline T* erase(const T* it, const T* it_last){ IM_ASSERT(it >= Data && it < Data + Size && it_last > it && it_last <= Data + Size); const ptrdiff_t count = it_last - it; const ptrdiff_t off = it - Data; memmove(Data + off, Data + off + count, ((size_t)Size - (size_t)off - count) * sizeof(T)); Size -= (int)count; return Data + off; }
|
||||
inline T* erase(const T* it, const T* it_last){ IM_ASSERT(it >= Data && it < Data + Size && it_last > it && it_last <= Data + Size); const ptrdiff_t count = it_last - it; const ptrdiff_t off = it - Data; memmove(Data + off, Data + off + count, ((size_t)Size - (size_t)off - (size_t)count) * sizeof(T)); Size -= (int)count; return Data + off; }
|
||||
inline T* erase_unsorted(const T* it) { IM_ASSERT(it >= Data && it < Data + Size); const ptrdiff_t off = it - Data; if (it < Data + Size - 1) memcpy(Data + off, Data + Size - 1, sizeof(T)); Size--; return Data + off; }
|
||||
inline T* insert(const T* it, const T& v) { IM_ASSERT(it >= Data && it <= Data + Size); const ptrdiff_t off = it - Data; if (Size == Capacity) reserve(_grow_capacity(Size + 1)); if (off < (int)Size) memmove(Data + off + 1, Data + off, ((size_t)Size - (size_t)off) * sizeof(T)); memcpy(&Data[off], &v, sizeof(v)); Size++; return Data + off; }
|
||||
inline bool contains(const T& v) const { const T* data = Data; const T* data_end = Data + Size; while (data < data_end) if (*data++ == v) return true; return false; }
|
||||
@ -1930,12 +1930,13 @@ struct ImGuiIO
|
||||
ImVec2 MousePosPrev; // Previous mouse position (note that MouseDelta is not necessary == MousePos-MousePosPrev, in case either position is invalid)
|
||||
ImVec2 MouseClickedPos[5]; // Position at time of clicking
|
||||
double MouseClickedTime[5]; // Time of last click (used to figure out double-click)
|
||||
bool MouseClicked[5]; // Mouse button went from !Down to Down
|
||||
bool MouseDoubleClicked[5]; // Has mouse button been double-clicked?
|
||||
bool MouseClicked[5]; // Mouse button went from !Down to Down (same as MouseClickedCount[x] != 0)
|
||||
bool MouseDoubleClicked[5]; // Has mouse button been double-clicked? (same as MouseClickedCount[x] == 2)
|
||||
ImU16 MouseClickedCount[5]; // == 0 (not clicked), == 1 (same as MouseClicked[]), == 2 (double-clicked), == 3 (triple-clicked) etc. when going from !Down to Down
|
||||
ImU16 MouseClickedLastCount[5]; // Count successive number of clicks. Stays valid after mouse release. Reset after another click is done.
|
||||
bool MouseReleased[5]; // Mouse button went from Down to !Down
|
||||
bool MouseDownOwned[5]; // Track if button was clicked inside a dear imgui window or over void blocked by a popup. We don't request mouse capture from the application if click started outside ImGui bounds.
|
||||
bool MouseDownOwnedUnlessPopupClose[5];//Track if button was clicked inside a dear imgui window.
|
||||
bool MouseDownWasDoubleClick[5]; // Track if button down was a double-click
|
||||
float MouseDownDuration[5]; // Duration the mouse button has been down (0.0f == just clicked)
|
||||
float MouseDownDurationPrev[5]; // Previous time the mouse button has been down
|
||||
ImVec2 MouseDragMaxDistanceAbs[5]; // Maximum distance, absolute, on each axis, of how much mouse has traveled from the clicking point
|
||||
@ -2170,10 +2171,12 @@ struct ImGuiStorage
|
||||
};
|
||||
|
||||
// Helper: Manually clip large list of items.
|
||||
// If you are submitting lots of evenly spaced items and you have a random access to the list, you can perform coarse
|
||||
// clipping based on visibility to save yourself from processing those items at all.
|
||||
// If you have lots evenly spaced items and you have a random access to the list, you can perform coarse
|
||||
// clipping based on visibility to only submit items that are in view.
|
||||
// The clipper calculates the range of visible items and advance the cursor to compensate for the non-visible items we have skipped.
|
||||
// (Dear ImGui already clip items based on their bounds but it needs to measure text size to do so, whereas manual coarse clipping before submission makes this cost and your own data fetching/submission cost almost null)
|
||||
// (Dear ImGui already clip items based on their bounds but: it needs to first layout the item to do so, and generally
|
||||
// fetching/submitting your own data incurs additional cost. Coarse clipping using ImGuiListClipper allows you to easily
|
||||
// scale using lists with tens of thousands of items without a problem)
|
||||
// Usage:
|
||||
// ImGuiListClipper clipper;
|
||||
// clipper.Begin(1000); // We have 1000 elements, evenly spaced.
|
||||
@ -2182,30 +2185,30 @@ struct ImGuiStorage
|
||||
// ImGui::Text("line number %d", i);
|
||||
// Generally what happens is:
|
||||
// - Clipper lets you process the first element (DisplayStart = 0, DisplayEnd = 1) regardless of it being visible or not.
|
||||
// - User code submit one element.
|
||||
// - User code submit that one element.
|
||||
// - Clipper can measure the height of the first element
|
||||
// - Clipper calculate the actual range of elements to display based on the current clipping rectangle, position the cursor before the first visible element.
|
||||
// - User code submit visible elements.
|
||||
// - The clipper also handles various subtleties related to keyboard/gamepad navigation, wrapping etc.
|
||||
struct ImGuiListClipper
|
||||
{
|
||||
int DisplayStart;
|
||||
int DisplayEnd;
|
||||
|
||||
// [Internal]
|
||||
int ItemsCount;
|
||||
int StepNo;
|
||||
int ItemsFrozen;
|
||||
float ItemsHeight;
|
||||
float StartPosY;
|
||||
|
||||
IMGUI_API ImGuiListClipper();
|
||||
IMGUI_API ~ImGuiListClipper();
|
||||
int DisplayStart; // First item to display, updated by each call to Step()
|
||||
int DisplayEnd; // End of items to display (exclusive)
|
||||
int ItemsCount; // [Internal] Number of items
|
||||
float ItemsHeight; // [Internal] Height of item after a first step and item submission can calculate it
|
||||
float StartPosY; // [Internal] Cursor position at the time of Begin() or after table frozen rows are all processed
|
||||
void* TempData; // [Internal] Internal data
|
||||
|
||||
// items_count: Use INT_MAX if you don't know how many items you have (in which case the cursor won't be advanced in the final step)
|
||||
// items_height: Use -1.0f to be calculated automatically on first step. Otherwise pass in the distance between your items, typically GetTextLineHeightWithSpacing() or GetFrameHeightWithSpacing().
|
||||
IMGUI_API void Begin(int items_count, float items_height = -1.0f); // Automatically called by constructor if you passed 'items_count' or by Step() in Step 1.
|
||||
IMGUI_API void End(); // Automatically called on the last call of Step() that returns false.
|
||||
IMGUI_API bool Step(); // Call until it returns false. The DisplayStart/DisplayEnd fields will be set and you can process/draw those items.
|
||||
IMGUI_API ImGuiListClipper();
|
||||
IMGUI_API ~ImGuiListClipper();
|
||||
IMGUI_API void Begin(int items_count, float items_height = -1.0f);
|
||||
IMGUI_API void End(); // Automatically called on the last call of Step() that returns false.
|
||||
IMGUI_API bool Step(); // Call until it returns false. The DisplayStart/DisplayEnd fields will be set and you can process/draw those items.
|
||||
|
||||
// Call ForceDisplayRangeByIndices() before first call to Step() if you need a range of items to be displayed regardless of visibility.
|
||||
IMGUI_API void ForceDisplayRangeByIndices(int item_min, int item_max); // item_max is exclusive e.g. use (42, 42+1) to make item 42 always visible BUT due to alignment/padding of certain items it is likely that an extra item may be included on either end of the display range.
|
||||
|
||||
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
|
||||
inline ImGuiListClipper(int items_count, float items_height = -1.0f) { memset(this, 0, sizeof(*this)); ItemsCount = -1; Begin(items_count, items_height); } // [removed in 1.79]
|
||||
@ -2828,6 +2831,8 @@ struct ImGuiViewport
|
||||
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
|
||||
namespace ImGui
|
||||
{
|
||||
// OBSOLETED in 1.86 (from November 2021)
|
||||
IMGUI_API void CalcListClipping(int items_count, float items_height, int* out_items_display_start, int* out_items_display_end); // Calculate coarse clipping for large list of evenly sized items. Prefer using ImGuiListClipper.
|
||||
// OBSOLETED in 1.85 (from August 2021)
|
||||
static inline float GetWindowContentRegionWidth() { return GetWindowContentRegionMax().x - GetWindowContentRegionMin().x; }
|
||||
// OBSOLETED in 1.81 (from February 2021)
|
||||
|
235
imgui_demo.cpp
235
imgui_demo.cpp
File diff suppressed because it is too large
Load Diff
@ -1,4 +1,4 @@
|
||||
// dear imgui, v1.85
|
||||
// dear imgui, v1.86
|
||||
// (drawing and font code)
|
||||
|
||||
/*
|
||||
@ -473,6 +473,7 @@ void ImDrawList::_PopUnusedDrawCmd()
|
||||
|
||||
void ImDrawList::AddCallback(ImDrawCallback callback, void* callback_data)
|
||||
{
|
||||
IM_ASSERT_PARANOID(CmdBuffer.Size > 0);
|
||||
ImDrawCmd* curr_cmd = &CmdBuffer.Data[CmdBuffer.Size - 1];
|
||||
IM_ASSERT(curr_cmd->UserCallback == NULL);
|
||||
if (curr_cmd->ElemCount != 0)
|
||||
@ -494,6 +495,7 @@ void ImDrawList::AddCallback(ImDrawCallback callback, void* callback_data)
|
||||
// Try to merge two last draw commands
|
||||
void ImDrawList::_TryMergeDrawCmds()
|
||||
{
|
||||
IM_ASSERT_PARANOID(CmdBuffer.Size > 0);
|
||||
ImDrawCmd* curr_cmd = &CmdBuffer.Data[CmdBuffer.Size - 1];
|
||||
ImDrawCmd* prev_cmd = curr_cmd - 1;
|
||||
if (ImDrawCmd_HeaderCompare(curr_cmd, prev_cmd) == 0 && curr_cmd->UserCallback == NULL && prev_cmd->UserCallback == NULL)
|
||||
@ -508,6 +510,7 @@ void ImDrawList::_TryMergeDrawCmds()
|
||||
void ImDrawList::_OnChangedClipRect()
|
||||
{
|
||||
// If current command is used with different settings we need to add a new command
|
||||
IM_ASSERT_PARANOID(CmdBuffer.Size > 0);
|
||||
ImDrawCmd* curr_cmd = &CmdBuffer.Data[CmdBuffer.Size - 1];
|
||||
if (curr_cmd->ElemCount != 0 && memcmp(&curr_cmd->ClipRect, &_CmdHeader.ClipRect, sizeof(ImVec4)) != 0)
|
||||
{
|
||||
@ -530,6 +533,7 @@ void ImDrawList::_OnChangedClipRect()
|
||||
void ImDrawList::_OnChangedTextureID()
|
||||
{
|
||||
// If current command is used with different settings we need to add a new command
|
||||
IM_ASSERT_PARANOID(CmdBuffer.Size > 0);
|
||||
ImDrawCmd* curr_cmd = &CmdBuffer.Data[CmdBuffer.Size - 1];
|
||||
if (curr_cmd->ElemCount != 0 && curr_cmd->TextureId != _CmdHeader.TextureId)
|
||||
{
|
||||
@ -553,6 +557,7 @@ void ImDrawList::_OnChangedVtxOffset()
|
||||
{
|
||||
// We don't need to compare curr_cmd->VtxOffset != _CmdHeader.VtxOffset because we know it'll be different at the time we call this.
|
||||
_VtxCurrentIdx = 0;
|
||||
IM_ASSERT_PARANOID(CmdBuffer.Size > 0);
|
||||
ImDrawCmd* curr_cmd = &CmdBuffer.Data[CmdBuffer.Size - 1];
|
||||
//IM_ASSERT(curr_cmd->VtxOffset != _CmdHeader.VtxOffset); // See #3349
|
||||
if (curr_cmd->ElemCount != 0)
|
||||
@ -1919,37 +1924,38 @@ ImFontConfig::ImFontConfig()
|
||||
|
||||
// A work of art lies ahead! (. = white layer, X = black layer, others are blank)
|
||||
// The 2x2 white texels on the top left are the ones we'll use everywhere in Dear ImGui to render filled shapes.
|
||||
const int FONT_ATLAS_DEFAULT_TEX_DATA_W = 108; // Actual texture will be 2 times that + 1 spacing.
|
||||
// (This is used when io.MouseDrawCursor = true)
|
||||
const int FONT_ATLAS_DEFAULT_TEX_DATA_W = 122; // Actual texture will be 2 times that + 1 spacing.
|
||||
const int FONT_ATLAS_DEFAULT_TEX_DATA_H = 27;
|
||||
static const char FONT_ATLAS_DEFAULT_TEX_DATA_PIXELS[FONT_ATLAS_DEFAULT_TEX_DATA_W * FONT_ATLAS_DEFAULT_TEX_DATA_H + 1] =
|
||||
{
|
||||
"..- -XXXXXXX- X - X -XXXXXXX - XXXXXXX- XX "
|
||||
"..- -X.....X- X.X - X.X -X.....X - X.....X- X..X "
|
||||
"--- -XXX.XXX- X...X - X...X -X....X - X....X- X..X "
|
||||
"X - X.X - X.....X - X.....X -X...X - X...X- X..X "
|
||||
"XX - X.X -X.......X- X.......X -X..X.X - X.X..X- X..X "
|
||||
"X.X - X.X -XXXX.XXXX- XXXX.XXXX -X.X X.X - X.X X.X- X..XXX "
|
||||
"X..X - X.X - X.X - X.X -XX X.X - X.X XX- X..X..XXX "
|
||||
"X...X - X.X - X.X - XX X.X XX - X.X - X.X - X..X..X..XX "
|
||||
"X....X - X.X - X.X - X.X X.X X.X - X.X - X.X - X..X..X..X.X "
|
||||
"X.....X - X.X - X.X - X..X X.X X..X - X.X - X.X -XXX X..X..X..X..X"
|
||||
"X......X - X.X - X.X - X...XXXXXX.XXXXXX...X - X.X XX-XX X.X -X..XX........X..X"
|
||||
"X.......X - X.X - X.X -X.....................X- X.X X.X-X.X X.X -X...X...........X"
|
||||
"X........X - X.X - X.X - X...XXXXXX.XXXXXX...X - X.X..X-X..X.X - X..............X"
|
||||
"X.........X -XXX.XXX- X.X - X..X X.X X..X - X...X-X...X - X.............X"
|
||||
"X..........X-X.....X- X.X - X.X X.X X.X - X....X-X....X - X.............X"
|
||||
"X......XXXXX-XXXXXXX- X.X - XX X.X XX - X.....X-X.....X - X............X"
|
||||
"X...X..X --------- X.X - X.X - XXXXXXX-XXXXXXX - X...........X "
|
||||
"X..X X..X - -XXXX.XXXX- XXXX.XXXX ------------------------------------- X..........X "
|
||||
"X.X X..X - -X.......X- X.......X - XX XX - - X..........X "
|
||||
"XX X..X - - X.....X - X.....X - X.X X.X - - X........X "
|
||||
" X..X - X...X - X...X - X..X X..X - - X........X "
|
||||
" XX - X.X - X.X - X...XXXXXXXXXXXXX...X - - XXXXXXXXXX "
|
||||
"------------ - X - X -X.....................X- ------------------"
|
||||
" ----------------------------------- X...XXXXXXXXXXXXX...X - "
|
||||
" - X..X X..X - "
|
||||
" - X.X X.X - "
|
||||
" - XX XX - "
|
||||
"..- -XXXXXXX- X - X -XXXXXXX - XXXXXXX- XX - XX XX "
|
||||
"..- -X.....X- X.X - X.X -X.....X - X.....X- X..X -X..X X..X"
|
||||
"--- -XXX.XXX- X...X - X...X -X....X - X....X- X..X -X...X X...X"
|
||||
"X - X.X - X.....X - X.....X -X...X - X...X- X..X - X...X X...X "
|
||||
"XX - X.X -X.......X- X.......X -X..X.X - X.X..X- X..X - X...X...X "
|
||||
"X.X - X.X -XXXX.XXXX- XXXX.XXXX -X.X X.X - X.X X.X- X..XXX - X.....X "
|
||||
"X..X - X.X - X.X - X.X -XX X.X - X.X XX- X..X..XXX - X...X "
|
||||
"X...X - X.X - X.X - XX X.X XX - X.X - X.X - X..X..X..XX - X.X "
|
||||
"X....X - X.X - X.X - X.X X.X X.X - X.X - X.X - X..X..X..X.X - X...X "
|
||||
"X.....X - X.X - X.X - X..X X.X X..X - X.X - X.X -XXX X..X..X..X..X- X.....X "
|
||||
"X......X - X.X - X.X - X...XXXXXX.XXXXXX...X - X.X XX-XX X.X -X..XX........X..X- X...X...X "
|
||||
"X.......X - X.X - X.X -X.....................X- X.X X.X-X.X X.X -X...X...........X- X...X X...X "
|
||||
"X........X - X.X - X.X - X...XXXXXX.XXXXXX...X - X.X..X-X..X.X - X..............X-X...X X...X"
|
||||
"X.........X -XXX.XXX- X.X - X..X X.X X..X - X...X-X...X - X.............X-X..X X..X"
|
||||
"X..........X-X.....X- X.X - X.X X.X X.X - X....X-X....X - X.............X- XX XX "
|
||||
"X......XXXXX-XXXXXXX- X.X - XX X.X XX - X.....X-X.....X - X............X--------------"
|
||||
"X...X..X --------- X.X - X.X - XXXXXXX-XXXXXXX - X...........X - "
|
||||
"X..X X..X - -XXXX.XXXX- XXXX.XXXX ------------------------------------- X..........X - "
|
||||
"X.X X..X - -X.......X- X.......X - XX XX - - X..........X - "
|
||||
"XX X..X - - X.....X - X.....X - X.X X.X - - X........X - "
|
||||
" X..X - - X...X - X...X - X..X X..X - - X........X - "
|
||||
" XX - - X.X - X.X - X...XXXXXXXXXXXXX...X - - XXXXXXXXXX - "
|
||||
"------------- - X - X -X.....................X- ------------------- "
|
||||
" ----------------------------------- X...XXXXXXXXXXXXX...X - "
|
||||
" - X..X X..X - "
|
||||
" - X.X X.X - "
|
||||
" - XX XX - "
|
||||
};
|
||||
|
||||
static const ImVec2 FONT_ATLAS_DEFAULT_TEX_CURSOR_DATA[ImGuiMouseCursor_COUNT][3] =
|
||||
@ -1963,6 +1969,7 @@ static const ImVec2 FONT_ATLAS_DEFAULT_TEX_CURSOR_DATA[ImGuiMouseCursor_COUNT][3
|
||||
{ ImVec2(73,0), ImVec2(17,17), ImVec2( 8, 8) }, // ImGuiMouseCursor_ResizeNESW
|
||||
{ ImVec2(55,0), ImVec2(17,17), ImVec2( 8, 8) }, // ImGuiMouseCursor_ResizeNWSE
|
||||
{ ImVec2(91,0), ImVec2(17,22), ImVec2( 5, 0) }, // ImGuiMouseCursor_Hand
|
||||
{ ImVec2(109,0),ImVec2(13,15), ImVec2( 6, 7) }, // ImGuiMouseCursor_NotAllowed
|
||||
};
|
||||
|
||||
ImFontAtlas::ImFontAtlas()
|
||||
@ -3073,8 +3080,8 @@ void ImFontGlyphRangesBuilder::AddText(const char* text, const char* text_end)
|
||||
void ImFontGlyphRangesBuilder::AddRanges(const ImWchar* ranges)
|
||||
{
|
||||
for (; ranges[0]; ranges += 2)
|
||||
for (ImWchar c = ranges[0]; c <= ranges[1]; c++)
|
||||
AddChar(c);
|
||||
for (unsigned int c = ranges[0]; c <= ranges[1] && c <= IM_UNICODE_CODEPOINT_MAX; c++) //-V560
|
||||
AddChar((ImWchar)c);
|
||||
}
|
||||
|
||||
void ImFontGlyphRangesBuilder::BuildRanges(ImVector<ImWchar>* out_ranges)
|
||||
@ -3899,10 +3906,10 @@ void ImGui::RenderRectFilledWithHole(ImDrawList* draw_list, ImRect outer, ImRect
|
||||
const bool fill_R = (inner.Max.x < outer.Max.x);
|
||||
const bool fill_U = (inner.Min.y > outer.Min.y);
|
||||
const bool fill_D = (inner.Max.y < outer.Max.y);
|
||||
if (fill_L) draw_list->AddRectFilled(ImVec2(outer.Min.x, inner.Min.y), ImVec2(inner.Min.x, inner.Max.y), col, rounding, (fill_U ? 0 : ImDrawFlags_RoundCornersTopLeft) | (fill_D ? 0 : ImDrawFlags_RoundCornersBottomLeft));
|
||||
if (fill_R) draw_list->AddRectFilled(ImVec2(inner.Max.x, inner.Min.y), ImVec2(outer.Max.x, inner.Max.y), col, rounding, (fill_U ? 0 : ImDrawFlags_RoundCornersTopRight) | (fill_D ? 0 : ImDrawFlags_RoundCornersBottomRight));
|
||||
if (fill_U) draw_list->AddRectFilled(ImVec2(inner.Min.x, outer.Min.y), ImVec2(inner.Max.x, inner.Min.y), col, rounding, (fill_L ? 0 : ImDrawFlags_RoundCornersTopLeft) | (fill_R ? 0 : ImDrawFlags_RoundCornersTopRight));
|
||||
if (fill_D) draw_list->AddRectFilled(ImVec2(inner.Min.x, inner.Max.y), ImVec2(inner.Max.x, outer.Max.y), col, rounding, (fill_L ? 0 : ImDrawFlags_RoundCornersBottomLeft) | (fill_R ? 0 : ImDrawFlags_RoundCornersBottomRight));
|
||||
if (fill_L) draw_list->AddRectFilled(ImVec2(outer.Min.x, inner.Min.y), ImVec2(inner.Min.x, inner.Max.y), col, rounding, ImDrawFlags_RoundCornersNone | (fill_U ? 0 : ImDrawFlags_RoundCornersTopLeft) | (fill_D ? 0 : ImDrawFlags_RoundCornersBottomLeft));
|
||||
if (fill_R) draw_list->AddRectFilled(ImVec2(inner.Max.x, inner.Min.y), ImVec2(outer.Max.x, inner.Max.y), col, rounding, ImDrawFlags_RoundCornersNone | (fill_U ? 0 : ImDrawFlags_RoundCornersTopRight) | (fill_D ? 0 : ImDrawFlags_RoundCornersBottomRight));
|
||||
if (fill_U) draw_list->AddRectFilled(ImVec2(inner.Min.x, outer.Min.y), ImVec2(inner.Max.x, inner.Min.y), col, rounding, ImDrawFlags_RoundCornersNone | (fill_L ? 0 : ImDrawFlags_RoundCornersTopLeft) | (fill_R ? 0 : ImDrawFlags_RoundCornersTopRight));
|
||||
if (fill_D) draw_list->AddRectFilled(ImVec2(inner.Min.x, inner.Max.y), ImVec2(inner.Max.x, outer.Max.y), col, rounding, ImDrawFlags_RoundCornersNone | (fill_L ? 0 : ImDrawFlags_RoundCornersBottomLeft) | (fill_R ? 0 : ImDrawFlags_RoundCornersBottomRight));
|
||||
if (fill_L && fill_U) draw_list->AddRectFilled(ImVec2(outer.Min.x, outer.Min.y), ImVec2(inner.Min.x, inner.Min.y), col, rounding, ImDrawFlags_RoundCornersTopLeft);
|
||||
if (fill_R && fill_U) draw_list->AddRectFilled(ImVec2(inner.Max.x, outer.Min.y), ImVec2(outer.Max.x, inner.Min.y), col, rounding, ImDrawFlags_RoundCornersTopRight);
|
||||
if (fill_L && fill_D) draw_list->AddRectFilled(ImVec2(outer.Min.x, inner.Max.y), ImVec2(inner.Min.x, outer.Max.y), col, rounding, ImDrawFlags_RoundCornersBottomLeft);
|
||||
|
145
imgui_internal.h
145
imgui_internal.h
@ -1,4 +1,4 @@
|
||||
// dear imgui, v1.85
|
||||
// dear imgui, v1.86
|
||||
// (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!
|
||||
@ -18,6 +18,7 @@ Index of this file:
|
||||
// [SECTION] Generic helpers
|
||||
// [SECTION] ImDrawList support
|
||||
// [SECTION] Widgets support: flags, enums, data structures
|
||||
// [SECTION] Clipper support
|
||||
// [SECTION] Navigation support
|
||||
// [SECTION] Columns support
|
||||
// [SECTION] Multi-select support
|
||||
@ -252,12 +253,19 @@ namespace ImStb
|
||||
#endif
|
||||
|
||||
// Debug Tools
|
||||
// Use 'Metrics->Tools->Item Picker' to break into the call-stack of a specific item.
|
||||
// Use 'Metrics/Debugger->Tools->Item Picker' to break into the call-stack of a specific item.
|
||||
// This will call IM_DEBUG_BREAK() which you may redefine yourself. See https://github.com/scottt/debugbreak for more reference.
|
||||
#ifndef IM_DEBUG_BREAK
|
||||
#if defined(__clang__)
|
||||
#define IM_DEBUG_BREAK() __builtin_debugtrap()
|
||||
#elif defined (_MSC_VER)
|
||||
#if defined (_MSC_VER)
|
||||
#define IM_DEBUG_BREAK() __debugbreak()
|
||||
#elif defined(__clang__)
|
||||
#define IM_DEBUG_BREAK() __builtin_debugtrap()
|
||||
#elif defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
|
||||
#define IM_DEBUG_BREAK() __asm__ volatile("int $0x03")
|
||||
#elif defined(__GNUC__) && defined(__thumb__)
|
||||
#define IM_DEBUG_BREAK() __asm__ volatile(".inst 0xde01")
|
||||
#elif defined(__GNUC__) && defined(__arm__) && !defined(__thumb__)
|
||||
#define IM_DEBUG_BREAK() __asm__ volatile(".inst 0xe7f001f0");
|
||||
#else
|
||||
#define IM_DEBUG_BREAK() IM_ASSERT(0) // It is expected that you define IM_DEBUG_BREAK() into something that will break nicely in a debugger!
|
||||
#endif
|
||||
@ -294,7 +302,9 @@ static inline ImGuiID ImHash(const void* data, int size, ImU32 seed = 0) { ret
|
||||
#endif
|
||||
|
||||
// Helpers: Sorting
|
||||
#define ImQsort qsort
|
||||
#ifndef ImQsort
|
||||
static inline void ImQsort(void* base, size_t count, size_t size_of_element, int(IMGUI_CDECL *compare_func)(void const*, void const*)) { if (count > 1) qsort(base, count, size_of_element, compare_func); }
|
||||
#endif
|
||||
|
||||
// Helpers: Color Blending
|
||||
IMGUI_API ImU32 ImAlphaBlendColors(ImU32 col_a, ImU32 col_b);
|
||||
@ -401,8 +411,8 @@ 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); }
|
||||
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
|
||||
@ -438,6 +448,7 @@ static inline float ImDot(const ImVec2& a, const ImVec2& b)
|
||||
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); }
|
||||
static inline bool ImIsFloatAboveGuaranteedIntegerPrecision(float f) { return f <= -16777216 || f >= 16777216; }
|
||||
IM_MSVC_RUNTIME_CHECKS_RESTORE
|
||||
|
||||
// Helpers: Geometry
|
||||
@ -1019,8 +1030,6 @@ struct IMGUI_API ImGuiInputTextState
|
||||
bool SelectedAllMouseLock; // after a double-click to select all, we ignore further mouse drags to update selection
|
||||
bool Edited; // edited this frame
|
||||
ImGuiInputTextFlags Flags; // copy of InputText() flags
|
||||
ImGuiInputTextCallback UserCallback; // "
|
||||
void* UserCallbackData; // "
|
||||
|
||||
ImGuiInputTextState() { memset(this, 0, sizeof(*this)); }
|
||||
void ClearText() { CurLenW = CurLenA = 0; TextW[0] = 0; TextA[0] = 0; CursorClamp(); }
|
||||
@ -1162,6 +1171,35 @@ struct ImGuiPtrOrIndex
|
||||
ImGuiPtrOrIndex(int index) { Ptr = NULL; Index = index; }
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// [SECTION] Clipper support
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
struct ImGuiListClipperRange
|
||||
{
|
||||
int Min;
|
||||
int Max;
|
||||
bool PosToIndexConvert; // Begin/End are absolute position (will be converted to indices later)
|
||||
ImS8 PosToIndexOffsetMin; // Add to Min after converting to indices
|
||||
ImS8 PosToIndexOffsetMax; // Add to Min after converting to indices
|
||||
|
||||
static ImGuiListClipperRange FromIndices(int min, int max) { ImGuiListClipperRange r = { min, max, false, 0, 0 }; return r; }
|
||||
static ImGuiListClipperRange FromPositions(float y1, float y2, int off_min, int off_max) { ImGuiListClipperRange r = { (int)y1, (int)y2, true, (ImS8)off_min, (ImS8)off_max }; return r; }
|
||||
};
|
||||
|
||||
// Temporary clipper data, buffers shared/reused between instances
|
||||
struct ImGuiListClipperData
|
||||
{
|
||||
ImGuiListClipper* ListClipper;
|
||||
float LossynessOffset;
|
||||
int StepNo;
|
||||
int ItemsFrozen;
|
||||
ImVector<ImGuiListClipperRange> Ranges;
|
||||
|
||||
ImGuiListClipperData() { memset(this, 0, sizeof(*this)); }
|
||||
void Reset(ImGuiListClipper* clipper) { ListClipper = clipper; StepNo = ItemsFrozen = 0; Ranges.resize(0); }
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// [SECTION] Navigation support
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -1201,9 +1239,10 @@ enum ImGuiNavHighlightFlags_
|
||||
enum ImGuiNavDirSourceFlags_
|
||||
{
|
||||
ImGuiNavDirSourceFlags_None = 0,
|
||||
ImGuiNavDirSourceFlags_Keyboard = 1 << 0,
|
||||
ImGuiNavDirSourceFlags_PadDPad = 1 << 1,
|
||||
ImGuiNavDirSourceFlags_PadLStick = 1 << 2
|
||||
ImGuiNavDirSourceFlags_RawKeyboard = 1 << 0, // Raw keyboard (not pulled from nav), faciliate use of some functions before we can unify nav and keys
|
||||
ImGuiNavDirSourceFlags_Keyboard = 1 << 1,
|
||||
ImGuiNavDirSourceFlags_PadDPad = 1 << 2,
|
||||
ImGuiNavDirSourceFlags_PadLStick = 1 << 3
|
||||
};
|
||||
|
||||
enum ImGuiNavMoveFlags_
|
||||
@ -1218,9 +1257,10 @@ enum ImGuiNavMoveFlags_
|
||||
ImGuiNavMoveFlags_ScrollToEdgeY = 1 << 6, // Force scrolling to min/max (used by Home/End) // FIXME-NAV: Aim to remove or reword, probably unnecessary
|
||||
ImGuiNavMoveFlags_Forwarded = 1 << 7,
|
||||
ImGuiNavMoveFlags_DebugNoResult = 1 << 8, // Dummy scoring for debug purpose, don't apply result
|
||||
ImGuiNavMoveFlags_Tabbing = 1 << 9, // == Focus + Activate if item is Inputable + DontChangeNavHighlight
|
||||
ImGuiNavMoveFlags_Activate = 1 << 10,
|
||||
ImGuiNavMoveFlags_DontSetNavHighlight = 1 << 11 // Do not alter the visible state of keyboard vs mouse nav highlight
|
||||
ImGuiNavMoveFlags_FocusApi = 1 << 9,
|
||||
ImGuiNavMoveFlags_Tabbing = 1 << 10, // == Focus + Activate if item is Inputable + DontChangeNavHighlight
|
||||
ImGuiNavMoveFlags_Activate = 1 << 11,
|
||||
ImGuiNavMoveFlags_DontSetNavHighlight = 1 << 12 // Do not alter the visible state of keyboard vs mouse nav highlight
|
||||
};
|
||||
|
||||
enum ImGuiNavLayer
|
||||
@ -1540,6 +1580,7 @@ struct ImGuiContext
|
||||
ImVector<ImGuiGroupData>GroupStack; // Stack for BeginGroup()/EndGroup() - not inherited by Begin()
|
||||
ImVector<ImGuiPopupData>OpenPopupStack; // Which popups are open (persistent)
|
||||
ImVector<ImGuiPopupData>BeginPopupStack; // Which level of BeginPopup() we are in (reset every frame)
|
||||
int BeginMenuCount;
|
||||
|
||||
// Viewports
|
||||
ImVector<ImGuiViewportP*> Viewports; // Active viewports (Size==1 in 'master' branch). Each viewports hold their copy of ImDrawData.
|
||||
@ -1553,7 +1594,6 @@ struct ImGuiContext
|
||||
ImGuiID NavActivatePressedId; // ~~ IsNavInputPressed(ImGuiNavInput_Activate) ? NavId : 0
|
||||
ImGuiID NavActivateInputId; // ~~ IsNavInputPressed(ImGuiNavInput_Input) ? NavId : 0; ImGuiActivateFlags_PreferInput will be set and NavActivateId will be 0.
|
||||
ImGuiActivateFlags NavActivateFlags;
|
||||
ImGuiID NavJustTabbedId; // Just tabbed to this id.
|
||||
ImGuiID NavJustMovedToId; // Just navigated to this id (result of a successfully MoveRequest).
|
||||
ImGuiID NavJustMovedToFocusScopeId; // Just navigated to this focus scope id (result of a successfully MoveRequest).
|
||||
ImGuiKeyModFlags NavJustMovedToKeyMods;
|
||||
@ -1561,7 +1601,6 @@ struct ImGuiContext
|
||||
ImGuiActivateFlags NavNextActivateFlags;
|
||||
ImGuiInputSource NavInputSource; // Keyboard or Gamepad mode? THIS WILL ONLY BE None or NavGamepad or NavKeyboard.
|
||||
ImGuiNavLayer NavLayer; // Layer we are navigating on. For now the system is hard-coded for 0=main contents and 1=menu/title bar, may expose layers later.
|
||||
int NavIdTabCounter; // == NavWindow->DC.FocusIdxTabCounter at time of NavId processing
|
||||
bool NavIdIsAlive; // Nav widget has been seen this frame ~~ NavRectRel is valid
|
||||
bool NavMousePosDirty; // When set we will update mouse position if (io.ConfigFlags & ImGuiConfigFlags_NavEnableSetMousePos) if set (NB: this not enabled by default)
|
||||
bool NavDisableHighlight; // When user starts using mouse, we hide gamepad/keyboard highlight (NB: but they are still available, which is why NavDisableHighlight isn't always != NavDisableMouseHover)
|
||||
@ -1583,11 +1622,14 @@ struct ImGuiContext
|
||||
ImGuiDir NavMoveDirForDebug;
|
||||
ImGuiDir NavMoveClipDir; // FIXME-NAV: Describe the purpose of this better. Might want to rename?
|
||||
ImRect NavScoringRect; // Rectangle used for scoring, in screen space. Based of window->NavRectRel[], modified for directional navigation scoring.
|
||||
ImRect NavScoringNoClipRect; // Some nav operations (such as PageUp/PageDown) enforce a region which clipper will attempt to always keep submitted
|
||||
int NavScoringDebugCount; // Metrics for debugging
|
||||
int NavTabbingInputableRemaining; // >0 when counting items for tabbing
|
||||
int NavTabbingDir; // Generally -1 or +1, 0 when tabbing without a nav id
|
||||
int NavTabbingCounter; // >0 when counting items for tabbing
|
||||
ImGuiNavItemData NavMoveResultLocal; // Best move request candidate within NavWindow
|
||||
ImGuiNavItemData NavMoveResultLocalVisible; // 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)
|
||||
ImGuiNavItemData NavTabbingResultFirst; // First tabbing request candidate within NavWindow and flattened hierarchy
|
||||
|
||||
// Navigation: Windowing (CTRL+TAB for list, or Menu button + keys or directional pads to move/resize)
|
||||
ImGuiWindow* NavWindowingTarget; // Target window when doing CTRL+Tab (or Pad Menu + FocusPrev/Next), this window is temporarily displayed top-most!
|
||||
@ -1597,13 +1639,6 @@ struct ImGuiContext
|
||||
float NavWindowingHighlightAlpha;
|
||||
bool NavWindowingToggleLayer;
|
||||
|
||||
// Legacy Focus/Tabbing system (older than Nav, active even if Nav is disabled, misnamed. FIXME-NAV: This needs a redesign!)
|
||||
ImGuiWindow* TabFocusRequestCurrWindow; //
|
||||
ImGuiWindow* TabFocusRequestNextWindow; //
|
||||
int TabFocusRequestCurrCounterTabStop; // Tab item being requested for focus, stored as an index
|
||||
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)
|
||||
ImGuiMouseCursor MouseCursor;
|
||||
@ -1627,11 +1662,15 @@ struct ImGuiContext
|
||||
ImVector<unsigned char> DragDropPayloadBufHeap; // We don't expose the ImVector<> directly, ImGuiPayload only holds pointer+size
|
||||
unsigned char DragDropPayloadBufLocal[16]; // Local buffer for small payloads
|
||||
|
||||
// Clipper
|
||||
int ClipperTempDataStacked;
|
||||
ImVector<ImGuiListClipperData> ClipperTempData;
|
||||
|
||||
// Table
|
||||
ImGuiTable* CurrentTable;
|
||||
int CurrentTableStackIdx;
|
||||
ImPool<ImGuiTable> Tables;
|
||||
ImVector<ImGuiTableTempData> TablesTempDataStack;
|
||||
int TablesTempDataStacked; // Temporary table data size (because we leave previous instances undestructed, we generally don't use TablesTempData.Size)
|
||||
ImVector<ImGuiTableTempData> TablesTempData; // Temporary table data (buffers reused/shared across instances, support nesting)
|
||||
ImPool<ImGuiTable> Tables; // Persistent table data
|
||||
ImVector<float> TablesLastTimeActive; // Last used timestamp of each tables (SOA, for efficient GC)
|
||||
ImVector<ImDrawChannel> DrawChannelsTempMergeBuffer;
|
||||
|
||||
@ -1763,15 +1802,15 @@ struct ImGuiContext
|
||||
LastActiveIdTimer = 0.0f;
|
||||
|
||||
CurrentItemFlags = ImGuiItemFlags_None;
|
||||
BeginMenuCount = 0;
|
||||
|
||||
NavWindow = NULL;
|
||||
NavId = NavFocusScopeId = NavActivateId = NavActivateDownId = NavActivatePressedId = NavActivateInputId = 0;
|
||||
NavJustTabbedId = NavJustMovedToId = NavJustMovedToFocusScopeId = NavNextActivateId = 0;
|
||||
NavJustMovedToId = NavJustMovedToFocusScopeId = NavNextActivateId = 0;
|
||||
NavActivateFlags = NavNextActivateFlags = ImGuiActivateFlags_None;
|
||||
NavJustMovedToKeyMods = ImGuiKeyModFlags_None;
|
||||
NavInputSource = ImGuiInputSource_None;
|
||||
NavLayer = ImGuiNavLayer_Main;
|
||||
NavIdTabCounter = INT_MAX;
|
||||
NavIdIsAlive = false;
|
||||
NavMousePosDirty = false;
|
||||
NavDisableHighlight = true;
|
||||
@ -1788,17 +1827,13 @@ struct ImGuiContext
|
||||
NavMoveKeyMods = ImGuiKeyModFlags_None;
|
||||
NavMoveDir = NavMoveDirForDebug = NavMoveClipDir = ImGuiDir_None;
|
||||
NavScoringDebugCount = 0;
|
||||
NavTabbingInputableRemaining = 0;
|
||||
NavTabbingDir = 0;
|
||||
NavTabbingCounter = 0;
|
||||
|
||||
NavWindowingTarget = NavWindowingTargetAnim = NavWindowingListWindow = NULL;
|
||||
NavWindowingTimer = NavWindowingHighlightAlpha = 0.0f;
|
||||
NavWindowingToggleLayer = false;
|
||||
|
||||
TabFocusRequestCurrWindow = TabFocusRequestNextWindow = NULL;
|
||||
TabFocusRequestCurrCounterTabStop = INT_MAX;
|
||||
TabFocusRequestNextCounterTabStop = INT_MAX;
|
||||
TabFocusPressed = false;
|
||||
|
||||
DimBgRatio = 0.0f;
|
||||
MouseCursor = ImGuiMouseCursor_Arrow;
|
||||
|
||||
@ -1814,8 +1849,10 @@ struct ImGuiContext
|
||||
DragDropHoldJustPressedId = 0;
|
||||
memset(DragDropPayloadBufLocal, 0, sizeof(DragDropPayloadBufLocal));
|
||||
|
||||
ClipperTempDataStacked = 0;
|
||||
|
||||
CurrentTable = NULL;
|
||||
CurrentTableStackIdx = -1;
|
||||
TablesTempDataStacked = 0;
|
||||
CurrentTabBar = NULL;
|
||||
|
||||
TempInputId = 0;
|
||||
@ -1882,6 +1919,7 @@ struct IMGUI_API ImGuiWindowTempData
|
||||
ImVec1 Indent; // Indentation / start position from left of window (increased by TreePush/TreePop, etc.)
|
||||
ImVec1 ColumnsOffset; // Offset to the current column (if ColumnsCurrent > 0). FIXME: This and the above should be a stack to allow use cases like Tree->Column->Tree. Need revamp columns API.
|
||||
ImVec1 GroupOffset;
|
||||
ImVec2 CursorStartPosLossyness;// Record the loss of precision of CursorStartPos due to really large scrolling amount. This is used by clipper to compensentate and fix the most common use case of large scroll area.
|
||||
|
||||
// Keyboard/Gamepad navigation
|
||||
ImGuiNavLayer NavLayerCurrent; // Current layer, 0..31 (we currently only use 0..1)
|
||||
@ -1903,7 +1941,6 @@ struct IMGUI_API ImGuiWindowTempData
|
||||
int CurrentTableIdx; // Current table index (into g.Tables)
|
||||
ImGuiLayoutType LayoutType;
|
||||
ImGuiLayoutType ParentLayoutType; // Layout type of parent window at the time of Begin()
|
||||
int FocusCounterTabStop; // (Legacy Focus/Tabbing system) Same, but only count widgets which you can Tab through.
|
||||
|
||||
// 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.
|
||||
@ -1947,6 +1984,7 @@ struct IMGUI_API ImGuiWindow
|
||||
bool Appearing; // Set during the frame where the window is appearing (or re-appearing)
|
||||
bool Hidden; // Do not display (== HiddenFrames*** > 0)
|
||||
bool IsFallbackWindow; // Set on the "Debug##Default" window.
|
||||
bool IsExplicitChild; // Set when passed _ChildWindow, left to false by BeginDocked()
|
||||
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)
|
||||
@ -1994,6 +2032,7 @@ struct IMGUI_API ImGuiWindow
|
||||
ImDrawList* DrawList; // == &DrawListInst (for backward compatibility reason with code using imgui_internal.h we keep this a pointer)
|
||||
ImDrawList DrawListInst;
|
||||
ImGuiWindow* ParentWindow; // If we are a child _or_ popup _or_ docked window, this is pointing to our parent. Otherwise NULL.
|
||||
ImGuiWindow* ParentWindowInBeginStack;
|
||||
ImGuiWindow* RootWindow; // Point to ourself or first ancestor that is not a child window. Doesn't cross through popups/dock nodes.
|
||||
ImGuiWindow* RootWindowPopupTree; // Point to ourself or first ancestor that is not a child window. Cross through popups parent<>child.
|
||||
ImGuiWindow* RootWindowForTitleBarHighlight; // Point to ourself or first ancestor which will display TitleBgActive color when this window is active.
|
||||
@ -2067,7 +2106,7 @@ struct ImGuiTabItem
|
||||
};
|
||||
|
||||
// Storage for a tab bar (sizeof() 152 bytes)
|
||||
struct ImGuiTabBar
|
||||
struct IMGUI_API ImGuiTabBar
|
||||
{
|
||||
ImVector<ImGuiTabItem> Tabs;
|
||||
ImGuiTabBarFlags Flags;
|
||||
@ -2192,7 +2231,7 @@ struct ImGuiTableCellData
|
||||
};
|
||||
|
||||
// FIXME-TABLE: more transient data could be stored in a per-stacked table structure: DrawSplitter, SortSpecs, incoming RowData
|
||||
struct ImGuiTable
|
||||
struct IMGUI_API ImGuiTable
|
||||
{
|
||||
ImGuiID ID;
|
||||
ImGuiTableFlags Flags;
|
||||
@ -2298,14 +2337,14 @@ struct ImGuiTable
|
||||
bool MemoryCompacted;
|
||||
bool HostSkipItems; // Backup of InnerWindow->SkipItem at the end of BeginTable(), because we will overwrite InnerWindow->SkipItem on a per-column basis
|
||||
|
||||
IMGUI_API ImGuiTable() { memset(this, 0, sizeof(*this)); LastFrameActive = -1; }
|
||||
IMGUI_API ~ImGuiTable() { IM_FREE(RawData); }
|
||||
ImGuiTable() { memset(this, 0, sizeof(*this)); LastFrameActive = -1; }
|
||||
~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.
|
||||
struct ImGuiTableTempData
|
||||
struct IMGUI_API ImGuiTableTempData
|
||||
{
|
||||
int TableIndex; // Index in g.Tables.Buf[] pool
|
||||
float LastTimeActive; // Last timestamp this structure was used
|
||||
@ -2322,7 +2361,7 @@ struct ImGuiTableTempData
|
||||
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; }
|
||||
ImGuiTableTempData() { memset(this, 0, sizeof(*this)); LastTimeActive = -1.0f; }
|
||||
};
|
||||
|
||||
// sizeof() ~ 12
|
||||
@ -2382,12 +2421,15 @@ namespace ImGui
|
||||
IMGUI_API void UpdateWindowParentAndRootLinks(ImGuiWindow* window, ImGuiWindowFlags flags, ImGuiWindow* parent_window);
|
||||
IMGUI_API ImVec2 CalcWindowNextAutoFitSize(ImGuiWindow* window);
|
||||
IMGUI_API bool IsWindowChildOf(ImGuiWindow* window, ImGuiWindow* potential_parent, bool popup_hierarchy);
|
||||
IMGUI_API bool IsWindowWithinBeginStackOf(ImGuiWindow* window, ImGuiWindow* potential_parent);
|
||||
IMGUI_API bool IsWindowAbove(ImGuiWindow* potential_above, ImGuiWindow* potential_below);
|
||||
IMGUI_API bool IsWindowNavFocusable(ImGuiWindow* window);
|
||||
IMGUI_API void SetWindowPos(ImGuiWindow* window, const ImVec2& pos, ImGuiCond cond = 0);
|
||||
IMGUI_API void SetWindowSize(ImGuiWindow* window, const ImVec2& size, ImGuiCond cond = 0);
|
||||
IMGUI_API void SetWindowCollapsed(ImGuiWindow* window, bool collapsed, ImGuiCond cond = 0);
|
||||
IMGUI_API void SetWindowHitTestHole(ImGuiWindow* window, const ImVec2& pos, const ImVec2& size);
|
||||
inline ImRect WindowRectAbsToRel(ImGuiWindow* window, const ImRect& r) { ImVec2 off = window->DC.CursorStartPos; return ImRect(r.Min.x - off.x, r.Min.y - off.y, r.Max.x - off.x, r.Max.y - off.y); }
|
||||
inline ImRect WindowRectRelToAbs(ImGuiWindow* window, const ImRect& r) { ImVec2 off = window->DC.CursorStartPos; return ImRect(r.Min.x + off.x, r.Min.y + off.y, r.Max.x + off.x, r.Max.y + off.y); }
|
||||
|
||||
// Windows: Display Order and Focus Order
|
||||
IMGUI_API void FocusWindow(ImGuiWindow* window);
|
||||
@ -2395,6 +2437,9 @@ namespace ImGui
|
||||
IMGUI_API void BringWindowToFocusFront(ImGuiWindow* window);
|
||||
IMGUI_API void BringWindowToDisplayFront(ImGuiWindow* window);
|
||||
IMGUI_API void BringWindowToDisplayBack(ImGuiWindow* window);
|
||||
IMGUI_API void BringWindowToDisplayBehind(ImGuiWindow* window, ImGuiWindow* above_window);
|
||||
IMGUI_API int FindWindowDisplayIndex(ImGuiWindow* window);
|
||||
IMGUI_API ImGuiWindow* FindBottomMostVisibleWindowWithinBeginStack(ImGuiWindow* window);
|
||||
|
||||
// Fonts, drawing
|
||||
IMGUI_API void SetCurrentFont(ImFont* font);
|
||||
@ -2463,8 +2508,8 @@ namespace ImGui
|
||||
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, ImGuiItemFlags extra_flags = 0);
|
||||
IMGUI_API bool ItemHoverable(const ImRect& bb, ImGuiID id);
|
||||
IMGUI_API void ItemInputable(ImGuiWindow* window, ImGuiID id);
|
||||
IMGUI_API bool IsClippedEx(const ImRect& bb, ImGuiID id);
|
||||
IMGUI_API void SetLastItemData(ImGuiID item_id, ImGuiItemFlags in_flags, ImGuiItemStatusFlags status_flags, const ImRect& item_rect);
|
||||
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);
|
||||
@ -2501,9 +2546,10 @@ namespace ImGui
|
||||
IMGUI_API void ClosePopupsExceptModals();
|
||||
IMGUI_API bool IsPopupOpen(ImGuiID id, ImGuiPopupFlags popup_flags);
|
||||
IMGUI_API bool BeginPopupEx(ImGuiID id, ImGuiWindowFlags extra_flags);
|
||||
IMGUI_API void BeginTooltipEx(ImGuiWindowFlags extra_flags, ImGuiTooltipFlags tooltip_flags);
|
||||
IMGUI_API void BeginTooltipEx(ImGuiTooltipFlags tooltip_flags, ImGuiWindowFlags extra_window_flags);
|
||||
IMGUI_API ImRect GetPopupAllowedExtentRect(ImGuiWindow* window);
|
||||
IMGUI_API ImGuiWindow* GetTopMostPopupModal();
|
||||
IMGUI_API ImGuiWindow* GetTopMostAndVisiblePopupModal();
|
||||
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);
|
||||
|
||||
@ -2523,7 +2569,7 @@ namespace ImGui
|
||||
IMGUI_API bool NavMoveRequestButNoResultYet();
|
||||
IMGUI_API void NavMoveRequestSubmit(ImGuiDir move_dir, ImGuiDir clip_dir, ImGuiNavMoveFlags move_flags, ImGuiScrollFlags scroll_flags);
|
||||
IMGUI_API void NavMoveRequestForward(ImGuiDir move_dir, ImGuiDir clip_dir, ImGuiNavMoveFlags move_flags, ImGuiScrollFlags scroll_flags);
|
||||
IMGUI_API void NavMoveRequestResolveWithLastItem();
|
||||
IMGUI_API void NavMoveRequestResolveWithLastItem(ImGuiNavItemData* result);
|
||||
IMGUI_API void NavMoveRequestCancel();
|
||||
IMGUI_API void NavMoveRequestApplyResult();
|
||||
IMGUI_API void NavMoveRequestTryWrapping(ImGuiWindow* window, ImGuiNavMoveFlags move_flags);
|
||||
@ -2671,7 +2717,7 @@ namespace ImGui
|
||||
IMGUI_API bool CollapseButton(ImGuiID id, const ImVec2& pos);
|
||||
IMGUI_API bool ArrowButtonEx(const char* str_id, ImGuiDir dir, ImVec2 size_arg, ImGuiButtonFlags flags = 0);
|
||||
IMGUI_API void Scrollbar(ImGuiAxis axis);
|
||||
IMGUI_API bool ScrollbarEx(const ImRect& bb, ImGuiID id, ImGuiAxis axis, float* p_scroll_v, float avail_v, float contents_v, ImDrawFlags flags);
|
||||
IMGUI_API bool ScrollbarEx(const ImRect& bb, ImGuiID id, ImGuiAxis axis, ImS64* p_scroll_v, ImS64 avail_v, ImS64 contents_v, ImDrawFlags flags);
|
||||
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);
|
||||
@ -2751,6 +2797,7 @@ namespace ImGui
|
||||
IMGUI_API void DebugNodeWindow(ImGuiWindow* window, const char* label);
|
||||
IMGUI_API void DebugNodeWindowSettings(ImGuiWindowSettings* settings);
|
||||
IMGUI_API void DebugNodeWindowsList(ImVector<ImGuiWindow*>* windows, const char* label);
|
||||
IMGUI_API void DebugNodeWindowsListByBeginStackParent(ImGuiWindow** windows, int windows_size, ImGuiWindow* parent_in_begin_stack);
|
||||
IMGUI_API void DebugNodeViewport(ImGuiViewportP* viewport);
|
||||
IMGUI_API void DebugRenderViewportThumbnail(ImDrawList* draw_list, ImGuiViewportP* viewport, const ImRect& bb);
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
// dear imgui, v1.85
|
||||
// dear imgui, v1.86
|
||||
// (tables and columns code)
|
||||
|
||||
/*
|
||||
@ -340,10 +340,9 @@ bool ImGui::BeginTableEx(const char* name, ImGuiID id, int columns_count, ImG
|
||||
|
||||
// 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];
|
||||
if (++g.TablesTempDataStacked > g.TablesTempData.Size)
|
||||
g.TablesTempData.resize(g.TablesTempDataStacked, ImGuiTableTempData());
|
||||
ImGuiTableTempData* temp_data = table->TempData = &g.TablesTempData[g.TablesTempDataStacked - 1];
|
||||
temp_data->TableIndex = table_idx;
|
||||
table->DrawSplitter = &table->TempData->DrawSplitter;
|
||||
table->DrawSplitter->Clear();
|
||||
@ -1382,9 +1381,8 @@ void ImGui::EndTable()
|
||||
|
||||
// Clear or restore current table, if any
|
||||
IM_ASSERT(g.CurrentWindow == outer_window && g.CurrentTable == table);
|
||||
IM_ASSERT(g.CurrentTableStackIdx >= 0);
|
||||
g.CurrentTableStackIdx--;
|
||||
temp_data = g.CurrentTableStackIdx >= 0 ? &g.TablesTempDataStack[g.CurrentTableStackIdx] : NULL;
|
||||
IM_ASSERT(g.TablesTempDataStacked > 0);
|
||||
temp_data = (--g.TablesTempDataStacked > 0) ? &g.TablesTempData[g.TablesTempDataStacked - 1] : NULL;
|
||||
g.CurrentTable = temp_data ? g.Tables.GetByIndex(temp_data->TableIndex) : NULL;
|
||||
if (g.CurrentTable)
|
||||
{
|
||||
|
@ -1,4 +1,4 @@
|
||||
// dear imgui, v1.85
|
||||
// dear imgui, v1.86
|
||||
// (widgets code)
|
||||
|
||||
/*
|
||||
@ -564,7 +564,7 @@ bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool
|
||||
SetFocusID(id, window);
|
||||
FocusWindow(window);
|
||||
}
|
||||
if ((flags & ImGuiButtonFlags_PressedOnClick) || ((flags & ImGuiButtonFlags_PressedOnDoubleClick) && g.IO.MouseDoubleClicked[mouse_button_clicked]))
|
||||
if ((flags & ImGuiButtonFlags_PressedOnClick) || ((flags & ImGuiButtonFlags_PressedOnDoubleClick) && g.IO.MouseClickedCount[mouse_button_clicked] == 2))
|
||||
{
|
||||
pressed = true;
|
||||
if (flags & ImGuiButtonFlags_NoHoldingActiveId)
|
||||
@ -641,7 +641,7 @@ bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool
|
||||
if ((release_in || release_anywhere) && !g.DragDropActive)
|
||||
{
|
||||
// Report as pressed when releasing the mouse (this is the most common path)
|
||||
bool is_double_click_release = (flags & ImGuiButtonFlags_PressedOnDoubleClick) && g.IO.MouseDownWasDoubleClick[mouse_button];
|
||||
bool is_double_click_release = (flags & ImGuiButtonFlags_PressedOnDoubleClick) && g.IO.MouseReleased[mouse_button] && g.IO.MouseClickedLastCount[mouse_button] == 2;
|
||||
bool is_repeating_already = (flags & ImGuiButtonFlags_Repeat) && g.IO.MouseDownDurationPrev[mouse_button] >= g.IO.KeyRepeatDelay; // Repeat mode trumps <on release>
|
||||
if (!is_double_click_release && !is_repeating_already)
|
||||
pressed = true;
|
||||
@ -896,7 +896,9 @@ void ImGui::Scrollbar(ImGuiAxis axis)
|
||||
}
|
||||
float size_avail = window->InnerRect.Max[axis] - window->InnerRect.Min[axis];
|
||||
float size_contents = window->ContentSize[axis] + window->WindowPadding[axis] * 2.0f;
|
||||
ScrollbarEx(bb, id, axis, &window->Scroll[axis], size_avail, size_contents, rounding_corners);
|
||||
ImS64 scroll = (ImS64)window->Scroll[axis];
|
||||
ScrollbarEx(bb, id, axis, &scroll, (ImS64)size_avail, (ImS64)size_contents, rounding_corners);
|
||||
window->Scroll[axis] = (float)scroll;
|
||||
}
|
||||
|
||||
// Vertical/Horizontal scrollbar
|
||||
@ -905,7 +907,7 @@ void ImGui::Scrollbar(ImGuiAxis axis)
|
||||
// - We store values as normalized ratio and in a form that allows the window content to change while we are holding on a scrollbar
|
||||
// - We handle both horizontal and vertical scrollbars, which makes the terminology not ideal.
|
||||
// Still, the code should probably be made simpler..
|
||||
bool ImGui::ScrollbarEx(const ImRect& bb_frame, ImGuiID id, ImGuiAxis axis, float* p_scroll_v, float size_avail_v, float size_contents_v, ImDrawFlags flags)
|
||||
bool ImGui::ScrollbarEx(const ImRect& bb_frame, ImGuiID id, ImGuiAxis axis, ImS64* p_scroll_v, ImS64 size_avail_v, ImS64 size_contents_v, ImDrawFlags flags)
|
||||
{
|
||||
ImGuiContext& g = *GImGui;
|
||||
ImGuiWindow* window = g.CurrentWindow;
|
||||
@ -936,8 +938,8 @@ bool ImGui::ScrollbarEx(const ImRect& bb_frame, ImGuiID id, ImGuiAxis axis, floa
|
||||
// Calculate the height of our grabbable box. It generally represent the amount visible (vs the total scrollable amount)
|
||||
// But we maintain a minimum size in pixel to allow for the user to still aim inside.
|
||||
IM_ASSERT(ImMax(size_contents_v, size_avail_v) > 0.0f); // Adding this assert to check if the ImMax(XXX,1.0f) is still needed. PLEASE CONTACT ME if this triggers.
|
||||
const float win_size_v = ImMax(ImMax(size_contents_v, size_avail_v), 1.0f);
|
||||
const float grab_h_pixels = ImClamp(scrollbar_size_v * (size_avail_v / win_size_v), style.GrabMinSize, scrollbar_size_v);
|
||||
const ImS64 win_size_v = ImMax(ImMax(size_contents_v, size_avail_v), (ImS64)1);
|
||||
const float grab_h_pixels = ImClamp(scrollbar_size_v * ((float)size_avail_v / (float)win_size_v), style.GrabMinSize, scrollbar_size_v);
|
||||
const float grab_h_norm = grab_h_pixels / scrollbar_size_v;
|
||||
|
||||
// Handle input right away. None of the code of Begin() is relying on scrolling position before calling Scrollbar().
|
||||
@ -945,13 +947,13 @@ bool ImGui::ScrollbarEx(const ImRect& bb_frame, ImGuiID id, ImGuiAxis axis, floa
|
||||
bool hovered = false;
|
||||
ButtonBehavior(bb, id, &hovered, &held, ImGuiButtonFlags_NoNavFocus);
|
||||
|
||||
float scroll_max = ImMax(1.0f, size_contents_v - size_avail_v);
|
||||
float scroll_ratio = ImSaturate(*p_scroll_v / scroll_max);
|
||||
const ImS64 scroll_max = ImMax((ImS64)1, size_contents_v - size_avail_v);
|
||||
float scroll_ratio = ImSaturate((float)*p_scroll_v / (float)scroll_max);
|
||||
float grab_v_norm = scroll_ratio * (scrollbar_size_v - grab_h_pixels) / scrollbar_size_v; // Grab position in normalized space
|
||||
if (held && allow_interaction && grab_h_norm < 1.0f)
|
||||
{
|
||||
float scrollbar_pos_v = bb.Min[axis];
|
||||
float mouse_pos_v = g.IO.MousePos[axis];
|
||||
const float scrollbar_pos_v = bb.Min[axis];
|
||||
const float mouse_pos_v = g.IO.MousePos[axis];
|
||||
|
||||
// Click position in scrollbar normalized space (0.0f->1.0f)
|
||||
const float clicked_v_norm = ImSaturate((mouse_pos_v - scrollbar_pos_v) / scrollbar_size_v);
|
||||
@ -971,10 +973,10 @@ bool ImGui::ScrollbarEx(const ImRect& bb_frame, ImGuiID id, ImGuiAxis axis, floa
|
||||
// Apply scroll (p_scroll_v will generally point on one member of window->Scroll)
|
||||
// It is ok to modify Scroll here because we are being called in Begin() after the calculation of ContentSize and before setting up our starting position
|
||||
const float scroll_v_norm = ImSaturate((clicked_v_norm - g.ScrollbarClickDeltaToGrabCenter - grab_h_norm * 0.5f) / (1.0f - grab_h_norm));
|
||||
*p_scroll_v = IM_ROUND(scroll_v_norm * scroll_max);//(win_size_contents_v - win_size_v));
|
||||
*p_scroll_v = (ImS64)(scroll_v_norm * scroll_max);
|
||||
|
||||
// Update values for rendering
|
||||
scroll_ratio = ImSaturate(*p_scroll_v / scroll_max);
|
||||
scroll_ratio = ImSaturate((float)*p_scroll_v / (float)scroll_max);
|
||||
grab_v_norm = scroll_ratio * (scrollbar_size_v - grab_h_pixels) / scrollbar_size_v;
|
||||
|
||||
// Update distance to grab now that we have seeked and saturated
|
||||
@ -1391,11 +1393,20 @@ void ImGui::SeparatorEx(ImGuiSeparatorFlags flags)
|
||||
if (g.GroupStack.Size > 0 && g.GroupStack.back().WindowID == window->ID)
|
||||
x1 += window->DC.Indent.x;
|
||||
|
||||
// FIXME-WORKRECT: In theory we should simply be using WorkRect.Min.x/Max.x everywhere but it isn't aesthetically what we want,
|
||||
// need to introduce a variant of WorkRect for that purpose. (#4787)
|
||||
if (ImGuiTable* table = g.CurrentTable)
|
||||
{
|
||||
x1 = table->Columns[table->CurrentColumn].MinX;
|
||||
x2 = table->Columns[table->CurrentColumn].MaxX;
|
||||
}
|
||||
|
||||
ImGuiOldColumns* columns = (flags & ImGuiSeparatorFlags_SpanAllColumns) ? window->DC.CurrentColumns : NULL;
|
||||
if (columns)
|
||||
PushColumnsBackground();
|
||||
|
||||
// We don't provide our width to the layout so that it doesn't get feed back into AutoFit
|
||||
// FIXME: This prevents ->CursorMaxPos based bounding box evaluation from working (e.g. TableEndCell)
|
||||
const ImRect bb(ImVec2(x1, window->DC.CursorPos.y), ImVec2(x2, window->DC.CursorPos.y + thickness_draw));
|
||||
ItemSize(ImVec2(0.0f, thickness_layout));
|
||||
const bool item_visible = ItemAdd(bb, 0);
|
||||
@ -1424,7 +1435,7 @@ void ImGui::Separator()
|
||||
|
||||
// Those flags should eventually be overridable by the user
|
||||
ImGuiSeparatorFlags flags = (window->DC.LayoutType == ImGuiLayoutType_Horizontal) ? ImGuiSeparatorFlags_Vertical : ImGuiSeparatorFlags_Horizontal;
|
||||
flags |= ImGuiSeparatorFlags_SpanAllColumns;
|
||||
flags |= ImGuiSeparatorFlags_SpanAllColumns; // NB: this only applies to legacy Columns() api as they relied on Separator() a lot.
|
||||
SeparatorEx(flags);
|
||||
}
|
||||
|
||||
@ -2409,7 +2420,7 @@ bool ImGui::DragScalar(const char* label, ImGuiDataType data_type, void* p_data,
|
||||
{
|
||||
const bool input_requested_by_tabbing = temp_input_allowed && (g.LastItemData.StatusFlags & ImGuiItemStatusFlags_FocusedByTabbing) != 0;
|
||||
const bool clicked = (hovered && g.IO.MouseClicked[0]);
|
||||
const bool double_clicked = (hovered && g.IO.MouseDoubleClicked[0]);
|
||||
const bool double_clicked = (hovered && g.IO.MouseClickedCount[0] == 2);
|
||||
if (input_requested_by_tabbing || clicked || double_clicked || g.NavActivateId == id || g.NavActivateInputId == id)
|
||||
{
|
||||
SetActiveID(id, window);
|
||||
@ -3679,17 +3690,18 @@ static void STB_TEXTEDIT_LAYOUTROW(StbTexteditRow* r, ImGuiInputTextState* ob
|
||||
}
|
||||
|
||||
// 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 bool is_separator(unsigned int c) { return ImCharIsBlankW(c) || c==',' || c==';' || c=='(' || c==')' || c=='{' || c=='}' || c=='[' || c==']' || c=='|' || c=='\n' || c=='\r'; }
|
||||
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 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_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(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(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
|
||||
static int STB_TEXTEDIT_MOVEWORDRIGHT_MAC(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; }
|
||||
#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
|
||||
#ifdef __APPLE__ // FIXME: Move setting to IO structure
|
||||
#define STB_TEXTEDIT_MOVEWORDRIGHT STB_TEXTEDIT_MOVEWORDRIGHT_MAC
|
||||
#else
|
||||
static int STB_TEXTEDIT_MOVEWORDRIGHT_WIN(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; }
|
||||
#define STB_TEXTEDIT_MOVEWORDRIGHT STB_TEXTEDIT_MOVEWORDRIGHT_WIN
|
||||
#endif
|
||||
|
||||
static void STB_TEXTEDIT_DELETECHARS(ImGuiInputTextState* obj, int pos, int n)
|
||||
{
|
||||
@ -3881,11 +3893,12 @@ static bool InputTextFilterCharacter(unsigned int* p_char, ImGuiInputTextFlags f
|
||||
// Generic named filters
|
||||
if (apply_named_filters && (flags & (ImGuiInputTextFlags_CharsDecimal | ImGuiInputTextFlags_CharsHexadecimal | ImGuiInputTextFlags_CharsUppercase | ImGuiInputTextFlags_CharsNoBlank | ImGuiInputTextFlags_CharsScientific)))
|
||||
{
|
||||
// The libc allows overriding locale, with e.g. 'setlocale(LC_NUMERIC, "de_DE.UTF-8");' which affect the output/input of printf/scanf.
|
||||
// The libc allows overriding locale, with e.g. 'setlocale(LC_NUMERIC, "de_DE.UTF-8");' which affect the output/input of printf/scanf to use e.g. ',' instead of '.'.
|
||||
// The standard mandate that programs starts in the "C" locale where the decimal point is '.'.
|
||||
// We don't really intend to provide widespread support for it, but out of empathy for people stuck with using odd API, we support the bare minimum aka overriding the decimal point.
|
||||
// Change the default decimal_point with:
|
||||
// ImGui::GetCurrentContext()->PlatformLocaleDecimalPoint = *localeconv()->decimal_point;
|
||||
// Users of non-default decimal point (in particular ',') may be affected by word-selection logic (is_word_boundary_from_right/is_word_boundary_from_left) functions.
|
||||
ImGuiContext& g = *GImGui;
|
||||
const unsigned c_decimal_point = (unsigned int)g.PlatformLocaleDecimalPoint;
|
||||
|
||||
@ -3964,7 +3977,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
|
||||
if (is_resizable)
|
||||
IM_ASSERT(callback != NULL); // Must provide a callback if you set the ImGuiInputTextFlags_CallbackResize flag!
|
||||
|
||||
if (is_multiline) // Open group before calling GetID() because groups tracks id created within their scope,
|
||||
if (is_multiline) // Open group before calling GetID() because groups tracks id created within their scope (including the scrollbar)
|
||||
BeginGroup();
|
||||
const ImGuiID id = window->GetID(label);
|
||||
const ImVec2 label_size = CalcTextSize(label, NULL, true);
|
||||
@ -3977,6 +3990,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
|
||||
ImGuiWindow* draw_window = window;
|
||||
ImVec2 inner_size = frame_size;
|
||||
ImGuiItemStatusFlags item_status_flags = 0;
|
||||
ImGuiLastItemData item_data_backup;
|
||||
if (is_multiline)
|
||||
{
|
||||
ImVec2 backup_pos = window->DC.CursorPos;
|
||||
@ -3987,6 +4001,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
|
||||
return false;
|
||||
}
|
||||
item_status_flags = g.LastItemData.StatusFlags;
|
||||
item_data_backup = g.LastItemData;
|
||||
window->DC.CursorPos = backup_pos;
|
||||
|
||||
// We reproduce the contents of BeginChildFrame() in order to provide 'label' so our window internal data are easier to read/debug.
|
||||
@ -3994,8 +4009,9 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
|
||||
PushStyleColor(ImGuiCol_ChildBg, style.Colors[ImGuiCol_FrameBg]);
|
||||
PushStyleVar(ImGuiStyleVar_ChildRounding, style.FrameRounding);
|
||||
PushStyleVar(ImGuiStyleVar_ChildBorderSize, style.FrameBorderSize);
|
||||
PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0, 0)); // Ensure no clip rect so mouse hover can reach FramePadding edges
|
||||
bool child_visible = BeginChildEx(label, id, frame_bb.GetSize(), true, ImGuiWindowFlags_NoMove);
|
||||
PopStyleVar(2);
|
||||
PopStyleVar(3);
|
||||
PopStyleColor();
|
||||
if (!child_visible)
|
||||
{
|
||||
@ -4163,8 +4179,6 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
|
||||
state->Edited = false;
|
||||
state->BufCapacityA = buf_size;
|
||||
state->Flags = flags;
|
||||
state->UserCallback = callback;
|
||||
state->UserCallbackData = callback_user_data;
|
||||
|
||||
// Although we are active we don't prevent mouse from hovering other elements unless we are interacting right now with the widget.
|
||||
// Down the line we should have a cleaner library-wide concept of Selected vs Active.
|
||||
@ -4176,19 +4190,49 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
|
||||
const float mouse_y = (is_multiline ? (io.MousePos.y - draw_window->DC.CursorPos.y) : (g.FontSize * 0.5f));
|
||||
|
||||
const bool is_osx = io.ConfigMacOSXBehaviors;
|
||||
if (select_all || (hovered && !is_osx && io.MouseDoubleClicked[0]))
|
||||
if (select_all)
|
||||
{
|
||||
state->SelectAll();
|
||||
state->SelectedAllMouseLock = true;
|
||||
}
|
||||
else if (hovered && is_osx && io.MouseDoubleClicked[0])
|
||||
else if (hovered && io.MouseClickedCount[0] >= 2 && !io.KeyShift)
|
||||
{
|
||||
// Double-click select a word only, OS X style (by simulating keystrokes)
|
||||
state->OnKeyPressed(STB_TEXTEDIT_K_WORDLEFT);
|
||||
state->OnKeyPressed(STB_TEXTEDIT_K_WORDRIGHT | STB_TEXTEDIT_K_SHIFT);
|
||||
stb_textedit_click(state, &state->Stb, mouse_x, mouse_y);
|
||||
const int multiclick_count = (io.MouseClickedCount[0] - 2);
|
||||
if ((multiclick_count % 2) == 0)
|
||||
{
|
||||
// Double-click: Select word
|
||||
// We always use the "Mac" word advance for double-click select vs CTRL+Right which use the platform dependent variant:
|
||||
// FIXME: There are likely many ways to improve this behavior, but there's no "right" behavior (depends on use-case, software, OS)
|
||||
const bool is_bol = (state->Stb.cursor == 0) || ImStb::STB_TEXTEDIT_GETCHAR(state, state->Stb.cursor - 1) == '\n';
|
||||
if (STB_TEXT_HAS_SELECTION(&state->Stb) || !is_bol)
|
||||
state->OnKeyPressed(STB_TEXTEDIT_K_WORDLEFT);
|
||||
//state->OnKeyPressed(STB_TEXTEDIT_K_WORDRIGHT | STB_TEXTEDIT_K_SHIFT);
|
||||
if (!STB_TEXT_HAS_SELECTION(&state->Stb))
|
||||
ImStb::stb_textedit_prep_selection_at_cursor(&state->Stb);
|
||||
state->Stb.cursor = ImStb::STB_TEXTEDIT_MOVEWORDRIGHT_MAC(state, state->Stb.cursor);
|
||||
state->Stb.select_end = state->Stb.cursor;
|
||||
ImStb::stb_textedit_clamp(state, &state->Stb);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Triple-click: Select line
|
||||
const bool is_eol = ImStb::STB_TEXTEDIT_GETCHAR(state, state->Stb.cursor) == '\n';
|
||||
state->OnKeyPressed(STB_TEXTEDIT_K_LINESTART);
|
||||
state->OnKeyPressed(STB_TEXTEDIT_K_LINEEND | STB_TEXTEDIT_K_SHIFT);
|
||||
state->OnKeyPressed(STB_TEXTEDIT_K_RIGHT | STB_TEXTEDIT_K_SHIFT);
|
||||
if (!is_eol && is_multiline)
|
||||
{
|
||||
ImSwap(state->Stb.select_start, state->Stb.select_end);
|
||||
state->Stb.cursor = state->Stb.select_end;
|
||||
}
|
||||
state->CursorFollow = false;
|
||||
}
|
||||
state->CursorAnimReset();
|
||||
}
|
||||
else if (io.MouseClicked[0] && !state->SelectedAllMouseLock)
|
||||
{
|
||||
// FIXME: unselect on late click could be done release?
|
||||
if (hovered)
|
||||
{
|
||||
stb_textedit_click(state, &state->Stb, mouse_x, mouse_y);
|
||||
@ -4273,7 +4317,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
|
||||
else if (IsKeyPressedMap(ImGuiKey_PageDown) && is_multiline) { state->OnKeyPressed(STB_TEXTEDIT_K_PGDOWN | k_mask); scroll_y += row_count_per_page * g.FontSize; }
|
||||
else if (IsKeyPressedMap(ImGuiKey_Home)) { state->OnKeyPressed(io.KeyCtrl ? STB_TEXTEDIT_K_TEXTSTART | k_mask : STB_TEXTEDIT_K_LINESTART | k_mask); }
|
||||
else if (IsKeyPressedMap(ImGuiKey_End)) { state->OnKeyPressed(io.KeyCtrl ? STB_TEXTEDIT_K_TEXTEND | k_mask : STB_TEXTEDIT_K_LINEEND | k_mask); }
|
||||
else if (IsKeyPressedMap(ImGuiKey_Delete) && !is_readonly) { state->OnKeyPressed(STB_TEXTEDIT_K_DELETE | k_mask); }
|
||||
else if (IsKeyPressedMap(ImGuiKey_Delete) && !is_readonly && !is_cut) { state->OnKeyPressed(STB_TEXTEDIT_K_DELETE | k_mask); }
|
||||
else if (IsKeyPressedMap(ImGuiKey_Backspace) && !is_readonly)
|
||||
{
|
||||
if (!state->HasSelection())
|
||||
@ -4372,11 +4416,11 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
|
||||
}
|
||||
|
||||
// Process callbacks and apply result back to user's buffer.
|
||||
const char* apply_new_text = NULL;
|
||||
int apply_new_text_length = 0;
|
||||
if (g.ActiveId == id)
|
||||
{
|
||||
IM_ASSERT(state != NULL);
|
||||
const char* apply_new_text = NULL;
|
||||
int apply_new_text_length = 0;
|
||||
if (cancel_edit)
|
||||
{
|
||||
// Restore initial value. Only return true if restoring to the initial value changes the current buffer contents.
|
||||
@ -4452,8 +4496,9 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
|
||||
callback_data.Flags = flags;
|
||||
callback_data.UserData = callback_user_data;
|
||||
|
||||
char* callback_buf = is_readonly ? buf : state->TextA.Data;
|
||||
callback_data.EventKey = event_key;
|
||||
callback_data.Buf = state->TextA.Data;
|
||||
callback_data.Buf = callback_buf;
|
||||
callback_data.BufTextLen = state->CurLenA;
|
||||
callback_data.BufSize = state->BufCapacityA;
|
||||
callback_data.BufDirty = false;
|
||||
@ -4468,7 +4513,8 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
|
||||
callback(&callback_data);
|
||||
|
||||
// Read back what user may have modified
|
||||
IM_ASSERT(callback_data.Buf == state->TextA.Data); // Invalid to modify those fields
|
||||
callback_buf = is_readonly ? buf : state->TextA.Data; // Pointer may have been invalidated by a resize callback
|
||||
IM_ASSERT(callback_data.Buf == callback_buf); // Invalid to modify those fields
|
||||
IM_ASSERT(callback_data.BufSize == state->BufCapacityA);
|
||||
IM_ASSERT(callback_data.Flags == flags);
|
||||
const bool buf_dirty = callback_data.BufDirty;
|
||||
@ -4495,39 +4541,37 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
|
||||
}
|
||||
}
|
||||
|
||||
// Copy result to user buffer
|
||||
if (apply_new_text)
|
||||
{
|
||||
// We cannot test for 'backup_current_text_length != apply_new_text_length' here because we have no guarantee that the size
|
||||
// of our owned buffer matches the size of the string object held by the user, and by design we allow InputText() to be used
|
||||
// without any storage on user's side.
|
||||
IM_ASSERT(apply_new_text_length >= 0);
|
||||
if (is_resizable)
|
||||
{
|
||||
ImGuiInputTextCallbackData callback_data;
|
||||
callback_data.EventFlag = ImGuiInputTextFlags_CallbackResize;
|
||||
callback_data.Flags = flags;
|
||||
callback_data.Buf = buf;
|
||||
callback_data.BufTextLen = apply_new_text_length;
|
||||
callback_data.BufSize = ImMax(buf_size, apply_new_text_length + 1);
|
||||
callback_data.UserData = callback_user_data;
|
||||
callback(&callback_data);
|
||||
buf = callback_data.Buf;
|
||||
buf_size = callback_data.BufSize;
|
||||
apply_new_text_length = ImMin(callback_data.BufTextLen, buf_size - 1);
|
||||
IM_ASSERT(apply_new_text_length <= buf_size);
|
||||
}
|
||||
//IMGUI_DEBUG_LOG("InputText(\"%s\"): apply_new_text length %d\n", label, apply_new_text_length);
|
||||
|
||||
// If the underlying buffer resize was denied or not carried to the next frame, apply_new_text_length+1 may be >= buf_size.
|
||||
ImStrncpy(buf, apply_new_text, ImMin(apply_new_text_length + 1, buf_size));
|
||||
value_changed = true;
|
||||
}
|
||||
|
||||
// Clear temporary user storage
|
||||
state->Flags = ImGuiInputTextFlags_None;
|
||||
state->UserCallback = NULL;
|
||||
state->UserCallbackData = NULL;
|
||||
}
|
||||
|
||||
// Copy result to user buffer. This can currently only happen when (g.ActiveId == id)
|
||||
if (apply_new_text != NULL)
|
||||
{
|
||||
// We cannot test for 'backup_current_text_length != apply_new_text_length' here because we have no guarantee that the size
|
||||
// of our owned buffer matches the size of the string object held by the user, and by design we allow InputText() to be used
|
||||
// without any storage on user's side.
|
||||
IM_ASSERT(apply_new_text_length >= 0);
|
||||
if (is_resizable)
|
||||
{
|
||||
ImGuiInputTextCallbackData callback_data;
|
||||
callback_data.EventFlag = ImGuiInputTextFlags_CallbackResize;
|
||||
callback_data.Flags = flags;
|
||||
callback_data.Buf = buf;
|
||||
callback_data.BufTextLen = apply_new_text_length;
|
||||
callback_data.BufSize = ImMax(buf_size, apply_new_text_length + 1);
|
||||
callback_data.UserData = callback_user_data;
|
||||
callback(&callback_data);
|
||||
buf = callback_data.Buf;
|
||||
buf_size = callback_data.BufSize;
|
||||
apply_new_text_length = ImMin(callback_data.BufTextLen, buf_size - 1);
|
||||
IM_ASSERT(apply_new_text_length <= buf_size);
|
||||
}
|
||||
//IMGUI_DEBUG_LOG("InputText(\"%s\"): apply_new_text length %d\n", label, apply_new_text_length);
|
||||
|
||||
// If the underlying buffer resize was denied or not carried to the next frame, apply_new_text_length+1 may be >= buf_size.
|
||||
ImStrncpy(buf, apply_new_text, ImMin(apply_new_text_length + 1, buf_size));
|
||||
value_changed = true;
|
||||
}
|
||||
|
||||
// Release active ID at the end of the function (so e.g. pressing Return still does a final application of the value)
|
||||
@ -4649,7 +4693,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
|
||||
// Test if cursor is vertically visible
|
||||
if (cursor_offset.y - g.FontSize < scroll_y)
|
||||
scroll_y = ImMax(0.0f, cursor_offset.y - g.FontSize);
|
||||
else if (cursor_offset.y - inner_size.y >= scroll_y)
|
||||
else if (cursor_offset.y - (inner_size.y - style.FramePadding.y * 2.0f) >= scroll_y)
|
||||
scroll_y = cursor_offset.y - inner_size.y + style.FramePadding.y * 2.0f;
|
||||
const float scroll_max_y = ImMax((text_size.y + style.FramePadding.y * 2.0f) - inner_size.y, 0.0f);
|
||||
scroll_y = ImClamp(scroll_y, 0.0f, scroll_max_y);
|
||||
@ -4741,9 +4785,23 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
|
||||
|
||||
if (is_multiline)
|
||||
{
|
||||
// For focus requests to work on our multiline we need to ensure our child ItemAdd() call specifies the ImGuiItemFlags_Inputable (ref issue #4761)...
|
||||
Dummy(ImVec2(text_size.x, text_size.y + style.FramePadding.y));
|
||||
ImGuiItemFlags backup_item_flags = g.CurrentItemFlags;
|
||||
g.CurrentItemFlags |= ImGuiItemFlags_Inputable | ImGuiItemFlags_NoTabStop;
|
||||
EndChild();
|
||||
item_data_backup.StatusFlags |= (g.LastItemData.StatusFlags & ImGuiItemStatusFlags_HoveredWindow);
|
||||
g.CurrentItemFlags = backup_item_flags;
|
||||
|
||||
// ...and then we need to undo the group overriding last item data, which gets a bit messy as EndGroup() tries to forward scrollbar being active...
|
||||
// FIXME: This quite messy/tricky, should attempt to get rid of the child window.
|
||||
EndGroup();
|
||||
if (g.LastItemData.ID == 0)
|
||||
{
|
||||
g.LastItemData.ID = id;
|
||||
g.LastItemData.InFlags = item_data_backup.InFlags;
|
||||
g.LastItemData.StatusFlags = item_data_backup.StatusFlags;
|
||||
}
|
||||
}
|
||||
|
||||
// Log as text
|
||||
@ -5548,7 +5606,7 @@ void ImGui::ColorTooltip(const char* text, const float* col, ImGuiColorEditFlags
|
||||
{
|
||||
ImGuiContext& g = *GImGui;
|
||||
|
||||
BeginTooltipEx(0, ImGuiTooltipFlags_OverridePreviousTooltip);
|
||||
BeginTooltipEx(ImGuiTooltipFlags_OverridePreviousTooltip, ImGuiWindowFlags_None);
|
||||
const char* text_end = text ? FindRenderedTextEnd(text, NULL) : text;
|
||||
if (text_end > text)
|
||||
{
|
||||
@ -5919,7 +5977,7 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l
|
||||
toggled = true;
|
||||
if (flags & ImGuiTreeNodeFlags_OpenOnArrow)
|
||||
toggled |= is_mouse_x_over_arrow && !g.NavDisableMouseHover; // Lightweight equivalent of IsMouseHoveringRect() since ButtonBehavior() already did the job
|
||||
if ((flags & ImGuiTreeNodeFlags_OpenOnDoubleClick) && g.IO.MouseDoubleClicked[0])
|
||||
if ((flags & ImGuiTreeNodeFlags_OpenOnDoubleClick) && g.IO.MouseClickedCount[0] == 2)
|
||||
toggled = true;
|
||||
}
|
||||
else if (pressed && g.DragDropHoldJustPressedId == id)
|
||||
@ -6226,7 +6284,7 @@ bool ImGui::Selectable(const char* label, bool selected, ImGuiSelectableFlags fl
|
||||
{
|
||||
if (!g.NavDisableMouseHover && g.NavWindow == window && g.NavLayer == window->DC.NavLayerCurrent)
|
||||
{
|
||||
SetNavID(id, window->DC.NavLayerCurrent, window->DC.NavFocusScopeIdCurrent, ImRect(bb.Min - window->Pos, bb.Max - window->Pos)); // (bb == NavRect)
|
||||
SetNavID(id, window->DC.NavLayerCurrent, window->DC.NavFocusScopeIdCurrent, WindowRectAbsToRel(window, bb)); // (bb == NavRect)
|
||||
g.NavDisableHighlight = true;
|
||||
}
|
||||
}
|
||||
@ -6810,6 +6868,23 @@ void ImGui::EndMainMenuBar()
|
||||
End();
|
||||
}
|
||||
|
||||
static bool IsRootOfOpenMenuSet()
|
||||
{
|
||||
ImGuiContext& g = *GImGui;
|
||||
ImGuiWindow* window = g.CurrentWindow;
|
||||
if ((g.OpenPopupStack.Size <= g.BeginPopupStack.Size) || (window->Flags & ImGuiWindowFlags_ChildMenu))
|
||||
return false;
|
||||
|
||||
// Initially we used 'OpenParentId' to differentiate multiple menu sets from each others (e.g. inside menu bar vs loose menu items) based on parent ID.
|
||||
// This would however prevent the use of e.g. PuhsID() user code submitting menus.
|
||||
// Previously this worked between popup and a first child menu because the first child menu always had the _ChildWindow flag,
|
||||
// making hovering on parent popup possible while first child menu was focused - but this was generally a bug with other side effects.
|
||||
// Instead we don't treat Popup specifically (in order to consistently support menu features in them), maybe the first child menu of a Popup
|
||||
// doesn't have the _ChildWindow flag, and we rely on this IsRootOfOpenMenuSet() check to allow hovering between root window/popup and first chilld menu.
|
||||
const ImGuiPopupData* upper_popup = &g.OpenPopupStack[g.BeginPopupStack.Size];
|
||||
return (/*upper_popup->OpenParentId == window->IDStack.back() &&*/ upper_popup->Window && (upper_popup->Window->Flags & ImGuiWindowFlags_ChildMenu));
|
||||
}
|
||||
|
||||
bool ImGui::BeginMenuEx(const char* label, const char* icon, bool enabled)
|
||||
{
|
||||
ImGuiWindow* window = GetCurrentWindow();
|
||||
@ -6822,8 +6897,9 @@ bool ImGui::BeginMenuEx(const char* label, const char* icon, bool enabled)
|
||||
bool menu_is_open = IsPopupOpen(id, ImGuiPopupFlags_None);
|
||||
|
||||
// Sub-menus are ChildWindow so that mouse can be hovering across them (otherwise top-most popup menu would steal focus and not allow hovering on parent menu)
|
||||
// The first menu in a hierarchy isn't so hovering doesn't get accross (otherwise e.g. resizing borders with ImGuiButtonFlags_FlattenChildren would react), but top-most BeginMenu() will bypass that limitation.
|
||||
ImGuiWindowFlags flags = ImGuiWindowFlags_ChildMenu | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_NoNavFocus;
|
||||
if (window->Flags & (ImGuiWindowFlags_Popup | ImGuiWindowFlags_ChildMenu))
|
||||
if (window->Flags & ImGuiWindowFlags_ChildMenu)
|
||||
flags |= ImGuiWindowFlags_ChildWindow;
|
||||
|
||||
// If a menu with same the ID was already submitted, we will append to it, matching the behavior of Begin().
|
||||
@ -6842,11 +6918,12 @@ bool ImGui::BeginMenuEx(const char* label, const char* icon, bool enabled)
|
||||
g.MenusIdSubmittedThisFrame.push_back(id);
|
||||
|
||||
ImVec2 label_size = CalcTextSize(label, NULL, true);
|
||||
bool pressed;
|
||||
bool menuset_is_open = !(window->Flags & ImGuiWindowFlags_Popup) && (g.OpenPopupStack.Size > g.BeginPopupStack.Size && g.OpenPopupStack[g.BeginPopupStack.Size].OpenParentId == window->IDStack.back());
|
||||
|
||||
// Odd hack to allow hovering across menus of a same menu-set (otherwise we wouldn't be able to hover parent without always being a Child window)
|
||||
const bool menuset_is_open = IsRootOfOpenMenuSet();
|
||||
ImGuiWindow* backed_nav_window = g.NavWindow;
|
||||
if (menuset_is_open)
|
||||
g.NavWindow = window; // Odd hack to allow hovering across menus of a same menu-set (otherwise we wouldn't be able to hover parent)
|
||||
g.NavWindow = window;
|
||||
|
||||
// The reference position stored in popup_pos will be used by Begin() to find a suitable position for the child menu,
|
||||
// However the final position is going to be different! It is chosen by FindBestWindowPosForPopup().
|
||||
@ -6856,6 +6933,7 @@ bool ImGui::BeginMenuEx(const char* label, const char* icon, bool enabled)
|
||||
if (!enabled)
|
||||
BeginDisabled();
|
||||
const ImGuiMenuColumns* offsets = &window->DC.MenuColumns;
|
||||
bool pressed;
|
||||
if (window->DC.LayoutType == ImGuiLayoutType_Horizontal)
|
||||
{
|
||||
// Menu inside an horizontal menu bar
|
||||
@ -6972,7 +7050,9 @@ bool ImGui::BeginMenuEx(const char* label, const char* icon, bool enabled)
|
||||
if (menu_is_open)
|
||||
{
|
||||
SetNextWindowPos(popup_pos, ImGuiCond_Always); // Note: this is super misleading! The value will serve as reference for FindBestWindowPosForPopup(), not actual pos.
|
||||
PushStyleVar(ImGuiStyleVar_ChildRounding, style.PopupRounding); // First level will use _PopupRounding, subsequent will use _ChildRounding
|
||||
menu_is_open = BeginPopupEx(id, flags); // menu_is_open can be 'false' when the popup is completely clipped (e.g. zero size display)
|
||||
PopStyleVar();
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -7015,13 +7095,19 @@ bool ImGui::MenuItemEx(const char* label, const char* icon, const char* shortcut
|
||||
ImVec2 pos = window->DC.CursorPos;
|
||||
ImVec2 label_size = CalcTextSize(label, NULL, true);
|
||||
|
||||
const bool menuset_is_open = IsRootOfOpenMenuSet();
|
||||
ImGuiWindow* backed_nav_window = g.NavWindow;
|
||||
if (menuset_is_open)
|
||||
g.NavWindow = window;
|
||||
|
||||
// We've been using the equivalent of ImGuiSelectableFlags_SetNavIdOnHover on all Selectable() since early Nav system days (commit 43ee5d73),
|
||||
// but I am unsure whether this should be kept at all. For now moved it to be an opt-in feature used by menus only.
|
||||
bool pressed;
|
||||
PushID(label);
|
||||
if (!enabled)
|
||||
BeginDisabled();
|
||||
const ImGuiSelectableFlags flags = ImGuiSelectableFlags_SelectOnRelease | ImGuiSelectableFlags_SetNavIdOnHover;
|
||||
|
||||
const ImGuiSelectableFlags selectable_flags = ImGuiSelectableFlags_SelectOnRelease | ImGuiSelectableFlags_SetNavIdOnHover;
|
||||
const ImGuiMenuColumns* offsets = &window->DC.MenuColumns;
|
||||
if (window->DC.LayoutType == ImGuiLayoutType_Horizontal)
|
||||
{
|
||||
@ -7031,7 +7117,7 @@ bool ImGui::MenuItemEx(const char* label, const char* icon, const char* shortcut
|
||||
window->DC.CursorPos.x += IM_FLOOR(style.ItemSpacing.x * 0.5f);
|
||||
ImVec2 text_pos(window->DC.CursorPos.x + offsets->OffsetLabel, window->DC.CursorPos.y + window->DC.CurrLineTextBaseOffset);
|
||||
PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(style.ItemSpacing.x * 2.0f, style.ItemSpacing.y));
|
||||
pressed = Selectable("", selected, flags, ImVec2(w, 0.0f));
|
||||
pressed = Selectable("", selected, selectable_flags, ImVec2(w, 0.0f));
|
||||
PopStyleVar();
|
||||
RenderText(text_pos, label);
|
||||
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().
|
||||
@ -7046,7 +7132,7 @@ bool ImGui::MenuItemEx(const char* label, const char* icon, const char* shortcut
|
||||
float checkmark_w = IM_FLOOR(g.FontSize * 1.20f);
|
||||
float min_w = window->DC.MenuColumns.DeclColumns(icon_w, label_size.x, shortcut_w, checkmark_w); // Feedback for next frame
|
||||
float stretch_w = ImMax(0.0f, GetContentRegionAvail().x - min_w);
|
||||
pressed = Selectable("", false, flags | ImGuiSelectableFlags_SpanAvailWidth, ImVec2(min_w, 0.0f));
|
||||
pressed = Selectable("", false, selectable_flags | ImGuiSelectableFlags_SpanAvailWidth, ImVec2(min_w, 0.0f));
|
||||
RenderText(pos + ImVec2(offsets->OffsetLabel, 0.0f), label);
|
||||
if (icon_w > 0.0f)
|
||||
RenderText(pos + ImVec2(offsets->OffsetIcon, 0.0f), icon);
|
||||
@ -7063,6 +7149,8 @@ bool ImGui::MenuItemEx(const char* label, const char* icon, const char* shortcut
|
||||
if (!enabled)
|
||||
EndDisabled();
|
||||
PopID();
|
||||
if (menuset_is_open)
|
||||
g.NavWindow = backed_nav_window;
|
||||
|
||||
return pressed;
|
||||
}
|
||||
@ -7205,8 +7293,7 @@ bool ImGui::BeginTabBarEx(ImGuiTabBar* tab_bar, const ImRect& tab_bar_bb, ImG
|
||||
|
||||
// Ensure correct ordering when toggling ImGuiTabBarFlags_Reorderable flag, or when a new tab was added while being not reorderable
|
||||
if ((flags & ImGuiTabBarFlags_Reorderable) != (tab_bar->Flags & ImGuiTabBarFlags_Reorderable) || (tab_bar->TabsAddedNew && !(flags & ImGuiTabBarFlags_Reorderable)))
|
||||
if (tab_bar->Tabs.Size > 1)
|
||||
ImQsort(tab_bar->Tabs.Data, tab_bar->Tabs.Size, sizeof(ImGuiTabItem), TabItemComparerByBeginOrder);
|
||||
ImQsort(tab_bar->Tabs.Data, tab_bar->Tabs.Size, sizeof(ImGuiTabItem), TabItemComparerByBeginOrder);
|
||||
tab_bar->TabsAddedNew = false;
|
||||
|
||||
// Flags
|
||||
|
@ -226,6 +226,12 @@ namespace
|
||||
uint32_t glyph_index = FT_Get_Char_Index(Face, codepoint);
|
||||
if (glyph_index == 0)
|
||||
return NULL;
|
||||
|
||||
// If this crash for you: FreeType 2.11.0 has a crash bug on some bitmap/colored fonts.
|
||||
// - https://gitlab.freedesktop.org/freetype/freetype/-/issues/1076
|
||||
// - https://github.com/ocornut/imgui/issues/4567
|
||||
// - https://github.com/ocornut/imgui/issues/4566
|
||||
// You can use FreeType 2.10, or the patched version of 2.11.0 in VcPkg, or probably any upcoming FreeType version.
|
||||
FT_Error error = FT_Load_Glyph(Face, glyph_index, LoadFlags);
|
||||
if (error)
|
||||
return NULL;
|
||||
|
Reference in New Issue
Block a user