imgui.cpp (imgui-1.86) | : | imgui.cpp (imgui-1.87) | ||
---|---|---|---|---|
// dear imgui, v1.86 | // dear imgui, v1.87 | |||
// (main code and documentation) | // (main code and documentation) | |||
// Help: | // Help: | |||
// - Read FAQ at http://dearimgui.org/faq | // - Read FAQ at http://dearimgui.org/faq | |||
// - Newcomers, read 'Programmer guide' below for notes on how to setup Dear ImG ui in your codebase. | // - Newcomers, read 'Programmer guide' below for notes on how to setup Dear ImG ui in your codebase. | |||
// - Call and read ImGui::ShowDemoWindow() in imgui_demo.cpp. All applications i n examples/ are doing that. | // - Call and read ImGui::ShowDemoWindow() in imgui_demo.cpp. All applications i n examples/ are doing that. | |||
// Read imgui.cpp for details, links and comments. | // Read imgui.cpp for details, links and comments. | |||
// Resources: | // Resources: | |||
// - FAQ http://dearimgui.org/faq | // - FAQ http://dearimgui.org/faq | |||
skipping to change at line 73 | skipping to change at line 73 | |||
// [SECTION] MISC HELPERS/UTILITIES (File functions) | // [SECTION] MISC HELPERS/UTILITIES (File functions) | |||
// [SECTION] MISC HELPERS/UTILITIES (ImText* functions) | // [SECTION] MISC HELPERS/UTILITIES (ImText* functions) | |||
// [SECTION] MISC HELPERS/UTILITIES (Color functions) | // [SECTION] MISC HELPERS/UTILITIES (Color functions) | |||
// [SECTION] ImGuiStorage | // [SECTION] ImGuiStorage | |||
// [SECTION] ImGuiTextFilter | // [SECTION] ImGuiTextFilter | |||
// [SECTION] ImGuiTextBuffer | // [SECTION] ImGuiTextBuffer | |||
// [SECTION] ImGuiListClipper | // [SECTION] ImGuiListClipper | |||
// [SECTION] STYLING | // [SECTION] STYLING | |||
// [SECTION] RENDER HELPERS | // [SECTION] RENDER HELPERS | |||
// [SECTION] MAIN CODE (most of the code! lots of stuff, needs tidying up!) | // [SECTION] MAIN CODE (most of the code! lots of stuff, needs tidying up!) | |||
// [SECTION] INPUTS | ||||
// [SECTION] ERROR CHECKING | // [SECTION] ERROR CHECKING | |||
// [SECTION] LAYOUT | // [SECTION] LAYOUT | |||
// [SECTION] SCROLLING | // [SECTION] SCROLLING | |||
// [SECTION] TOOLTIPS | // [SECTION] TOOLTIPS | |||
// [SECTION] POPUPS | // [SECTION] POPUPS | |||
// [SECTION] KEYBOARD/GAMEPAD NAVIGATION | // [SECTION] KEYBOARD/GAMEPAD NAVIGATION | |||
// [SECTION] DRAG AND DROP | // [SECTION] DRAG AND DROP | |||
// [SECTION] LOGGING/CAPTURING | // [SECTION] LOGGING/CAPTURING | |||
// [SECTION] SETTINGS | // [SECTION] SETTINGS | |||
// [SECTION] VIEWPORTS | // [SECTION] VIEWPORTS | |||
skipping to change at line 129 | skipping to change at line 130 | |||
- CTRL+Click on a slider or drag box to input value as text. | - CTRL+Click on a slider or drag box to input value as text. | |||
- Use mouse wheel to scroll. | - Use mouse wheel to scroll. | |||
- Text editor: | - Text editor: | |||
- Hold SHIFT or use mouse to select text. | - Hold SHIFT or use mouse to select text. | |||
- CTRL+Left/Right to word jump. | - CTRL+Left/Right to word jump. | |||
- CTRL+Shift+Left/Right to select words. | - CTRL+Shift+Left/Right to select words. | |||
- CTRL+A our Double-Click to select all. | - CTRL+A our Double-Click to select all. | |||
- CTRL+X,CTRL+C,CTRL+V to use OS clipboard/ | - CTRL+X,CTRL+C,CTRL+V to use OS clipboard/ | |||
- CTRL+Z,CTRL+Y to undo/redo. | - CTRL+Z,CTRL+Y to undo/redo. | |||
- ESCAPE to revert text to its original value. | - ESCAPE to revert text to its original value. | |||
- You can apply arithmetic operators +,*,/ on numerical values. Use +- to sub tract (because - would set a negative value!) | ||||
- Controls are automatically adjusted for OSX to match standard OSX text edit ing operations. | - Controls are automatically adjusted for OSX to match standard OSX text edit ing operations. | |||
- General Keyboard controls: enable with ImGuiConfigFlags_NavEnableKeyboard. | - General Keyboard controls: enable with ImGuiConfigFlags_NavEnableKeyboard. | |||
- General Gamepad controls: enable with ImGuiConfigFlags_NavEnableGamepad. See suggested mappings in imgui.h ImGuiNavInput_ + download PNG/PSD at http://dearim gui.org/controls_sheets | - General Gamepad controls: enable with ImGuiConfigFlags_NavEnableGamepad. See suggested mappings in imgui.h ImGuiNavInput_ + download PNG/PSD at http://dearim gui.org/controls_sheets | |||
PROGRAMMER GUIDE | PROGRAMMER GUIDE | |||
================ | ================ | |||
READ FIRST | READ FIRST | |||
---------- | ---------- | |||
- Remember to check the wonderful Wiki (https://github.com/ocornut/imgui/wiki) | - Remember to check the wonderful Wiki (https://github.com/ocornut/imgui/wiki) | |||
skipping to change at line 252 | skipping to change at line 252 | |||
io.Fonts->SetTexID((void*)texture); | io.Fonts->SetTexID((void*)texture); | |||
// Application main loop | // Application main loop | |||
while (true) | while (true) | |||
{ | { | |||
// Setup low-level inputs, e.g. on Win32: calling GetKeyboardState(), or write to those fields from your Windows message handlers, etc. | // Setup low-level inputs, e.g. on Win32: calling GetKeyboardState(), or write to those fields from your Windows message handlers, etc. | |||
// (In the examples/ app this is usually done within the ImGui_ImplXXX_N ewFrame() function from one of the demo Platform Backends) | // (In the examples/ app this is usually done within the ImGui_ImplXXX_N ewFrame() function from one of the demo Platform Backends) | |||
io.DeltaTime = 1.0f/60.0f; // set the time elapsed since th e previous frame (in seconds) | io.DeltaTime = 1.0f/60.0f; // set the time elapsed since th e previous frame (in seconds) | |||
io.DisplaySize.x = 1920.0f; // set the current display width | io.DisplaySize.x = 1920.0f; // set the current display width | |||
io.DisplaySize.y = 1280.0f; // set the current display heigh t here | io.DisplaySize.y = 1280.0f; // set the current display heigh t here | |||
io.MousePos = my_mouse_pos; // set the mouse position | io.AddMousePosEvent(mouse_x, mouse_y); // update mouse position | |||
io.MouseDown[0] = my_mouse_buttons[0]; // set the mouse button states | io.AddMouseButtonEvent(0, mouse_b[0]); // update mouse button states | |||
io.MouseDown[1] = my_mouse_buttons[1]; | io.AddMouseButtonEvent(1, mouse_b[1]); // update mouse button states | |||
// Call NewFrame(), after this point you can use ImGui::* functions anyt ime | // Call NewFrame(), after this point you can use ImGui::* functions anyt ime | |||
// (So you want to try calling NewFrame() as early as you can in your ma in loop to be able to use Dear ImGui everywhere) | // (So you want to try calling NewFrame() as early as you can in your ma in loop to be able to use Dear ImGui everywhere) | |||
ImGui::NewFrame(); | ImGui::NewFrame(); | |||
// Most of your application code here | // Most of your application code here | |||
ImGui::Text("Hello, world!"); | ImGui::Text("Hello, world!"); | |||
MyGameUpdate(); // may use any Dear ImGui functions, e.g. ImGui::Begin(" My window"); ImGui::Text("Hello, world!"); ImGui::End(); | MyGameUpdate(); // may use any Dear ImGui functions, e.g. ImGui::Begin(" My window"); ImGui::Text("Hello, world!"); ImGui::End(); | |||
MyGameRender(); // may use any Dear ImGui functions as well! | MyGameRender(); // may use any Dear ImGui functions as well! | |||
skipping to change at line 291 | skipping to change at line 291 | |||
HOW A SIMPLE RENDERING FUNCTION MAY LOOK LIKE | HOW A SIMPLE RENDERING FUNCTION MAY LOOK LIKE | |||
--------------------------------------------- | --------------------------------------------- | |||
The backends in impl_impl_XXX.cpp files contain many working implementations of a rendering function. | The backends in impl_impl_XXX.cpp files contain many working implementations of a rendering function. | |||
void void MyImGuiRenderFunction(ImDrawData* draw_data) | void void MyImGuiRenderFunction(ImDrawData* draw_data) | |||
{ | { | |||
// TODO: Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled | // TODO: Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled | |||
// TODO: Setup viewport covering draw_data->DisplayPos to draw_data->Disp layPos + draw_data->DisplaySize | // TODO: Setup viewport covering draw_data->DisplayPos to draw_data->Disp layPos + draw_data->DisplaySize | |||
// TODO: Setup orthographic projection matrix cover draw_data->DisplayPos to draw_data->DisplayPos + draw_data->DisplaySize | // TODO: Setup orthographic projection matrix cover draw_data->DisplayPos to draw_data->DisplayPos + draw_data->DisplaySize | |||
// TODO: Setup shader: vertex { float2 pos, float2 uv, u32 color }, fragm ent shader sample color from 1 texture, multiply by vertex color. | // TODO: Setup shader: vertex { float2 pos, float2 uv, u32 color }, fragm ent shader sample color from 1 texture, multiply by vertex color. | |||
ImVec2 clip_off = draw_data->DisplayPos; | ||||
for (int n = 0; n < draw_data->CmdListsCount; n++) | for (int n = 0; n < draw_data->CmdListsCount; n++) | |||
{ | { | |||
const ImDrawList* cmd_list = draw_data->CmdLists[n]; | const ImDrawList* cmd_list = draw_data->CmdLists[n]; | |||
const ImDrawVert* vtx_buffer = cmd_list->VtxBuffer.Data; // vertex bu ffer generated by Dear ImGui | const ImDrawVert* vtx_buffer = cmd_list->VtxBuffer.Data; // vertex bu ffer generated by Dear ImGui | |||
const ImDrawIdx* idx_buffer = cmd_list->IdxBuffer.Data; // index buf fer generated by Dear ImGui | const ImDrawIdx* idx_buffer = cmd_list->IdxBuffer.Data; // index buf fer generated by Dear ImGui | |||
for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++) | for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++) | |||
{ | { | |||
const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i]; | const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i]; | |||
if (pcmd->UserCallback) | if (pcmd->UserCallback) | |||
{ | { | |||
pcmd->UserCallback(cmd_list, pcmd); | pcmd->UserCallback(cmd_list, pcmd); | |||
} | } | |||
else | else | |||
{ | { | |||
// The texture for the draw call is specified by pcmd->GetTexID | // Project scissor/clipping rectangles into framebuffer space | |||
(). | ImVec2 clip_min(pcmd->ClipRect.x - clip_off.x, pcmd->ClipRect.y | |||
// The vast majority of draw calls will use the Dear ImGui text | - clip_off.y); | |||
ure atlas, which value you have set yourself during initialization. | ImVec2 clip_max(pcmd->ClipRect.z - clip_off.x, pcmd->ClipRect.w | |||
MyEngineBindTexture((MyTexture*)pcmd->GetTexID()); | - clip_off.y); | |||
if (clip_max.x <= clip_min.x || clip_max.y <= clip_min.y) | ||||
continue; | ||||
// We are using scissoring to clip some objects. All low-level graphics API should support it. | // We are using scissoring to clip some objects. All low-level graphics API should support it. | |||
// - If your engine doesn't support scissoring yet, you may ign ore this at first. You will get some small glitches | // - If your engine doesn't support scissoring yet, you may ign ore this at first. You will get some small glitches | |||
// (some elements visible outside their bounds) but you can f ix that once everything else works! | // (some elements visible outside their bounds) but you can f ix that once everything else works! | |||
// - Clipping coordinates are provided in imgui coordinates spa ce: | // - Clipping coordinates are provided in imgui coordinates spa ce: | |||
// - For a given viewport, draw_data->DisplayPos == viewport- >Pos and draw_data->DisplaySize == viewport->Size | // - For a given viewport, draw_data->DisplayPos == viewport- >Pos and draw_data->DisplaySize == viewport->Size | |||
// - In a single viewport application, draw_data->DisplayPos == (0,0) and draw_data->DisplaySize == io.DisplaySize, but always use GetMainVie wport()->Pos/Size instead of hardcoding those values. | // - In a single viewport application, draw_data->DisplayPos == (0,0) and draw_data->DisplaySize == io.DisplaySize, but always use GetMainVie wport()->Pos/Size instead of hardcoding those values. | |||
// - In the interest of supporting multi-viewport application s (see 'docking' branch on github), | // - In the interest of supporting multi-viewport application s (see 'docking' branch on github), | |||
// always subtract draw_data->DisplayPos from clipping boun ds to convert them to your viewport space. | // always subtract draw_data->DisplayPos from clipping boun ds to convert them to your viewport space. | |||
// - Note that pcmd->ClipRect contains Min+Max bounds. Some gra phics API may use Min+Max, other may use Min+Size (size being Max-Min) | // - Note that pcmd->ClipRect contains Min+Max bounds. Some gra phics API may use Min+Max, other may use Min+Size (size being Max-Min) | |||
ImVec2 pos = draw_data->DisplayPos; | MyEngineSetScissor(clip_min.x, clip_min.y, clip_max.x, clip_max | |||
MyEngineScissor((int)(pcmd->ClipRect.x - pos.x), (int)(pcmd->Cl | .y); | |||
ipRect.y - pos.y), (int)(pcmd->ClipRect.z - pos.x), (int)(pcmd->ClipRect.w - pos | ||||
.y)); | // The texture for the draw call is specified by pcmd->GetTexID | |||
(). | ||||
// The vast majority of draw calls will use the Dear ImGui text | ||||
ure atlas, which value you have set yourself during initialization. | ||||
MyEngineBindTexture((MyTexture*)pcmd->GetTexID()); | ||||
// Render 'pcmd->ElemCount/3' indexed triangles. | // Render 'pcmd->ElemCount/3' indexed triangles. | |||
// By default the indices ImDrawIdx are 16-bit, you can change them to 32-bit in imconfig.h if your engine doesn't support 16-bit indices. | // By default the indices ImDrawIdx are 16-bit, you can change them to 32-bit in imconfig.h if your engine doesn't support 16-bit indices. | |||
MyEngineDrawIndexedTriangles(pcmd->ElemCount, sizeof(ImDrawIdx) == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, idx_buffer, vtx_buffer); | MyEngineDrawIndexedTriangles(pcmd->ElemCount, sizeof(ImDrawIdx) == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, idx_buffer + pcmd->IdxOffset, vtx_b uffer, pcmd->VtxOffset); | |||
} | } | |||
idx_buffer += pcmd->ElemCount; | ||||
} | } | |||
} | } | |||
} | } | |||
USING GAMEPAD/KEYBOARD NAVIGATION CONTROLS | USING GAMEPAD/KEYBOARD NAVIGATION CONTROLS | |||
------------------------------------------ | ------------------------------------------ | |||
- The gamepad/keyboard navigation is fairly functional and keeps being improved . | - The gamepad/keyboard navigation is fairly functional and keeps being improved . | |||
- Gamepad support is particularly useful to use Dear ImGui on a console system (e.g. PS4, Switch, XB1) without a mouse! | - Gamepad support is particularly useful to use Dear ImGui on a console system (e.g. PS4, Switch, XB1) without a mouse! | |||
- You can ask questions and report issues at https://github.com/ocornut/imgui/i ssues/787 | - You can ask questions and report issues at https://github.com/ocornut/imgui/i ssues/787 | |||
- The initial focus was to support game controllers, but keyboard is becoming i ncreasingly and decently usable. | - The initial focus was to support game controllers, but keyboard is becoming i ncreasingly and decently usable. | |||
- Keyboard: | - Keyboard: | |||
- Set io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard to enable. | - Application: Set io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard to e | |||
NewFrame() will automatically fill io.NavInputs[] based on your io.KeysDow | nable. | |||
n[] + io.KeyMap[] arrays. | - Internally: NewFrame() will automatically fill io.NavInputs[] based on bac | |||
- When keyboard navigation is active (io.NavActive + ImGuiConfigFlags_NavEna | kend's io.AddKeyEvent() calls. | |||
bleKeyboard), the io.WantCaptureKeyboard flag | - When keyboard navigation is active (io.NavActive + ImGuiConfigFlags_NavEna | |||
will be set. For more advanced uses, you may want to read from: | bleKeyboard), | |||
the io.WantCaptureKeyboard flag will be set. For more advanced uses, you m | ||||
ay want to read from: | ||||
- io.NavActive: true when a window is focused and it doesn't have the ImG uiWindowFlags_NoNavInputs flag set. | - io.NavActive: true when a window is focused and it doesn't have the ImG uiWindowFlags_NoNavInputs flag set. | |||
- io.NavVisible: true when the navigation cursor is visible (and usually goes false when mouse is used). | - io.NavVisible: true when the navigation cursor is visible (and usually goes false when mouse is used). | |||
- or query focus information with e.g. IsWindowFocused(ImGuiFocusedFlags_ AnyWindow), IsItemFocused() etc. functions. | - or query focus information with e.g. IsWindowFocused(ImGuiFocusedFlags_ AnyWindow), IsItemFocused() etc. functions. | |||
Please reach out if you think the game vs navigation input sharing could b e improved. | Please reach out if you think the game vs navigation input sharing could b e improved. | |||
- Gamepad: | - Gamepad: | |||
- Set io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad to enable. | - Application: Set io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad to en | |||
- Backend: Set io.BackendFlags |= ImGuiBackendFlags_HasGamepad + fill the io | able. | |||
.NavInputs[] fields before calling NewFrame(). | - Backend: Set io.BackendFlags |= ImGuiBackendFlags_HasGamepad + call io.Add | |||
Note that io.NavInputs[] is cleared by EndFrame(). | KeyEvent/AddKeyAnalogEvent() with ImGuiKey_Gamepad_XXX keys. | |||
- See 'enum ImGuiNavInput_' in imgui.h for a description of inputs. For each | For analog values (0.0f to 1.0f), backend is responsible to handling a dea | |||
entry of io.NavInputs[], set the following values: | d-zone and rescaling inputs accordingly. | |||
0.0f= not held. 1.0f= fully held. Pass intermediate 0.0f..1.0f values f | Backend code will probably need to transform your raw inputs (such as e.g. | |||
or analog triggers/sticks. | remapping your 0.2..0.9 raw input range to 0.0..1.0 imgui range, etc.). | |||
- We use a simple >0.0f test for activation testing, and won't attempt to te | - Internally: NewFrame() will automatically fill io.NavInputs[] based on bac | |||
st for a dead-zone. | kend's io.AddKeyEvent() + io.AddKeyAnalogEvent() calls. | |||
Your code will probably need to transform your raw inputs (such as e.g. re | - BEFORE 1.87, BACKENDS USED TO WRITE DIRECTLY TO io.NavInputs[]. This is go | |||
mapping your 0.2..0.9 raw input range to 0.0..1.0 imgui range, etc.). | ing to be obsoleted in the future. Please call io functions instead! | |||
- You can download PNG/PSD files depicting the gamepad controls for common c ontrollers at: http://dearimgui.org/controls_sheets | - You can download PNG/PSD files depicting the gamepad controls for common c ontrollers at: http://dearimgui.org/controls_sheets | |||
- If you need to share inputs between your game and the imgui parts, the eas | - If you need to share inputs between your game and the Dear ImGui interface | |||
iest approach is to go all-or-nothing, with a buttons combo | , the easiest approach is to go all-or-nothing, | |||
to toggle the target. Please reach out if you think the game vs navigation | with a buttons combo to toggle the target. Please reach out if you think t | |||
input sharing could be improved. | he game vs navigation input sharing could be improved. | |||
- Mouse: | - Mouse: | |||
- PS4 users: Consider emulating a mouse cursor with DualShock4 touch pad or a spare analog stick as a mouse-emulation fallback. | - PS4/PS5 users: Consider emulating a mouse cursor with DualShock4 touch pad or a spare analog stick as a mouse-emulation fallback. | |||
- Consoles/Tablet/Phone users: Consider using a Synergy 1.x server (on your PC) + uSynergy.c (on your console/tablet/phone app) to share your PC mouse/keybo ard. | - Consoles/Tablet/Phone users: Consider using a Synergy 1.x server (on your PC) + uSynergy.c (on your console/tablet/phone app) to share your PC mouse/keybo ard. | |||
- On a TV/console system where readability may be lower or mouse inputs may be awkward, you may want to set the ImGuiConfigFlags_NavEnableSetMousePos flag. | - On a TV/console system where readability may be lower or mouse inputs may be awkward, you may want to set the ImGuiConfigFlags_NavEnableSetMousePos flag. | |||
Enabling ImGuiConfigFlags_NavEnableSetMousePos + ImGuiBackendFlags_HasSetM ousePos instructs dear imgui to move your mouse cursor along with navigation mov ements. | Enabling ImGuiConfigFlags_NavEnableSetMousePos + ImGuiBackendFlags_HasSetM ousePos instructs dear imgui to move your mouse cursor along with navigation mov ements. | |||
When enabled, the NewFrame() function may alter 'io.MousePos' and set 'io. WantSetMousePos' to notify you that it wants the mouse cursor to be moved. | When enabled, the NewFrame() function may alter 'io.MousePos' and set 'io. WantSetMousePos' to notify you that it wants the mouse cursor to be moved. | |||
When that happens your backend NEEDS to move the OS or underlying mouse cu rsor on the next frame. Some of the backends in examples/ do that. | When that happens your backend NEEDS to move the OS or underlying mouse cu rsor on the next frame. Some of the backends in examples/ do that. | |||
(If you set the NavEnableSetMousePos flag but don't honor 'io.WantSetMouse Pos' properly, imgui will misbehave as it will see your mouse moving back and fo rth!) | (If you set the NavEnableSetMousePos flag but don't honor 'io.WantSetMouse Pos' properly, imgui will misbehave as it will see your mouse moving back and fo rth!) | |||
(In a setup when you may not have easy control over the mouse cursor, e.g. uSynergy.c doesn't expose moving remote mouse cursor, you may want | (In a setup when you may not have easy control over the mouse cursor, e.g. uSynergy.c doesn't expose moving remote mouse cursor, you may want | |||
to set a boolean to ignore your other external mouse positions until the external source is moved again.) | to set a boolean to ignore your other external mouse positions until the external source is moved again.) | |||
API BREAKING CHANGES | API BREAKING CHANGES | |||
==================== | ==================== | |||
Occasionally introducing changes that are breaking the API. We try to make the breakage minor and easy to fix. | Occasionally introducing changes that are breaking the API. We try to make the breakage minor and easy to fix. | |||
Below is a change-log of API breaking changes only. If you are using one of the functions listed, expect to have to fix some code. | Below is a change-log of API breaking changes only. If you are using one of the functions listed, expect to have to fix some code. | |||
When you are not sure about an old symbol or function name, try using the Searc h/Find function of your IDE to look for comments or references in all imgui file s. | When you are not sure about an old symbol or function name, try using the Searc h/Find function of your IDE to look for comments or references in all imgui file s. | |||
You can read releases logs https://github.com/ocornut/imgui/releases for more d etails. | You can read releases logs https://github.com/ocornut/imgui/releases for more d etails. | |||
- 2022/01/20 (1.87) - inputs: reworded gamepad IO. | ||||
- Backend writing to io.NavInputs[] -> backen | ||||
d should call io.AddKeyEvent()/io.AddKeyAnalogEvent() with ImGuiKey_GamepadXXX v | ||||
alues. | ||||
- 2022/01/19 (1.87) - sliders, drags: removed support for legacy arithmetic ope | ||||
rators (+,+-,*,/) when inputing text. This doesn't break any api/code but a feat | ||||
ure that used to be accessible by end-users (which seemingly no one used). | ||||
- 2022/01/17 (1.87) - inputs: reworked mouse IO. | ||||
- Backend writing to io.MousePos -> backen | ||||
d should call io.AddMousePosEvent() | ||||
- Backend writing to io.MouseDown[] -> backen | ||||
d should call io.AddMouseButtonEvent() | ||||
- Backend writing to io.MouseWheel -> backen | ||||
d should call io.AddMouseWheelEvent() | ||||
- Backend writing to io.MouseHoveredViewport -> backen | ||||
d should call io.AddMouseViewportEvent() [Docking branch w/ multi-viewports only | ||||
] | ||||
- 2022/01/10 (1.87) - inputs: reworked keyboard IO. Removed io.KeyMap[], io.Key | ||||
sDown[] in favor of calling io.AddKeyEvent(). Removed GetKeyIndex(), now unecess | ||||
ary. All IsKeyXXX() functions now take ImGuiKey values. All features are still f | ||||
unctional until IMGUI_DISABLE_OBSOLETE_KEYIO is defined. Read Changelog and Rele | ||||
ase Notes for details. | ||||
- IsKeyPressed(MY_NATIVE_KEY_XXX) -> use Is | ||||
KeyPressed(ImGuiKey_XXX) | ||||
- IsKeyPressed(GetKeyIndex(ImGuiKey_XXX)) -> use Is | ||||
KeyPressed(ImGuiKey_XXX) | ||||
- Backend writing to io.KeyMap[],io.KeysDown[] -> backen | ||||
d should call io.AddKeyEvent() | ||||
- Backend writing to io.KeyCtrl, io.KeyShift.. -> backen | ||||
d should call io.AddKeyEvent() with ImGuiKey_ModXXX values. *IF YOU PULLED CODE | ||||
BETWEEN 2021/01/10 and 2021/01/27: We used to have a io.AddKeyModsEvent() functi | ||||
on which was now replaced by io.AddKeyEvent() with ImGuiKey_ModXXX values.* | ||||
- one case won't work with backward compatibility: if your | ||||
custom backend used ImGuiKey as mock native indices (e.g. "io.KeyMap[ImGuiKey_A] | ||||
= ImGuiKey_A") because those values are now larger than the legacy KeyDown[] ar | ||||
ray. Will assert. | ||||
- inputs: added ImGuiKey_ModCtrl/ImGuiKey_ModShift/ImGuiKey | ||||
_ModAlt/ImGuiKey_ModSuper values to submit keyboard modifiers using io.AddKeyEve | ||||
nt(), instead of writing directly to io.KeyCtrl, io.KeyShift, io.KeyAlt, io.KeyS | ||||
uper. | ||||
- 2022/01/05 (1.87) - inputs: renamed ImGuiKey_KeyPadEnter to ImGuiKey_KeypadEn | ||||
ter to align with new symbols. Kept redirection enum. | ||||
- 2022/01/05 (1.87) - removed io.ImeSetInputScreenPosFn() in favor of more flex | ||||
ible io.SetPlatformImeDataFn(). Removed 'void* io.ImeWindowHandle' in favor of w | ||||
riting to 'void* ImGuiViewport::PlatformHandleRaw'. | ||||
- 2022/01/01 (1.87) - commented out redirecting functions/enums names that were | ||||
marked obsolete in 1.69, 1.70, 1.71, 1.72 (March-July 2019) | ||||
- ImGui::SetNextTreeNodeOpen() -> use ImGui::SetN | ||||
extItemOpen() | ||||
- ImGui::GetContentRegionAvailWidth() -> use ImGui::GetC | ||||
ontentRegionAvail().x | ||||
- ImGui::TreeAdvanceToLabelPos() -> use ImGui::SetC | ||||
ursorPosX(ImGui::GetCursorPosX() + ImGui::GetTreeNodeToLabelSpacing()); | ||||
- ImFontAtlas::CustomRect -> use ImFontAtlas | ||||
CustomRect | ||||
- ImGuiColorEditFlags_RGB/HSV/HEX -> use ImGuiColorE | ||||
ditFlags_DisplayRGB/HSV/Hex | ||||
- 2021/12/20 (1.86) - backends: removed obsolete Marmalade backend (imgui_impl_ marmalade.cpp) + example. Find last supported version at https://github.com/ocor nut/imgui/wiki/Bindings | - 2021/12/20 (1.86) - backends: removed obsolete Marmalade backend (imgui_impl_ marmalade.cpp) + example. Find last supported version at https://github.com/ocor nut/imgui/wiki/Bindings | |||
- 2021/11/04 (1.86) - removed CalcListClipping() function. Prefer using ImGuiLi stClipper which can return non-contiguous ranges. Please open an issue if you th ink you really need this function. | - 2021/11/04 (1.86) - removed CalcListClipping() function. Prefer using ImGuiLi stClipper which can return non-contiguous ranges. Please open an issue if you th ink you really need this function. | |||
- 2021/08/23 (1.85) - removed GetWindowContentRegionWidth() function. keep inli ne redirection helper. can use 'GetWindowContentRegionMax().x - GetWindowContent RegionMin().x' instead for generally 'GetContentRegionAvail().x' is more useful. | - 2021/08/23 (1.85) - removed GetWindowContentRegionWidth() function. keep inli ne redirection helper. can use 'GetWindowContentRegionMax().x - GetWindowContent RegionMin().x' instead for generally 'GetContentRegionAvail().x' is more useful. | |||
- 2021/07/26 (1.84) - commented out redirecting functions/enums names that were marked obsolete in 1.67 and 1.69 (March 2019): | - 2021/07/26 (1.84) - commented out redirecting functions/enums names that were marked obsolete in 1.67 and 1.69 (March 2019): | |||
- ImGui::GetOverlayDrawList() -> use ImGui::GetForegroun dDrawList() | - ImGui::GetOverlayDrawList() -> use ImGui::GetForegroun dDrawList() | |||
- ImFont::GlyphRangesBuilder -> use ImFontGlyphRangesBu ilder | - ImFont::GlyphRangesBuilder -> use ImFontGlyphRangesBu ilder | |||
- 2021/05/19 (1.83) - backends: obsoleted direct access to ImDrawCmd::TextureId in favor of calling ImDrawCmd::GetTexID(). | - 2021/05/19 (1.83) - backends: obsoleted direct access to ImDrawCmd::TextureId in favor of calling ImDrawCmd::GetTexID(). | |||
- if you are using official backends from the source tre e: you have nothing to do. | - if you are using official backends from the source tre e: you have nothing to do. | |||
- if you have copied old backend code or using your own: change access to draw_cmd->TextureId to draw_cmd->GetTexID(). | - if you have copied old backend code or using your own: change access to draw_cmd->TextureId to draw_cmd->GetTexID(). | |||
- 2021/03/12 (1.82) - upgraded ImDrawList::AddRect(), AddRectFilled(), PathRect () to use ImDrawFlags instead of ImDrawCornersFlags. | - 2021/03/12 (1.82) - upgraded ImDrawList::AddRect(), AddRectFilled(), PathRect () to use ImDrawFlags instead of ImDrawCornersFlags. | |||
skipping to change at line 901 | skipping to change at line 928 | |||
// Settings | // Settings | |||
static void WindowSettingsHandler_ClearAll(ImGuiContext*, ImGuiSetti ngsHandler*); | static void WindowSettingsHandler_ClearAll(ImGuiContext*, ImGuiSetti ngsHandler*); | |||
static void* WindowSettingsHandler_ReadOpen(ImGuiContext*, ImGuiSetti ngsHandler*, const char* name); | static void* WindowSettingsHandler_ReadOpen(ImGuiContext*, ImGuiSetti ngsHandler*, const char* name); | |||
static void WindowSettingsHandler_ReadLine(ImGuiContext*, ImGuiSetti ngsHandler*, void* entry, const char* line); | static void WindowSettingsHandler_ReadLine(ImGuiContext*, ImGuiSetti ngsHandler*, void* entry, const char* line); | |||
static void WindowSettingsHandler_ApplyAll(ImGuiContext*, ImGuiSetti ngsHandler*); | static void WindowSettingsHandler_ApplyAll(ImGuiContext*, ImGuiSetti ngsHandler*); | |||
static void WindowSettingsHandler_WriteAll(ImGuiContext*, ImGuiSetti ngsHandler*, ImGuiTextBuffer* buf); | static void WindowSettingsHandler_WriteAll(ImGuiContext*, ImGuiSetti ngsHandler*, ImGuiTextBuffer* buf); | |||
// Platform Dependents default implementation for IO functions | // Platform Dependents default implementation for IO functions | |||
static const char* GetClipboardTextFn_DefaultImpl(void* user_data); | static const char* GetClipboardTextFn_DefaultImpl(void* user_data); | |||
static void SetClipboardTextFn_DefaultImpl(void* user_data, const ch ar* text); | static void SetClipboardTextFn_DefaultImpl(void* user_data, const ch ar* text); | |||
static void ImeSetInputScreenPosFn_DefaultImpl(int x, int y); | static void SetPlatformImeDataFn_DefaultImpl(ImGuiViewport* viewport , ImGuiPlatformImeData* data); | |||
namespace ImGui | namespace ImGui | |||
{ | { | |||
// Navigation | // Navigation | |||
static void NavUpdate(); | static void NavUpdate(); | |||
static void NavUpdateWindowing(); | static void NavUpdateWindowing(); | |||
static void NavUpdateWindowingOverlay(); | static void NavUpdateWindowingOverlay(); | |||
static void NavUpdateCancelRequest(); | static void NavUpdateCancelRequest(); | |||
static void NavUpdateCreateMoveRequest(); | static void NavUpdateCreateMoveRequest(); | |||
static void NavUpdateCreateTabbingRequest(); | static void NavUpdateCreateTabbingRequest(); | |||
skipping to change at line 935 | skipping to change at line 962 | |||
static int FindWindowFocusIndex(ImGuiWindow* window); | static int FindWindowFocusIndex(ImGuiWindow* window); | |||
// Error Checking and Debug Tools | // Error Checking and Debug Tools | |||
static void ErrorCheckNewFrameSanityChecks(); | static void ErrorCheckNewFrameSanityChecks(); | |||
static void ErrorCheckEndFrameSanityChecks(); | static void ErrorCheckEndFrameSanityChecks(); | |||
static void UpdateDebugToolItemPicker(); | static void UpdateDebugToolItemPicker(); | |||
static void UpdateDebugToolStackQueries(); | static void UpdateDebugToolStackQueries(); | |||
// Misc | // Misc | |||
static void UpdateSettings(); | static void UpdateSettings(); | |||
static void UpdateKeyboardInputs(); | ||||
static void UpdateMouseInputs(); | static void UpdateMouseInputs(); | |||
static void UpdateMouseWheel(); | static void UpdateMouseWheel(); | |||
static bool UpdateWindowManualResize(ImGuiWindow* window, const ImVe c2& size_auto_fit, int* border_held, int resize_grip_count, ImU32 resize_grip_co l[4], const ImRect& visibility_rect); | static bool UpdateWindowManualResize(ImGuiWindow* window, const ImVe c2& size_auto_fit, int* border_held, int resize_grip_count, ImU32 resize_grip_co l[4], const ImRect& visibility_rect); | |||
static void RenderWindowOuterBorders(ImGuiWindow* window); | static void RenderWindowOuterBorders(ImGuiWindow* window); | |||
static void RenderWindowDecorations(ImGuiWindow* window, const ImRec t& title_bar_rect, bool title_bar_is_highlight, int resize_grip_count, const ImU 32 resize_grip_col[4], float resize_grip_draw_size); | static void RenderWindowDecorations(ImGuiWindow* window, const ImRec t& title_bar_rect, bool title_bar_is_highlight, int resize_grip_count, const ImU 32 resize_grip_col[4], float resize_grip_draw_size); | |||
static void RenderWindowTitleBarContents(ImGuiWindow* window, const ImRect& title_bar_rect, const char* name, bool* p_open); | static void RenderWindowTitleBarContents(ImGuiWindow* window, const ImRect& title_bar_rect, const char* name, bool* p_open); | |||
static void RenderDimmedBackgroundBehindWindow(ImGuiWindow* window, ImU32 col); | static void RenderDimmedBackgroundBehindWindow(ImGuiWindow* window, ImU32 col); | |||
static void RenderDimmedBackgrounds(); | static void RenderDimmedBackgrounds(); | |||
static ImGuiWindow* FindBlockingModal(ImGuiWindow* window); | static ImGuiWindow* FindBlockingModal(ImGuiWindow* window); | |||
skipping to change at line 1076 | skipping to change at line 1104 | |||
TabMinWidthForCloseButton = (TabMinWidthForCloseButton != FLT_MAX) ? ImFloor (TabMinWidthForCloseButton * scale_factor) : FLT_MAX; | TabMinWidthForCloseButton = (TabMinWidthForCloseButton != FLT_MAX) ? ImFloor (TabMinWidthForCloseButton * scale_factor) : FLT_MAX; | |||
DisplayWindowPadding = ImFloor(DisplayWindowPadding * scale_factor); | DisplayWindowPadding = ImFloor(DisplayWindowPadding * scale_factor); | |||
DisplaySafeAreaPadding = ImFloor(DisplaySafeAreaPadding * scale_factor); | DisplaySafeAreaPadding = ImFloor(DisplaySafeAreaPadding * scale_factor); | |||
MouseCursorScale = ImFloor(MouseCursorScale * scale_factor); | MouseCursorScale = ImFloor(MouseCursorScale * scale_factor); | |||
} | } | |||
ImGuiIO::ImGuiIO() | ImGuiIO::ImGuiIO() | |||
{ | { | |||
// Most fields are initialized with zero | // Most fields are initialized with zero | |||
memset(this, 0, sizeof(*this)); | memset(this, 0, sizeof(*this)); | |||
IM_ASSERT(IM_ARRAYSIZE(ImGuiIO::MouseDown) == ImGuiMouseButton_COUNT && IM_A RRAYSIZE(ImGuiIO::MouseClicked) == ImGuiMouseButton_COUNT); // Our pre-C++11 IM_ STATIC_ASSERT() macros triggers warning on modern compilers so we don't use it h ere. | IM_STATIC_ASSERT(IM_ARRAYSIZE(ImGuiIO::MouseDown) == ImGuiMouseButton_COUNT && IM_ARRAYSIZE(ImGuiIO::MouseClicked) == ImGuiMouseButton_COUNT); | |||
// Settings | // Settings | |||
ConfigFlags = ImGuiConfigFlags_None; | ConfigFlags = ImGuiConfigFlags_None; | |||
BackendFlags = ImGuiBackendFlags_None; | BackendFlags = ImGuiBackendFlags_None; | |||
DisplaySize = ImVec2(-1.0f, -1.0f); | DisplaySize = ImVec2(-1.0f, -1.0f); | |||
DeltaTime = 1.0f / 60.0f; | DeltaTime = 1.0f / 60.0f; | |||
IniSavingRate = 5.0f; | IniSavingRate = 5.0f; | |||
IniFilename = "imgui.ini"; // Important: "imgui.ini" is relative to current working dir, most apps will want to lock this to an absolute path (e.g. same pat h as executables). | IniFilename = "imgui.ini"; // Important: "imgui.ini" is relative to current working dir, most apps will want to lock this to an absolute path (e.g. same pat h as executables). | |||
LogFilename = "imgui_log.txt"; | LogFilename = "imgui_log.txt"; | |||
MouseDoubleClickTime = 0.30f; | MouseDoubleClickTime = 0.30f; | |||
MouseDoubleClickMaxDist = 6.0f; | MouseDoubleClickMaxDist = 6.0f; | |||
#ifndef IMGUI_DISABLE_OBSOLETE_KEYIO | ||||
for (int i = 0; i < ImGuiKey_COUNT; i++) | for (int i = 0; i < ImGuiKey_COUNT; i++) | |||
KeyMap[i] = -1; | KeyMap[i] = -1; | |||
#endif | ||||
KeyRepeatDelay = 0.275f; | KeyRepeatDelay = 0.275f; | |||
KeyRepeatRate = 0.050f; | KeyRepeatRate = 0.050f; | |||
UserData = NULL; | UserData = NULL; | |||
Fonts = NULL; | Fonts = NULL; | |||
FontGlobalScale = 1.0f; | FontGlobalScale = 1.0f; | |||
FontDefault = NULL; | FontDefault = NULL; | |||
FontAllowUserScaling = false; | FontAllowUserScaling = false; | |||
DisplayFramebufferScale = ImVec2(1.0f, 1.0f); | DisplayFramebufferScale = ImVec2(1.0f, 1.0f); | |||
// Miscellaneous options | // Miscellaneous options | |||
MouseDrawCursor = false; | MouseDrawCursor = false; | |||
#ifdef __APPLE__ | #ifdef __APPLE__ | |||
ConfigMacOSXBehaviors = true; // Set Mac OS X style defaults based on __APP LE__ compile time flag | ConfigMacOSXBehaviors = true; // Set Mac OS X style defaults based on __APP LE__ compile time flag | |||
#else | #else | |||
ConfigMacOSXBehaviors = false; | ConfigMacOSXBehaviors = false; | |||
#endif | #endif | |||
ConfigInputTrickleEventQueue = true; | ||||
ConfigInputTextCursorBlink = true; | ConfigInputTextCursorBlink = true; | |||
ConfigWindowsResizeFromEdges = true; | ConfigWindowsResizeFromEdges = true; | |||
ConfigWindowsMoveFromTitleBarOnly = false; | ConfigWindowsMoveFromTitleBarOnly = false; | |||
ConfigMemoryCompactTimer = 60.0f; | ConfigMemoryCompactTimer = 60.0f; | |||
// Platform Functions | // Platform Functions | |||
BackendPlatformName = BackendRendererName = NULL; | BackendPlatformName = BackendRendererName = NULL; | |||
BackendPlatformUserData = BackendRendererUserData = BackendLanguageUserData = NULL; | BackendPlatformUserData = BackendRendererUserData = BackendLanguageUserData = NULL; | |||
GetClipboardTextFn = GetClipboardTextFn_DefaultImpl; // Platform dependent default implementations | GetClipboardTextFn = GetClipboardTextFn_DefaultImpl; // Platform dependent default implementations | |||
SetClipboardTextFn = SetClipboardTextFn_DefaultImpl; | SetClipboardTextFn = SetClipboardTextFn_DefaultImpl; | |||
ClipboardUserData = NULL; | ClipboardUserData = NULL; | |||
ImeSetInputScreenPosFn = ImeSetInputScreenPosFn_DefaultImpl; | SetPlatformImeDataFn = SetPlatformImeDataFn_DefaultImpl; | |||
ImeWindowHandle = NULL; | ||||
// Input (NB: we already have memset zero the entire structure!) | // Input (NB: we already have memset zero the entire structure!) | |||
MousePos = ImVec2(-FLT_MAX, -FLT_MAX); | MousePos = ImVec2(-FLT_MAX, -FLT_MAX); | |||
MousePosPrev = ImVec2(-FLT_MAX, -FLT_MAX); | MousePosPrev = ImVec2(-FLT_MAX, -FLT_MAX); | |||
MouseDragThreshold = 6.0f; | MouseDragThreshold = 6.0f; | |||
for (int i = 0; i < IM_ARRAYSIZE(MouseDownDuration); i++) MouseDownDuration[ i] = MouseDownDurationPrev[i] = -1.0f; | for (int i = 0; i < IM_ARRAYSIZE(MouseDownDuration); i++) MouseDownDuration[ i] = MouseDownDurationPrev[i] = -1.0f; | |||
for (int i = 0; i < IM_ARRAYSIZE(KeysDownDuration); i++) KeysDownDuration[i] = KeysDownDurationPrev[i] = -1.0f; | for (int i = 0; i < IM_ARRAYSIZE(KeysData); i++) { KeysData[i].DownDuration = KeysData[i].DownDurationPrev = -1.0f; } | |||
for (int i = 0; i < IM_ARRAYSIZE(NavInputsDownDuration); i++) NavInputsDownD uration[i] = -1.0f; | for (int i = 0; i < IM_ARRAYSIZE(NavInputsDownDuration); i++) NavInputsDownD uration[i] = -1.0f; | |||
BackendUsingLegacyKeyArrays = (ImS8)-1; | ||||
BackendUsingLegacyNavInputArray = true; // assume using legacy array until p | ||||
roven wrong | ||||
} | } | |||
// Pass in translated ASCII characters for text input. | // Pass in translated ASCII characters for text input. | |||
// - with glfw you can get those from the callback set in glfwSetCharCallback() | // - with glfw you can get those from the callback set in glfwSetCharCallback() | |||
// - on Windows you can get those using ToAscii+keyboard state, or via the WM_CH AR message | // - on Windows you can get those using ToAscii+keyboard state, or via the WM_CH AR message | |||
// FIXME: Should in theory be called "AddCharacterEvent()" to be consistent with new API | ||||
void ImGuiIO::AddInputCharacter(unsigned int c) | void ImGuiIO::AddInputCharacter(unsigned int c) | |||
{ | { | |||
if (c != 0) | ImGuiContext& g = *GImGui; | |||
InputQueueCharacters.push_back(c <= IM_UNICODE_CODEPOINT_MAX ? (ImWchar) | IM_ASSERT(&g.IO == this && "Can only add events to current context."); | |||
c : IM_UNICODE_CODEPOINT_INVALID); | if (c == 0) | |||
return; | ||||
ImGuiInputEvent e; | ||||
e.Type = ImGuiInputEventType_Char; | ||||
e.Source = ImGuiInputSource_Keyboard; | ||||
e.Text.Char = c; | ||||
g.InputEventsQueue.push_back(e); | ||||
} | } | |||
// UTF16 strings use surrogate pairs to encode codepoints >= 0x10000, so | // UTF16 strings use surrogate pairs to encode codepoints >= 0x10000, so | |||
// we should save the high surrogate. | // we should save the high surrogate. | |||
void ImGuiIO::AddInputCharacterUTF16(ImWchar16 c) | void ImGuiIO::AddInputCharacterUTF16(ImWchar16 c) | |||
{ | { | |||
if (c == 0 && InputQueueSurrogate == 0) | if (c == 0 && InputQueueSurrogate == 0) | |||
return; | return; | |||
if ((c & 0xFC00) == 0xD800) // High surrogate, must save | if ((c & 0xFC00) == 0xD800) // High surrogate, must save | |||
{ | { | |||
if (InputQueueSurrogate != 0) | if (InputQueueSurrogate != 0) | |||
InputQueueCharacters.push_back(IM_UNICODE_CODEPOINT_INVALID); | AddInputCharacter(IM_UNICODE_CODEPOINT_INVALID); | |||
InputQueueSurrogate = c; | InputQueueSurrogate = c; | |||
return; | return; | |||
} | } | |||
ImWchar cp = c; | ImWchar cp = c; | |||
if (InputQueueSurrogate != 0) | if (InputQueueSurrogate != 0) | |||
{ | { | |||
if ((c & 0xFC00) != 0xDC00) // Invalid low surrogate | if ((c & 0xFC00) != 0xDC00) // Invalid low surrogate | |||
{ | { | |||
InputQueueCharacters.push_back(IM_UNICODE_CODEPOINT_INVALID); | AddInputCharacter(IM_UNICODE_CODEPOINT_INVALID); | |||
} | } | |||
else | else | |||
{ | { | |||
#if IM_UNICODE_CODEPOINT_MAX == 0xFFFF | #if IM_UNICODE_CODEPOINT_MAX == 0xFFFF | |||
cp = IM_UNICODE_CODEPOINT_INVALID; // Codepoint will not fit in ImWc har | cp = IM_UNICODE_CODEPOINT_INVALID; // Codepoint will not fit in ImWc har | |||
#else | #else | |||
cp = (ImWchar)(((InputQueueSurrogate - 0xD800) << 10) + (c - 0xDC00) + 0x10000); | cp = (ImWchar)(((InputQueueSurrogate - 0xD800) << 10) + (c - 0xDC00) + 0x10000); | |||
#endif | #endif | |||
} | } | |||
InputQueueSurrogate = 0; | InputQueueSurrogate = 0; | |||
} | } | |||
InputQueueCharacters.push_back(cp); | AddInputCharacter((unsigned)cp); | |||
} | } | |||
void ImGuiIO::AddInputCharactersUTF8(const char* utf8_chars) | void ImGuiIO::AddInputCharactersUTF8(const char* utf8_chars) | |||
{ | { | |||
while (*utf8_chars != 0) | while (*utf8_chars != 0) | |||
{ | { | |||
unsigned int c = 0; | unsigned int c = 0; | |||
utf8_chars += ImTextCharFromUtf8(&c, utf8_chars, NULL); | utf8_chars += ImTextCharFromUtf8(&c, utf8_chars, NULL); | |||
if (c != 0) | if (c != 0) | |||
InputQueueCharacters.push_back((ImWchar)c); | AddInputCharacter(c); | |||
} | } | |||
} | } | |||
void ImGuiIO::ClearInputCharacters() | void ImGuiIO::ClearInputCharacters() | |||
{ | { | |||
InputQueueCharacters.resize(0); | InputQueueCharacters.resize(0); | |||
} | } | |||
void ImGuiIO::ClearInputKeys() | void ImGuiIO::ClearInputKeys() | |||
{ | { | |||
#ifndef IMGUI_DISABLE_OBSOLETE_KEYIO | ||||
memset(KeysDown, 0, sizeof(KeysDown)); | memset(KeysDown, 0, sizeof(KeysDown)); | |||
for (int n = 0; n < IM_ARRAYSIZE(KeysDownDuration); n++) | #endif | |||
KeysDownDuration[n] = KeysDownDurationPrev[n] = -1.0f; | for (int n = 0; n < IM_ARRAYSIZE(KeysData); n++) | |||
{ | ||||
KeysData[n].Down = false; | ||||
KeysData[n].DownDuration = -1.0f; | ||||
KeysData[n].DownDurationPrev = -1.0f; | ||||
} | ||||
KeyCtrl = KeyShift = KeyAlt = KeySuper = false; | KeyCtrl = KeyShift = KeyAlt = KeySuper = false; | |||
KeyMods = KeyModsPrev = ImGuiKeyModFlags_None; | KeyMods = KeyModsPrev = ImGuiKeyModFlags_None; | |||
for (int n = 0; n < IM_ARRAYSIZE(NavInputsDownDuration); n++) | for (int n = 0; n < IM_ARRAYSIZE(NavInputsDownDuration); n++) | |||
NavInputsDownDuration[n] = NavInputsDownDurationPrev[n] = -1.0f; | NavInputsDownDuration[n] = NavInputsDownDurationPrev[n] = -1.0f; | |||
} | } | |||
// Queue a new key down/up event. | ||||
// - ImGuiKey key: Translated key (as in, generally ImGuiKey_A matches the | ||||
key end-user would use to emit an 'A' character) | ||||
// - bool down: Is the key down? use false to signify a key release. | ||||
// - float analog_value: 0.0f..1.0f | ||||
void ImGuiIO::AddKeyAnalogEvent(ImGuiKey key, bool down, float analog_value) | ||||
{ | ||||
//if (e->Down) { IMGUI_DEBUG_LOG("AddKeyEvent() Key='%s' %d, NativeKeycode = | ||||
%d, NativeScancode = %d\n", ImGui::GetKeyName(e->Key), e->Down, e->NativeKeycod | ||||
e, e->NativeScancode); } | ||||
if (key == ImGuiKey_None) | ||||
return; | ||||
ImGuiContext& g = *GImGui; | ||||
IM_ASSERT(&g.IO == this && "Can only add events to current context."); | ||||
IM_ASSERT(ImGui::IsNamedKey(key)); // Backend needs to pass a valid ImGuiKey | ||||
_ constant. 0..511 values are legacy native key codes which are not accepted by | ||||
this API. | ||||
// Verify that backend isn't mixing up using new io.AddKeyEvent() api and ol | ||||
d io.KeysDown[] + io.KeyMap[] data. | ||||
#ifndef IMGUI_DISABLE_OBSOLETE_KEYIO | ||||
IM_ASSERT((BackendUsingLegacyKeyArrays == -1 || BackendUsingLegacyKeyArrays | ||||
== 0) && "Backend needs to either only use io.AddKeyEvent(), either only fill le | ||||
gacy io.KeysDown[] + io.KeyMap[]. Not both!"); | ||||
if (BackendUsingLegacyKeyArrays == -1) | ||||
for (int n = ImGuiKey_NamedKey_BEGIN; n < ImGuiKey_NamedKey_END; n++) | ||||
IM_ASSERT(KeyMap[n] == -1 && "Backend needs to either only use io.Ad | ||||
dKeyEvent(), either only fill legacy io.KeysDown[] + io.KeyMap[]. Not both!"); | ||||
BackendUsingLegacyKeyArrays = 0; | ||||
#endif | ||||
if (ImGui::IsGamepadKey(key)) | ||||
BackendUsingLegacyNavInputArray = false; | ||||
// Partial filter of duplicates (not strictly needed, but makes data neater | ||||
in particular for key mods and gamepad values which are most commonly spmamed) | ||||
ImGuiKeyData* key_data = ImGui::GetKeyData(key); | ||||
if (key_data->Down == down && key_data->AnalogValue == analog_value) | ||||
{ | ||||
bool found = false; | ||||
for (int n = g.InputEventsQueue.Size - 1; n >= 0 && !found; n--) | ||||
if (g.InputEventsQueue[n].Type == ImGuiInputEventType_Key && g.Input | ||||
EventsQueue[n].Key.Key == key) | ||||
found = true; | ||||
if (!found) | ||||
return; | ||||
} | ||||
// Add event | ||||
ImGuiInputEvent e; | ||||
e.Type = ImGuiInputEventType_Key; | ||||
e.Source = ImGui::IsGamepadKey(key) ? ImGuiInputSource_Gamepad : ImGuiInputS | ||||
ource_Keyboard; | ||||
e.Key.Key = key; | ||||
e.Key.Down = down; | ||||
e.Key.AnalogValue = analog_value; | ||||
g.InputEventsQueue.push_back(e); | ||||
} | ||||
void ImGuiIO::AddKeyEvent(ImGuiKey key, bool down) | ||||
{ | ||||
AddKeyAnalogEvent(key, down, down ? 1.0f : 0.0f); | ||||
} | ||||
// [Optional] Call after AddKeyEvent(). | ||||
// Specify native keycode, scancode + Specify index for legacy <1.87 IsKeyXXX() | ||||
functions with native indices. | ||||
// If you are writing a backend in 2022 or don't use IsKeyXXX() with native valu | ||||
es that are not ImGuiKey values, you can avoid calling this. | ||||
void ImGuiIO::SetKeyEventNativeData(ImGuiKey key, int native_keycode, int native | ||||
_scancode, int native_legacy_index) | ||||
{ | ||||
if (key == ImGuiKey_None) | ||||
return; | ||||
IM_ASSERT(ImGui::IsNamedKey(key)); // >= 512 | ||||
IM_ASSERT(native_legacy_index == -1 || ImGui::IsLegacyKey(native_legacy_inde | ||||
x)); // >= 0 && <= 511 | ||||
IM_UNUSED(native_keycode); // Yet unused | ||||
IM_UNUSED(native_scancode); // Yet unused | ||||
// Build native->imgui map so old user code can still call key functions wit | ||||
h native 0..511 values. | ||||
#ifndef IMGUI_DISABLE_OBSOLETE_KEYIO | ||||
const int legacy_key = (native_legacy_index != -1) ? native_legacy_index : n | ||||
ative_keycode; | ||||
if (ImGui::IsLegacyKey(legacy_key)) | ||||
KeyMap[legacy_key] = key; | ||||
#else | ||||
IM_UNUSED(key); | ||||
IM_UNUSED(native_legacy_index); | ||||
#endif | ||||
} | ||||
// Queue a mouse move event | ||||
void ImGuiIO::AddMousePosEvent(float x, float y) | ||||
{ | ||||
ImGuiContext& g = *GImGui; | ||||
IM_ASSERT(&g.IO == this && "Can only add events to current context."); | ||||
ImGuiInputEvent e; | ||||
e.Type = ImGuiInputEventType_MousePos; | ||||
e.Source = ImGuiInputSource_Mouse; | ||||
e.MousePos.PosX = x; | ||||
e.MousePos.PosY = y; | ||||
g.InputEventsQueue.push_back(e); | ||||
} | ||||
void ImGuiIO::AddMouseButtonEvent(int mouse_button, bool down) | ||||
{ | ||||
ImGuiContext& g = *GImGui; | ||||
IM_ASSERT(&g.IO == this && "Can only add events to current context."); | ||||
IM_ASSERT(mouse_button >= 0 && mouse_button < ImGuiMouseButton_COUNT); | ||||
ImGuiInputEvent e; | ||||
e.Type = ImGuiInputEventType_MouseButton; | ||||
e.Source = ImGuiInputSource_Mouse; | ||||
e.MouseButton.Button = mouse_button; | ||||
e.MouseButton.Down = down; | ||||
g.InputEventsQueue.push_back(e); | ||||
} | ||||
// Queue a mouse wheel event (most mouse/API will only have a Y component) | ||||
void ImGuiIO::AddMouseWheelEvent(float wheel_x, float wheel_y) | ||||
{ | ||||
ImGuiContext& g = *GImGui; | ||||
IM_ASSERT(&g.IO == this && "Can only add events to current context."); | ||||
if (wheel_x == 0.0f && wheel_y == 0.0f) | ||||
return; | ||||
ImGuiInputEvent e; | ||||
e.Type = ImGuiInputEventType_MouseWheel; | ||||
e.Source = ImGuiInputSource_Mouse; | ||||
e.MouseWheel.WheelX = wheel_x; | ||||
e.MouseWheel.WheelY = wheel_y; | ||||
g.InputEventsQueue.push_back(e); | ||||
} | ||||
void ImGuiIO::AddFocusEvent(bool focused) | void ImGuiIO::AddFocusEvent(bool focused) | |||
{ | { | |||
// We intentionally overwrite this and process in NewFrame(), in order to gi | ImGuiContext& g = *GImGui; | |||
ve a chance | IM_ASSERT(&g.IO == this && "Can only add events to current context."); | |||
// to multi-viewports backends to queue AddFocusEvent(false),AddFocusEvent(t | ||||
rue) in same frame. | ImGuiInputEvent e; | |||
AppFocusLost = !focused; | e.Type = ImGuiInputEventType_Focus; | |||
e.AppFocused.Focused = focused; | ||||
g.InputEventsQueue.push_back(e); | ||||
} | } | |||
//----------------------------------------------------------------------------- | //----------------------------------------------------------------------------- | |||
// [SECTION] MISC HELPERS/UTILITIES (Geometry functions) | // [SECTION] MISC HELPERS/UTILITIES (Geometry functions) | |||
//----------------------------------------------------------------------------- | //----------------------------------------------------------------------------- | |||
ImVec2 ImBezierCubicClosestPoint(const ImVec2& p1, const ImVec2& p2, const ImVec 2& p3, const ImVec2& p4, const ImVec2& p, int num_segments) | ImVec2 ImBezierCubicClosestPoint(const ImVec2& p1, const ImVec2& p2, const ImVec 2& p3, const ImVec2& p4, const ImVec2& p, int num_segments) | |||
{ | { | |||
IM_ASSERT(num_segments > 0); // Use ImBezierCubicClosestPointCasteljau() | IM_ASSERT(num_segments > 0); // Use ImBezierCubicClosestPointCasteljau() | |||
ImVec2 p_last = p1; | ImVec2 p_last = p1; | |||
skipping to change at line 3191 | skipping to change at line 3360 | |||
} | } | |||
} | } | |||
g.ActiveId = id; | g.ActiveId = id; | |||
g.ActiveIdAllowOverlap = false; | g.ActiveIdAllowOverlap = false; | |||
g.ActiveIdNoClearOnFocusLoss = false; | g.ActiveIdNoClearOnFocusLoss = false; | |||
g.ActiveIdWindow = window; | g.ActiveIdWindow = window; | |||
g.ActiveIdHasBeenEditedThisFrame = false; | g.ActiveIdHasBeenEditedThisFrame = false; | |||
if (id) | if (id) | |||
{ | { | |||
g.ActiveIdIsAlive = id; | g.ActiveIdIsAlive = id; | |||
g.ActiveIdSource = (g.NavActivateId == id || g.NavActivateInputId == id || g.NavJustMovedToId == id) ? ImGuiInputSource_Nav : ImGuiInputSource_Mouse; | g.ActiveIdSource = (g.NavActivateId == id || g.NavActivateInputId == id || g.NavJustMovedToId == id) ? (ImGuiInputSource)ImGuiInputSource_Nav : ImGuiInp utSource_Mouse; | |||
} | } | |||
// Clear declaration of inputs claimed by the widget | // Clear declaration of inputs claimed by the widget | |||
// (Please note that this is WIP and not all keys/inputs are thoroughly decl ared by all widgets yet) | // (Please note that this is WIP and not all keys/inputs are thoroughly decl ared by all widgets yet) | |||
g.ActiveIdUsingMouseWheel = false; | g.ActiveIdUsingMouseWheel = false; | |||
g.ActiveIdUsingNavDirMask = 0x00; | g.ActiveIdUsingNavDirMask = 0x00; | |||
g.ActiveIdUsingNavInputMask = 0x00; | g.ActiveIdUsingNavInputMask = 0x00; | |||
g.ActiveIdUsingKeyInputMask = 0x00; | g.ActiveIdUsingKeyInputMask.ClearAllBits(); | |||
} | } | |||
void ImGui::ClearActiveID() | void ImGui::ClearActiveID() | |||
{ | { | |||
SetActiveID(0, NULL); // g.ActiveId = 0; | SetActiveID(0, NULL); // g.ActiveId = 0; | |||
} | } | |||
void ImGui::SetHoveredID(ImGuiID id) | void ImGui::SetHoveredID(ImGuiID id) | |||
{ | { | |||
ImGuiContext& g = *GImGui; | ImGuiContext& g = *GImGui; | |||
skipping to change at line 3730 | skipping to change at line 3899 | |||
bool hovered_window_above_modal = g.HoveredWindow && (modal == NULL || I sWindowAbove(g.HoveredWindow, modal)); | bool hovered_window_above_modal = g.HoveredWindow && (modal == NULL || I sWindowAbove(g.HoveredWindow, modal)); | |||
ClosePopupsOverWindow(hovered_window_above_modal ? g.HoveredWindow : mod al, true); | ClosePopupsOverWindow(hovered_window_above_modal ? g.HoveredWindow : mod al, true); | |||
} | } | |||
} | } | |||
static bool IsWindowActiveAndVisible(ImGuiWindow* window) | static bool IsWindowActiveAndVisible(ImGuiWindow* window) | |||
{ | { | |||
return (window->Active) && (!window->Hidden); | return (window->Active) && (!window->Hidden); | |||
} | } | |||
static void ImGui::UpdateKeyboardInputs() | ||||
{ | ||||
ImGuiContext& g = *GImGui; | ||||
ImGuiIO& io = g.IO; | ||||
// Synchronize io.KeyMods with individual modifiers io.KeyXXX bools | ||||
io.KeyMods = GetMergedKeyModFlags(); | ||||
// Import legacy keys or verify they are not used | ||||
#ifndef IMGUI_DISABLE_OBSOLETE_KEYIO | ||||
if (io.BackendUsingLegacyKeyArrays == 0) | ||||
{ | ||||
// Backend used new io.AddKeyEvent() API: Good! Verify that old arrays a | ||||
re never written too. | ||||
for (int n = 0; n < IM_ARRAYSIZE(io.KeysDown); n++) | ||||
IM_ASSERT(io.KeysDown[n] == false && "Backend needs to either only u | ||||
se io.AddKeyEvent(), either only fill legacy io.KeysDown[] + io.KeyMap[]. Not bo | ||||
th!"); | ||||
} | ||||
else | ||||
{ | ||||
if (g.FrameCount == 0) | ||||
for (int n = ImGuiKey_LegacyNativeKey_BEGIN; n < ImGuiKey_LegacyNati | ||||
veKey_END; n++) | ||||
IM_ASSERT(g.IO.KeyMap[n] == -1 && "Backend is not allowed to wri | ||||
te to io.KeyMap[0..511]!"); | ||||
// Build reverse KeyMap (Named -> Legacy) | ||||
for (int n = ImGuiKey_NamedKey_BEGIN; n < ImGuiKey_NamedKey_END; n++) | ||||
if (io.KeyMap[n] != -1) | ||||
{ | ||||
IM_ASSERT(IsLegacyKey((ImGuiKey)io.KeyMap[n])); | ||||
io.KeyMap[io.KeyMap[n]] = n; | ||||
} | ||||
// Import legacy keys into new ones | ||||
for (int n = ImGuiKey_LegacyNativeKey_BEGIN; n < ImGuiKey_LegacyNativeKe | ||||
y_END; n++) | ||||
if (io.KeysDown[n] || io.BackendUsingLegacyKeyArrays == 1) | ||||
{ | ||||
const ImGuiKey key = (ImGuiKey)(io.KeyMap[n] != -1 ? io.KeyMap[n | ||||
] : n); | ||||
IM_ASSERT(io.KeyMap[n] == -1 || IsNamedKey(key)); | ||||
io.KeysData[key].Down = io.KeysDown[n]; | ||||
io.BackendUsingLegacyKeyArrays = 1; | ||||
} | ||||
if (io.BackendUsingLegacyKeyArrays == 1) | ||||
{ | ||||
io.KeysData[ImGuiKey_ModCtrl].Down = io.KeyCtrl; | ||||
io.KeysData[ImGuiKey_ModShift].Down = io.KeyShift; | ||||
io.KeysData[ImGuiKey_ModAlt].Down = io.KeyAlt; | ||||
io.KeysData[ImGuiKey_ModSuper].Down = io.KeySuper; | ||||
} | ||||
} | ||||
#endif | ||||
// Clear gamepad data if disabled | ||||
if ((io.BackendFlags & ImGuiBackendFlags_HasGamepad) == 0) | ||||
for (int i = ImGuiKey_Gamepad_BEGIN; i < ImGuiKey_Gamepad_END; i++) | ||||
{ | ||||
io.KeysData[i - ImGuiKey_KeysData_OFFSET].Down = false; | ||||
io.KeysData[i - ImGuiKey_KeysData_OFFSET].AnalogValue = 0.0f; | ||||
} | ||||
// Update keys | ||||
for (int i = 0; i < IM_ARRAYSIZE(io.KeysData); i++) | ||||
{ | ||||
ImGuiKeyData& key_data = io.KeysData[i]; | ||||
key_data.DownDurationPrev = key_data.DownDuration; | ||||
key_data.DownDuration = key_data.Down ? (key_data.DownDuration < 0.0f ? | ||||
0.0f : key_data.DownDuration + io.DeltaTime) : -1.0f; | ||||
} | ||||
} | ||||
static void ImGui::UpdateMouseInputs() | static void ImGui::UpdateMouseInputs() | |||
{ | { | |||
ImGuiContext& g = *GImGui; | ImGuiContext& g = *GImGui; | |||
ImGuiIO& io = g.IO; | ||||
// Round mouse position to avoid spreading non-rounded position (e.g. Update ManualResize doesn't support them well) | // Round mouse position to avoid spreading non-rounded position (e.g. Update ManualResize doesn't support them well) | |||
if (IsMousePosValid(&g.IO.MousePos)) | if (IsMousePosValid(&io.MousePos)) | |||
g.IO.MousePos = g.MouseLastValidPos = ImFloor(g.IO.MousePos); | io.MousePos = g.MouseLastValidPos = ImFloorSigned(io.MousePos); | |||
// If mouse just appeared or disappeared (usually denoted by -FLT_MAX compon ents) we cancel out movement in MouseDelta | // If mouse just appeared or disappeared (usually denoted by -FLT_MAX compon ents) we cancel out movement in MouseDelta | |||
if (IsMousePosValid(&g.IO.MousePos) && IsMousePosValid(&g.IO.MousePosPrev)) | if (IsMousePosValid(&io.MousePos) && IsMousePosValid(&io.MousePosPrev)) | |||
g.IO.MouseDelta = g.IO.MousePos - g.IO.MousePosPrev; | io.MouseDelta = io.MousePos - io.MousePosPrev; | |||
else | else | |||
g.IO.MouseDelta = ImVec2(0.0f, 0.0f); | io.MouseDelta = ImVec2(0.0f, 0.0f); | |||
// If mouse moved we re-enable mouse hovering in case it was disabled by gam epad/keyboard. In theory should use a >0.0f threshold but would need to reset in everywhere we set this to true. | // If mouse moved we re-enable mouse hovering in case it was disabled by gam epad/keyboard. In theory should use a >0.0f threshold but would need to reset in everywhere we set this to true. | |||
if (g.IO.MouseDelta.x != 0.0f || g.IO.MouseDelta.y != 0.0f) | if (io.MouseDelta.x != 0.0f || io.MouseDelta.y != 0.0f) | |||
g.NavDisableMouseHover = false; | g.NavDisableMouseHover = false; | |||
g.IO.MousePosPrev = g.IO.MousePos; | io.MousePosPrev = io.MousePos; | |||
for (int i = 0; i < IM_ARRAYSIZE(g.IO.MouseDown); i++) | for (int i = 0; i < IM_ARRAYSIZE(io.MouseDown); i++) | |||
{ | { | |||
g.IO.MouseClicked[i] = g.IO.MouseDown[i] && g.IO.MouseDownDuration[i] < | io.MouseClicked[i] = io.MouseDown[i] && io.MouseDownDuration[i] < 0.0f; | |||
0.0f; | io.MouseClickedCount[i] = 0; // Will be filled below | |||
g.IO.MouseClickedCount[i] = 0; // Will be filled below | io.MouseReleased[i] = !io.MouseDown[i] && io.MouseDownDuration[i] >= 0.0 | |||
g.IO.MouseReleased[i] = !g.IO.MouseDown[i] && g.IO.MouseDownDuration[i] | f; | |||
>= 0.0f; | io.MouseDownDurationPrev[i] = io.MouseDownDuration[i]; | |||
g.IO.MouseDownDurationPrev[i] = g.IO.MouseDownDuration[i]; | io.MouseDownDuration[i] = io.MouseDown[i] ? (io.MouseDownDuration[i] < 0 | |||
g.IO.MouseDownDuration[i] = g.IO.MouseDown[i] ? (g.IO.MouseDownDuration[ | .0f ? 0.0f : io.MouseDownDuration[i] + io.DeltaTime) : -1.0f; | |||
i] < 0.0f ? 0.0f : g.IO.MouseDownDuration[i] + g.IO.DeltaTime) : -1.0f; | if (io.MouseClicked[i]) | |||
if (g.IO.MouseClicked[i]) | ||||
{ | { | |||
bool is_repeated_click = false; | bool is_repeated_click = false; | |||
if ((float)(g.Time - g.IO.MouseClickedTime[i]) < g.IO.MouseDoubleCli ckTime) | if ((float)(g.Time - io.MouseClickedTime[i]) < io.MouseDoubleClickTi me) | |||
{ | { | |||
ImVec2 delta_from_click_pos = IsMousePosValid(&g.IO.MousePos) ? | ImVec2 delta_from_click_pos = IsMousePosValid(&io.MousePos) ? (i | |||
(g.IO.MousePos - g.IO.MouseClickedPos[i]) : ImVec2(0.0f, 0.0f); | o.MousePos - io.MouseClickedPos[i]) : ImVec2(0.0f, 0.0f); | |||
if (ImLengthSqr(delta_from_click_pos) < g.IO.MouseDoubleClickMax | if (ImLengthSqr(delta_from_click_pos) < io.MouseDoubleClickMaxDi | |||
Dist * g.IO.MouseDoubleClickMaxDist) | st * io.MouseDoubleClickMaxDist) | |||
is_repeated_click = true; | is_repeated_click = true; | |||
} | } | |||
if (is_repeated_click) | if (is_repeated_click) | |||
g.IO.MouseClickedLastCount[i]++; | io.MouseClickedLastCount[i]++; | |||
else | else | |||
g.IO.MouseClickedLastCount[i] = 1; | io.MouseClickedLastCount[i] = 1; | |||
g.IO.MouseClickedTime[i] = g.Time; | io.MouseClickedTime[i] = g.Time; | |||
g.IO.MouseClickedPos[i] = g.IO.MousePos; | io.MouseClickedPos[i] = io.MousePos; | |||
g.IO.MouseClickedCount[i] = g.IO.MouseClickedLastCount[i]; | io.MouseClickedCount[i] = io.MouseClickedLastCount[i]; | |||
g.IO.MouseDragMaxDistanceAbs[i] = ImVec2(0.0f, 0.0f); | io.MouseDragMaxDistanceSqr[i] = 0.0f; | |||
g.IO.MouseDragMaxDistanceSqr[i] = 0.0f; | ||||
} | } | |||
else if (g.IO.MouseDown[i]) | else if (io.MouseDown[i]) | |||
{ | { | |||
// Maintain the maximum distance we reaching from the initial click position, which is used with dragging threshold | // Maintain the maximum distance we reaching from the initial click position, which is used with dragging threshold | |||
ImVec2 delta_from_click_pos = IsMousePosValid(&g.IO.MousePos) ? (g.I | float delta_sqr_click_pos = IsMousePosValid(&io.MousePos) ? ImLength | |||
O.MousePos - g.IO.MouseClickedPos[i]) : ImVec2(0.0f, 0.0f); | Sqr(io.MousePos - io.MouseClickedPos[i]) : 0.0f; | |||
g.IO.MouseDragMaxDistanceSqr[i] = ImMax(g.IO.MouseDragMaxDistanceSqr | io.MouseDragMaxDistanceSqr[i] = ImMax(io.MouseDragMaxDistanceSqr[i], | |||
[i], ImLengthSqr(delta_from_click_pos)); | delta_sqr_click_pos); | |||
g.IO.MouseDragMaxDistanceAbs[i].x = ImMax(g.IO.MouseDragMaxDistanceA | ||||
bs[i].x, delta_from_click_pos.x < 0.0f ? -delta_from_click_pos.x : delta_from_cl | ||||
ick_pos.x); | ||||
g.IO.MouseDragMaxDistanceAbs[i].y = ImMax(g.IO.MouseDragMaxDistanceA | ||||
bs[i].y, delta_from_click_pos.y < 0.0f ? -delta_from_click_pos.y : delta_from_cl | ||||
ick_pos.y); | ||||
} | } | |||
// We provide io.MouseDoubleClicked[] as a legacy service | // We provide io.MouseDoubleClicked[] as a legacy service | |||
g.IO.MouseDoubleClicked[i] = (g.IO.MouseClickedCount[i] == 2); | io.MouseDoubleClicked[i] = (io.MouseClickedCount[i] == 2); | |||
// Clicking any mouse button reactivate mouse hovering which may have be en deactivated by gamepad/keyboard navigation | // Clicking any mouse button reactivate mouse hovering which may have be en deactivated by gamepad/keyboard navigation | |||
if (g.IO.MouseClicked[i]) | if (io.MouseClicked[i]) | |||
g.NavDisableMouseHover = false; | g.NavDisableMouseHover = false; | |||
} | } | |||
} | } | |||
static void StartLockWheelingWindow(ImGuiWindow* window) | static void StartLockWheelingWindow(ImGuiWindow* window) | |||
{ | { | |||
ImGuiContext& g = *GImGui; | ImGuiContext& g = *GImGui; | |||
if (g.WheelingWindow == window) | if (g.WheelingWindow == window) | |||
return; | return; | |||
g.WheelingWindow = window; | g.WheelingWindow = window; | |||
skipping to change at line 4077 | skipping to change at line 4310 | |||
g.ActiveIdIsAlive = 0; | g.ActiveIdIsAlive = 0; | |||
g.ActiveIdHasBeenEditedThisFrame = false; | g.ActiveIdHasBeenEditedThisFrame = false; | |||
g.ActiveIdPreviousFrameIsAlive = false; | g.ActiveIdPreviousFrameIsAlive = false; | |||
g.ActiveIdIsJustActivated = false; | g.ActiveIdIsJustActivated = false; | |||
if (g.TempInputId != 0 && g.ActiveId != g.TempInputId) | if (g.TempInputId != 0 && g.ActiveId != g.TempInputId) | |||
g.TempInputId = 0; | g.TempInputId = 0; | |||
if (g.ActiveId == 0) | if (g.ActiveId == 0) | |||
{ | { | |||
g.ActiveIdUsingNavDirMask = 0x00; | g.ActiveIdUsingNavDirMask = 0x00; | |||
g.ActiveIdUsingNavInputMask = 0x00; | g.ActiveIdUsingNavInputMask = 0x00; | |||
g.ActiveIdUsingKeyInputMask = 0x00; | g.ActiveIdUsingKeyInputMask.ClearAllBits(); | |||
} | } | |||
// Drag and drop | // Drag and drop | |||
g.DragDropAcceptIdPrev = g.DragDropAcceptIdCurr; | g.DragDropAcceptIdPrev = g.DragDropAcceptIdCurr; | |||
g.DragDropAcceptIdCurr = 0; | g.DragDropAcceptIdCurr = 0; | |||
g.DragDropAcceptIdCurrRectSurface = FLT_MAX; | g.DragDropAcceptIdCurrRectSurface = FLT_MAX; | |||
g.DragDropWithinSource = false; | g.DragDropWithinSource = false; | |||
g.DragDropWithinTarget = false; | g.DragDropWithinTarget = false; | |||
g.DragDropHoldJustPressedId = 0; | g.DragDropHoldJustPressedId = 0; | |||
// Close popups on focus lost (currently wip/opt-in) | // Close popups on focus lost (currently wip/opt-in) | |||
//if (g.IO.AppFocusLost) | //if (g.IO.AppFocusLost) | |||
// ClosePopupsExceptModals(); | // ClosePopupsExceptModals(); | |||
// Clear buttons state when focus is lost | // Process input queue (trickle as many events as possible) | |||
// (this is useful so e.g. releasing Alt after focus loss on Alt-Tab doesn't | g.InputEventsTrail.resize(0); | |||
trigger the Alt menu toggle) | UpdateInputEvents(g.IO.ConfigInputTrickleEventQueue); | |||
if (g.IO.AppFocusLost) | ||||
{ | ||||
g.IO.ClearInputKeys(); | ||||
g.IO.AppFocusLost = false; | ||||
} | ||||
// Update keyboard input state | // Update keyboard input state | |||
// Synchronize io.KeyMods with individual modifiers io.KeyXXX bools | UpdateKeyboardInputs(); | |||
g.IO.KeyMods = GetMergedKeyModFlags(); | ||||
memcpy(g.IO.KeysDownDurationPrev, g.IO.KeysDownDuration, sizeof(g.IO.KeysDow | //IM_ASSERT(g.IO.KeyCtrl == IsKeyDown(ImGuiKey_LeftCtrl) || IsKeyDown(ImGuiK | |||
nDuration)); | ey_RightCtrl)); | |||
for (int i = 0; i < IM_ARRAYSIZE(g.IO.KeysDown); i++) | //IM_ASSERT(g.IO.KeyShift == IsKeyDown(ImGuiKey_LeftShift) || IsKeyDown(ImGu | |||
g.IO.KeysDownDuration[i] = g.IO.KeysDown[i] ? (g.IO.KeysDownDuration[i] | iKey_RightShift)); | |||
< 0.0f ? 0.0f : g.IO.KeysDownDuration[i] + g.IO.DeltaTime) : -1.0f; | //IM_ASSERT(g.IO.KeyAlt == IsKeyDown(ImGuiKey_LeftAlt) || IsKeyDown(ImGuiKey | |||
_RightAlt)); | ||||
//IM_ASSERT(g.IO.KeySuper == IsKeyDown(ImGuiKey_LeftSuper) || IsKeyDown(ImGu | ||||
iKey_RightSuper)); | ||||
// Update gamepad/keyboard navigation | // Update gamepad/keyboard navigation | |||
NavUpdate(); | NavUpdate(); | |||
// Update mouse input state | // Update mouse input state | |||
UpdateMouseInputs(); | UpdateMouseInputs(); | |||
// Find hovered window | // Find hovered window | |||
// (needs to be before UpdateMouseMovingWindowNewFrame so we fill g.HoveredW indowUnderMovingWindow on the mouse release frame) | // (needs to be before UpdateMouseMovingWindowNewFrame so we fill g.HoveredW indowUnderMovingWindow on the mouse release frame) | |||
UpdateHoveredWindowAndCaptureFlags(); | UpdateHoveredWindowAndCaptureFlags(); | |||
skipping to change at line 4128 | skipping to change at line 4358 | |||
UpdateMouseMovingWindowNewFrame(); | UpdateMouseMovingWindowNewFrame(); | |||
// Background darkening/whitening | // Background darkening/whitening | |||
if (GetTopMostPopupModal() != NULL || (g.NavWindowingTarget != NULL && g.Nav WindowingHighlightAlpha > 0.0f)) | if (GetTopMostPopupModal() != NULL || (g.NavWindowingTarget != NULL && g.Nav WindowingHighlightAlpha > 0.0f)) | |||
g.DimBgRatio = ImMin(g.DimBgRatio + g.IO.DeltaTime * 6.0f, 1.0f); | g.DimBgRatio = ImMin(g.DimBgRatio + g.IO.DeltaTime * 6.0f, 1.0f); | |||
else | else | |||
g.DimBgRatio = ImMax(g.DimBgRatio - g.IO.DeltaTime * 10.0f, 0.0f); | g.DimBgRatio = ImMax(g.DimBgRatio - g.IO.DeltaTime * 10.0f, 0.0f); | |||
g.MouseCursor = ImGuiMouseCursor_Arrow; | g.MouseCursor = ImGuiMouseCursor_Arrow; | |||
g.WantCaptureMouseNextFrame = g.WantCaptureKeyboardNextFrame = g.WantTextInp utNextFrame = -1; | g.WantCaptureMouseNextFrame = g.WantCaptureKeyboardNextFrame = g.WantTextInp utNextFrame = -1; | |||
g.PlatformImePos = ImVec2(1.0f, 1.0f); // OS Input Method Editor showing on | ||||
top-left of our window by default | // Platform IME data: reset for the frame | |||
g.PlatformImeDataPrev = g.PlatformImeData; | ||||
g.PlatformImeData.WantVisible = false; | ||||
// Mouse wheel scrolling, scale | // Mouse wheel scrolling, scale | |||
UpdateMouseWheel(); | UpdateMouseWheel(); | |||
// Mark all windows as not visible and compact unused memory. | // Mark all windows as not visible and compact unused memory. | |||
IM_ASSERT(g.WindowsFocusOrder.Size <= g.Windows.Size); | IM_ASSERT(g.WindowsFocusOrder.Size <= g.Windows.Size); | |||
const float memory_compact_start_time = (g.GcCompactAll || g.IO.ConfigMemory CompactTimer < 0.0f) ? FLT_MAX : (float)g.Time - g.IO.ConfigMemoryCompactTimer; | const float memory_compact_start_time = (g.GcCompactAll || g.IO.ConfigMemory CompactTimer < 0.0f) ? FLT_MAX : (float)g.Time - g.IO.ConfigMemoryCompactTimer; | |||
for (int i = 0; i != g.Windows.Size; i++) | for (int i = 0; i != g.Windows.Size; i++) | |||
{ | { | |||
ImGuiWindow* window = g.Windows[i]; | ImGuiWindow* window = g.Windows[i]; | |||
skipping to change at line 4324 | skipping to change at line 4557 | |||
{ | { | |||
ImGuiWindow* child = window->DC.ChildWindows[i]; | ImGuiWindow* child = window->DC.ChildWindows[i]; | |||
if (child->Active) | if (child->Active) | |||
AddWindowToSortBuffer(out_sorted_windows, child); | AddWindowToSortBuffer(out_sorted_windows, child); | |||
} | } | |||
} | } | |||
} | } | |||
static void AddDrawListToDrawData(ImVector<ImDrawList*>* out_list, ImDrawList* d raw_list) | static void AddDrawListToDrawData(ImVector<ImDrawList*>* out_list, ImDrawList* d raw_list) | |||
{ | { | |||
// Remove trailing command if unused. | ||||
// Technically we could return directly instead of popping, but this make th | ||||
ings looks neat in Metrics/Debugger window as well. | ||||
draw_list->_PopUnusedDrawCmd(); | ||||
if (draw_list->CmdBuffer.Size == 0) | if (draw_list->CmdBuffer.Size == 0) | |||
return; | return; | |||
if (draw_list->CmdBuffer.Size == 1 && draw_list->CmdBuffer[0].ElemCount == 0 | ||||
&& draw_list->CmdBuffer[0].UserCallback == NULL) | ||||
return; | ||||
// Draw list sanity check. Detect mismatch between PrimReserve() calls and i ncrementing _VtxCurrentIdx, _VtxWritePtr etc. | // Draw list sanity check. Detect mismatch between PrimReserve() calls and i ncrementing _VtxCurrentIdx, _VtxWritePtr etc. | |||
// May trigger for you if you are using PrimXXX functions incorrectly. | // May trigger for you if you are using PrimXXX functions incorrectly. | |||
IM_ASSERT(draw_list->VtxBuffer.Size == 0 || draw_list->_VtxWritePtr == draw_ list->VtxBuffer.Data + draw_list->VtxBuffer.Size); | IM_ASSERT(draw_list->VtxBuffer.Size == 0 || draw_list->_VtxWritePtr == draw_ list->VtxBuffer.Data + draw_list->VtxBuffer.Size); | |||
IM_ASSERT(draw_list->IdxBuffer.Size == 0 || draw_list->_IdxWritePtr == draw_ list->IdxBuffer.Data + draw_list->IdxBuffer.Size); | IM_ASSERT(draw_list->IdxBuffer.Size == 0 || draw_list->_IdxWritePtr == draw_ list->IdxBuffer.Data + draw_list->IdxBuffer.Size); | |||
if (!(draw_list->Flags & ImDrawListFlags_AllowVtxOffset)) | if (!(draw_list->Flags & ImDrawListFlags_AllowVtxOffset)) | |||
IM_ASSERT((int)draw_list->_VtxCurrentIdx == draw_list->VtxBuffer.Size); | IM_ASSERT((int)draw_list->_VtxCurrentIdx == draw_list->VtxBuffer.Size); | |||
// Check that draw_list doesn't use more vertices than indexable (default Im DrawIdx = unsigned short = 2 bytes = 64K vertices per ImDrawList = per window) | // Check that draw_list doesn't use more vertices than indexable (default Im DrawIdx = unsigned short = 2 bytes = 64K vertices per ImDrawList = per window) | |||
// If this assert triggers because you are drawing lots of stuff manually: | // If this assert triggers because you are drawing lots of stuff manually: | |||
skipping to change at line 4414 | skipping to change at line 4646 | |||
ImDrawData* draw_data = &viewport->DrawDataP; | ImDrawData* draw_data = &viewport->DrawDataP; | |||
draw_data->Valid = true; | draw_data->Valid = true; | |||
draw_data->CmdLists = (draw_lists->Size > 0) ? draw_lists->Data : NULL; | draw_data->CmdLists = (draw_lists->Size > 0) ? draw_lists->Data : NULL; | |||
draw_data->CmdListsCount = draw_lists->Size; | draw_data->CmdListsCount = draw_lists->Size; | |||
draw_data->TotalVtxCount = draw_data->TotalIdxCount = 0; | draw_data->TotalVtxCount = draw_data->TotalIdxCount = 0; | |||
draw_data->DisplayPos = viewport->Pos; | draw_data->DisplayPos = viewport->Pos; | |||
draw_data->DisplaySize = viewport->Size; | draw_data->DisplaySize = viewport->Size; | |||
draw_data->FramebufferScale = io.DisplayFramebufferScale; | draw_data->FramebufferScale = io.DisplayFramebufferScale; | |||
for (int n = 0; n < draw_lists->Size; n++) | for (int n = 0; n < draw_lists->Size; n++) | |||
{ | { | |||
draw_data->TotalVtxCount += draw_lists->Data[n]->VtxBuffer.Size; | ImDrawList* draw_list = draw_lists->Data[n]; | |||
draw_data->TotalIdxCount += draw_lists->Data[n]->IdxBuffer.Size; | draw_list->_PopUnusedDrawCmd(); | |||
draw_data->TotalVtxCount += draw_list->VtxBuffer.Size; | ||||
draw_data->TotalIdxCount += draw_list->IdxBuffer.Size; | ||||
} | } | |||
} | } | |||
// Push a clipping rectangle for both ImGui logic (hit-testing etc.) and low-lev el ImDrawList rendering. | // Push a clipping rectangle for both ImGui logic (hit-testing etc.) and low-lev el ImDrawList rendering. | |||
// - When using this function it is sane to ensure that float are perfectly roun ded to integer values, | // - When using this function it is sane to ensure that float are perfectly roun ded to integer values, | |||
// so that e.g. (int)(max.x-min.x) in user's render produce correct result. | // so that e.g. (int)(max.x-min.x) in user's render produce correct result. | |||
// - If the code here changes, may need to update code of functions like NextCol umn() and PushColumnClipRect(): | // - If the code here changes, may need to update code of functions like NextCol umn() and PushColumnClipRect(): | |||
// some frequently called functions which to modify both channels and clipping simultaneously tend to use the | // some frequently called functions which to modify both channels and clipping simultaneously tend to use the | |||
// more specialized SetWindowClipRectBeforeSetChannel() to avoid extraneous up dates of underlying ImDrawCmds. | // more specialized SetWindowClipRectBeforeSetChannel() to avoid extraneous up dates of underlying ImDrawCmds. | |||
void ImGui::PushClipRect(const ImVec2& clip_rect_min, const ImVec2& clip_rect_ma x, bool intersect_with_current_clip_rect) | void ImGui::PushClipRect(const ImVec2& clip_rect_min, const ImVec2& clip_rect_ma x, bool intersect_with_current_clip_rect) | |||
skipping to change at line 4451 | skipping to change at line 4685 | |||
if ((col & IM_COL32_A_MASK) == 0) | if ((col & IM_COL32_A_MASK) == 0) | |||
return; | return; | |||
ImGuiViewportP* viewport = (ImGuiViewportP*)GetMainViewport(); | ImGuiViewportP* viewport = (ImGuiViewportP*)GetMainViewport(); | |||
ImRect viewport_rect = viewport->GetMainRect(); | ImRect viewport_rect = viewport->GetMainRect(); | |||
// Draw behind window by moving the draw command at the FRONT of the draw li st | // Draw behind window by moving the draw command at the FRONT of the draw li st | |||
{ | { | |||
// We've already called AddWindowToDrawData() which called DrawList->Cha nnelsMerge() on DockNodeHost windows, | // We've already called AddWindowToDrawData() which called DrawList->Cha nnelsMerge() on DockNodeHost windows, | |||
// and draw list have been trimmed already, hence the explicit recreatio n of a draw command if missing. | // and draw list have been trimmed already, hence the explicit recreatio n of a draw command if missing. | |||
// FIXME: This is creating complication, might be simpler if we could in ject a drawlist in drawdata at a given position and not attempt to manipulate Im DrawCmd order. | ||||
ImDrawList* draw_list = window->RootWindow->DrawList; | ImDrawList* draw_list = window->RootWindow->DrawList; | |||
if (draw_list->CmdBuffer.Size == 0) | if (draw_list->CmdBuffer.Size == 0) | |||
draw_list->AddDrawCmd(); | draw_list->AddDrawCmd(); | |||
draw_list->PushClipRect(viewport_rect.Min - ImVec2(1, 1), viewport_rect. Max + ImVec2(1, 1), false); // Ensure ImDrawCmd are not merged | draw_list->PushClipRect(viewport_rect.Min - ImVec2(1, 1), viewport_rect. Max + ImVec2(1, 1), false); // Ensure ImDrawCmd are not merged | |||
draw_list->AddRectFilled(viewport_rect.Min, viewport_rect.Max, col); | draw_list->AddRectFilled(viewport_rect.Min, viewport_rect.Max, col); | |||
ImDrawCmd cmd = draw_list->CmdBuffer.back(); | ImDrawCmd cmd = draw_list->CmdBuffer.back(); | |||
IM_ASSERT(cmd.ElemCount == 6); | IM_ASSERT(cmd.ElemCount == 6); | |||
draw_list->CmdBuffer.pop_back(); | draw_list->CmdBuffer.pop_back(); | |||
draw_list->CmdBuffer.push_front(cmd); | draw_list->CmdBuffer.push_front(cmd); | |||
draw_list->PopClipRect(); | draw_list->PopClipRect(); | |||
draw_list->AddDrawCmd(); // We need to create a command as CmdBuffer.bac k().IdxOffset won't be correct if we append to same command. | ||||
} | } | |||
} | } | |||
ImGuiWindow* ImGui::FindBottomMostVisibleWindowWithinBeginStack(ImGuiWindow* par ent_window) | ImGuiWindow* ImGui::FindBottomMostVisibleWindowWithinBeginStack(ImGuiWindow* par ent_window) | |||
{ | { | |||
ImGuiContext& g = *GImGui; | ImGuiContext& g = *GImGui; | |||
ImGuiWindow* bottom_most_visible_window = parent_window; | ImGuiWindow* bottom_most_visible_window = parent_window; | |||
for (int i = FindWindowDisplayIndex(parent_window); i >= 0; i--) | for (int i = FindWindowDisplayIndex(parent_window); i >= 0; i--) | |||
{ | { | |||
ImGuiWindow* window = g.Windows[i]; | ImGuiWindow* window = g.Windows[i]; | |||
skipping to change at line 4485 | skipping to change at line 4721 | |||
if (IsWindowActiveAndVisible(window) && GetWindowDisplayLayer(window) <= GetWindowDisplayLayer(parent_window)) | if (IsWindowActiveAndVisible(window) && GetWindowDisplayLayer(window) <= GetWindowDisplayLayer(parent_window)) | |||
bottom_most_visible_window = window; | bottom_most_visible_window = window; | |||
} | } | |||
return bottom_most_visible_window; | return bottom_most_visible_window; | |||
} | } | |||
static void ImGui::RenderDimmedBackgrounds() | static void ImGui::RenderDimmedBackgrounds() | |||
{ | { | |||
ImGuiContext& g = *GImGui; | ImGuiContext& g = *GImGui; | |||
ImGuiWindow* modal_window = GetTopMostAndVisiblePopupModal(); | ImGuiWindow* modal_window = GetTopMostAndVisiblePopupModal(); | |||
if (g.DimBgRatio <= 0.0f && g.NavWindowingHighlightAlpha <= 0.0f) | ||||
return; | ||||
const bool dim_bg_for_modal = (modal_window != NULL); | const bool dim_bg_for_modal = (modal_window != NULL); | |||
const bool dim_bg_for_window_list = (g.NavWindowingTargetAnim != NULL && g.N avWindowingTargetAnim->Active); | const bool dim_bg_for_window_list = (g.NavWindowingTargetAnim != NULL && g.N avWindowingTargetAnim->Active); | |||
if (!dim_bg_for_modal && !dim_bg_for_window_list) | if (!dim_bg_for_modal && !dim_bg_for_window_list) | |||
return; | return; | |||
if (dim_bg_for_modal) | if (dim_bg_for_modal) | |||
{ | { | |||
// Draw dimming behind modal or a begin stack child, whichever comes fir st in draw order. | // Draw dimming behind modal or a begin stack child, whichever comes fir st in draw order. | |||
ImGuiWindow* dim_behind_window = FindBottomMostVisibleWindowWithinBeginS tack(modal_window); | ImGuiWindow* dim_behind_window = FindBottomMostVisibleWindowWithinBeginS tack(modal_window); | |||
RenderDimmedBackgroundBehindWindow(dim_behind_window, GetColorU32(ImGuiC ol_ModalWindowDimBg, g.DimBgRatio)); | RenderDimmedBackgroundBehindWindow(dim_behind_window, GetColorU32(ImGuiC ol_ModalWindowDimBg, g.DimBgRatio)); | |||
skipping to change at line 4532 | skipping to change at line 4770 | |||
// Don't process EndFrame() multiple times. | // Don't process EndFrame() multiple times. | |||
if (g.FrameCountEnded == g.FrameCount) | if (g.FrameCountEnded == g.FrameCount) | |||
return; | return; | |||
IM_ASSERT(g.WithinFrameScope && "Forgot to call ImGui::NewFrame()?"); | IM_ASSERT(g.WithinFrameScope && "Forgot to call ImGui::NewFrame()?"); | |||
CallContextHooks(&g, ImGuiContextHookType_EndFramePre); | CallContextHooks(&g, ImGuiContextHookType_EndFramePre); | |||
ErrorCheckEndFrameSanityChecks(); | ErrorCheckEndFrameSanityChecks(); | |||
// Notify OS when our Input Method Editor cursor has moved (e.g. CJK inputs | // Notify Platform/OS when our Input Method Editor cursor has moved (e.g. CJ | |||
using Microsoft IME) | K inputs using Microsoft IME) | |||
if (g.IO.ImeSetInputScreenPosFn && (g.PlatformImeLastPos.x == FLT_MAX || ImL | if (g.IO.SetPlatformImeDataFn && memcmp(&g.PlatformImeData, &g.PlatformImeDa | |||
engthSqr(g.PlatformImeLastPos - g.PlatformImePos) > 0.0001f)) | taPrev, sizeof(ImGuiPlatformImeData)) != 0) | |||
{ | g.IO.SetPlatformImeDataFn(GetMainViewport(), &g.PlatformImeData); | |||
g.IO.ImeSetInputScreenPosFn((int)g.PlatformImePos.x, (int)g.PlatformImeP | ||||
os.y); | ||||
g.PlatformImeLastPos = g.PlatformImePos; | ||||
} | ||||
// Hide implicit/fallback "Debug" window if it hasn't been used | // Hide implicit/fallback "Debug" window if it hasn't been used | |||
g.WithinFrameScopeWithImplicitWindow = false; | g.WithinFrameScopeWithImplicitWindow = false; | |||
if (g.CurrentWindow && !g.CurrentWindow->WriteAccessed) | if (g.CurrentWindow && !g.CurrentWindow->WriteAccessed) | |||
g.CurrentWindow->Active = false; | g.CurrentWindow->Active = false; | |||
End(); | End(); | |||
// Update navigation: CTRL+Tab, wrap-around requests | // Update navigation: CTRL+Tab, wrap-around requests | |||
NavEndFrame(); | NavEndFrame(); | |||
skipping to change at line 4753 | skipping to change at line 4988 | |||
if (hovered_window_ignoring_moving_window == NULL && (!g.MovingWindow || window->RootWindow != g.MovingWindow->RootWindow)) | if (hovered_window_ignoring_moving_window == NULL && (!g.MovingWindow || window->RootWindow != g.MovingWindow->RootWindow)) | |||
hovered_window_ignoring_moving_window = window; | hovered_window_ignoring_moving_window = window; | |||
if (hovered_window && hovered_window_ignoring_moving_window) | if (hovered_window && hovered_window_ignoring_moving_window) | |||
break; | break; | |||
} | } | |||
g.HoveredWindow = hovered_window; | g.HoveredWindow = hovered_window; | |||
g.HoveredWindowUnderMovingWindow = hovered_window_ignoring_moving_window; | g.HoveredWindowUnderMovingWindow = hovered_window_ignoring_moving_window; | |||
} | } | |||
// Test if mouse cursor is hovering given rectangle | ||||
// NB- Rectangle is clipped by our current clip setting | ||||
// NB- Expand the rectangle to be generous on imprecise inputs systems (g.Style. | ||||
TouchExtraPadding) | ||||
bool ImGui::IsMouseHoveringRect(const ImVec2& r_min, const ImVec2& r_max, bool c | ||||
lip) | ||||
{ | ||||
ImGuiContext& g = *GImGui; | ||||
// Clip | ||||
ImRect rect_clipped(r_min, r_max); | ||||
if (clip) | ||||
rect_clipped.ClipWith(g.CurrentWindow->ClipRect); | ||||
// Expand for touch input | ||||
const ImRect rect_for_touch(rect_clipped.Min - g.Style.TouchExtraPadding, re | ||||
ct_clipped.Max + g.Style.TouchExtraPadding); | ||||
if (!rect_for_touch.Contains(g.IO.MousePos)) | ||||
return false; | ||||
return true; | ||||
} | ||||
int ImGui::GetKeyIndex(ImGuiKey imgui_key) | ||||
{ | ||||
IM_ASSERT(imgui_key >= 0 && imgui_key < ImGuiKey_COUNT); | ||||
ImGuiContext& g = *GImGui; | ||||
return g.IO.KeyMap[imgui_key]; | ||||
} | ||||
// Note that dear imgui doesn't know the semantic of each entry of io.KeysDown[] | ||||
! | ||||
// Use your own indices/enums according to how your backend/engine stored them i | ||||
nto io.KeysDown[]! | ||||
bool ImGui::IsKeyDown(int user_key_index) | ||||
{ | ||||
if (user_key_index < 0) | ||||
return false; | ||||
ImGuiContext& g = *GImGui; | ||||
IM_ASSERT(user_key_index >= 0 && user_key_index < IM_ARRAYSIZE(g.IO.KeysDown | ||||
)); | ||||
return g.IO.KeysDown[user_key_index]; | ||||
} | ||||
// t0 = previous time (e.g.: g.Time - g.IO.DeltaTime) | ||||
// t1 = current time (e.g.: g.Time) | ||||
// An event is triggered at: | ||||
// t = 0.0f t = repeat_delay, t = repeat_delay + repeat_rate*N | ||||
int ImGui::CalcTypematicRepeatAmount(float t0, float t1, float repeat_delay, flo | ||||
at repeat_rate) | ||||
{ | ||||
if (t1 == 0.0f) | ||||
return 1; | ||||
if (t0 >= t1) | ||||
return 0; | ||||
if (repeat_rate <= 0.0f) | ||||
return (t0 < repeat_delay) && (t1 >= repeat_delay); | ||||
const int count_t0 = (t0 < repeat_delay) ? -1 : (int)((t0 - repeat_delay) / | ||||
repeat_rate); | ||||
const int count_t1 = (t1 < repeat_delay) ? -1 : (int)((t1 - repeat_delay) / | ||||
repeat_rate); | ||||
const int count = count_t1 - count_t0; | ||||
return count; | ||||
} | ||||
int ImGui::GetKeyPressedAmount(int key_index, float repeat_delay, float repeat_r | ||||
ate) | ||||
{ | ||||
ImGuiContext& g = *GImGui; | ||||
if (key_index < 0) | ||||
return 0; | ||||
IM_ASSERT(key_index >= 0 && key_index < IM_ARRAYSIZE(g.IO.KeysDown)); | ||||
const float t = g.IO.KeysDownDuration[key_index]; | ||||
return CalcTypematicRepeatAmount(t - g.IO.DeltaTime, t, repeat_delay, repeat | ||||
_rate); | ||||
} | ||||
bool ImGui::IsKeyPressed(int user_key_index, bool repeat) | ||||
{ | ||||
ImGuiContext& g = *GImGui; | ||||
if (user_key_index < 0) | ||||
return false; | ||||
IM_ASSERT(user_key_index >= 0 && user_key_index < IM_ARRAYSIZE(g.IO.KeysDown | ||||
)); | ||||
const float t = g.IO.KeysDownDuration[user_key_index]; | ||||
if (t == 0.0f) | ||||
return true; | ||||
if (repeat && t > g.IO.KeyRepeatDelay) | ||||
return GetKeyPressedAmount(user_key_index, g.IO.KeyRepeatDelay, g.IO.Key | ||||
RepeatRate) > 0; | ||||
return false; | ||||
} | ||||
bool ImGui::IsKeyReleased(int user_key_index) | ||||
{ | ||||
ImGuiContext& g = *GImGui; | ||||
if (user_key_index < 0) return false; | ||||
IM_ASSERT(user_key_index >= 0 && user_key_index < IM_ARRAYSIZE(g.IO.KeysDown | ||||
)); | ||||
return g.IO.KeysDownDurationPrev[user_key_index] >= 0.0f && !g.IO.KeysDown[u | ||||
ser_key_index]; | ||||
} | ||||
bool ImGui::IsMouseDown(ImGuiMouseButton button) | ||||
{ | ||||
ImGuiContext& g = *GImGui; | ||||
IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(g.IO.MouseDown)); | ||||
return g.IO.MouseDown[button]; | ||||
} | ||||
bool ImGui::IsMouseClicked(ImGuiMouseButton button, bool repeat) | ||||
{ | ||||
ImGuiContext& g = *GImGui; | ||||
IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(g.IO.MouseDown)); | ||||
const float t = g.IO.MouseDownDuration[button]; | ||||
if (t == 0.0f) | ||||
return true; | ||||
if (repeat && t > g.IO.KeyRepeatDelay) | ||||
{ | ||||
// FIXME: 2019/05/03: Our old repeat code was wrong here and led to doub | ||||
ling the repeat rate, which made it an ok rate for repeat on mouse hold. | ||||
int amount = CalcTypematicRepeatAmount(t - g.IO.DeltaTime, t, g.IO.KeyRe | ||||
peatDelay, g.IO.KeyRepeatRate * 0.50f); | ||||
if (amount > 0) | ||||
return true; | ||||
} | ||||
return false; | ||||
} | ||||
bool ImGui::IsMouseReleased(ImGuiMouseButton button) | ||||
{ | ||||
ImGuiContext& g = *GImGui; | ||||
IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(g.IO.MouseDown)); | ||||
return g.IO.MouseReleased[button]; | ||||
} | ||||
bool ImGui::IsMouseDoubleClicked(ImGuiMouseButton button) | ||||
{ | ||||
ImGuiContext& g = *GImGui; | ||||
IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(g.IO.MouseDown)); | ||||
return g.IO.MouseClickedCount[button] == 2; | ||||
} | ||||
int ImGui::GetMouseClickedCount(ImGuiMouseButton button) | ||||
{ | ||||
ImGuiContext& g = *GImGui; | ||||
IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(g.IO.MouseDown)); | ||||
return g.IO.MouseClickedCount[button]; | ||||
} | ||||
// Return if a mouse click/drag went past the given threshold. Valid to call dur | ||||
ing the MouseReleased frame. | ||||
// [Internal] This doesn't test if the button is pressed | ||||
bool ImGui::IsMouseDragPastThreshold(ImGuiMouseButton button, float lock_thresho | ||||
ld) | ||||
{ | ||||
ImGuiContext& g = *GImGui; | ||||
IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(g.IO.MouseDown)); | ||||
if (lock_threshold < 0.0f) | ||||
lock_threshold = g.IO.MouseDragThreshold; | ||||
return g.IO.MouseDragMaxDistanceSqr[button] >= lock_threshold * lock_thresho | ||||
ld; | ||||
} | ||||
bool ImGui::IsMouseDragging(ImGuiMouseButton button, float lock_threshold) | ||||
{ | ||||
ImGuiContext& g = *GImGui; | ||||
IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(g.IO.MouseDown)); | ||||
if (!g.IO.MouseDown[button]) | ||||
return false; | ||||
return IsMouseDragPastThreshold(button, lock_threshold); | ||||
} | ||||
ImVec2 ImGui::GetMousePos() | ||||
{ | ||||
ImGuiContext& g = *GImGui; | ||||
return g.IO.MousePos; | ||||
} | ||||
// NB: prefer to call right after BeginPopup(). At the time Selectable/MenuItem | ||||
is activated, the popup is already closed! | ||||
ImVec2 ImGui::GetMousePosOnOpeningCurrentPopup() | ||||
{ | ||||
ImGuiContext& g = *GImGui; | ||||
if (g.BeginPopupStack.Size > 0) | ||||
return g.OpenPopupStack[g.BeginPopupStack.Size - 1].OpenMousePos; | ||||
return g.IO.MousePos; | ||||
} | ||||
// We typically use ImVec2(-FLT_MAX,-FLT_MAX) to denote an invalid mouse positio | ||||
n. | ||||
bool ImGui::IsMousePosValid(const ImVec2* mouse_pos) | ||||
{ | ||||
// The assert is only to silence a false-positive in XCode Static Analysis. | ||||
// Because GImGui is not dereferenced in every code path, the static analyze | ||||
r assume that it may be NULL (which it doesn't for other functions). | ||||
IM_ASSERT(GImGui != NULL); | ||||
const float MOUSE_INVALID = -256000.0f; | ||||
ImVec2 p = mouse_pos ? *mouse_pos : GImGui->IO.MousePos; | ||||
return p.x >= MOUSE_INVALID && p.y >= MOUSE_INVALID; | ||||
} | ||||
bool ImGui::IsAnyMouseDown() | ||||
{ | ||||
ImGuiContext& g = *GImGui; | ||||
for (int n = 0; n < IM_ARRAYSIZE(g.IO.MouseDown); n++) | ||||
if (g.IO.MouseDown[n]) | ||||
return true; | ||||
return false; | ||||
} | ||||
// Return the delta from the initial clicking position while the mouse button is | ||||
clicked or was just released. | ||||
// This is locked and return 0.0f until the mouse moves past a distance threshol | ||||
d at least once. | ||||
// NB: This is only valid if IsMousePosValid(). backends in theory should always | ||||
keep mouse position valid when dragging even outside the client window. | ||||
ImVec2 ImGui::GetMouseDragDelta(ImGuiMouseButton button, float lock_threshold) | ||||
{ | ||||
ImGuiContext& g = *GImGui; | ||||
IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(g.IO.MouseDown)); | ||||
if (lock_threshold < 0.0f) | ||||
lock_threshold = g.IO.MouseDragThreshold; | ||||
if (g.IO.MouseDown[button] || g.IO.MouseReleased[button]) | ||||
if (g.IO.MouseDragMaxDistanceSqr[button] >= lock_threshold * lock_thresh | ||||
old) | ||||
if (IsMousePosValid(&g.IO.MousePos) && IsMousePosValid(&g.IO.MouseCl | ||||
ickedPos[button])) | ||||
return g.IO.MousePos - g.IO.MouseClickedPos[button]; | ||||
return ImVec2(0.0f, 0.0f); | ||||
} | ||||
void ImGui::ResetMouseDragDelta(ImGuiMouseButton button) | ||||
{ | ||||
ImGuiContext& g = *GImGui; | ||||
IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(g.IO.MouseDown)); | ||||
// NB: We don't need to reset g.IO.MouseDragMaxDistanceSqr | ||||
g.IO.MouseClickedPos[button] = g.IO.MousePos; | ||||
} | ||||
ImGuiMouseCursor ImGui::GetMouseCursor() | ||||
{ | ||||
return GImGui->MouseCursor; | ||||
} | ||||
void ImGui::SetMouseCursor(ImGuiMouseCursor cursor_type) | ||||
{ | ||||
GImGui->MouseCursor = cursor_type; | ||||
} | ||||
void ImGui::CaptureKeyboardFromApp(bool capture) | ||||
{ | ||||
GImGui->WantCaptureKeyboardNextFrame = capture ? 1 : 0; | ||||
} | ||||
void ImGui::CaptureMouseFromApp(bool capture) | ||||
{ | ||||
GImGui->WantCaptureMouseNextFrame = capture ? 1 : 0; | ||||
} | ||||
bool ImGui::IsItemActive() | bool ImGui::IsItemActive() | |||
{ | { | |||
ImGuiContext& g = *GImGui; | ImGuiContext& g = *GImGui; | |||
if (g.ActiveId) | if (g.ActiveId) | |||
return g.ActiveId == g.LastItemData.ID; | return g.ActiveId == g.LastItemData.ID; | |||
return false; | return false; | |||
} | } | |||
bool ImGui::IsItemActivated() | bool ImGui::IsItemActivated() | |||
{ | { | |||
skipping to change at line 5102 | skipping to change at line 5105 | |||
if (g.ActiveId == id) | if (g.ActiveId == id) | |||
g.ActiveIdUsingMouseWheel = true; | g.ActiveIdUsingMouseWheel = true; | |||
} | } | |||
void ImGui::SetActiveIdUsingNavAndKeys() | void ImGui::SetActiveIdUsingNavAndKeys() | |||
{ | { | |||
ImGuiContext& g = *GImGui; | ImGuiContext& g = *GImGui; | |||
IM_ASSERT(g.ActiveId != 0); | IM_ASSERT(g.ActiveId != 0); | |||
g.ActiveIdUsingNavDirMask = ~(ImU32)0; | g.ActiveIdUsingNavDirMask = ~(ImU32)0; | |||
g.ActiveIdUsingNavInputMask = ~(ImU32)0; | g.ActiveIdUsingNavInputMask = ~(ImU32)0; | |||
g.ActiveIdUsingKeyInputMask = ~(ImU64)0; | g.ActiveIdUsingKeyInputMask.SetAllBits(); | |||
NavMoveRequestCancel(); | NavMoveRequestCancel(); | |||
} | } | |||
ImVec2 ImGui::GetItemRectMin() | ImVec2 ImGui::GetItemRectMin() | |||
{ | { | |||
ImGuiContext& g = *GImGui; | ImGuiContext& g = *GImGui; | |||
return g.LastItemData.Rect.Min; | return g.LastItemData.Rect.Min; | |||
} | } | |||
ImVec2 ImGui::GetItemRectMax() | ImVec2 ImGui::GetItemRectMax() | |||
skipping to change at line 5915 | skipping to change at line 5918 | |||
static ImGuiWindow* ImGui::FindBlockingModal(ImGuiWindow* window) | static ImGuiWindow* ImGui::FindBlockingModal(ImGuiWindow* window) | |||
{ | { | |||
ImGuiContext& g = *GImGui; | ImGuiContext& g = *GImGui; | |||
if (g.OpenPopupStack.Size <= 0) | if (g.OpenPopupStack.Size <= 0) | |||
return NULL; | return NULL; | |||
// Find a modal that has common parent with specified window. Specified wind ow should be positioned behind that modal. | // Find a modal that has common parent with specified window. Specified wind ow should be positioned behind that modal. | |||
for (int i = g.OpenPopupStack.Size - 1; i >= 0; i--) | for (int i = g.OpenPopupStack.Size - 1; i >= 0; i--) | |||
{ | { | |||
ImGuiWindow* popup_window = g.OpenPopupStack.Data[i].Window; | ImGuiWindow* popup_window = g.OpenPopupStack.Data[i].Window; | |||
if (popup_window == NULL || !popup_window->WasActive || !(popup_window-> | if (popup_window == NULL || !(popup_window->Flags & ImGuiWindowFlags_Mod | |||
Flags & ImGuiWindowFlags_Modal)) // Check WasActive, because this code may run b | al)) | |||
efore popup renders on current frame. | continue; | |||
if (!popup_window->Active && !popup_window->WasActive) // Check Was | ||||
Active, because this code may run before popup renders on current frame, also ch | ||||
eck Active to handle newly created windows. | ||||
continue; | continue; | |||
if (IsWindowWithinBeginStackOf(window, popup_window)) // Window is rendered over last modal, no render order change needed. | if (IsWindowWithinBeginStackOf(window, popup_window)) // Window is rendered over last modal, no render order change needed. | |||
break; | break; | |||
for (ImGuiWindow* parent = popup_window->ParentWindowInBeginStack->RootW indow; parent != NULL; parent = parent->ParentWindowInBeginStack->RootWindow) | for (ImGuiWindow* parent = popup_window->ParentWindowInBeginStack->RootW indow; parent != NULL; parent = parent->ParentWindowInBeginStack->RootWindow) | |||
if (IsWindowWithinBeginStackOf(window, parent)) | if (IsWindowWithinBeginStackOf(window, parent)) | |||
return popup_window; // Place win dow above its begin stack parent. | return popup_window; // Place win dow above its begin stack parent. | |||
} | } | |||
return NULL; | return NULL; | |||
} | } | |||
skipping to change at line 6077 | skipping to change at line 6082 | |||
if (g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasFocus) | if (g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasFocus) | |||
FocusWindow(window); | FocusWindow(window); | |||
if (window->Appearing) | if (window->Appearing) | |||
SetWindowConditionAllowFlags(window, ImGuiCond_Appearing, false); | SetWindowConditionAllowFlags(window, ImGuiCond_Appearing, false); | |||
// When reusing window again multiple times a frame, just append content (do n't need to setup again) | // When reusing window again multiple times a frame, just append content (do n't need to setup again) | |||
if (first_begin_of_the_frame) | if (first_begin_of_the_frame) | |||
{ | { | |||
// Initialize | // Initialize | |||
const bool window_is_child_tooltip = (flags & ImGuiWindowFlags_ChildWind ow) && (flags & ImGuiWindowFlags_Tooltip); // FIXME-WIP: Undocumented behavior o f Child+Tooltip for pinned tooltip (#1345) | const bool window_is_child_tooltip = (flags & ImGuiWindowFlags_ChildWind ow) && (flags & ImGuiWindowFlags_Tooltip); // FIXME-WIP: Undocumented behavior o f Child+Tooltip for pinned tooltip (#1345) | |||
const bool window_just_appearing_after_hidden_for_resize = (window->Hidd enFramesCannotSkipItems > 0); | ||||
window->Active = true; | window->Active = true; | |||
window->HasCloseButton = (p_open != NULL); | window->HasCloseButton = (p_open != NULL); | |||
window->ClipRect = ImVec4(-FLT_MAX, -FLT_MAX, +FLT_MAX, +FLT_MAX); | window->ClipRect = ImVec4(-FLT_MAX, -FLT_MAX, +FLT_MAX, +FLT_MAX); | |||
window->IDStack.resize(1); | window->IDStack.resize(1); | |||
window->DrawList->_ResetForNewFrame(); | window->DrawList->_ResetForNewFrame(); | |||
window->DC.CurrentTableIdx = -1; | window->DC.CurrentTableIdx = -1; | |||
// Restore buffer capacity when woken from a compacted state, to avoid | // Restore buffer capacity when woken from a compacted state, to avoid | |||
if (window->MemoryCompacted) | if (window->MemoryCompacted) | |||
GcAwakeTransientWindowBuffers(window); | GcAwakeTransientWindowBuffers(window); | |||
skipping to change at line 6103 | skipping to change at line 6109 | |||
if (window_title_visible_elsewhere && !window_just_created && strcmp(nam e, window->Name) != 0) | if (window_title_visible_elsewhere && !window_just_created && strcmp(nam e, window->Name) != 0) | |||
{ | { | |||
size_t buf_len = (size_t)window->NameBufLen; | size_t buf_len = (size_t)window->NameBufLen; | |||
window->Name = ImStrdupcpy(window->Name, &buf_len, name); | window->Name = ImStrdupcpy(window->Name, &buf_len, name); | |||
window->NameBufLen = (int)buf_len; | window->NameBufLen = (int)buf_len; | |||
} | } | |||
// UPDATE CONTENTS SIZE, UPDATE HIDDEN STATUS | // UPDATE CONTENTS SIZE, UPDATE HIDDEN STATUS | |||
// Update contents size from last frame for auto-fitting (or use explici t size) | // Update contents size from last frame for auto-fitting (or use explici t size) | |||
const bool window_just_appearing_after_hidden_for_resize = (window->Hidd enFramesCannotSkipItems > 0); | ||||
CalcWindowContentSizes(window, &window->ContentSize, &window->ContentSiz eIdeal); | CalcWindowContentSizes(window, &window->ContentSize, &window->ContentSiz eIdeal); | |||
if (window->HiddenFramesCanSkipItems > 0) | if (window->HiddenFramesCanSkipItems > 0) | |||
window->HiddenFramesCanSkipItems--; | window->HiddenFramesCanSkipItems--; | |||
if (window->HiddenFramesCannotSkipItems > 0) | if (window->HiddenFramesCannotSkipItems > 0) | |||
window->HiddenFramesCannotSkipItems--; | window->HiddenFramesCannotSkipItems--; | |||
if (window->HiddenFramesForRenderOnly > 0) | if (window->HiddenFramesForRenderOnly > 0) | |||
window->HiddenFramesForRenderOnly--; | window->HiddenFramesForRenderOnly--; | |||
// Hide new windows for one frame until they calculate their size | // Hide new windows for one frame until they calculate their size | |||
if (window_just_created && (!window_size_x_set_by_api || !window_size_y_ set_by_api)) | if (window_just_created && (!window_size_x_set_by_api || !window_size_y_ set_by_api)) | |||
skipping to change at line 6293 | skipping to change at line 6298 | |||
want_focus = false; | want_focus = false; | |||
if (window == window->RootWindow) | if (window == window->RootWindow) | |||
{ | { | |||
ImGuiWindow* blocking_modal = FindBlockingModal(window); | ImGuiWindow* blocking_modal = FindBlockingModal(window); | |||
IM_ASSERT(blocking_modal != NULL); | IM_ASSERT(blocking_modal != NULL); | |||
BringWindowToDisplayBehind(window, blocking_modal); | BringWindowToDisplayBehind(window, blocking_modal); | |||
} | } | |||
} | } | |||
} | } | |||
// [Test Engine] Register whole window in the item system | ||||
#ifdef IMGUI_ENABLE_TEST_ENGINE | ||||
if (g.TestEngineHookItems) | ||||
{ | ||||
IM_ASSERT(window->IDStack.Size == 1); | ||||
window->IDStack.Size = 0; | ||||
IMGUI_TEST_ENGINE_ITEM_ADD(window->Rect(), window->ID); | ||||
IMGUI_TEST_ENGINE_ITEM_INFO(window->ID, window->Name, (g.HoveredWind | ||||
ow == window) ? ImGuiItemStatusFlags_HoveredRect : 0); | ||||
window->IDStack.Size = 1; | ||||
} | ||||
#endif | ||||
// Handle manual resize: Resize Grips, Borders, Gamepad | // Handle manual resize: Resize Grips, Borders, Gamepad | |||
int border_held = -1; | int border_held = -1; | |||
ImU32 resize_grip_col[4] = {}; | ImU32 resize_grip_col[4] = {}; | |||
const int resize_grip_count = g.IO.ConfigWindowsResizeFromEdges ? 2 : 1; // Allow resize from lower-left if we have the mouse cursor feedback for it. | const int resize_grip_count = g.IO.ConfigWindowsResizeFromEdges ? 2 : 1; // Allow resize from lower-left if we have the mouse cursor feedback for it. | |||
const float resize_grip_draw_size = IM_FLOOR(ImMax(g.FontSize * 1.10f, w indow->WindowRounding + 1.0f + g.FontSize * 0.2f)); | const float resize_grip_draw_size = IM_FLOOR(ImMax(g.FontSize * 1.10f, w indow->WindowRounding + 1.0f + g.FontSize * 0.2f)); | |||
if (!window->Collapsed) | if (!window->Collapsed) | |||
if (UpdateWindowManualResize(window, size_auto_fit, &border_held, re size_grip_count, &resize_grip_col[0], visibility_rect)) | if (UpdateWindowManualResize(window, size_auto_fit, &border_held, re size_grip_count, &resize_grip_col[0], visibility_rect)) | |||
use_current_size_for_scrollbar_x = use_current_size_for_scrollba r_y = true; | use_current_size_for_scrollbar_x = use_current_size_for_scrollba r_y = true; | |||
window->ResizeBorderHeld = (signed char)border_held; | window->ResizeBorderHeld = (signed char)border_held; | |||
skipping to change at line 6514 | skipping to change at line 6531 | |||
//if (g.NavWindow == window && g.ActiveId == 0) | //if (g.NavWindow == window && g.ActiveId == 0) | |||
if (g.ActiveId == window->MoveId) | if (g.ActiveId == window->MoveId) | |||
if (g.IO.KeyCtrl && IsKeyPressedMap(ImGuiKey_C)) | if (g.IO.KeyCtrl && IsKeyPressedMap(ImGuiKey_C)) | |||
LogToClipboard(); | LogToClipboard(); | |||
*/ | */ | |||
// We fill last item data based on Title Bar/Tab, in order for IsItemHov ered() and IsItemActive() to be usable after Begin(). | // We fill last item data based on Title Bar/Tab, in order for IsItemHov ered() and IsItemActive() to be usable after Begin(). | |||
// This is useful to allow creating context menus on title bar only, etc . | // This is useful to allow creating context menus on title bar only, etc . | |||
SetLastItemData(window->MoveId, g.CurrentItemFlags, IsMouseHoveringRect( title_bar_rect.Min, title_bar_rect.Max, false) ? ImGuiItemStatusFlags_HoveredRec t : 0, title_bar_rect); | SetLastItemData(window->MoveId, g.CurrentItemFlags, IsMouseHoveringRect( title_bar_rect.Min, title_bar_rect.Max, false) ? ImGuiItemStatusFlags_HoveredRec t : 0, title_bar_rect); | |||
#ifdef IMGUI_ENABLE_TEST_ENGINE | // [Test Engine] Register title bar / tab | |||
if (!(window->Flags & ImGuiWindowFlags_NoTitleBar)) | if (!(window->Flags & ImGuiWindowFlags_NoTitleBar)) | |||
IMGUI_TEST_ENGINE_ITEM_ADD(g.LastItemData.Rect, g.LastItemData.ID); | IMGUI_TEST_ENGINE_ITEM_ADD(g.LastItemData.Rect, g.LastItemData.ID); | |||
#endif | ||||
} | } | |||
else | else | |||
{ | { | |||
// Append | // Append | |||
SetCurrentWindow(window); | SetCurrentWindow(window); | |||
} | } | |||
// Pull/inherit current state | // Pull/inherit current state | |||
window->DC.NavFocusScopeIdCurrent = (flags & ImGuiWindowFlags_ChildWindow) ? parent_window->DC.NavFocusScopeIdCurrent : window->GetID("#FOCUSSCOPE"); // Inh erit from parent only // -V595 | window->DC.NavFocusScopeIdCurrent = (flags & ImGuiWindowFlags_ChildWindow) ? parent_window->DC.NavFocusScopeIdCurrent : window->GetID("#FOCUSSCOPE"); // Inh erit from parent only // -V595 | |||
skipping to change at line 7446 | skipping to change at line 7462 | |||
return window->ClipRect.Overlaps(ImRect(window->DC.CursorPos, window->DC.Cur sorPos + size)); | return window->ClipRect.Overlaps(ImRect(window->DC.CursorPos, window->DC.Cur sorPos + size)); | |||
} | } | |||
bool ImGui::IsRectVisible(const ImVec2& rect_min, const ImVec2& rect_max) | bool ImGui::IsRectVisible(const ImVec2& rect_min, const ImVec2& rect_max) | |||
{ | { | |||
ImGuiWindow* window = GImGui->CurrentWindow; | ImGuiWindow* window = GImGui->CurrentWindow; | |||
return window->ClipRect.Overlaps(ImRect(rect_min, rect_max)); | return window->ClipRect.Overlaps(ImRect(rect_min, rect_max)); | |||
} | } | |||
//----------------------------------------------------------------------------- | //----------------------------------------------------------------------------- | |||
// [SECTION] INPUTS | ||||
//----------------------------------------------------------------------------- | ||||
// Test if mouse cursor is hovering given rectangle | ||||
// NB- Rectangle is clipped by our current clip setting | ||||
// NB- Expand the rectangle to be generous on imprecise inputs systems (g.Style. | ||||
TouchExtraPadding) | ||||
bool ImGui::IsMouseHoveringRect(const ImVec2& r_min, const ImVec2& r_max, bool c | ||||
lip) | ||||
{ | ||||
ImGuiContext& g = *GImGui; | ||||
// Clip | ||||
ImRect rect_clipped(r_min, r_max); | ||||
if (clip) | ||||
rect_clipped.ClipWith(g.CurrentWindow->ClipRect); | ||||
// Expand for touch input | ||||
const ImRect rect_for_touch(rect_clipped.Min - g.Style.TouchExtraPadding, re | ||||
ct_clipped.Max + g.Style.TouchExtraPadding); | ||||
if (!rect_for_touch.Contains(g.IO.MousePos)) | ||||
return false; | ||||
return true; | ||||
} | ||||
ImGuiKeyData* ImGui::GetKeyData(ImGuiKey key) | ||||
{ | ||||
ImGuiContext& g = *GImGui; | ||||
int index; | ||||
#ifndef IMGUI_DISABLE_OBSOLETE_KEYIO | ||||
IM_ASSERT(key >= ImGuiKey_LegacyNativeKey_BEGIN && key < ImGuiKey_NamedKey_E | ||||
ND); | ||||
if (IsLegacyKey(key)) | ||||
index = (g.IO.KeyMap[key] != -1) ? g.IO.KeyMap[key] : key; // Remap nati | ||||
ve->imgui or imgui->native | ||||
else | ||||
index = key; | ||||
#else | ||||
IM_ASSERT(IsNamedKey(key) && "Support for user key indices was dropped in fa | ||||
vor of ImGuiKey. Please update backend & user code."); | ||||
index = key - ImGuiKey_NamedKey_BEGIN; | ||||
#endif | ||||
return &g.IO.KeysData[index]; | ||||
} | ||||
#ifndef IMGUI_DISABLE_OBSOLETE_KEYIO | ||||
int ImGui::GetKeyIndex(ImGuiKey key) | ||||
{ | ||||
ImGuiContext& g = *GImGui; | ||||
IM_ASSERT(IsNamedKey(key)); | ||||
const ImGuiKeyData* key_data = GetKeyData(key); | ||||
return (int)(key_data - g.IO.KeysData); | ||||
} | ||||
#endif | ||||
// Those names a provided for debugging purpose and are not meant to be saved pe | ||||
rsistently not compared. | ||||
static const char* const GKeyNames[] = | ||||
{ | ||||
"Tab", "LeftArrow", "RightArrow", "UpArrow", "DownArrow", "PageUp", "PageDow | ||||
n", | ||||
"Home", "End", "Insert", "Delete", "Backspace", "Space", "Enter", "Escape", | ||||
"LeftCtrl", "LeftShift", "LeftAlt", "LeftSuper", "RightCtrl", "RightShift", | ||||
"RightAlt", "RightSuper", "Menu", | ||||
"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", " | ||||
F", "G", "H", | ||||
"I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", " | ||||
X", "Y", "Z", | ||||
"F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9", "F10", "F11", "F12", | ||||
"Apostrophe", "Comma", "Minus", "Period", "Slash", "Semicolon", "Equal", "Le | ||||
ftBracket", | ||||
"Backslash", "RightBracket", "GraveAccent", "CapsLock", "ScrollLock", "NumLo | ||||
ck", "PrintScreen", | ||||
"Pause", "Keypad0", "Keypad1", "Keypad2", "Keypad3", "Keypad4", "Keypad5", " | ||||
Keypad6", | ||||
"Keypad7", "Keypad8", "Keypad9", "KeypadDecimal", "KeypadDivide", "KeypadMul | ||||
tiply", | ||||
"KeypadSubtract", "KeypadAdd", "KeypadEnter", "KeypadEqual", | ||||
"GamepadStart", "GamepadBack", "GamepadFaceUp", "GamepadFaceDown", "GamepadF | ||||
aceLeft", "GamepadFaceRight", | ||||
"GamepadDpadUp", "GamepadDpadDown", "GamepadDpadLeft", "GamepadDpadRight", | ||||
"GamepadL1", "GamepadR1", "GamepadL2", "GamepadR2", "GamepadL3", "GamepadR3" | ||||
, | ||||
"GamepadLStickUp", "GamepadLStickDown", "GamepadLStickLeft", "GamepadLStickR | ||||
ight", | ||||
"GamepadRStickUp", "GamepadRStickDown", "GamepadRStickLeft", "GamepadRStickR | ||||
ight", | ||||
"ModCtrl", "ModShift", "ModAlt", "ModSuper" | ||||
}; | ||||
IM_STATIC_ASSERT(ImGuiKey_NamedKey_COUNT == IM_ARRAYSIZE(GKeyNames)); | ||||
const char* ImGui::GetKeyName(ImGuiKey key) | ||||
{ | ||||
#ifdef IMGUI_DISABLE_OBSOLETE_KEYIO | ||||
IM_ASSERT((IsNamedKey(key) || key == ImGuiKey_None) && "Support for user key | ||||
indices was dropped in favor of ImGuiKey. Please update backend and user code." | ||||
); | ||||
#else | ||||
if (IsLegacyKey(key)) | ||||
{ | ||||
ImGuiIO& io = GetIO(); | ||||
if (io.KeyMap[key] == -1) | ||||
return "N/A"; | ||||
IM_ASSERT(IsNamedKey((ImGuiKey)io.KeyMap[key])); | ||||
key = (ImGuiKey)io.KeyMap[key]; | ||||
} | ||||
#endif | ||||
if (key == ImGuiKey_None) | ||||
return "None"; | ||||
if (!IsNamedKey(key)) | ||||
return "Unknown"; | ||||
return GKeyNames[key - ImGuiKey_NamedKey_BEGIN]; | ||||
} | ||||
// Note that Dear ImGui doesn't know the meaning/semantic of ImGuiKey from 0..51 | ||||
1: they are legacy native keycodes. | ||||
// Consider transitioning from 'IsKeyDown(MY_ENGINE_KEY_A)' (<1.87) to IsKeyDown | ||||
(ImGuiKey_A) (>= 1.87) | ||||
bool ImGui::IsKeyDown(ImGuiKey key) | ||||
{ | ||||
const ImGuiKeyData* key_data = GetKeyData(key); | ||||
return key_data->Down; | ||||
} | ||||
// t0 = previous time (e.g.: g.Time - g.IO.DeltaTime) | ||||
// t1 = current time (e.g.: g.Time) | ||||
// An event is triggered at: | ||||
// t = 0.0f t = repeat_delay, t = repeat_delay + repeat_rate*N | ||||
int ImGui::CalcTypematicRepeatAmount(float t0, float t1, float repeat_delay, flo | ||||
at repeat_rate) | ||||
{ | ||||
if (t1 == 0.0f) | ||||
return 1; | ||||
if (t0 >= t1) | ||||
return 0; | ||||
if (repeat_rate <= 0.0f) | ||||
return (t0 < repeat_delay) && (t1 >= repeat_delay); | ||||
const int count_t0 = (t0 < repeat_delay) ? -1 : (int)((t0 - repeat_delay) / | ||||
repeat_rate); | ||||
const int count_t1 = (t1 < repeat_delay) ? -1 : (int)((t1 - repeat_delay) / | ||||
repeat_rate); | ||||
const int count = count_t1 - count_t0; | ||||
return count; | ||||
} | ||||
int ImGui::GetKeyPressedAmount(ImGuiKey key, float repeat_delay, float repeat_ra | ||||
te) | ||||
{ | ||||
ImGuiContext& g = *GImGui; | ||||
const ImGuiKeyData* key_data = GetKeyData(key); | ||||
const float t = key_data->DownDuration; | ||||
return CalcTypematicRepeatAmount(t - g.IO.DeltaTime, t, repeat_delay, repeat | ||||
_rate); | ||||
} | ||||
bool ImGui::IsKeyPressed(ImGuiKey key, bool repeat) | ||||
{ | ||||
ImGuiContext& g = *GImGui; | ||||
const ImGuiKeyData* key_data = GetKeyData(key); | ||||
const float t = key_data->DownDuration; | ||||
if (t == 0.0f) | ||||
return true; | ||||
if (repeat && t > g.IO.KeyRepeatDelay) | ||||
return GetKeyPressedAmount(key, g.IO.KeyRepeatDelay, g.IO.KeyRepeatRate) | ||||
> 0; | ||||
return false; | ||||
} | ||||
bool ImGui::IsKeyReleased(ImGuiKey key) | ||||
{ | ||||
const ImGuiKeyData* key_data = GetKeyData(key); | ||||
return key_data->DownDurationPrev >= 0.0f && !key_data->Down; | ||||
} | ||||
bool ImGui::IsMouseDown(ImGuiMouseButton button) | ||||
{ | ||||
ImGuiContext& g = *GImGui; | ||||
IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(g.IO.MouseDown)); | ||||
return g.IO.MouseDown[button]; | ||||
} | ||||
bool ImGui::IsMouseClicked(ImGuiMouseButton button, bool repeat) | ||||
{ | ||||
ImGuiContext& g = *GImGui; | ||||
IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(g.IO.MouseDown)); | ||||
const float t = g.IO.MouseDownDuration[button]; | ||||
if (t == 0.0f) | ||||
return true; | ||||
if (repeat && t > g.IO.KeyRepeatDelay) | ||||
{ | ||||
// FIXME: 2019/05/03: Our old repeat code was wrong here and led to doub | ||||
ling the repeat rate, which made it an ok rate for repeat on mouse hold. | ||||
int amount = CalcTypematicRepeatAmount(t - g.IO.DeltaTime, t, g.IO.KeyRe | ||||
peatDelay, g.IO.KeyRepeatRate * 0.50f); | ||||
if (amount > 0) | ||||
return true; | ||||
} | ||||
return false; | ||||
} | ||||
bool ImGui::IsMouseReleased(ImGuiMouseButton button) | ||||
{ | ||||
ImGuiContext& g = *GImGui; | ||||
IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(g.IO.MouseDown)); | ||||
return g.IO.MouseReleased[button]; | ||||
} | ||||
bool ImGui::IsMouseDoubleClicked(ImGuiMouseButton button) | ||||
{ | ||||
ImGuiContext& g = *GImGui; | ||||
IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(g.IO.MouseDown)); | ||||
return g.IO.MouseClickedCount[button] == 2; | ||||
} | ||||
int ImGui::GetMouseClickedCount(ImGuiMouseButton button) | ||||
{ | ||||
ImGuiContext& g = *GImGui; | ||||
IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(g.IO.MouseDown)); | ||||
return g.IO.MouseClickedCount[button]; | ||||
} | ||||
// Return if a mouse click/drag went past the given threshold. Valid to call dur | ||||
ing the MouseReleased frame. | ||||
// [Internal] This doesn't test if the button is pressed | ||||
bool ImGui::IsMouseDragPastThreshold(ImGuiMouseButton button, float lock_thresho | ||||
ld) | ||||
{ | ||||
ImGuiContext& g = *GImGui; | ||||
IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(g.IO.MouseDown)); | ||||
if (lock_threshold < 0.0f) | ||||
lock_threshold = g.IO.MouseDragThreshold; | ||||
return g.IO.MouseDragMaxDistanceSqr[button] >= lock_threshold * lock_thresho | ||||
ld; | ||||
} | ||||
bool ImGui::IsMouseDragging(ImGuiMouseButton button, float lock_threshold) | ||||
{ | ||||
ImGuiContext& g = *GImGui; | ||||
IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(g.IO.MouseDown)); | ||||
if (!g.IO.MouseDown[button]) | ||||
return false; | ||||
return IsMouseDragPastThreshold(button, lock_threshold); | ||||
} | ||||
ImVec2 ImGui::GetMousePos() | ||||
{ | ||||
ImGuiContext& g = *GImGui; | ||||
return g.IO.MousePos; | ||||
} | ||||
// NB: prefer to call right after BeginPopup(). At the time Selectable/MenuItem | ||||
is activated, the popup is already closed! | ||||
ImVec2 ImGui::GetMousePosOnOpeningCurrentPopup() | ||||
{ | ||||
ImGuiContext& g = *GImGui; | ||||
if (g.BeginPopupStack.Size > 0) | ||||
return g.OpenPopupStack[g.BeginPopupStack.Size - 1].OpenMousePos; | ||||
return g.IO.MousePos; | ||||
} | ||||
// We typically use ImVec2(-FLT_MAX,-FLT_MAX) to denote an invalid mouse positio | ||||
n. | ||||
bool ImGui::IsMousePosValid(const ImVec2* mouse_pos) | ||||
{ | ||||
// The assert is only to silence a false-positive in XCode Static Analysis. | ||||
// Because GImGui is not dereferenced in every code path, the static analyze | ||||
r assume that it may be NULL (which it doesn't for other functions). | ||||
IM_ASSERT(GImGui != NULL); | ||||
const float MOUSE_INVALID = -256000.0f; | ||||
ImVec2 p = mouse_pos ? *mouse_pos : GImGui->IO.MousePos; | ||||
return p.x >= MOUSE_INVALID && p.y >= MOUSE_INVALID; | ||||
} | ||||
// [WILL OBSOLETE] This was designed for backends, but prefer having backend mai | ||||
ntain a mask of held mouse buttons, because upcoming input queue system will mak | ||||
e this invalid. | ||||
bool ImGui::IsAnyMouseDown() | ||||
{ | ||||
ImGuiContext& g = *GImGui; | ||||
for (int n = 0; n < IM_ARRAYSIZE(g.IO.MouseDown); n++) | ||||
if (g.IO.MouseDown[n]) | ||||
return true; | ||||
return false; | ||||
} | ||||
// Return the delta from the initial clicking position while the mouse button is | ||||
clicked or was just released. | ||||
// This is locked and return 0.0f until the mouse moves past a distance threshol | ||||
d at least once. | ||||
// NB: This is only valid if IsMousePosValid(). backends in theory should always | ||||
keep mouse position valid when dragging even outside the client window. | ||||
ImVec2 ImGui::GetMouseDragDelta(ImGuiMouseButton button, float lock_threshold) | ||||
{ | ||||
ImGuiContext& g = *GImGui; | ||||
IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(g.IO.MouseDown)); | ||||
if (lock_threshold < 0.0f) | ||||
lock_threshold = g.IO.MouseDragThreshold; | ||||
if (g.IO.MouseDown[button] || g.IO.MouseReleased[button]) | ||||
if (g.IO.MouseDragMaxDistanceSqr[button] >= lock_threshold * lock_thresh | ||||
old) | ||||
if (IsMousePosValid(&g.IO.MousePos) && IsMousePosValid(&g.IO.MouseCl | ||||
ickedPos[button])) | ||||
return g.IO.MousePos - g.IO.MouseClickedPos[button]; | ||||
return ImVec2(0.0f, 0.0f); | ||||
} | ||||
void ImGui::ResetMouseDragDelta(ImGuiMouseButton button) | ||||
{ | ||||
ImGuiContext& g = *GImGui; | ||||
IM_ASSERT(button >= 0 && button < IM_ARRAYSIZE(g.IO.MouseDown)); | ||||
// NB: We don't need to reset g.IO.MouseDragMaxDistanceSqr | ||||
g.IO.MouseClickedPos[button] = g.IO.MousePos; | ||||
} | ||||
ImGuiMouseCursor ImGui::GetMouseCursor() | ||||
{ | ||||
ImGuiContext& g = *GImGui; | ||||
return g.MouseCursor; | ||||
} | ||||
void ImGui::SetMouseCursor(ImGuiMouseCursor cursor_type) | ||||
{ | ||||
ImGuiContext& g = *GImGui; | ||||
g.MouseCursor = cursor_type; | ||||
} | ||||
void ImGui::CaptureKeyboardFromApp(bool capture) | ||||
{ | ||||
ImGuiContext& g = *GImGui; | ||||
g.WantCaptureKeyboardNextFrame = capture ? 1 : 0; | ||||
} | ||||
void ImGui::CaptureMouseFromApp(bool capture) | ||||
{ | ||||
ImGuiContext& g = *GImGui; | ||||
g.WantCaptureMouseNextFrame = capture ? 1 : 0; | ||||
} | ||||
static const char* GetInputSourceName(ImGuiInputSource source) | ||||
{ | ||||
const char* input_source_names[] = { "None", "Mouse", "Keyboard", "Gamepad", | ||||
"Nav", "Clipboard" }; | ||||
IM_ASSERT(IM_ARRAYSIZE(input_source_names) == ImGuiInputSource_COUNT && sour | ||||
ce >= 0 && source < ImGuiInputSource_COUNT); | ||||
return input_source_names[source]; | ||||
} | ||||
// Process input queue | ||||
// - trickle_fast_inputs = false : process all events, turn into flattened input | ||||
state (e.g. successive down/up/down/up will be lost) | ||||
// - trickle_fast_inputs = true : process as many events as possible (successiv | ||||
e down/up/down/up will be trickled over several frames so nothing is lost) (new | ||||
feature in 1.87) | ||||
void ImGui::UpdateInputEvents(bool trickle_fast_inputs) | ||||
{ | ||||
ImGuiContext& g = *GImGui; | ||||
ImGuiIO& io = g.IO; | ||||
bool mouse_moved = false, mouse_wheeled = false, key_changed = false, text_i | ||||
nputed = false; | ||||
int mouse_button_changed = 0x00; | ||||
ImBitArray<ImGuiKey_KeysData_SIZE> key_changed_mask; | ||||
int event_n = 0; | ||||
for (; event_n < g.InputEventsQueue.Size; event_n++) | ||||
{ | ||||
const ImGuiInputEvent* e = &g.InputEventsQueue[event_n]; | ||||
if (e->Type == ImGuiInputEventType_MousePos) | ||||
{ | ||||
ImVec2 event_pos(e->MousePos.PosX, e->MousePos.PosY); | ||||
if (IsMousePosValid(&event_pos)) | ||||
event_pos = ImVec2(ImFloorSigned(event_pos.x), ImFloorSigned(eve | ||||
nt_pos.y)); // Apply same flooring as UpdateMouseInputs() | ||||
if (io.MousePos.x != event_pos.x || io.MousePos.y != event_pos.y) | ||||
{ | ||||
// Trickling Rule: Stop processing queued events if we already h | ||||
andled a mouse button change | ||||
if (trickle_fast_inputs && (mouse_button_changed != 0 || mouse_w | ||||
heeled || key_changed || text_inputed)) | ||||
break; | ||||
io.MousePos = event_pos; | ||||
mouse_moved = true; | ||||
} | ||||
} | ||||
else if (e->Type == ImGuiInputEventType_MouseButton) | ||||
{ | ||||
const ImGuiMouseButton button = e->MouseButton.Button; | ||||
IM_ASSERT(button >= 0 && button < ImGuiMouseButton_COUNT); | ||||
if (io.MouseDown[button] != e->MouseButton.Down) | ||||
{ | ||||
// Trickling Rule: Stop processing queued events if we got multi | ||||
ple action on the same button | ||||
if (trickle_fast_inputs && ((mouse_button_changed & (1 << button | ||||
)) || mouse_wheeled)) | ||||
break; | ||||
io.MouseDown[button] = e->MouseButton.Down; | ||||
mouse_button_changed |= (1 << button); | ||||
} | ||||
} | ||||
else if (e->Type == ImGuiInputEventType_MouseWheel) | ||||
{ | ||||
if (e->MouseWheel.WheelX != 0.0f || e->MouseWheel.WheelY != 0.0f) | ||||
{ | ||||
// Trickling Rule: Stop processing queued events if we got multi | ||||
ple action on the event | ||||
if (trickle_fast_inputs && (mouse_wheeled || mouse_button_change | ||||
d != 0)) | ||||
break; | ||||
io.MouseWheelH += e->MouseWheel.WheelX; | ||||
io.MouseWheel += e->MouseWheel.WheelY; | ||||
mouse_wheeled = true; | ||||
} | ||||
} | ||||
else if (e->Type == ImGuiInputEventType_Key) | ||||
{ | ||||
ImGuiKey key = e->Key.Key; | ||||
IM_ASSERT(key != ImGuiKey_None); | ||||
const int keydata_index = (key - ImGuiKey_KeysData_OFFSET); | ||||
ImGuiKeyData* keydata = &io.KeysData[keydata_index]; | ||||
if (keydata->Down != e->Key.Down || keydata->AnalogValue != e->Key.A | ||||
nalogValue) | ||||
{ | ||||
// Trickling Rule: Stop processing queued events if we got multi | ||||
ple action on the same button | ||||
if (trickle_fast_inputs && keydata->Down != e->Key.Down && (key_ | ||||
changed_mask.TestBit(keydata_index) || text_inputed || mouse_button_changed != 0 | ||||
)) | ||||
break; | ||||
keydata->Down = e->Key.Down; | ||||
keydata->AnalogValue = e->Key.AnalogValue; | ||||
key_changed = true; | ||||
key_changed_mask.SetBit(keydata_index); | ||||
if (key == ImGuiKey_ModCtrl || key == ImGuiKey_ModShift || key = | ||||
= ImGuiKey_ModAlt || key == ImGuiKey_ModSuper) | ||||
{ | ||||
if (key == ImGuiKey_ModCtrl) { io.KeyCtrl = keydata->Down; } | ||||
if (key == ImGuiKey_ModShift) { io.KeyShift = keydata->Down; | ||||
} | ||||
if (key == ImGuiKey_ModAlt) { io.KeyAlt = keydata->Down; } | ||||
if (key == ImGuiKey_ModSuper) { io.KeySuper = keydata->Down; | ||||
} | ||||
io.KeyMods = GetMergedKeyModFlags(); | ||||
} | ||||
} | ||||
} | ||||
else if (e->Type == ImGuiInputEventType_Char) | ||||
{ | ||||
// Trickling Rule: Stop processing queued events if keys/mouse have | ||||
been interacted with | ||||
if (trickle_fast_inputs && (key_changed || mouse_button_changed != 0 | ||||
|| mouse_moved || mouse_wheeled)) | ||||
break; | ||||
unsigned int c = e->Text.Char; | ||||
io.InputQueueCharacters.push_back(c <= IM_UNICODE_CODEPOINT_MAX ? (I | ||||
mWchar)c : IM_UNICODE_CODEPOINT_INVALID); | ||||
text_inputed = true; | ||||
} | ||||
else if (e->Type == ImGuiInputEventType_Focus) | ||||
{ | ||||
// We intentionally overwrite this and process lower, in order to gi | ||||
ve a chance | ||||
// to multi-viewports backends to queue AddFocusEvent(false) + AddFo | ||||
cusEvent(true) in same frame. | ||||
io.AppFocusLost = !e->AppFocused.Focused; | ||||
} | ||||
else | ||||
{ | ||||
IM_ASSERT(0 && "Unknown event!"); | ||||
} | ||||
} | ||||
// Record trail (for domain-specific applications wanting to access a precis | ||||
e trail) | ||||
//if (event_n != 0) IMGUI_DEBUG_LOG("Processed: %d / Remaining: %d\n", event | ||||
_n, g.InputEventsQueue.Size - event_n); | ||||
for (int n = 0; n < event_n; n++) | ||||
g.InputEventsTrail.push_back(g.InputEventsQueue[n]); | ||||
// Remaining events will be processed on the next frame | ||||
if (event_n == g.InputEventsQueue.Size) | ||||
g.InputEventsQueue.resize(0); | ||||
else | ||||
g.InputEventsQueue.erase(g.InputEventsQueue.Data, g.InputEventsQueue.Dat | ||||
a + event_n); | ||||
// Clear buttons state when focus is lost | ||||
// (this is useful so e.g. releasing Alt after focus loss on Alt-Tab doesn't | ||||
trigger the Alt menu toggle) | ||||
if (g.IO.AppFocusLost) | ||||
{ | ||||
g.IO.ClearInputKeys(); | ||||
g.IO.AppFocusLost = false; | ||||
} | ||||
} | ||||
//----------------------------------------------------------------------------- | ||||
// [SECTION] ERROR CHECKING | // [SECTION] ERROR CHECKING | |||
//----------------------------------------------------------------------------- | //----------------------------------------------------------------------------- | |||
// Helper function to verify ABI compatibility between caller code and compiled version of Dear ImGui. | // Helper function to verify ABI compatibility between caller code and compiled version of Dear ImGui. | |||
// Verify that the type sizes are matching between the calling file's compilatio n unit and imgui.cpp's compilation unit | // Verify that the type sizes are matching between the calling file's compilatio n unit and imgui.cpp's compilation unit | |||
// If the user has inconsistent compilation settings, imgui configuration #defin e, packing pragma, etc. your user code | // If the user has inconsistent compilation settings, imgui configuration #defin e, packing pragma, etc. your user code | |||
// may see different structures than what imgui.cpp sees, which is problematic. | // may see different structures than what imgui.cpp sees, which is problematic. | |||
// We usually require settings to be in imconfig.h to make sure that they are ac cessible to all compilation units involved with Dear ImGui. | // We usually require settings to be in imconfig.h to make sure that they are ac cessible to all compilation units involved with Dear ImGui. | |||
bool ImGui::DebugCheckVersionAndDataLayout(const char* version, size_t sz_io, si ze_t sz_style, size_t sz_vec2, size_t sz_vec4, size_t sz_vert, size_t sz_idx) | bool ImGui::DebugCheckVersionAndDataLayout(const char* version, size_t sz_io, si ze_t sz_style, size_t sz_vec2, size_t sz_vec4, size_t sz_vert, size_t sz_idx) | |||
{ | { | |||
skipping to change at line 7491 | skipping to change at line 7933 | |||
IM_ASSERT(g.Initialized); | IM_ASSERT(g.Initialized); | |||
IM_ASSERT((g.IO.DeltaTime > 0.0f || g.FrameCount == 0) && "Need a positive DeltaTime!"); | IM_ASSERT((g.IO.DeltaTime > 0.0f || g.FrameCount == 0) && "Need a positive DeltaTime!"); | |||
IM_ASSERT((g.FrameCount == 0 || g.FrameCountEnded == g.FrameCount) && "Forg ot to call Render() or EndFrame() at the end of the previous frame?"); | IM_ASSERT((g.FrameCount == 0 || g.FrameCountEnded == g.FrameCount) && "Forg ot to call Render() or EndFrame() at the end of the previous frame?"); | |||
IM_ASSERT(g.IO.DisplaySize.x >= 0.0f && g.IO.DisplaySize.y >= 0.0f && "Inva lid DisplaySize value!"); | IM_ASSERT(g.IO.DisplaySize.x >= 0.0f && g.IO.DisplaySize.y >= 0.0f && "Inva lid DisplaySize value!"); | |||
IM_ASSERT(g.IO.Fonts->IsBuilt() && "Font Atlas not built! Make sure you called ImGui_ImplXXXX_NewFrame() function for re nderer backend, which should call io.Fonts->GetTexDataAsRGBA32() / GetTexDataAsA lpha8()"); | IM_ASSERT(g.IO.Fonts->IsBuilt() && "Font Atlas not built! Make sure you called ImGui_ImplXXXX_NewFrame() function for re nderer backend, which should call io.Fonts->GetTexDataAsRGBA32() / GetTexDataAsA lpha8()"); | |||
IM_ASSERT(g.Style.CurveTessellationTol > 0.0f && "Inva lid style setting!"); | IM_ASSERT(g.Style.CurveTessellationTol > 0.0f && "Inva lid style setting!"); | |||
IM_ASSERT(g.Style.CircleTessellationMaxError > 0.0f && "Inva lid style setting!"); | IM_ASSERT(g.Style.CircleTessellationMaxError > 0.0f && "Inva lid style setting!"); | |||
IM_ASSERT(g.Style.Alpha >= 0.0f && g.Style.Alpha <= 1.0f && "Inva lid style setting!"); // Allows us to avoid a few clamps in color computations | IM_ASSERT(g.Style.Alpha >= 0.0f && g.Style.Alpha <= 1.0f && "Inva lid style setting!"); // Allows us to avoid a few clamps in color computations | |||
IM_ASSERT(g.Style.WindowMinSize.x >= 1.0f && g.Style.WindowMinSize.y >= 1.0f && "Invalid style setting."); | IM_ASSERT(g.Style.WindowMinSize.x >= 1.0f && g.Style.WindowMinSize.y >= 1.0f && "Invalid style setting."); | |||
IM_ASSERT(g.Style.WindowMenuButtonPosition == ImGuiDir_None || g.Style.Windo wMenuButtonPosition == ImGuiDir_Left || g.Style.WindowMenuButtonPosition == ImGu iDir_Right); | IM_ASSERT(g.Style.WindowMenuButtonPosition == ImGuiDir_None || g.Style.Windo wMenuButtonPosition == ImGuiDir_Left || g.Style.WindowMenuButtonPosition == ImGu iDir_Right); | |||
for (int n = 0; n < ImGuiKey_COUNT; n++) | #ifndef IMGUI_DISABLE_OBSOLETE_KEYIO | |||
IM_ASSERT(g.IO.KeyMap[n] >= -1 && g.IO.KeyMap[n] < IM_ARRAYSIZE(g.IO.Key | for (int n = ImGuiKey_NamedKey_BEGIN; n < ImGuiKey_COUNT; n++) | |||
sDown) && "io.KeyMap[] contains an out of bound value (need to be 0..512, or -1 | IM_ASSERT(g.IO.KeyMap[n] >= -1 && g.IO.KeyMap[n] < IM_ARRAYSIZE(g.IO.Key | |||
for unmapped key)"); | sDown) && "io.KeyMap[] contains an out of bound value (need to be 0..511, or -1 | |||
for unmapped key)"); | ||||
// Check: required key mapping (we intentionally do NOT check all keys to no t pressure user into setting up everything, but Space is required and was only a dded in 1.60 WIP) | // Check: required key mapping (we intentionally do NOT check all keys to no t pressure user into setting up everything, but Space is required and was only a dded in 1.60 WIP) | |||
if (g.IO.ConfigFlags & ImGuiConfigFlags_NavEnableKeyboard) | if ((g.IO.ConfigFlags & ImGuiConfigFlags_NavEnableKeyboard) && g.IO.BackendU singLegacyKeyArrays == 1) | |||
IM_ASSERT(g.IO.KeyMap[ImGuiKey_Space] != -1 && "ImGuiKey_Space is not ma pped, required for keyboard navigation."); | IM_ASSERT(g.IO.KeyMap[ImGuiKey_Space] != -1 && "ImGuiKey_Space is not ma pped, required for keyboard navigation."); | |||
#endif | ||||
// Check: the io.ConfigWindowsResizeFromEdges option requires backend to hon or mouse cursor changes and set the ImGuiBackendFlags_HasMouseCursors flag accor dingly. | // Check: the io.ConfigWindowsResizeFromEdges option requires backend to hon or mouse cursor changes and set the ImGuiBackendFlags_HasMouseCursors flag accor dingly. | |||
if (g.IO.ConfigWindowsResizeFromEdges && !(g.IO.BackendFlags & ImGuiBackendF lags_HasMouseCursors)) | if (g.IO.ConfigWindowsResizeFromEdges && !(g.IO.BackendFlags & ImGuiBackendF lags_HasMouseCursors)) | |||
g.IO.ConfigWindowsResizeFromEdges = false; | g.IO.ConfigWindowsResizeFromEdges = false; | |||
} | } | |||
static void ImGui::ErrorCheckEndFrameSanityChecks() | static void ImGui::ErrorCheckEndFrameSanityChecks() | |||
{ | { | |||
ImGuiContext& g = *GImGui; | ImGuiContext& g = *GImGui; | |||
skipping to change at line 8747 | skipping to change at line 9191 | |||
bool ImGui::BeginPopup(const char* str_id, ImGuiWindowFlags flags) | bool ImGui::BeginPopup(const char* str_id, ImGuiWindowFlags flags) | |||
{ | { | |||
ImGuiContext& g = *GImGui; | ImGuiContext& g = *GImGui; | |||
if (g.OpenPopupStack.Size <= g.BeginPopupStack.Size) // Early out for perfor mance | if (g.OpenPopupStack.Size <= g.BeginPopupStack.Size) // Early out for perfor mance | |||
{ | { | |||
g.NextWindowData.ClearFlags(); // We behave like Begin() and need to con sume those values | g.NextWindowData.ClearFlags(); // We behave like Begin() and need to con sume those values | |||
return false; | return false; | |||
} | } | |||
flags |= ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoTitleBar | I mGuiWindowFlags_NoSavedSettings; | flags |= ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoTitleBar | I mGuiWindowFlags_NoSavedSettings; | |||
return BeginPopupEx(g.CurrentWindow->GetID(str_id), flags); | ImGuiID id = g.CurrentWindow->GetID(str_id); | |||
return BeginPopupEx(id, flags); | ||||
} | } | |||
// If 'p_open' is specified for a modal popup window, the popup will have a regu lar close button which will close the popup. | // If 'p_open' is specified for a modal popup window, the popup will have a regu lar close button which will close the popup. | |||
// Note that popup visibility status is owned by Dear ImGui (and manipulated wit h e.g. OpenPopup) so the actual value of *p_open is meaningless here. | // Note that popup visibility status is owned by Dear ImGui (and manipulated wit h e.g. OpenPopup) so the actual value of *p_open is meaningless here. | |||
bool ImGui::BeginPopupModal(const char* name, bool* p_open, ImGuiWindowFlags fla gs) | bool ImGui::BeginPopupModal(const char* name, bool* p_open, ImGuiWindowFlags fla gs) | |||
{ | { | |||
ImGuiContext& g = *GImGui; | ImGuiContext& g = *GImGui; | |||
ImGuiWindow* window = g.CurrentWindow; | ImGuiWindow* window = g.CurrentWindow; | |||
const ImGuiID id = window->GetID(name); | const ImGuiID id = window->GetID(name); | |||
if (!IsPopupOpen(id, ImGuiPopupFlags_None)) | if (!IsPopupOpen(id, ImGuiPopupFlags_None)) | |||
skipping to change at line 8826 | skipping to change at line 9271 | |||
} | } | |||
// This is a helper to handle the simplest case of associating one named popup t o one given widget. | // This is a helper to handle the simplest case of associating one named popup t o one given widget. | |||
// - To create a popup associated to the last item, you generally want to pass a NULL value to str_id. | // - To create a popup associated to the last item, you generally want to pass a NULL value to str_id. | |||
// - To create a popup with a specific identifier, pass it in str_id. | // - To create a popup with a specific identifier, pass it in str_id. | |||
// - This is useful when using using BeginPopupContextItem() on an item which doesn't have an identifier, e.g. a Text() call. | // - This is useful when using using BeginPopupContextItem() on an item which doesn't have an identifier, e.g. a Text() call. | |||
// - This is useful when multiple code locations may want to manipulate/open the same popup, given an explicit id. | // - This is useful when multiple code locations may want to manipulate/open the same popup, given an explicit id. | |||
// - You may want to handle the whole on user side if you have specific needs (e .g. tweaking IsItemHovered() parameters). | // - You may want to handle the whole on user side if you have specific needs (e .g. tweaking IsItemHovered() parameters). | |||
// This is essentially the same as: | // This is essentially the same as: | |||
// id = str_id ? GetID(str_id) : GetItemID(); | // id = str_id ? GetID(str_id) : GetItemID(); | |||
// OpenPopupOnItemClick(str_id); | // OpenPopupOnItemClick(str_id, ImGuiPopupFlags_MouseButtonRight); | |||
// return BeginPopup(id); | // return BeginPopup(id); | |||
// Which is essentially the same as: | // Which is essentially the same as: | |||
// id = str_id ? GetID(str_id) : GetItemID(); | // id = str_id ? GetID(str_id) : GetItemID(); | |||
// if (IsItemHovered() && IsMouseReleased(ImGuiMouseButton_Right)) | // if (IsItemHovered() && IsMouseReleased(ImGuiMouseButton_Right)) | |||
// OpenPopup(id); | // OpenPopup(id); | |||
// return BeginPopup(id); | // return BeginPopup(id); | |||
// The main difference being that this is tweaked to avoid computing the ID tw ice. | // The main difference being that this is tweaked to avoid computing the ID tw ice. | |||
bool ImGui::BeginPopupContextItem(const char* str_id, ImGuiPopupFlags popup_flag s) | bool ImGui::BeginPopupContextItem(const char* str_id, ImGuiPopupFlags popup_flag s) | |||
{ | { | |||
ImGuiContext& g = *GImGui; | ImGuiContext& g = *GImGui; | |||
skipping to change at line 8987 | skipping to change at line 9432 | |||
float horizontal_overlap = g.Style.ItemInnerSpacing.x; // We want some o verlap to convey the relative depth of each menu (currently the amount of overla p is hard-coded to style.ItemSpacing.x). | float horizontal_overlap = g.Style.ItemInnerSpacing.x; // We want some o verlap to convey the relative depth of each menu (currently the amount of overla p is hard-coded to style.ItemSpacing.x). | |||
ImRect r_avoid; | ImRect r_avoid; | |||
if (parent_window->DC.MenuBarAppending) | if (parent_window->DC.MenuBarAppending) | |||
r_avoid = ImRect(-FLT_MAX, parent_window->ClipRect.Min.y, FLT_MAX, p arent_window->ClipRect.Max.y); // Avoid parent menu-bar. If we wanted multi-line menu-bar, we may instead want to have the calling window setup e.g. a NextWindo wData.PosConstraintAvoidRect field | r_avoid = ImRect(-FLT_MAX, parent_window->ClipRect.Min.y, FLT_MAX, p arent_window->ClipRect.Max.y); // Avoid parent menu-bar. If we wanted multi-line menu-bar, we may instead want to have the calling window setup e.g. a NextWindo wData.PosConstraintAvoidRect field | |||
else | else | |||
r_avoid = ImRect(parent_window->Pos.x + horizontal_overlap, -FLT_MAX , parent_window->Pos.x + parent_window->Size.x - horizontal_overlap - parent_win dow->ScrollbarSizes.x, FLT_MAX); | r_avoid = ImRect(parent_window->Pos.x + horizontal_overlap, -FLT_MAX , parent_window->Pos.x + parent_window->Size.x - horizontal_overlap - parent_win dow->ScrollbarSizes.x, FLT_MAX); | |||
return FindBestWindowPosForPopupEx(window->Pos, window->Size, &window->A utoPosLastDirection, r_outer, r_avoid, ImGuiPopupPositionPolicy_Default); | return FindBestWindowPosForPopupEx(window->Pos, window->Size, &window->A utoPosLastDirection, r_outer, r_avoid, ImGuiPopupPositionPolicy_Default); | |||
} | } | |||
if (window->Flags & ImGuiWindowFlags_Popup) | if (window->Flags & ImGuiWindowFlags_Popup) | |||
{ | { | |||
ImRect r_avoid = ImRect(window->Pos.x - 1, window->Pos.y - 1, window->Po | return FindBestWindowPosForPopupEx(window->Pos, window->Size, &window->A | |||
s.x + 1, window->Pos.y + 1); | utoPosLastDirection, r_outer, ImRect(window->Pos, window->Pos), ImGuiPopupPositi | |||
return FindBestWindowPosForPopupEx(window->Pos, window->Size, &window->A | onPolicy_Default); // Ideally we'd disable r_avoid here | |||
utoPosLastDirection, r_outer, r_avoid, ImGuiPopupPositionPolicy_Default); | ||||
} | } | |||
if (window->Flags & ImGuiWindowFlags_Tooltip) | if (window->Flags & ImGuiWindowFlags_Tooltip) | |||
{ | { | |||
// Position tooltip (always follows mouse) | // Position tooltip (always follows mouse) | |||
float sc = g.Style.MouseCursorScale; | float sc = g.Style.MouseCursorScale; | |||
ImVec2 ref_pos = NavCalcPreferredRefPos(); | ImVec2 ref_pos = NavCalcPreferredRefPos(); | |||
ImRect r_avoid; | ImRect r_avoid; | |||
if (!g.NavDisableHighlight && g.NavDisableMouseHover && !(g.IO.ConfigFla gs & ImGuiConfigFlags_NavEnableSetMousePos)) | if (!g.NavDisableHighlight && g.NavDisableMouseHover && !(g.IO.ConfigFla gs & ImGuiConfigFlags_NavEnableSetMousePos)) | |||
r_avoid = ImRect(ref_pos.x - 16, ref_pos.y - 8, ref_pos.x + 16, ref_ pos.y + 8); | r_avoid = ImRect(ref_pos.x - 16, ref_pos.y - 8, ref_pos.x + 16, ref_ pos.y + 8); | |||
else | else | |||
skipping to change at line 9497 | skipping to change at line 9941 | |||
} | } | |||
} | } | |||
static ImVec2 ImGui::NavCalcPreferredRefPos() | static ImVec2 ImGui::NavCalcPreferredRefPos() | |||
{ | { | |||
ImGuiContext& g = *GImGui; | ImGuiContext& g = *GImGui; | |||
ImGuiWindow* window = g.NavWindow; | ImGuiWindow* window = g.NavWindow; | |||
if (g.NavDisableHighlight || !g.NavDisableMouseHover || !window) | if (g.NavDisableHighlight || !g.NavDisableMouseHover || !window) | |||
{ | { | |||
// Mouse (we need a fallback in case the mouse becomes invalid after bei ng used) | // Mouse (we need a fallback in case the mouse becomes invalid after bei ng used) | |||
if (IsMousePosValid(&g.IO.MousePos)) | // The +1.0f offset when stored by OpenPopupEx() allows reopening this o | |||
return g.IO.MousePos; | r another popup (same or another mouse button) while not moving the mouse, it is | |||
return g.MouseLastValidPos; | pretty standard. | |||
// In theory we could move that +1.0f offset in OpenPopupEx() | ||||
ImVec2 p = IsMousePosValid(&g.IO.MousePos) ? g.IO.MousePos : g.MouseLast | ||||
ValidPos; | ||||
return ImVec2(p.x + 1.0f, p.y); | ||||
} | } | |||
else | else | |||
{ | { | |||
// When navigation is active and mouse is disabled, pick a position arou nd the bottom left of the currently navigated item | // When navigation is active and mouse is disabled, pick a position arou nd the bottom left of the currently navigated item | |||
// Take account of upcoming scrolling (maybe set mouse pos should be don e in EndFrame?) | // Take account of upcoming scrolling (maybe set mouse pos should be don e in EndFrame?) | |||
ImRect rect_rel = WindowRectRelToAbs(window, window->NavRectRel[g.NavLay er]); | ImRect rect_rel = WindowRectRelToAbs(window, window->NavRectRel[g.NavLay er]); | |||
if (window->LastFrameActive != g.FrameCount && (window->ScrollTarget.x ! = FLT_MAX || window->ScrollTarget.y != FLT_MAX)) | if (window->LastFrameActive != g.FrameCount && (window->ScrollTarget.x ! = FLT_MAX || window->ScrollTarget.y != FLT_MAX)) | |||
{ | { | |||
ImVec2 next_scroll = CalcNextScrollFromScrollTargetAndClamp(window); | ImVec2 next_scroll = CalcNextScrollFromScrollTargetAndClamp(window); | |||
rect_rel.Translate(window->Scroll - next_scroll); | rect_rel.Translate(window->Scroll - next_scroll); | |||
} | } | |||
ImVec2 pos = ImVec2(rect_rel.Min.x + ImMin(g.Style.FramePadding.x * 4, r ect_rel.GetWidth()), rect_rel.Max.y - ImMin(g.Style.FramePadding.y, rect_rel.Get Height())); | ImVec2 pos = ImVec2(rect_rel.Min.x + ImMin(g.Style.FramePadding.x * 4, r ect_rel.GetWidth()), rect_rel.Max.y - ImMin(g.Style.FramePadding.y, rect_rel.Get Height())); | |||
ImGuiViewport* viewport = GetMainViewport(); | ImGuiViewport* viewport = GetMainViewport(); | |||
return ImFloor(ImClamp(pos, viewport->Pos, viewport->Pos + viewport->Siz e)); // ImFloor() is important because non-integer mouse position application in backend might be lossy and result in undesirable non-zero delta. | return ImFloor(ImClamp(pos, viewport->Pos, viewport->Pos + viewport->Siz e)); // ImFloor() is important because non-integer mouse position application in backend might be lossy and result in undesirable non-zero delta. | |||
} | } | |||
} | } | |||
const char* ImGui::GetNavInputName(ImGuiNavInput n) | ||||
{ | ||||
static const char* names[] = | ||||
{ | ||||
"Activate", "Cancel", "Input", "Menu", "DpadLeft", "DpadRight", "DpadUp" | ||||
, "DpadDown", "LStickLeft", "LStickRight", "LStickUp", "LStickDown", | ||||
"FocusPrev", "FocusNext", "TweakSlow", "TweakFast", "KeyLeft", "KeyRight | ||||
", "KeyUp", "KeyDown" | ||||
}; | ||||
IM_ASSERT(IM_ARRAYSIZE(names) == ImGuiNavInput_COUNT); | ||||
IM_ASSERT(n >= 0 && n < ImGuiNavInput_COUNT); | ||||
return names[n]; | ||||
} | ||||
float ImGui::GetNavInputAmount(ImGuiNavInput n, ImGuiInputReadMode mode) | float ImGui::GetNavInputAmount(ImGuiNavInput n, ImGuiInputReadMode mode) | |||
{ | { | |||
ImGuiContext& g = *GImGui; | ImGuiContext& g = *GImGui; | |||
if (mode == ImGuiInputReadMode_Down) | if (mode == ImGuiInputReadMode_Down) | |||
return g.IO.NavInputs[n]; // Instant, read analo g input (0.0f..1.0f, as provided by user) | return g.IO.NavInputs[n]; // Instant, read analo g input (0.0f..1.0f, as provided by user) | |||
const float t = g.IO.NavInputsDownDuration[n]; | const float t = g.IO.NavInputsDownDuration[n]; | |||
if (t < 0.0f && mode == ImGuiInputReadMode_Released) // Return 1.0f when ju st released, no repeat, ignore analog input. | if (t < 0.0f && mode == ImGuiInputReadMode_Released) // Return 1.0f when ju st released, no repeat, ignore analog input. | |||
return (g.IO.NavInputsDownDurationPrev[n] >= 0.0f ? 1.0f : 0.0f); | return (g.IO.NavInputsDownDurationPrev[n] >= 0.0f ? 1.0f : 0.0f); | |||
if (t < 0.0f) | if (t < 0.0f) | |||
skipping to change at line 9543 | skipping to change at line 10000 | |||
return (float)CalcTypematicRepeatAmount(t - g.IO.DeltaTime, t, g.IO.KeyR epeatDelay * 1.25f, g.IO.KeyRepeatRate * 2.00f); | return (float)CalcTypematicRepeatAmount(t - g.IO.DeltaTime, t, g.IO.KeyR epeatDelay * 1.25f, g.IO.KeyRepeatRate * 2.00f); | |||
if (mode == ImGuiInputReadMode_RepeatFast) | if (mode == ImGuiInputReadMode_RepeatFast) | |||
return (float)CalcTypematicRepeatAmount(t - g.IO.DeltaTime, t, g.IO.KeyR epeatDelay * 0.72f, g.IO.KeyRepeatRate * 0.30f); | return (float)CalcTypematicRepeatAmount(t - g.IO.DeltaTime, t, g.IO.KeyR epeatDelay * 0.72f, g.IO.KeyRepeatRate * 0.30f); | |||
return 0.0f; | return 0.0f; | |||
} | } | |||
ImVec2 ImGui::GetNavInputAmount2d(ImGuiNavDirSourceFlags dir_sources, ImGuiInput ReadMode mode, float slow_factor, float fast_factor) | ImVec2 ImGui::GetNavInputAmount2d(ImGuiNavDirSourceFlags dir_sources, ImGuiInput ReadMode mode, float slow_factor, float fast_factor) | |||
{ | { | |||
ImVec2 delta(0.0f, 0.0f); | ImVec2 delta(0.0f, 0.0f); | |||
if (dir_sources & ImGuiNavDirSourceFlags_RawKeyboard) | if (dir_sources & ImGuiNavDirSourceFlags_RawKeyboard) | |||
delta += ImVec2((float)IsKeyDown(GetKeyIndex(ImGuiKey_RightArrow)) - (fl oat)IsKeyDown(GetKeyIndex(ImGuiKey_LeftArrow)), (float)IsKeyDown(GetKeyIndex(ImG uiKey_DownArrow)) - (float)IsKeyDown(GetKeyIndex(ImGuiKey_UpArrow))); | delta += ImVec2((float)IsKeyDown(ImGuiKey_RightArrow) - (float)IsKeyDown (ImGuiKey_LeftArrow), (float)IsKeyDown(ImGuiKey_DownArrow) - (float)IsKeyDown(Im GuiKey_UpArrow)); | |||
if (dir_sources & ImGuiNavDirSourceFlags_Keyboard) | if (dir_sources & ImGuiNavDirSourceFlags_Keyboard) | |||
delta += ImVec2(GetNavInputAmount(ImGuiNavInput_KeyRight_, mode) - Get NavInputAmount(ImGuiNavInput_KeyLeft_, mode), GetNavInputAmount(ImGuiNavInput_ KeyDown_, mode) - GetNavInputAmount(ImGuiNavInput_KeyUp_, mode)); | delta += ImVec2(GetNavInputAmount(ImGuiNavInput_KeyRight_, mode) - Get NavInputAmount(ImGuiNavInput_KeyLeft_, mode), GetNavInputAmount(ImGuiNavInput_ KeyDown_, mode) - GetNavInputAmount(ImGuiNavInput_KeyUp_, mode)); | |||
if (dir_sources & ImGuiNavDirSourceFlags_PadDPad) | if (dir_sources & ImGuiNavDirSourceFlags_PadDPad) | |||
delta += ImVec2(GetNavInputAmount(ImGuiNavInput_DpadRight, mode) - Get NavInputAmount(ImGuiNavInput_DpadLeft, mode), GetNavInputAmount(ImGuiNavInput_ DpadDown, mode) - GetNavInputAmount(ImGuiNavInput_DpadUp, mode)); | delta += ImVec2(GetNavInputAmount(ImGuiNavInput_DpadRight, mode) - Get NavInputAmount(ImGuiNavInput_DpadLeft, mode), GetNavInputAmount(ImGuiNavInput_ DpadDown, mode) - GetNavInputAmount(ImGuiNavInput_DpadUp, mode)); | |||
if (dir_sources & ImGuiNavDirSourceFlags_PadLStick) | if (dir_sources & ImGuiNavDirSourceFlags_PadLStick) | |||
delta += ImVec2(GetNavInputAmount(ImGuiNavInput_LStickRight, mode) - Get NavInputAmount(ImGuiNavInput_LStickLeft, mode), GetNavInputAmount(ImGuiNavInput_ LStickDown, mode) - GetNavInputAmount(ImGuiNavInput_LStickUp, mode)); | delta += ImVec2(GetNavInputAmount(ImGuiNavInput_LStickRight, mode) - Get NavInputAmount(ImGuiNavInput_LStickLeft, mode), GetNavInputAmount(ImGuiNavInput_ LStickDown, mode) - GetNavInputAmount(ImGuiNavInput_LStickUp, mode)); | |||
if (slow_factor != 0.0f && IsNavInputDown(ImGuiNavInput_TweakSlow)) | if (slow_factor != 0.0f && IsNavInputDown(ImGuiNavInput_TweakSlow)) | |||
delta *= slow_factor; | delta *= slow_factor; | |||
if (fast_factor != 0.0f && IsNavInputDown(ImGuiNavInput_TweakFast)) | if (fast_factor != 0.0f && IsNavInputDown(ImGuiNavInput_TweakFast)) | |||
delta *= fast_factor; | delta *= fast_factor; | |||
skipping to change at line 9565 | skipping to change at line 10022 | |||
} | } | |||
static void ImGui::NavUpdate() | static void ImGui::NavUpdate() | |||
{ | { | |||
ImGuiContext& g = *GImGui; | ImGuiContext& g = *GImGui; | |||
ImGuiIO& io = g.IO; | ImGuiIO& io = g.IO; | |||
io.WantSetMousePos = false; | io.WantSetMousePos = false; | |||
//if (g.NavScoringDebugCount > 0) IMGUI_DEBUG_LOG("NavScoringDebugCount %d f or '%s' layer %d (Init:%d, Move:%d)\n", g.NavScoringDebugCount, g.NavWindow ? g. NavWindow->Name : "NULL", g.NavLayer, g.NavInitRequest || g.NavInitResultId != 0 , g.NavMoveRequest); | //if (g.NavScoringDebugCount > 0) IMGUI_DEBUG_LOG("NavScoringDebugCount %d f or '%s' layer %d (Init:%d, Move:%d)\n", g.NavScoringDebugCount, g.NavWindow ? g. NavWindow->Name : "NULL", g.NavLayer, g.NavInitRequest || g.NavInitResultId != 0 , g.NavMoveRequest); | |||
// Update Gamepad->Nav inputs mapping | ||||
// Set input source as Gamepad when buttons are pressed (as some features di ffers when used with Gamepad vs Keyboard) | // Set input source as Gamepad when buttons are pressed (as some features di ffers when used with Gamepad vs Keyboard) | |||
// (do it before we map Keyboard input!) | ||||
const bool nav_keyboard_active = (io.ConfigFlags & ImGuiConfigFlags_NavEnabl | ||||
eKeyboard) != 0; | ||||
const bool nav_gamepad_active = (io.ConfigFlags & ImGuiConfigFlags_NavEnable Gamepad) != 0 && (io.BackendFlags & ImGuiBackendFlags_HasGamepad) != 0; | const bool nav_gamepad_active = (io.ConfigFlags & ImGuiConfigFlags_NavEnable Gamepad) != 0 && (io.BackendFlags & ImGuiBackendFlags_HasGamepad) != 0; | |||
if (nav_gamepad_active && g.NavInputSource != ImGuiInputSource_Gamepad) | if (nav_gamepad_active && g.IO.BackendUsingLegacyNavInputArray == false) | |||
{ | { | |||
if (io.NavInputs[ImGuiNavInput_Activate] > 0.0f || io.NavInputs[ImGuiNav | for (int n = 0; n < ImGuiNavInput_COUNT; n++) | |||
Input_Input] > 0.0f || io.NavInputs[ImGuiNavInput_Cancel] > 0.0f || io.NavInputs | IM_ASSERT(io.NavInputs[n] == 0.0f && "Backend needs to either only u | |||
[ImGuiNavInput_Menu] > 0.0f | se io.AddKeyEvent()/io.AddKeyAnalogEvent(), either only fill legacy io.NavInputs | |||
|| io.NavInputs[ImGuiNavInput_DpadLeft] > 0.0f || io.NavInputs[ImGui | []. Not both!"); | |||
NavInput_DpadRight] > 0.0f || io.NavInputs[ImGuiNavInput_DpadUp] > 0.0f || io.Na | #define NAV_MAP_KEY(_KEY, _NAV_INPUT, _ACTIVATE_NAV) do { io.NavInputs[ | |||
vInputs[ImGuiNavInput_DpadDown] > 0.0f) | _NAV_INPUT] = io.KeysData[_KEY - ImGuiKey_KeysData_OFFSET].AnalogValue; if (_ACT | |||
g.NavInputSource = ImGuiInputSource_Gamepad; | IVATE_NAV && io.NavInputs[_NAV_INPUT] > 0.0f) { g.NavInputSource = ImGuiInputSou | |||
rce_Gamepad; } } while (0) | ||||
NAV_MAP_KEY(ImGuiKey_GamepadFaceDown, ImGuiNavInput_Activate, true); | ||||
NAV_MAP_KEY(ImGuiKey_GamepadFaceRight, ImGuiNavInput_Cancel, true); | ||||
NAV_MAP_KEY(ImGuiKey_GamepadFaceLeft, ImGuiNavInput_Menu, true); | ||||
NAV_MAP_KEY(ImGuiKey_GamepadFaceUp, ImGuiNavInput_Input, true); | ||||
NAV_MAP_KEY(ImGuiKey_GamepadDpadLeft, ImGuiNavInput_DpadLeft, true); | ||||
NAV_MAP_KEY(ImGuiKey_GamepadDpadRight, ImGuiNavInput_DpadRight, true); | ||||
NAV_MAP_KEY(ImGuiKey_GamepadDpadUp, ImGuiNavInput_DpadUp, true); | ||||
NAV_MAP_KEY(ImGuiKey_GamepadDpadDown, ImGuiNavInput_DpadDown, true); | ||||
NAV_MAP_KEY(ImGuiKey_GamepadL1, ImGuiNavInput_FocusPrev, false); | ||||
NAV_MAP_KEY(ImGuiKey_GamepadR1, ImGuiNavInput_FocusNext, false); | ||||
NAV_MAP_KEY(ImGuiKey_GamepadL1, ImGuiNavInput_TweakSlow, false); | ||||
NAV_MAP_KEY(ImGuiKey_GamepadR1, ImGuiNavInput_TweakFast, false); | ||||
NAV_MAP_KEY(ImGuiKey_GamepadLStickLeft, ImGuiNavInput_LStickLeft, false) | ||||
; | ||||
NAV_MAP_KEY(ImGuiKey_GamepadLStickRight, ImGuiNavInput_LStickRight, fals | ||||
e); | ||||
NAV_MAP_KEY(ImGuiKey_GamepadLStickUp, ImGuiNavInput_LStickUp, false); | ||||
NAV_MAP_KEY(ImGuiKey_GamepadLStickDown, ImGuiNavInput_LStickDown, false) | ||||
; | ||||
#undef NAV_MAP_KEY | ||||
} | } | |||
// Update Keyboard->Nav inputs mapping | // Update Keyboard->Nav inputs mapping | |||
const bool nav_keyboard_active = (io.ConfigFlags & ImGuiConfigFlags_NavEnabl eKeyboard) != 0; | ||||
if (nav_keyboard_active) | if (nav_keyboard_active) | |||
{ | { | |||
#define NAV_MAP_KEY(_KEY, _NAV_INPUT) do { if (IsKeyDown(io.KeyMap[_KEY ])) { io.NavInputs[_NAV_INPUT] = 1.0f; g.NavInputSource = ImGuiInputSource_Keybo ard; } } while (0) | #define NAV_MAP_KEY(_KEY, _NAV_INPUT) do { if (IsKeyDown(_KEY)) { io.Na vInputs[_NAV_INPUT] = 1.0f; g.NavInputSource = ImGuiInputSource_Keyboard; } } wh ile (0) | |||
NAV_MAP_KEY(ImGuiKey_Space, ImGuiNavInput_Activate ); | NAV_MAP_KEY(ImGuiKey_Space, ImGuiNavInput_Activate ); | |||
NAV_MAP_KEY(ImGuiKey_Enter, ImGuiNavInput_Input ); | NAV_MAP_KEY(ImGuiKey_Enter, ImGuiNavInput_Input ); | |||
NAV_MAP_KEY(ImGuiKey_Escape, ImGuiNavInput_Cancel ); | NAV_MAP_KEY(ImGuiKey_Escape, ImGuiNavInput_Cancel ); | |||
NAV_MAP_KEY(ImGuiKey_LeftArrow, ImGuiNavInput_KeyLeft_ ); | NAV_MAP_KEY(ImGuiKey_LeftArrow, ImGuiNavInput_KeyLeft_ ); | |||
NAV_MAP_KEY(ImGuiKey_RightArrow,ImGuiNavInput_KeyRight_); | NAV_MAP_KEY(ImGuiKey_RightArrow,ImGuiNavInput_KeyRight_); | |||
NAV_MAP_KEY(ImGuiKey_UpArrow, ImGuiNavInput_KeyUp_ ); | NAV_MAP_KEY(ImGuiKey_UpArrow, ImGuiNavInput_KeyUp_ ); | |||
NAV_MAP_KEY(ImGuiKey_DownArrow, ImGuiNavInput_KeyDown_ ); | NAV_MAP_KEY(ImGuiKey_DownArrow, ImGuiNavInput_KeyDown_ ); | |||
if (io.KeyCtrl) | if (io.KeyCtrl) | |||
io.NavInputs[ImGuiNavInput_TweakSlow] = 1.0f; | io.NavInputs[ImGuiNavInput_TweakSlow] = 1.0f; | |||
if (io.KeyShift) | if (io.KeyShift) | |||
skipping to change at line 9797 | skipping to change at line 10271 | |||
if (window && g.NavMoveDir == ImGuiDir_None && nav_keyboard_active) | if (window && g.NavMoveDir == ImGuiDir_None && nav_keyboard_active) | |||
scoring_rect_offset_y = NavUpdatePageUpPageDown(); | scoring_rect_offset_y = NavUpdatePageUpPageDown(); | |||
if (scoring_rect_offset_y != 0.0f) | if (scoring_rect_offset_y != 0.0f) | |||
{ | { | |||
g.NavScoringNoClipRect = window->InnerRect; | g.NavScoringNoClipRect = window->InnerRect; | |||
g.NavScoringNoClipRect.TranslateY(scoring_rect_offset_y); | g.NavScoringNoClipRect.TranslateY(scoring_rect_offset_y); | |||
} | } | |||
// [DEBUG] Always send a request | // [DEBUG] Always send a request | |||
#if IMGUI_DEBUG_NAV_SCORING | #if IMGUI_DEBUG_NAV_SCORING | |||
if (io.KeyCtrl && IsKeyPressedMap(ImGuiKey_C)) | if (io.KeyCtrl && IsKeyPressed(ImGuiKey_C)) | |||
g.NavMoveDirForDebug = (ImGuiDir)((g.NavMoveDirForDebug + 1) & 3); | g.NavMoveDirForDebug = (ImGuiDir)((g.NavMoveDirForDebug + 1) & 3); | |||
if (io.KeyCtrl && g.NavMoveDir == ImGuiDir_None) | if (io.KeyCtrl && g.NavMoveDir == ImGuiDir_None) | |||
{ | { | |||
g.NavMoveDir = g.NavMoveDirForDebug; | g.NavMoveDir = g.NavMoveDirForDebug; | |||
g.NavMoveFlags |= ImGuiNavMoveFlags_DebugNoResult; | g.NavMoveFlags |= ImGuiNavMoveFlags_DebugNoResult; | |||
} | } | |||
#endif | #endif | |||
// Submit | // Submit | |||
g.NavMoveForwardToNextFrame = false; | g.NavMoveForwardToNextFrame = false; | |||
skipping to change at line 9823 | skipping to change at line 10297 | |||
{ | { | |||
IMGUI_DEBUG_LOG_NAV("[nav] NavInitRequest: from move, window \"%s\", lay er=%d\n", g.NavWindow->Name, g.NavLayer); | IMGUI_DEBUG_LOG_NAV("[nav] NavInitRequest: from move, window \"%s\", lay er=%d\n", g.NavWindow->Name, g.NavLayer); | |||
g.NavInitRequest = g.NavInitRequestFromMove = true; | g.NavInitRequest = g.NavInitRequestFromMove = true; | |||
g.NavInitResultId = 0; | g.NavInitResultId = 0; | |||
g.NavDisableHighlight = false; | g.NavDisableHighlight = false; | |||
} | } | |||
// When using gamepad, we project the reference nav bounding box into window visible area. | // When using gamepad, we project the reference nav bounding box into window visible area. | |||
// This is to allow resuming navigation inside the visible area after doing a large amount of scrolling, since with gamepad every movements are relative | // This is to allow resuming navigation inside the visible area after doing a large amount of scrolling, since with gamepad every movements are relative | |||
// (can't focus a visible object like we can with the mouse). | // (can't focus a visible object like we can with the mouse). | |||
if (g.NavMoveSubmitted && g.NavInputSource == ImGuiInputSource_Gamepad && g. NavLayer == ImGuiNavLayer_Main && window != NULL) | if (g.NavMoveSubmitted && g.NavInputSource == ImGuiInputSource_Gamepad && g. NavLayer == ImGuiNavLayer_Main && window != NULL)// && (g.NavMoveFlags & ImGuiNa vMoveFlags_Forwarded)) | |||
{ | { | |||
ImRect window_rect_rel = WindowRectAbsToRel(window, ImRect(window->Inner | bool clamp_x = (g.NavMoveFlags & (ImGuiNavMoveFlags_LoopX | ImGuiNavMove | |||
Rect.Min - ImVec2(1, 1), window->InnerRect.Max + ImVec2(1, 1))); | Flags_WrapX)) == 0; | |||
if (!window_rect_rel.Contains(window->NavRectRel[g.NavLayer])) | bool clamp_y = (g.NavMoveFlags & (ImGuiNavMoveFlags_LoopY | ImGuiNavMove | |||
{ | Flags_WrapY)) == 0; | |||
IMGUI_DEBUG_LOG_NAV("[nav] NavMoveRequest: clamp NavRectRel\n"); | ImRect inner_rect_rel = WindowRectAbsToRel(window, ImRect(window->InnerR | |||
float pad = window->CalcFontSize() * 0.5f; | ect.Min - ImVec2(1, 1), window->InnerRect.Max + ImVec2(1, 1))); | |||
window_rect_rel.Expand(ImVec2(-ImMin(window_rect_rel.GetWidth(), pad | if ((clamp_x || clamp_y) && !inner_rect_rel.Contains(window->NavRectRel[ | |||
), -ImMin(window_rect_rel.GetHeight(), pad))); // Terrible approximation for the | g.NavLayer])) | |||
intent of starting navigation from first fully visible item | { | |||
window->NavRectRel[g.NavLayer].ClipWithFull(window_rect_rel); | IMGUI_DEBUG_LOG_NAV("[nav] NavMoveRequest: clamp NavRectRel for game | |||
pad move\n"); | ||||
float pad_x = ImMin(inner_rect_rel.GetWidth(), window->CalcFontSize( | ||||
) * 0.5f); | ||||
float pad_y = ImMin(inner_rect_rel.GetHeight(), window->CalcFontSize | ||||
() * 0.5f); // Terrible approximation for the intent of starting navigation from | ||||
first fully visible item | ||||
inner_rect_rel.Min.x = clamp_x ? (inner_rect_rel.Min.x + pad_x) : -F | ||||
LT_MAX; | ||||
inner_rect_rel.Max.x = clamp_x ? (inner_rect_rel.Max.x - pad_x) : +F | ||||
LT_MAX; | ||||
inner_rect_rel.Min.y = clamp_y ? (inner_rect_rel.Min.y + pad_y) : -F | ||||
LT_MAX; | ||||
inner_rect_rel.Max.y = clamp_y ? (inner_rect_rel.Max.y - pad_y) : +F | ||||
LT_MAX; | ||||
window->NavRectRel[g.NavLayer].ClipWithFull(inner_rect_rel); | ||||
g.NavId = g.NavFocusScopeId = 0; | g.NavId = g.NavFocusScopeId = 0; | |||
} | } | |||
} | } | |||
// For scoring we use a single segment on the left side our current item bou nding box (not touching the edge to avoid box overlap with zero-spaced items) | // For scoring we use a single segment on the left side our current item bou nding box (not touching the edge to avoid box overlap with zero-spaced items) | |||
ImRect scoring_rect; | ImRect scoring_rect; | |||
if (window != NULL) | if (window != NULL) | |||
{ | { | |||
ImRect nav_rect_rel = !window->NavRectRel[g.NavLayer].IsInverted() ? win dow->NavRectRel[g.NavLayer] : ImRect(0, 0, 0, 0); | ImRect nav_rect_rel = !window->NavRectRel[g.NavLayer].IsInverted() ? win dow->NavRectRel[g.NavLayer] : ImRect(0, 0, 0, 0); | |||
scoring_rect = WindowRectRelToAbs(window, nav_rect_rel); | scoring_rect = WindowRectRelToAbs(window, nav_rect_rel); | |||
skipping to change at line 9861 | skipping to change at line 10341 | |||
} | } | |||
void ImGui::NavUpdateCreateTabbingRequest() | void ImGui::NavUpdateCreateTabbingRequest() | |||
{ | { | |||
ImGuiContext& g = *GImGui; | ImGuiContext& g = *GImGui; | |||
ImGuiWindow* window = g.NavWindow; | ImGuiWindow* window = g.NavWindow; | |||
IM_ASSERT(g.NavMoveDir == ImGuiDir_None); | IM_ASSERT(g.NavMoveDir == ImGuiDir_None); | |||
if (window == NULL || g.NavWindowingTarget != NULL || (window->Flags & ImGui WindowFlags_NoNavInputs)) | if (window == NULL || g.NavWindowingTarget != NULL || (window->Flags & ImGui WindowFlags_NoNavInputs)) | |||
return; | return; | |||
const bool tab_pressed = IsKeyPressedMap(ImGuiKey_Tab, true) && !IsActiveIdU singKey(ImGuiKey_Tab) && !g.IO.KeyCtrl && !g.IO.KeyAlt; | const bool tab_pressed = IsKeyPressed(ImGuiKey_Tab, true) && !IsActiveIdUsin gKey(ImGuiKey_Tab) && !g.IO.KeyCtrl && !g.IO.KeyAlt; | |||
if (!tab_pressed) | if (!tab_pressed) | |||
return; | return; | |||
// Initiate tabbing request | // Initiate tabbing request | |||
// (this is ALWAYS ENABLED, regardless of ImGuiConfigFlags_NavEnableKeyboard flag!) | // (this is ALWAYS ENABLED, regardless of ImGuiConfigFlags_NavEnableKeyboard flag!) | |||
// Initially this was designed to use counters and modulo arithmetic, but th at could not work with unsubmitted items (list clipper). Instead we use a strate gy close to other move requests. | // Initially this was designed to use counters and modulo arithmetic, but th at could not work with unsubmitted items (list clipper). Instead we use a strate gy close to other move requests. | |||
// See NavProcessItemForTabbingRequest() for a description of the various fo rward/backward tabbing cases with and without wrapping. | // See NavProcessItemForTabbingRequest() for a description of the various fo rward/backward tabbing cases with and without wrapping. | |||
//// FIXME: We use (g.ActiveId == 0) but (g.NavDisableHighlight == false) mi ght be righter once we can tab through anything | //// FIXME: We use (g.ActiveId == 0) but (g.NavDisableHighlight == false) mi ght be righter once we can tab through anything | |||
g.NavTabbingDir = g.IO.KeyShift ? -1 : (g.ActiveId == 0) ? 0 : +1; | g.NavTabbingDir = g.IO.KeyShift ? -1 : (g.ActiveId == 0) ? 0 : +1; | |||
ImGuiScrollFlags scroll_flags = window->Appearing ? ImGuiScrollFlags_KeepVis ibleEdgeX | ImGuiScrollFlags_AlwaysCenterY : ImGuiScrollFlags_KeepVisibleEdgeX | ImGuiScrollFlags_KeepVisibleEdgeY; | ImGuiScrollFlags scroll_flags = window->Appearing ? ImGuiScrollFlags_KeepVis ibleEdgeX | ImGuiScrollFlags_AlwaysCenterY : ImGuiScrollFlags_KeepVisibleEdgeX | ImGuiScrollFlags_KeepVisibleEdgeY; | |||
skipping to change at line 10022 | skipping to change at line 10502 | |||
} | } | |||
} | } | |||
// Handle PageUp/PageDown/Home/End keys | // Handle PageUp/PageDown/Home/End keys | |||
// Called from NavUpdateCreateMoveRequest() which will use our output to create a move request | // Called from NavUpdateCreateMoveRequest() which will use our output to create a move request | |||
// FIXME-NAV: This doesn't work properly with NavFlattened siblings as we use Na vWindow rectangle for reference | // FIXME-NAV: This doesn't work properly with NavFlattened siblings as we use Na vWindow rectangle for reference | |||
// FIXME-NAV: how to get Home/End to aim at the beginning/end of a 2D grid? | // FIXME-NAV: how to get Home/End to aim at the beginning/end of a 2D grid? | |||
static float ImGui::NavUpdatePageUpPageDown() | static float ImGui::NavUpdatePageUpPageDown() | |||
{ | { | |||
ImGuiContext& g = *GImGui; | ImGuiContext& g = *GImGui; | |||
ImGuiIO& io = g.IO; | ||||
ImGuiWindow* window = g.NavWindow; | ImGuiWindow* window = g.NavWindow; | |||
if ((window->Flags & ImGuiWindowFlags_NoNavInputs) || g.NavWindowingTarget ! = NULL) | if ((window->Flags & ImGuiWindowFlags_NoNavInputs) || g.NavWindowingTarget ! = NULL) | |||
return 0.0f; | return 0.0f; | |||
const bool page_up_held = IsKeyDown(io.KeyMap[ImGuiKey_PageUp]) && !IsActive | const bool page_up_held = IsKeyDown(ImGuiKey_PageUp) && !IsActiveIdUsingKey( | |||
IdUsingKey(ImGuiKey_PageUp); | ImGuiKey_PageUp); | |||
const bool page_down_held = IsKeyDown(io.KeyMap[ImGuiKey_PageDown]) && !IsAc | const bool page_down_held = IsKeyDown(ImGuiKey_PageDown) && !IsActiveIdUsing | |||
tiveIdUsingKey(ImGuiKey_PageDown); | Key(ImGuiKey_PageDown); | |||
const bool home_pressed = IsKeyPressed(io.KeyMap[ImGuiKey_Home]) && !IsActiv | const bool home_pressed = IsKeyPressed(ImGuiKey_Home) && !IsActiveIdUsingKey | |||
eIdUsingKey(ImGuiKey_Home); | (ImGuiKey_Home); | |||
const bool end_pressed = IsKeyPressed(io.KeyMap[ImGuiKey_End]) && !IsActiveI | const bool end_pressed = IsKeyPressed(ImGuiKey_End) && !IsActiveIdUsingKey(I | |||
dUsingKey(ImGuiKey_End); | mGuiKey_End); | |||
if (page_up_held == page_down_held && home_pressed == end_pressed) // Procee d if either (not both) are pressed, otherwise early out | if (page_up_held == page_down_held && home_pressed == end_pressed) // Procee d if either (not both) are pressed, otherwise early out | |||
return 0.0f; | return 0.0f; | |||
if (g.NavLayer != ImGuiNavLayer_Main) | if (g.NavLayer != ImGuiNavLayer_Main) | |||
NavRestoreLayer(ImGuiNavLayer_Main); | NavRestoreLayer(ImGuiNavLayer_Main); | |||
if (window->DC.NavLayersActiveMask == 0x00 && window->DC.NavHasScroll) | if (window->DC.NavLayersActiveMask == 0x00 && window->DC.NavHasScroll) | |||
{ | { | |||
// Fallback manual-scroll when window has no navigable item | // Fallback manual-scroll when window has no navigable item | |||
if (IsKeyPressed(io.KeyMap[ImGuiKey_PageUp], true)) | if (IsKeyPressed(ImGuiKey_PageUp, true)) | |||
SetScrollY(window, window->Scroll.y - window->InnerRect.GetHeight()) ; | SetScrollY(window, window->Scroll.y - window->InnerRect.GetHeight()) ; | |||
else if (IsKeyPressed(io.KeyMap[ImGuiKey_PageDown], true)) | else if (IsKeyPressed(ImGuiKey_PageDown, true)) | |||
SetScrollY(window, window->Scroll.y + window->InnerRect.GetHeight()) ; | SetScrollY(window, window->Scroll.y + window->InnerRect.GetHeight()) ; | |||
else if (home_pressed) | else if (home_pressed) | |||
SetScrollY(window, 0.0f); | SetScrollY(window, 0.0f); | |||
else if (end_pressed) | else if (end_pressed) | |||
SetScrollY(window, window->ScrollMax.y); | SetScrollY(window, window->ScrollMax.y); | |||
} | } | |||
else | else | |||
{ | { | |||
ImRect& nav_rect_rel = window->NavRectRel[g.NavLayer]; | ImRect& nav_rect_rel = window->NavRectRel[g.NavLayer]; | |||
const float page_offset_y = ImMax(0.0f, window->InnerRect.GetHeight() - window->CalcFontSize() * 1.0f + nav_rect_rel.GetHeight()); | const float page_offset_y = ImMax(0.0f, window->InnerRect.GetHeight() - window->CalcFontSize() * 1.0f + nav_rect_rel.GetHeight()); | |||
float nav_scoring_rect_offset_y = 0.0f; | float nav_scoring_rect_offset_y = 0.0f; | |||
if (IsKeyPressed(io.KeyMap[ImGuiKey_PageUp], true)) | if (IsKeyPressed(ImGuiKey_PageUp, true)) | |||
{ | { | |||
nav_scoring_rect_offset_y = -page_offset_y; | nav_scoring_rect_offset_y = -page_offset_y; | |||
g.NavMoveDir = ImGuiDir_Down; // Because our scoring rect is offset up, we request the down direction (so we can always land on the last item) | g.NavMoveDir = ImGuiDir_Down; // Because our scoring rect is offset up, we request the down direction (so we can always land on the last item) | |||
g.NavMoveClipDir = ImGuiDir_Up; | g.NavMoveClipDir = ImGuiDir_Up; | |||
g.NavMoveFlags = ImGuiNavMoveFlags_AllowCurrentNavId | ImGuiNavMoveF lags_AlsoScoreVisibleSet; | g.NavMoveFlags = ImGuiNavMoveFlags_AllowCurrentNavId | ImGuiNavMoveF lags_AlsoScoreVisibleSet; | |||
} | } | |||
else if (IsKeyPressed(io.KeyMap[ImGuiKey_PageDown], true)) | else if (IsKeyPressed(ImGuiKey_PageDown, true)) | |||
{ | { | |||
nav_scoring_rect_offset_y = +page_offset_y; | nav_scoring_rect_offset_y = +page_offset_y; | |||
g.NavMoveDir = ImGuiDir_Up; // Because our scoring rect is offset do wn, we request the up direction (so we can always land on the last item) | g.NavMoveDir = ImGuiDir_Up; // Because our scoring rect is offset do wn, we request the up direction (so we can always land on the last item) | |||
g.NavMoveClipDir = ImGuiDir_Down; | g.NavMoveClipDir = ImGuiDir_Down; | |||
g.NavMoveFlags = ImGuiNavMoveFlags_AllowCurrentNavId | ImGuiNavMoveF lags_AlsoScoreVisibleSet; | g.NavMoveFlags = ImGuiNavMoveFlags_AllowCurrentNavId | ImGuiNavMoveF lags_AlsoScoreVisibleSet; | |||
} | } | |||
else if (home_pressed) | else if (home_pressed) | |||
{ | { | |||
// FIXME-NAV: handling of Home/End is assuming that the top/bottom m ost item will be visible with Scroll.y == 0/ScrollMax.y | // FIXME-NAV: handling of Home/End is assuming that the top/bottom m ost item will be visible with Scroll.y == 0/ScrollMax.y | |||
// Scrolling will be handled via the ImGuiNavMoveFlags_ScrollToEdgeY flag, we don't scroll immediately to avoid scrolling happening before nav resul t. | // Scrolling will be handled via the ImGuiNavMoveFlags_ScrollToEdgeY flag, we don't scroll immediately to avoid scrolling happening before nav resul t. | |||
skipping to change at line 10227 | skipping to change at line 10705 | |||
// Fade out | // Fade out | |||
if (g.NavWindowingTargetAnim && g.NavWindowingTarget == NULL) | if (g.NavWindowingTargetAnim && g.NavWindowingTarget == NULL) | |||
{ | { | |||
g.NavWindowingHighlightAlpha = ImMax(g.NavWindowingHighlightAlpha - io.D eltaTime * 10.0f, 0.0f); | g.NavWindowingHighlightAlpha = ImMax(g.NavWindowingHighlightAlpha - io.D eltaTime * 10.0f, 0.0f); | |||
if (g.DimBgRatio <= 0.0f && g.NavWindowingHighlightAlpha <= 0.0f) | if (g.DimBgRatio <= 0.0f && g.NavWindowingHighlightAlpha <= 0.0f) | |||
g.NavWindowingTargetAnim = NULL; | g.NavWindowingTargetAnim = NULL; | |||
} | } | |||
// Start CTRL+Tab or Square+L/R window selection | // Start CTRL+Tab or Square+L/R window selection | |||
const bool start_windowing_with_gamepad = allow_windowing && !g.NavWindowing Target && IsNavInputTest(ImGuiNavInput_Menu, ImGuiInputReadMode_Pressed); | const bool start_windowing_with_gamepad = allow_windowing && !g.NavWindowing Target && IsNavInputTest(ImGuiNavInput_Menu, ImGuiInputReadMode_Pressed); | |||
const bool start_windowing_with_keyboard = allow_windowing && !g.NavWindowin gTarget && io.KeyCtrl && IsKeyPressedMap(ImGuiKey_Tab); | const bool start_windowing_with_keyboard = allow_windowing && !g.NavWindowin gTarget && io.KeyCtrl && IsKeyPressed(ImGuiKey_Tab); | |||
if (start_windowing_with_gamepad || start_windowing_with_keyboard) | if (start_windowing_with_gamepad || start_windowing_with_keyboard) | |||
if (ImGuiWindow* window = g.NavWindow ? g.NavWindow : FindWindowNavFocus able(g.WindowsFocusOrder.Size - 1, -INT_MAX, -1)) | if (ImGuiWindow* window = g.NavWindow ? g.NavWindow : FindWindowNavFocus able(g.WindowsFocusOrder.Size - 1, -INT_MAX, -1)) | |||
{ | { | |||
g.NavWindowingTarget = g.NavWindowingTargetAnim = window->RootWindow ; | g.NavWindowingTarget = g.NavWindowingTargetAnim = window->RootWindow ; | |||
g.NavWindowingTimer = g.NavWindowingHighlightAlpha = 0.0f; | g.NavWindowingTimer = g.NavWindowingHighlightAlpha = 0.0f; | |||
g.NavWindowingToggleLayer = start_windowing_with_gamepad ? true : fa lse; // Gamepad starts toggling layer | g.NavWindowingToggleLayer = start_windowing_with_gamepad ? true : fa lse; // Gamepad starts toggling layer | |||
g.NavInputSource = start_windowing_with_keyboard ? ImGuiInputSource_ Keyboard : ImGuiInputSource_Gamepad; | g.NavInputSource = start_windowing_with_keyboard ? ImGuiInputSource_ Keyboard : ImGuiInputSource_Gamepad; | |||
} | } | |||
// Gamepad update | // Gamepad update | |||
skipping to change at line 10269 | skipping to change at line 10747 | |||
apply_focus_window = g.NavWindowingTarget; | apply_focus_window = g.NavWindowingTarget; | |||
g.NavWindowingTarget = NULL; | g.NavWindowingTarget = NULL; | |||
} | } | |||
} | } | |||
// Keyboard: Focus | // Keyboard: Focus | |||
if (g.NavWindowingTarget && g.NavInputSource == ImGuiInputSource_Keyboard) | if (g.NavWindowingTarget && g.NavInputSource == ImGuiInputSource_Keyboard) | |||
{ | { | |||
// Visuals only appears after a brief time after pressing TAB the first time, so that a fast CTRL+TAB doesn't add visual noise | // Visuals only appears after a brief time after pressing TAB the first time, so that a fast CTRL+TAB doesn't add visual noise | |||
g.NavWindowingHighlightAlpha = ImMax(g.NavWindowingHighlightAlpha, ImSat urate((g.NavWindowingTimer - NAV_WINDOWING_HIGHLIGHT_DELAY) / 0.05f)); // 1.0f | g.NavWindowingHighlightAlpha = ImMax(g.NavWindowingHighlightAlpha, ImSat urate((g.NavWindowingTimer - NAV_WINDOWING_HIGHLIGHT_DELAY) / 0.05f)); // 1.0f | |||
if (IsKeyPressedMap(ImGuiKey_Tab, true)) | if (IsKeyPressed(ImGuiKey_Tab, true)) | |||
NavUpdateWindowingHighlightWindow(io.KeyShift ? +1 : -1); | NavUpdateWindowingHighlightWindow(io.KeyShift ? +1 : -1); | |||
if (!io.KeyCtrl) | if (!io.KeyCtrl) | |||
apply_focus_window = g.NavWindowingTarget; | apply_focus_window = g.NavWindowingTarget; | |||
} | } | |||
// Keyboard: Press and Release ALT to toggle menu layer | // Keyboard: Press and Release ALT to toggle menu layer | |||
// - Testing that only Alt is tested prevents Alt+Shift or AltGR from toggli ng menu layer. | // - Testing that only Alt is tested prevents Alt+Shift or AltGR from toggli ng menu layer. | |||
// - AltGR is normally Alt+Ctrl but we can't reliably detect it (not all bac kends/systems/layout emit it as Alt+Ctrl). But even on keyboards without AltGR w e don't want Alt+Ctrl to open menu anyway. | // - AltGR is normally Alt+Ctrl but we can't reliably detect it (not all bac kends/systems/layout emit it as Alt+Ctrl). But even on keyboards without AltGR w e don't want Alt+Ctrl to open menu anyway. | |||
const bool nav_keyboard_active = (io.ConfigFlags & ImGuiConfigFlags_NavEn ableKeyboard) != 0; | const bool nav_keyboard_active = (io.ConfigFlags & ImGuiConfigFlags_NavEn ableKeyboard) != 0; | |||
if (nav_keyboard_active && io.KeyMods == ImGuiKeyModFlags_Alt && (io.KeyMods Prev & ImGuiKeyModFlags_Alt) == 0) | if (nav_keyboard_active && io.KeyMods == ImGuiKeyModFlags_Alt && (io.KeyMods Prev & ImGuiKeyModFlags_Alt) == 0) | |||
skipping to change at line 10610 | skipping to change at line 11088 | |||
memcpy(payload.Data, data, data_size); | memcpy(payload.Data, data, data_size); | |||
} | } | |||
else | else | |||
{ | { | |||
payload.Data = NULL; | payload.Data = NULL; | |||
} | } | |||
payload.DataSize = (int)data_size; | payload.DataSize = (int)data_size; | |||
} | } | |||
payload.DataFrameCount = g.FrameCount; | payload.DataFrameCount = g.FrameCount; | |||
// Return whether the payload has been accepted | ||||
return (g.DragDropAcceptFrameCount == g.FrameCount) || (g.DragDropAcceptFram eCount == g.FrameCount - 1); | return (g.DragDropAcceptFrameCount == g.FrameCount) || (g.DragDropAcceptFram eCount == g.FrameCount - 1); | |||
} | } | |||
bool ImGui::BeginDragDropTargetCustom(const ImRect& bb, ImGuiID id) | bool ImGui::BeginDragDropTargetCustom(const ImRect& bb, ImGuiID id) | |||
{ | { | |||
ImGuiContext& g = *GImGui; | ImGuiContext& g = *GImGui; | |||
if (!g.DragDropActive) | if (!g.DragDropActive) | |||
return false; | return false; | |||
ImGuiWindow* window = g.CurrentWindow; | ImGuiWindow* window = g.CurrentWindow; | |||
skipping to change at line 11463 | skipping to change at line 11942 | |||
#endif | #endif | |||
// Win32 API IME support (for Asian languages, etc.) | // Win32 API IME support (for Asian languages, etc.) | |||
#if defined(_WIN32) && !defined(IMGUI_DISABLE_WIN32_FUNCTIONS) && !defined(IMGUI _DISABLE_WIN32_DEFAULT_IME_FUNCTIONS) | #if defined(_WIN32) && !defined(IMGUI_DISABLE_WIN32_FUNCTIONS) && !defined(IMGUI _DISABLE_WIN32_DEFAULT_IME_FUNCTIONS) | |||
#include <imm.h> | #include <imm.h> | |||
#ifdef _MSC_VER | #ifdef _MSC_VER | |||
#pragma comment(lib, "imm32") | #pragma comment(lib, "imm32") | |||
#endif | #endif | |||
static void ImeSetInputScreenPosFn_DefaultImpl(int x, int y) | static void SetPlatformImeDataFn_DefaultImpl(ImGuiViewport* viewport, ImGuiPlatf ormImeData* data) | |||
{ | { | |||
// Notify OS Input Method Editor of text input position | // Notify OS Input Method Editor of text input position | |||
ImGuiIO& io = ImGui::GetIO(); | HWND hwnd = (HWND)viewport->PlatformHandleRaw; | |||
if (HWND hwnd = (HWND)io.ImeWindowHandle) | #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS | |||
if (HIMC himc = ::ImmGetContext(hwnd)) | if (hwnd == 0) | |||
{ | hwnd = (HWND)ImGui::GetIO().ImeWindowHandle; | |||
COMPOSITIONFORM cf; | #endif | |||
cf.ptCurrentPos.x = x; | if (hwnd == 0) | |||
cf.ptCurrentPos.y = y; | return; | |||
cf.dwStyle = CFS_FORCE_POSITION; | ||||
::ImmSetCompositionWindow(himc, &cf); | ::ImmAssociateContextEx(hwnd, NULL, data->WantVisible ? IACE_DEFAULT : 0); | |||
::ImmReleaseContext(hwnd, himc); | ||||
} | if (HIMC himc = ::ImmGetContext(hwnd)) | |||
{ | ||||
COMPOSITIONFORM composition_form = {}; | ||||
composition_form.ptCurrentPos.x = (LONG)data->InputPos.x; | ||||
composition_form.ptCurrentPos.y = (LONG)data->InputPos.y; | ||||
composition_form.dwStyle = CFS_FORCE_POSITION; | ||||
::ImmSetCompositionWindow(himc, &composition_form); | ||||
CANDIDATEFORM candidate_form = {}; | ||||
candidate_form.dwStyle = CFS_CANDIDATEPOS; | ||||
candidate_form.ptCurrentPos.x = (LONG)data->InputPos.x; | ||||
candidate_form.ptCurrentPos.y = (LONG)data->InputPos.y; | ||||
::ImmSetCandidateWindow(himc, &candidate_form); | ||||
::ImmReleaseContext(hwnd, himc); | ||||
} | ||||
} | } | |||
#else | #else | |||
static void ImeSetInputScreenPosFn_DefaultImpl(int, int) {} | static void SetPlatformImeDataFn_DefaultImpl(ImGuiViewport*, ImGuiPlatformImeDat a*) {} | |||
#endif | #endif | |||
//----------------------------------------------------------------------------- | //----------------------------------------------------------------------------- | |||
// [SECTION] METRICS/DEBUGGER WINDOW | // [SECTION] METRICS/DEBUGGER WINDOW | |||
//----------------------------------------------------------------------------- | //----------------------------------------------------------------------------- | |||
// - RenderViewportThumbnail() [Internal] | // - RenderViewportThumbnail() [Internal] | |||
// - RenderViewportsThumbnails() [Internal] | // - RenderViewportsThumbnails() [Internal] | |||
// - MetricsHelpMarker() [Internal] | // - MetricsHelpMarker() [Internal] | |||
// - ShowMetricsWindow() | // - ShowMetricsWindow() | |||
skipping to change at line 11877 | skipping to change at line 12369 | |||
{ | { | |||
InputTextMultiline("##Ini", (char*)(void*)g.SettingsIniData.c_str(), g.SettingsIniData.Buf.Size, ImVec2(-FLT_MIN, GetTextLineHeight() * 20), ImGuiIn putTextFlags_ReadOnly); | InputTextMultiline("##Ini", (char*)(void*)g.SettingsIniData.c_str(), g.SettingsIniData.Buf.Size, ImVec2(-FLT_MIN, GetTextLineHeight() * 20), ImGuiIn putTextFlags_ReadOnly); | |||
TreePop(); | TreePop(); | |||
} | } | |||
TreePop(); | TreePop(); | |||
} | } | |||
// Misc Details | // Misc Details | |||
if (TreeNode("Internal state")) | if (TreeNode("Internal state")) | |||
{ | { | |||
const char* input_source_names[] = { "None", "Mouse", "Keyboard", "Gamep | ||||
ad", "Nav", "Clipboard" }; IM_ASSERT(IM_ARRAYSIZE(input_source_names) == ImGuiIn | ||||
putSource_COUNT); | ||||
Text("WINDOWING"); | Text("WINDOWING"); | |||
Indent(); | Indent(); | |||
Text("HoveredWindow: '%s'", g.HoveredWindow ? g.HoveredWindow->Name : "N ULL"); | Text("HoveredWindow: '%s'", g.HoveredWindow ? g.HoveredWindow->Name : "N ULL"); | |||
Text("HoveredWindow->Root: '%s'", g.HoveredWindow ? g.HoveredWindow->Roo tWindow->Name : "NULL"); | Text("HoveredWindow->Root: '%s'", g.HoveredWindow ? g.HoveredWindow->Roo tWindow->Name : "NULL"); | |||
Text("HoveredWindowUnderMovingWindow: '%s'", g.HoveredWindowUnderMovingW indow ? g.HoveredWindowUnderMovingWindow->Name : "NULL"); | Text("HoveredWindowUnderMovingWindow: '%s'", g.HoveredWindowUnderMovingW indow ? g.HoveredWindowUnderMovingWindow->Name : "NULL"); | |||
Text("MovingWindow: '%s'", g.MovingWindow ? g.MovingWindow->Name : "NULL "); | Text("MovingWindow: '%s'", g.MovingWindow ? g.MovingWindow->Name : "NULL "); | |||
Unindent(); | Unindent(); | |||
Text("ITEMS"); | Text("ITEMS"); | |||
Indent(); | Indent(); | |||
Text("ActiveId: 0x%08X/0x%08X (%.2f sec), AllowOverlap: %d, Source: %s", g.ActiveId, g.ActiveIdPreviousFrame, g.ActiveIdTimer, g.ActiveIdAllowOverlap, i nput_source_names[g.ActiveIdSource]); | Text("ActiveId: 0x%08X/0x%08X (%.2f sec), AllowOverlap: %d, Source: %s", g.ActiveId, g.ActiveIdPreviousFrame, g.ActiveIdTimer, g.ActiveIdAllowOverlap, G etInputSourceName(g.ActiveIdSource)); | |||
Text("ActiveIdWindow: '%s'", g.ActiveIdWindow ? g.ActiveIdWindow->Name : "NULL"); | Text("ActiveIdWindow: '%s'", g.ActiveIdWindow ? g.ActiveIdWindow->Name : "NULL"); | |||
Text("ActiveIdUsing: Wheel: %d, NavDirMask: %X, NavInputMask: %X, KeyInp | ||||
utMask: %llX", g.ActiveIdUsingMouseWheel, g.ActiveIdUsingNavDirMask, g.ActiveIdU | int active_id_using_key_input_count = 0; | |||
singNavInputMask, g.ActiveIdUsingKeyInputMask); | for (int n = 0; n < ImGuiKey_NamedKey_COUNT; n++) | |||
active_id_using_key_input_count += g.ActiveIdUsingKeyInputMask[n] ? | ||||
1 : 0; | ||||
Text("ActiveIdUsing: Wheel: %d, NavDirMask: %X, NavInputMask: %X, KeyInp | ||||
utMask: %d key(s)", g.ActiveIdUsingMouseWheel, g.ActiveIdUsingNavDirMask, g.Acti | ||||
veIdUsingNavInputMask, active_id_using_key_input_count); | ||||
Text("HoveredId: 0x%08X (%.2f sec), AllowOverlap: %d", g.HoveredIdPrevio usFrame, g.HoveredIdTimer, g.HoveredIdAllowOverlap); // Not displaying g.Hovered Id as it is update mid-frame | Text("HoveredId: 0x%08X (%.2f sec), AllowOverlap: %d", g.HoveredIdPrevio usFrame, g.HoveredIdTimer, g.HoveredIdAllowOverlap); // Not displaying g.Hovered Id as it is update mid-frame | |||
Text("DragDrop: %d, SourceId = 0x%08X, Payload \"%s\" (%d bytes)", g.Dra gDropActive, g.DragDropPayload.SourceId, g.DragDropPayload.DataType, g.DragDropP ayload.DataSize); | Text("DragDrop: %d, SourceId = 0x%08X, Payload \"%s\" (%d bytes)", g.Dra gDropActive, g.DragDropPayload.SourceId, g.DragDropPayload.DataType, g.DragDropP ayload.DataSize); | |||
Unindent(); | Unindent(); | |||
Text("NAV,FOCUS"); | Text("NAV,FOCUS"); | |||
Indent(); | Indent(); | |||
Text("NavWindow: '%s'", g.NavWindow ? g.NavWindow->Name : "NULL"); | Text("NavWindow: '%s'", g.NavWindow ? g.NavWindow->Name : "NULL"); | |||
Text("NavId: 0x%08X, NavLayer: %d", g.NavId, g.NavLayer); | Text("NavId: 0x%08X, NavLayer: %d", g.NavId, g.NavLayer); | |||
Text("NavInputSource: %s", input_source_names[g.NavInputSource]); | Text("NavInputSource: %s", GetInputSourceName(g.NavInputSource)); | |||
Text("NavActive: %d, NavVisible: %d", g.IO.NavActive, g.IO.NavVisible); | Text("NavActive: %d, NavVisible: %d", g.IO.NavActive, g.IO.NavVisible); | |||
Text("NavActivateId/DownId/PressedId/InputId: %08X/%08X/%08X/%08X", g.Na vActivateId, g.NavActivateDownId, g.NavActivatePressedId, g.NavActivateInputId); | Text("NavActivateId/DownId/PressedId/InputId: %08X/%08X/%08X/%08X", g.Na vActivateId, g.NavActivateDownId, g.NavActivatePressedId, g.NavActivateInputId); | |||
Text("NavActivateFlags: %04X", g.NavActivateFlags); | Text("NavActivateFlags: %04X", g.NavActivateFlags); | |||
Text("NavDisableHighlight: %d, NavDisableMouseHover: %d", g.NavDisableHi ghlight, g.NavDisableMouseHover); | Text("NavDisableHighlight: %d, NavDisableMouseHover: %d", g.NavDisableHi ghlight, g.NavDisableMouseHover); | |||
Text("NavFocusScopeId = 0x%08X", g.NavFocusScopeId); | Text("NavFocusScopeId = 0x%08X", g.NavFocusScopeId); | |||
Text("NavWindowingTarget: '%s'", g.NavWindowingTarget ? g.NavWindowingTa rget->Name : "NULL"); | Text("NavWindowingTarget: '%s'", g.NavWindowingTarget ? g.NavWindowingTa rget->Name : "NULL"); | |||
Unindent(); | Unindent(); | |||
TreePop(); | TreePop(); | |||
} | } | |||
skipping to change at line 12409 | skipping to change at line 12903 | |||
// [DEBUG] Item picker tool - start with DebugStartItemPicker() - useful to visu ally select an item and break into its call-stack. | // [DEBUG] Item picker tool - start with DebugStartItemPicker() - useful to visu ally select an item and break into its call-stack. | |||
void ImGui::UpdateDebugToolItemPicker() | void ImGui::UpdateDebugToolItemPicker() | |||
{ | { | |||
ImGuiContext& g = *GImGui; | ImGuiContext& g = *GImGui; | |||
g.DebugItemPickerBreakId = 0; | g.DebugItemPickerBreakId = 0; | |||
if (!g.DebugItemPickerActive) | if (!g.DebugItemPickerActive) | |||
return; | return; | |||
const ImGuiID hovered_id = g.HoveredIdPreviousFrame; | const ImGuiID hovered_id = g.HoveredIdPreviousFrame; | |||
SetMouseCursor(ImGuiMouseCursor_Hand); | SetMouseCursor(ImGuiMouseCursor_Hand); | |||
if (IsKeyPressedMap(ImGuiKey_Escape)) | if (IsKeyPressed(ImGuiKey_Escape)) | |||
g.DebugItemPickerActive = false; | g.DebugItemPickerActive = false; | |||
if (IsMouseClicked(0) && hovered_id) | if (IsMouseClicked(0) && hovered_id) | |||
{ | { | |||
g.DebugItemPickerBreakId = hovered_id; | g.DebugItemPickerBreakId = hovered_id; | |||
g.DebugItemPickerActive = false; | g.DebugItemPickerActive = false; | |||
} | } | |||
SetNextWindowBgAlpha(0.60f); | SetNextWindowBgAlpha(0.60f); | |||
BeginTooltip(); | BeginTooltip(); | |||
Text("HoveredId: 0x%08X", hovered_id); | Text("HoveredId: 0x%08X", hovered_id); | |||
Text("Press ESC to abort picking."); | Text("Press ESC to abort picking."); | |||
End of changes. 107 change blocks. | ||||
481 lines changed or deleted | 1094 lines changed or added |