Merge branch 'master' into docking

# Conflicts:
#	imgui.cpp
#	imgui_internal.h
This commit is contained in:
ocornut 2023-03-08 17:41:32 +01:00
commit e2cede6542
9 changed files with 193 additions and 134 deletions

View File

@ -504,4 +504,4 @@ jobs:
- name: Build example_android_opengl3
run: |
cd examples/example_android_opengl3/android
gradle assembleDebug
gradle assembleDebug --stacktrace

View File

@ -114,6 +114,14 @@ Breaking Changes:
Other changes:
- Nav: Made Enter key submit the same type of Activation event as Space key,
allowing to press buttons with Enter. (#5606)
(Enter emulates a "prefer text input" activation vs.
Space emulates a "prefer tweak" activation which is to closer to gamepad controls).
- Nav: Fixed an issue with Gamepad navigation when the movement lead to a scroll and
frame time > repeat rate. Triggering a new move request on the same frame as a move
result lead to an incorrect calculation and loss of navigation id. (#6171)
- IO: Lifted constraint to call io.AddEventXXX functions from current context. (#4921, #5856, #6199)
- Drag and Drop: Fixed handling of overlapping targets when smaller one is submitted
before and can accept the same data type. (#6183).
- Drag and Drop: Clear drag and drop state as soon as delivery is accepted in order to
@ -124,6 +132,7 @@ Other changes:
non-client area (e.g. OS decorations) when app is not focused. (#6045, #6162)
- Backends: SDL2, SDL3: Accept SDL_GetPerformanceCounter() not returning a monotonically
increasing value. (#6189, #6114, #3644) [@adamkewley]
- Examples: Android: Fixed example build for Gradle 8. (#6229, #6227) [@duddel]
-----------------------------------------------------------------------
VERSION 1.89.3 (Released 2023-02-14)

View File

@ -2,13 +2,15 @@ apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
android {
compileSdkVersion 29
buildToolsVersion "30.0.3"
ndkVersion "21.4.7075529"
compileSdkVersion 33
buildToolsVersion "33.0.2"
ndkVersion "25.2.9519653"
defaultConfig {
applicationId "imgui.example.android"
minSdkVersion 23
targetSdkVersion 29
namespace "imgui.example.android"
minSdkVersion 24
targetSdkVersion 33
versionCode 1
versionName "1.0"
}
@ -20,9 +22,19 @@ android {
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_11
targetCompatibility JavaVersion.VERSION_11
}
kotlinOptions {
jvmTarget="11"
}
externalNativeBuild {
cmake {
path "../../CMakeLists.txt"
version '3.22.1'
}
}
}

View File

@ -1,6 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="imgui.example.android">
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<application
android:label="ImGuiExample"
@ -11,7 +10,8 @@
<activity
android:name="imgui.example.android.MainActivity"
android:theme="@android:style/Theme.NoTitleBar.Fullscreen"
android:configChanges="orientation|keyboardHidden|screenSize">
android:configChanges="orientation|keyboardHidden|screenSize"
android:exported="false">
<meta-data android:name="android.app.lib_name"
android:value="ImGuiExample" />

View File

@ -1,12 +1,12 @@
buildscript {
ext.kotlin_version = '1.4.31'
ext.kotlin_version = '1.8.0'
repositories {
google()
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:4.1.0'
classpath 'com.android.tools.build:gradle:7.4.1'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}

191
imgui.cpp
View File

@ -46,7 +46,7 @@ DOCUMENTATION
- GETTING STARTED WITH INTEGRATING DEAR IMGUI IN YOUR CODE/ENGINE
- HOW A SIMPLE APPLICATION MAY LOOK LIKE
- HOW A SIMPLE RENDERING FUNCTION MAY LOOK LIKE
- USING GAMEPAD/KEYBOARD NAVIGATION CONTROLS
- USING KEYBOARD/GAMEPAD NAVIGATION CONTROLS
- API BREAKING CHANGES (read me when you update!)
- FREQUENTLY ASKED QUESTIONS (FAQ)
- Read all answers online: https://www.dearimgui.org/faq, or in docs/FAQ.md (with a Markdown viewer)
@ -345,13 +345,14 @@ CODE
}
USING GAMEPAD/KEYBOARD NAVIGATION CONTROLS
USING KEYBOARD/GAMEPAD NAVIGATION CONTROLS
------------------------------------------
- The gamepad/keyboard navigation is fairly functional and keeps being improved.
- The keyboard/gamepad navigation is fairly functional and keeps being improved.
- Gamepad support is particularly useful to use Dear ImGui on a console system (e.g. PlayStation, Switch, Xbox) without a mouse!
- The initial focus was to support game controllers, but keyboard is becoming increasingly and decently usable.
- Keyboard:
- Application: Set io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard to enable.
- Arrow keys to move. Space or Enter to activate (on a slider/drag: Space will tweak with arrow, Enter will input text).
- When keyboard navigation is active (io.NavActive + ImGuiConfigFlags_NavEnableKeyboard),
the io.WantCaptureKeyboard flag will be set. For more advanced uses, you may want to read from:
- io.NavActive: true when a window is focused and it doesn't have the ImGuiWindowFlags_NoNavInputs flag set.
@ -1002,8 +1003,8 @@ static void WindowSettingsHandler_ApplyAll(ImGuiContext*, ImGuiSetti
static void WindowSettingsHandler_WriteAll(ImGuiContext*, ImGuiSettingsHandler*, ImGuiTextBuffer* buf);
// Platform Dependents default implementation for IO functions
static const char* GetClipboardTextFn_DefaultImpl(void* user_data);
static void SetClipboardTextFn_DefaultImpl(void* user_data, const char* text);
static const char* GetClipboardTextFn_DefaultImpl(void* user_data_ctx);
static void SetClipboardTextFn_DefaultImpl(void* user_data_ctx, const char* text);
static void SetPlatformImeDataFn_DefaultImpl(ImGuiViewport* viewport, ImGuiPlatformImeData* data);
namespace ImGui
@ -1255,12 +1256,9 @@ ImGuiIO::ImGuiIO()
ConfigMemoryCompactTimer = 60.0f;
// Platform Functions
// Note: Initialize() will setup default clipboard/ime handlers.
BackendPlatformName = BackendRendererName = NULL;
BackendPlatformUserData = BackendRendererUserData = BackendLanguageUserData = NULL;
GetClipboardTextFn = GetClipboardTextFn_DefaultImpl; // Platform dependent default implementations
SetClipboardTextFn = SetClipboardTextFn_DefaultImpl;
ClipboardUserData = NULL;
SetPlatformImeDataFn = SetPlatformImeDataFn_DefaultImpl;
// Input (NB: we already have memset zero the entire structure!)
MousePos = ImVec2(-FLT_MAX, -FLT_MAX);
@ -1279,8 +1277,8 @@ ImGuiIO::ImGuiIO()
// FIXME: Should in theory be called "AddCharacterEvent()" to be consistent with new API
void ImGuiIO::AddInputCharacter(unsigned int c)
{
ImGuiContext& g = *GImGui;
IM_ASSERT(&g.IO == this && "Can only add events to current context.");
IM_ASSERT(Ctx != NULL);
ImGuiContext& g = *Ctx;
if (c == 0 || !AppAcceptingEvents)
return;
@ -1392,10 +1390,10 @@ static ImGuiInputEvent* FindLatestInputEvent(ImGuiInputEventType type, int arg =
void ImGuiIO::AddKeyAnalogEvent(ImGuiKey key, bool down, float analog_value)
{
//if (e->Down) { IMGUI_DEBUG_LOG_IO("AddKeyEvent() Key='%s' %d, NativeKeycode = %d, NativeScancode = %d\n", ImGui::GetKeyName(e->Key), e->Down, e->NativeKeycode, e->NativeScancode); }
IM_ASSERT(Ctx != NULL);
if (key == ImGuiKey_None || !AppAcceptingEvents)
return;
ImGuiContext& g = *GImGui;
IM_ASSERT(&g.IO == this && "Can only add events to current context.");
ImGuiContext& g = *Ctx;
IM_ASSERT(ImGui::IsNamedKeyOrModKey(key)); // Backend needs to pass a valid ImGuiKey_ constant. 0..511 values are legacy native key codes which are not accepted by this API.
IM_ASSERT(!ImGui::IsAliasKey(key)); // Backend cannot submit ImGuiKey_MouseXXX values they are automatically inferred from AddMouseXXX() events.
IM_ASSERT(key != ImGuiMod_Shortcut); // We could easily support the translation here but it seems saner to not accept it (TestEngine perform a translation itself)
@ -1470,8 +1468,8 @@ void ImGuiIO::SetAppAcceptingEvents(bool accepting_events)
// 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.");
IM_ASSERT(Ctx != NULL);
ImGuiContext& g = *Ctx;
if (!AppAcceptingEvents)
return;
@ -1494,8 +1492,8 @@ void ImGuiIO::AddMousePosEvent(float x, float y)
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(Ctx != NULL);
ImGuiContext& g = *Ctx;
IM_ASSERT(mouse_button >= 0 && mouse_button < ImGuiMouseButton_COUNT);
if (!AppAcceptingEvents)
return;
@ -1517,8 +1515,8 @@ void ImGuiIO::AddMouseButtonEvent(int mouse_button, bool down)
// Queue a mouse wheel event (some mouse/API may 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.");
IM_ASSERT(Ctx != NULL);
ImGuiContext& g = *Ctx;
// Filter duplicate (unlike most events, wheel values are relative and easy to filter)
if (!AppAcceptingEvents || (wheel_x == 0.0f && wheel_y == 0.0f))
@ -1555,8 +1553,8 @@ void ImGuiIO::AddMouseViewportEvent(ImGuiID viewport_id)
void ImGuiIO::AddFocusEvent(bool focused)
{
ImGuiContext& g = *GImGui;
IM_ASSERT(&g.IO == this && "Can only add events to current context.");
IM_ASSERT(Ctx != NULL);
ImGuiContext& g = *Ctx;
// Filter duplicate
const ImGuiInputEvent* latest_event = FindLatestInputEvent(ImGuiInputEventType_Focus);
@ -2765,6 +2763,8 @@ static void ImGuiListClipper_SeekCursorForItem(ImGuiListClipper* clipper, int it
ImGuiListClipper::ImGuiListClipper()
{
memset(this, 0, sizeof(*this));
Ctx = ImGui::GetCurrentContext();
IM_ASSERT(Ctx != NULL);
ItemsCount = -1;
}
@ -2775,7 +2775,7 @@ ImGuiListClipper::~ImGuiListClipper()
void ImGuiListClipper::Begin(int items_count, float items_height)
{
ImGuiContext& g = *GImGui;
ImGuiContext& g = *Ctx;
ImGuiWindow* window = g.CurrentWindow;
IMGUI_DEBUG_LOG_CLIPPER("Clipper: Begin(%d,%.2f) in '%s'\n", items_count, items_height, window->Name);
@ -2800,7 +2800,7 @@ void ImGuiListClipper::Begin(int items_count, float items_height)
void ImGuiListClipper::End()
{
ImGuiContext& g = *GImGui;
ImGuiContext& g = *Ctx;
if (ImGuiListClipperData* data = (ImGuiListClipperData*)TempData)
{
// In theory here we should assert that we are already at the right position, but it seems saner to just seek at the end and not assert/crash the user.
@ -2832,7 +2832,7 @@ void ImGuiListClipper::ForceDisplayRangeByIndices(int item_min, int item_max)
static bool ImGuiListClipper_StepInternal(ImGuiListClipper* clipper)
{
ImGuiContext& g = *GImGui;
ImGuiContext& g = *clipper->Ctx;
ImGuiWindow* window = g.CurrentWindow;
ImGuiListClipperData* data = (ImGuiListClipperData*)clipper->TempData;
IM_ASSERT(data != NULL && "Called ImGuiListClipper::Step() too many times, or before ImGuiListClipper::Begin() ?");
@ -2955,7 +2955,7 @@ static bool ImGuiListClipper_StepInternal(ImGuiListClipper* clipper)
bool ImGuiListClipper::Step()
{
ImGuiContext& g = *GImGui;
ImGuiContext& g = *Ctx;
bool need_items_height = (ItemsHeight <= 0.0f);
bool ret = ImGuiListClipper_StepInternal(this);
if (ret && (DisplayStart == DisplayEnd))
@ -3056,20 +3056,12 @@ void ImGui::PopStyleColor(int count)
}
}
struct ImGuiStyleVarInfo
{
ImGuiDataType Type;
ImU32 Count;
ImU32 Offset;
void* GetVarPtr(ImGuiStyle* style) const { return (void*)((unsigned char*)style + Offset); }
};
static const ImGuiCol GWindowDockStyleColors[ImGuiWindowDockStyleCol_COUNT] =
{
ImGuiCol_Text, ImGuiCol_Tab, ImGuiCol_TabHovered, ImGuiCol_TabActive, ImGuiCol_TabUnfocused, ImGuiCol_TabUnfocusedActive
};
static const ImGuiStyleVarInfo GStyleVarInfo[] =
static const ImGuiDataVarInfo GStyleVarInfo[] =
{
{ ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImGuiStyle, Alpha) }, // ImGuiStyleVar_Alpha
{ ImGuiDataType_Float, 1, (ImU32)IM_OFFSETOF(ImGuiStyle, DisabledAlpha) }, // ImGuiStyleVar_DisabledAlpha
@ -3101,39 +3093,39 @@ static const ImGuiStyleVarInfo GStyleVarInfo[] =
{ ImGuiDataType_Float, 2, (ImU32)IM_OFFSETOF(ImGuiStyle, SeparatorTextPadding) }, // ImGuiStyleVar_SeparatorTextPadding
};
static const ImGuiStyleVarInfo* GetStyleVarInfo(ImGuiStyleVar idx)
const ImGuiDataVarInfo* ImGui::GetStyleVarInfo(ImGuiStyleVar idx)
{
IM_ASSERT(idx >= 0 && idx < ImGuiStyleVar_COUNT);
IM_ASSERT(IM_ARRAYSIZE(GStyleVarInfo) == ImGuiStyleVar_COUNT);
IM_STATIC_ASSERT(IM_ARRAYSIZE(GStyleVarInfo) == ImGuiStyleVar_COUNT);
return &GStyleVarInfo[idx];
}
void ImGui::PushStyleVar(ImGuiStyleVar idx, float val)
{
const ImGuiStyleVarInfo* var_info = GetStyleVarInfo(idx);
ImGuiContext& g = *GImGui;
const ImGuiDataVarInfo* var_info = GetStyleVarInfo(idx);
if (var_info->Type == ImGuiDataType_Float && var_info->Count == 1)
{
ImGuiContext& g = *GImGui;
float* pvar = (float*)var_info->GetVarPtr(&g.Style);
g.StyleVarStack.push_back(ImGuiStyleMod(idx, *pvar));
*pvar = val;
return;
}
IM_ASSERT(0 && "Called PushStyleVar() float variant but variable is not a float!");
IM_ASSERT_USER_ERROR(0, "Called PushStyleVar() variant with wrong type!");
}
void ImGui::PushStyleVar(ImGuiStyleVar idx, const ImVec2& val)
{
const ImGuiStyleVarInfo* var_info = GetStyleVarInfo(idx);
ImGuiContext& g = *GImGui;
const ImGuiDataVarInfo* var_info = GetStyleVarInfo(idx);
if (var_info->Type == ImGuiDataType_Float && var_info->Count == 2)
{
ImGuiContext& g = *GImGui;
ImVec2* pvar = (ImVec2*)var_info->GetVarPtr(&g.Style);
g.StyleVarStack.push_back(ImGuiStyleMod(idx, *pvar));
*pvar = val;
return;
}
IM_ASSERT(0 && "Called PushStyleVar() ImVec2 variant but variable is not a ImVec2!");
IM_ASSERT_USER_ERROR(0, "Called PushStyleVar() variant with wrong type!");
}
void ImGui::PopStyleVar(int count)
@ -3148,7 +3140,7 @@ void ImGui::PopStyleVar(int count)
{
// We avoid a generic memcpy(data, &backup.Backup.., GDataTypeSize[info->Type] * info->Count), the overhead in Debug is not worth it.
ImGuiStyleMod& backup = g.StyleVarStack.back();
const ImGuiStyleVarInfo* info = GetStyleVarInfo(backup.VarIdx);
const ImGuiDataVarInfo* info = GetStyleVarInfo(backup.VarIdx);
void* data = info->GetVarPtr(&g.Style);
if (info->Type == ImGuiDataType_Float && info->Count == 1) { ((float*)data)[0] = backup.BackupFloat[0]; }
else if (info->Type == ImGuiDataType_Float && info->Count == 2) { ((float*)data)[0] = backup.BackupFloat[0]; ((float*)data)[1] = backup.BackupFloat[1]; }
@ -3566,6 +3558,12 @@ void ImGui::Initialize()
// Setup default localization table
LocalizeRegisterEntries(GLocalizationEntriesEnUS, IM_ARRAYSIZE(GLocalizationEntriesEnUS));
// Setup default platform clipboard/IME handlers.
g.IO.GetClipboardTextFn = GetClipboardTextFn_DefaultImpl; // Platform dependent default implementations
g.IO.SetClipboardTextFn = SetClipboardTextFn_DefaultImpl;
g.IO.ClipboardUserData = (void*)&g; // Default implementation use the ImGuiContext as user data (ideally those would be arguments to the function)
g.IO.SetPlatformImeDataFn = SetPlatformImeDataFn_DefaultImpl;
// Create default viewport
ImGuiViewportP* viewport = IM_NEW(ImGuiViewportP)();
viewport->ID = IMGUI_VIEWPORT_DEFAULT_ID;
@ -3704,9 +3702,10 @@ void ImGui::CallContextHooks(ImGuiContext* ctx, ImGuiContextHookType hook_type)
//-----------------------------------------------------------------------------
// ImGuiWindow is mostly a dumb struct. It merely has a constructor and a few helper methods
ImGuiWindow::ImGuiWindow(ImGuiContext* context, const char* name) : DrawListInst(NULL)
ImGuiWindow::ImGuiWindow(ImGuiContext* ctx, const char* name) : DrawListInst(NULL)
{
memset(this, 0, sizeof(*this));
Ctx = ctx;
Name = ImStrdup(name);
NameBufLen = (int)strlen(name) + 1;
ID = ImHashStr(name);
@ -3728,7 +3727,7 @@ ImGuiWindow::ImGuiWindow(ImGuiContext* context, const char* name) : DrawListInst
SettingsOffset = -1;
DockOrder = -1;
DrawList = &DrawListInst;
DrawList->_Data = &context->DrawListSharedData;
DrawList->_Data = &Ctx->DrawListSharedData;
DrawList->_OwnerName = Name;
IM_PLACEMENT_NEW(&WindowClass) ImGuiWindowClass();
}
@ -3744,7 +3743,7 @@ ImGuiID ImGuiWindow::GetID(const char* str, const char* str_end)
{
ImGuiID seed = IDStack.back();
ImGuiID id = ImHashStr(str, str_end ? (str_end - str) : 0, seed);
ImGuiContext& g = *GImGui;
ImGuiContext& g = *Ctx;
if (g.DebugHookIdInfo == id)
ImGui::DebugHookIdInfo(id, ImGuiDataType_String, str, str_end);
return id;
@ -3754,7 +3753,7 @@ ImGuiID ImGuiWindow::GetID(const void* ptr)
{
ImGuiID seed = IDStack.back();
ImGuiID id = ImHashData(&ptr, sizeof(void*), seed);
ImGuiContext& g = *GImGui;
ImGuiContext& g = *Ctx;
if (g.DebugHookIdInfo == id)
ImGui::DebugHookIdInfo(id, ImGuiDataType_Pointer, ptr, NULL);
return id;
@ -3764,7 +3763,7 @@ ImGuiID ImGuiWindow::GetID(int n)
{
ImGuiID seed = IDStack.back();
ImGuiID id = ImHashData(&n, sizeof(n), seed);
ImGuiContext& g = *GImGui;
ImGuiContext& g = *Ctx;
if (g.DebugHookIdInfo == id)
ImGui::DebugHookIdInfo(id, ImGuiDataType_S32, (void*)(intptr_t)n, NULL);
return id;
@ -3858,7 +3857,7 @@ void ImGui::SetActiveID(ImGuiID id, ImGuiWindow* window)
if (id)
{
g.ActiveIdIsAlive = id;
g.ActiveIdSource = (g.NavActivateId == id || g.NavActivateInputId == id || g.NavJustMovedToId == id) ? (ImGuiInputSource)ImGuiInputSource_Nav : ImGuiInputSource_Mouse;
g.ActiveIdSource = (g.NavActivateId == id || g.NavJustMovedToId == id) ? (ImGuiInputSource)ImGuiInputSource_Nav : ImGuiInputSource_Mouse;
}
// Clear declaration of inputs claimed by the widget
@ -4089,14 +4088,14 @@ bool ImGui::IsClippedEx(const ImRect& bb, ImGuiID id)
}
// This is also inlined in ItemAdd()
// Note: if ImGuiItemStatusFlags_HasDisplayRect is set, user needs to set window->DC.LastItemDisplayRect!
// Note: if ImGuiItemStatusFlags_HasDisplayRect is set, user needs to set g.LastItemData.DisplayRect.
void ImGui::SetLastItemData(ImGuiID item_id, ImGuiItemFlags in_flags, ImGuiItemStatusFlags item_flags, const ImRect& item_rect)
{
ImGuiContext& g = *GImGui;
g.LastItemData.ID = item_id;
g.LastItemData.InFlags = in_flags;
g.LastItemData.StatusFlags = item_flags;
g.LastItemData.Rect = item_rect;
g.LastItemData.Rect = g.LastItemData.NavRect = item_rect;
}
float ImGui::CalcWrapWidthForPos(const ImVec2& pos, float wrap_pos_x)
@ -4766,6 +4765,11 @@ void ImGui::NewFrame()
UpdateDebugToolStackQueries();
if (g.DebugLocateFrames > 0 && --g.DebugLocateFrames == 0)
g.DebugLocateId = 0;
if (g.DebugLogClipperAutoDisableFrames > 0 && --g.DebugLogClipperAutoDisableFrames == 0)
{
DebugLog("(Auto-disabled ImGuiDebugLogFlags_EventClipper to avoid spamming)\n");
g.DebugLogFlags &= ~ImGuiDebugLogFlags_EventClipper;
}
// Create implicit/fallback window - which we will only render it if the user has added something to it.
// We don't use "Debug" to avoid colliding with user trying to create a "Debug" window with custom flags.
@ -5076,7 +5080,20 @@ void ImGui::EndFrame()
{
ImGuiViewport* viewport = FindViewportByID(g.PlatformImeViewport);
IMGUI_DEBUG_LOG_IO("Calling io.SetPlatformImeDataFn(): WantVisible: %d, InputPos (%.2f,%.2f)\n", ime_data->WantVisible, ime_data->InputPos.x, ime_data->InputPos.y);
g.IO.SetPlatformImeDataFn(viewport ? viewport : GetMainViewport(), ime_data);
if (viewport == NULL)
viewport = GetMainViewport();
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
if (viewport->PlatformHandleRaw == NULL && g.IO.ImeWindowHandle != NULL)
{
viewport->PlatformHandleRaw = g.IO.ImeWindowHandle;
g.IO.SetPlatformImeDataFn(viewport, ime_data);
viewport->PlatformHandleRaw = NULL;
}
else
#endif
{
g.IO.SetPlatformImeDataFn(viewport, ime_data);
}
}
// Hide implicit/fallback "Debug" window if it hasn't been used
@ -6485,7 +6502,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
ImGuiWindowStackData window_stack_data;
window_stack_data.Window = window;
window_stack_data.ParentLastItemDataBackup = g.LastItemData;
window_stack_data.StackSizesOnBegin.SetToCurrentState();
window_stack_data.StackSizesOnBegin.SetToContextState(&g);
g.CurrentWindowStack.push_back(window_stack_data);
if (flags & ImGuiWindowFlags_ChildMenu)
g.BeginMenuCount++;
@ -6845,13 +6862,13 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
}
}
// [Test Engine] Register whole window in the item system
// [Test Engine] Register whole window in the item system (before submitting further decorations)
#ifdef IMGUI_ENABLE_TEST_ENGINE
if (g.TestEngineHookItems)
{
IM_ASSERT(window->IDStack.Size == 1);
window->IDStack.Size = 0; // As window->IDStack[0] == window->ID here, make sure TestEngine doesn't erroneously see window as parent of itself.
IMGUI_TEST_ENGINE_ITEM_ADD(window->Rect(), window->ID);
IMGUI_TEST_ENGINE_ITEM_ADD(window->ID, window->Rect(), NULL);
IMGUI_TEST_ENGINE_ITEM_INFO(window->ID, window->Name, (g.HoveredWindow == window) ? ImGuiItemStatusFlags_HoveredRect : 0);
window->IDStack.Size = 1;
}
@ -7142,10 +7159,10 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
DebugLocateItemResolveWithLastItem();
#endif
// [Test Engine] Register title bar / tab
// [Test Engine] Register title bar / tab with MoveId.
#ifdef IMGUI_ENABLE_TEST_ENGINE
if (!(window->Flags & ImGuiWindowFlags_NoTitleBar))
IMGUI_TEST_ENGINE_ITEM_ADD(g.LastItemData.Rect, g.LastItemData.ID);
IMGUI_TEST_ENGINE_ITEM_ADD(g.LastItemData.ID, g.LastItemData.Rect, &g.LastItemData);
#endif
}
else
@ -7276,7 +7293,7 @@ void ImGui::End()
g.BeginMenuCount--;
if (window->Flags & ImGuiWindowFlags_Popup)
g.BeginPopupStack.pop_back();
g.CurrentWindowStack.back().StackSizesOnBegin.CompareWithCurrentState();
g.CurrentWindowStack.back().StackSizesOnBegin.CompareWithContextState(&g);
g.CurrentWindowStack.pop_back();
SetCurrentWindow(g.CurrentWindowStack.Size == 0 ? NULL : g.CurrentWindowStack.back().Window);
if (g.CurrentWindow)
@ -9714,9 +9731,9 @@ void ImGui::ErrorCheckEndWindowRecover(ImGuiErrorLogCallback log_callback, vo
}
// Save current stack sizes for later compare
void ImGuiStackSizes::SetToCurrentState()
void ImGuiStackSizes::SetToContextState(ImGuiContext* ctx)
{
ImGuiContext& g = *GImGui;
ImGuiContext& g = *ctx;
ImGuiWindow* window = g.CurrentWindow;
SizeOfIDStack = (short)window->IDStack.Size;
SizeOfColorStack = (short)g.ColorStack.Size;
@ -9730,9 +9747,9 @@ void ImGuiStackSizes::SetToCurrentState()
}
// Compare to detect usage errors
void ImGuiStackSizes::CompareWithCurrentState()
void ImGuiStackSizes::CompareWithContextState(ImGuiContext* ctx)
{
ImGuiContext& g = *GImGui;
ImGuiContext& g = *ctx;
ImGuiWindow* window = g.CurrentWindow;
IM_UNUSED(window);
@ -9872,7 +9889,7 @@ bool ImGui::ItemAdd(const ImRect& bb, ImGuiID id, const ImRect* nav_bb_arg, ImGu
#ifdef IMGUI_ENABLE_TEST_ENGINE
if (id != 0)
IMGUI_TEST_ENGINE_ITEM_ADD(nav_bb_arg ? *nav_bb_arg : bb, id);
IMGUI_TEST_ENGINE_ITEM_ADD(id, g.LastItemData.NavRect, &g.LastItemData);
#endif
// Clipping test
@ -11740,7 +11757,7 @@ static void ImGui::NavUpdate()
NavUpdateCancelRequest();
// Process manual activation request
g.NavActivateId = g.NavActivateDownId = g.NavActivatePressedId = g.NavActivateInputId = 0;
g.NavActivateId = g.NavActivateDownId = g.NavActivatePressedId = 0;
g.NavActivateFlags = ImGuiActivateFlags_None;
if (g.NavId != 0 && !g.NavDisableHighlight && !g.NavWindowingTarget && g.NavWindow && !(g.NavWindow->Flags & ImGuiWindowFlags_NoNavInputs))
{
@ -11755,12 +11772,12 @@ static void ImGui::NavUpdate()
}
if ((g.ActiveId == 0 || g.ActiveId == g.NavId) && input_pressed)
{
g.NavActivateInputId = g.NavId;
g.NavActivateId = g.NavId;
g.NavActivateFlags = ImGuiActivateFlags_PreferInput;
}
if ((g.ActiveId == 0 || g.ActiveId == g.NavId) && activate_down)
if ((g.ActiveId == 0 || g.ActiveId == g.NavId) && (activate_down || input_down))
g.NavActivateDownId = g.NavId;
if ((g.ActiveId == 0 || g.ActiveId == g.NavId) && activate_pressed)
if ((g.ActiveId == 0 || g.ActiveId == g.NavId) && (activate_pressed || input_pressed))
g.NavActivatePressedId = g.NavId;
}
if (g.NavWindow && (g.NavWindow->Flags & ImGuiWindowFlags_NoNavInputs))
@ -11772,10 +11789,7 @@ static void ImGui::NavUpdate()
// FIXME-NAV: Those should eventually be queued (unlike focus they don't cancel each others)
if (g.NavNextActivateId != 0)
{
if (g.NavNextActivateFlags & ImGuiActivateFlags_PreferInput)
g.NavActivateInputId = g.NavNextActivateId;
else
g.NavActivateId = g.NavActivateDownId = g.NavActivatePressedId = g.NavNextActivateId;
g.NavActivateId = g.NavActivateDownId = g.NavActivatePressedId = g.NavNextActivateId;
g.NavActivateFlags = g.NavNextActivateFlags;
}
g.NavNextActivateId = 0;
@ -11930,16 +11944,21 @@ void ImGui::NavUpdateCreateMoveRequest()
}
// 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 all movements are relative
// (can't focus a visible object like we can with the mouse).
// This is to allow resuming navigation inside the visible area after doing a large amount of scrolling,
// since with gamepad all movements are relative (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)// && (g.NavMoveFlags & ImGuiNavMoveFlags_Forwarded))
{
bool clamp_x = (g.NavMoveFlags & (ImGuiNavMoveFlags_LoopX | ImGuiNavMoveFlags_WrapX)) == 0;
bool clamp_y = (g.NavMoveFlags & (ImGuiNavMoveFlags_LoopY | ImGuiNavMoveFlags_WrapY)) == 0;
ImRect inner_rect_rel = WindowRectAbsToRel(window, ImRect(window->InnerRect.Min - ImVec2(1, 1), window->InnerRect.Max + ImVec2(1, 1)));
// Take account of changing scroll to handle triggering a new move request on a scrolling frame. (#6171)
// Otherwise 'inner_rect_rel' would be off on the move result frame.
inner_rect_rel.Translate(CalcNextScrollFromScrollTargetAndClamp(window) - window->Scroll);
if ((clamp_x || clamp_y) && !inner_rect_rel.Contains(window->NavRectRel[g.NavLayer]))
{
//IMGUI_DEBUG_LOG_NAV("[nav] NavMoveRequest: clamp NavRectRel for gamepad move\n");
IMGUI_DEBUG_LOG_NAV("[nav] NavMoveRequest: clamp NavRectRel for gamepad 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) : -FLT_MAX;
@ -18392,9 +18411,9 @@ static void ImGui::DockSettingsHandler_WriteAll(ImGuiContext* ctx, ImGuiSettings
// Win32 clipboard implementation
// We use g.ClipboardHandlerData for temporary storage to ensure it is freed on Shutdown()
static const char* GetClipboardTextFn_DefaultImpl(void*)
static const char* GetClipboardTextFn_DefaultImpl(void* user_data_ctx)
{
ImGuiContext& g = *GImGui;
ImGuiContext& g = *(ImGuiContext*)user_data_ctx;
g.ClipboardHandlerData.clear();
if (!::OpenClipboard(NULL))
return NULL;
@ -18455,8 +18474,9 @@ static void SetClipboardTextFn_DefaultImpl(void*, const char* text)
}
}
static const char* GetClipboardTextFn_DefaultImpl(void*)
static const char* GetClipboardTextFn_DefaultImpl(void* user_data_ctx)
{
ImGuiContext& g = *(ImGuiContext*)user_data_ctx;
if (!main_clipboard)
PasteboardCreate(kPasteboardClipboard, &main_clipboard);
PasteboardSynchronize(main_clipboard);
@ -18474,7 +18494,6 @@ static const char* GetClipboardTextFn_DefaultImpl(void*)
CFDataRef cf_data;
if (PasteboardCopyItemFlavorData(main_clipboard, item_id, CFSTR("public.utf8-plain-text"), &cf_data) == noErr)
{
ImGuiContext& g = *GImGui;
g.ClipboardHandlerData.clear();
int length = (int)CFDataGetLength(cf_data);
g.ClipboardHandlerData.resize(length + 1);
@ -18491,15 +18510,15 @@ static const char* GetClipboardTextFn_DefaultImpl(void*)
#else
// Local Dear ImGui-only clipboard implementation, if user hasn't defined better clipboard handlers.
static const char* GetClipboardTextFn_DefaultImpl(void*)
static const char* GetClipboardTextFn_DefaultImpl(void* user_data_ctx)
{
ImGuiContext& g = *GImGui;
ImGuiContext& g = *(ImGuiContext*)user_data_ctx;
return g.ClipboardHandlerData.empty() ? NULL : g.ClipboardHandlerData.begin();
}
static void SetClipboardTextFn_DefaultImpl(void*, const char* text)
static void SetClipboardTextFn_DefaultImpl(void* user_data_ctx, const char* text)
{
ImGuiContext& g = *GImGui;
ImGuiContext& g = *(ImGuiContext*)user_data_ctx;
g.ClipboardHandlerData.clear();
const char* text_end = text + strlen(text);
g.ClipboardHandlerData.resize((int)(text_end - text) + 1);
@ -18521,10 +18540,6 @@ static void SetPlatformImeDataFn_DefaultImpl(ImGuiViewport* viewport, ImGuiPlatf
{
// Notify OS Input Method Editor of text input position
HWND hwnd = (HWND)viewport->PlatformHandleRaw;
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
if (hwnd == 0)
hwnd = (HWND)ImGui::GetIO().ImeWindowHandle;
#endif
if (hwnd == 0)
return;
@ -19280,7 +19295,7 @@ void ImGui::ShowMetricsWindow(bool* p_open)
DebugLocateItemOnHover(g.NavId);
Text("NavInputSource: %s", GetInputSourceName(g.NavInputSource));
Text("NavActive: %d, NavVisible: %d", g.IO.NavActive, g.IO.NavVisible);
Text("NavActivateId/DownId/PressedId/InputId: %08X/%08X/%08X/%08X", g.NavActivateId, g.NavActivateDownId, g.NavActivatePressedId, g.NavActivateInputId);
Text("NavActivateId/DownId/PressedId: %08X/%08X/%08X", g.NavActivateId, g.NavActivateDownId, g.NavActivatePressedId);
Text("NavActivateFlags: %04X", g.NavActivateFlags);
Text("NavDisableHighlight: %d, NavDisableMouseHover: %d", g.NavDisableHighlight, g.NavDisableMouseHover);
Text("NavFocusScopeId = 0x%08X", g.NavFocusScopeId);
@ -19922,7 +19937,7 @@ void ImGui::ShowDebugLogWindow(bool* p_open)
SameLine(); CheckboxFlags("Focus", &g.DebugLogFlags, ImGuiDebugLogFlags_EventFocus);
SameLine(); CheckboxFlags("Popup", &g.DebugLogFlags, ImGuiDebugLogFlags_EventPopup);
SameLine(); CheckboxFlags("Nav", &g.DebugLogFlags, ImGuiDebugLogFlags_EventNav);
SameLine(); CheckboxFlags("Clipper", &g.DebugLogFlags, ImGuiDebugLogFlags_EventClipper);
SameLine(); if (CheckboxFlags("Clipper", &g.DebugLogFlags, ImGuiDebugLogFlags_EventClipper)) { g.DebugLogClipperAutoDisableFrames = 2; } if (IsItemHovered()) SetTooltip("Clipper log auto-disabled after 2 frames");
SameLine(); CheckboxFlags("IO", &g.DebugLogFlags, ImGuiDebugLogFlags_EventIO);
SameLine(); CheckboxFlags("Docking", &g.DebugLogFlags, ImGuiDebugLogFlags_EventDocking);
SameLine(); CheckboxFlags("Viewport", &g.DebugLogFlags, ImGuiDebugLogFlags_EventViewport);

View File

@ -23,7 +23,7 @@
// Library Version
// (Integer encoded as XYYZZ for use in #if preprocessor conditionals, e.g. '#if IMGUI_VERSION_NUM > 12345')
#define IMGUI_VERSION "1.89.4 WIP"
#define IMGUI_VERSION_NUM 18933
#define IMGUI_VERSION_NUM 18935
#define IMGUI_HAS_TABLE
#define IMGUI_HAS_VIEWPORT // Viewport WIP branch
#define IMGUI_HAS_DOCK // Docking WIP branch
@ -2110,6 +2110,8 @@ struct ImGuiIO
// [Internal] Dear ImGui will maintain those fields. Forward compatibility not guaranteed!
//------------------------------------------------------------------
ImGuiContext* Ctx; // Parent UI context (needs to be set explicitly by parent).
// Main Input State
// (this block used to be written by backend, since 1.87 it is best to NOT write to those directly, call the AddXXX functions above instead)
// (reading from those variables is fair game, as they are extremely unlikely to be moving anywhere)
@ -2167,6 +2169,7 @@ struct ImGuiIO
// - ImGuiInputTextFlags_CallbackResize: Callback on buffer capacity changes request (beyond 'buf_size' parameter value), allowing the string to grow.
struct ImGuiInputTextCallbackData
{
ImGuiContext* Ctx; // Parent UI context
ImGuiInputTextFlags EventFlag; // One ImGuiInputTextFlags_Callback* // Read-only
ImGuiInputTextFlags Flags; // What user passed to InputText() // Read-only
void* UserData; // What user passed to InputText() // Read-only
@ -2412,6 +2415,7 @@ struct ImGuiStorage
// - The clipper also handles various subtleties related to keyboard/gamepad navigation, wrapping etc.
struct ImGuiListClipper
{
ImGuiContext* Ctx; // Parent UI context
int DisplayStart; // First item to display, updated by each call to Step()
int DisplayEnd; // End of items to display (exclusive)
int ItemsCount; // [Internal] Number of items

View File

@ -126,6 +126,7 @@ struct ImDrawListSharedData; // Data shared between all ImDrawList instan
struct ImGuiColorMod; // Stacked color modifier, backup of modified data so we can restore it
struct ImGuiContext; // Main Dear ImGui context
struct ImGuiContextHook; // Hook for extensions like ImGuiTestEngine
struct ImGuiDataVarInfo; // Variable information (e.g. to avoid style variables from an enum)
struct ImGuiDataTypeInfo; // Type information associated to a ImGuiDataType enum
struct ImGuiDockContext; // Docking system context
struct ImGuiDockRequest; // Docking system dock/undock queued request
@ -963,6 +964,14 @@ enum ImGuiPopupPositionPolicy
ImGuiPopupPositionPolicy_Tooltip,
};
struct ImGuiDataVarInfo
{
ImGuiDataType Type;
ImU32 Count; // 1+
ImU32 Offset; // Offset in parent structure
void* GetVarPtr(void* parent) const { return (void*)((unsigned char*)parent + Offset); }
};
struct ImGuiDataTypeTempStorage
{
ImU8 Data[8]; // Can fit any data up to ImGuiDataType_COUNT
@ -1053,7 +1062,7 @@ struct IMGUI_API ImGuiMenuColumns
// For a given item ID, access with ImGui::GetInputTextState()
struct IMGUI_API ImGuiInputTextState
{
ImGuiContext* Ctx; // parent dear imgui context
ImGuiContext* Ctx; // parent UI context (needs to be set explicitly by parent).
ImGuiID ID; // widget id owning the text state
int CurLenW, CurLenA; // we need to maintain our buffer length in both UTF-8 and wchar format. UTF-8 length is valid even if TextA is not.
ImVector<ImWchar> TextW; // edit buffer, we need to persist but can't guarantee the persistence of the user-provided buffer. so we copy into own buffer.
@ -1069,7 +1078,7 @@ struct IMGUI_API ImGuiInputTextState
bool Edited; // edited this frame
ImGuiInputTextFlags Flags; // copy of InputText() flags. may be used to check if e.g. ImGuiInputTextFlags_Password is set.
ImGuiInputTextState(ImGuiContext* ctx) { memset(this, 0, sizeof(*this)); Ctx = ctx;}
ImGuiInputTextState() { memset(this, 0, sizeof(*this)); }
void ClearText() { CurLenW = CurLenA = 0; TextW[0] = 0; TextA[0] = 0; CursorClamp(); }
void ClearFreeMemory() { TextW.clear(); TextA.clear(); InitialTextA.clear(); }
int GetUndoAvailCount() const { return Stb.undostate.undo_point; }
@ -1191,8 +1200,8 @@ struct IMGUI_API ImGuiStackSizes
short SizeOfDisabledStack;
ImGuiStackSizes() { memset(this, 0, sizeof(*this)); }
void SetToCurrentState();
void CompareWithCurrentState();
void SetToContextState(ImGuiContext* ctx);
void CompareWithContextState(ImGuiContext* ctx);
};
// Data saved for each window pushed into the stack
@ -1427,8 +1436,8 @@ struct ImGuiListClipperData
enum ImGuiActivateFlags_
{
ImGuiActivateFlags_None = 0,
ImGuiActivateFlags_PreferInput = 1 << 0, // Favor activation that requires keyboard text input (e.g. for Slider/Drag). Default if keyboard is available.
ImGuiActivateFlags_PreferTweak = 1 << 1, // Favor activation for tweaking with arrows or gamepad (e.g. for Slider/Drag). Default if keyboard is not available.
ImGuiActivateFlags_PreferInput = 1 << 0, // Favor activation that requires keyboard text input (e.g. for Slider/Drag). Default for Enter key.
ImGuiActivateFlags_PreferTweak = 1 << 1, // Favor activation for tweaking with arrows or gamepad (e.g. for Slider/Drag). Default for Space key and if keyboard is not used.
ImGuiActivateFlags_TryToPreserveState = 1 << 2, // Request widget to preserve state if it can (e.g. InputText will try to preserve cursor/selection)
};
@ -2013,10 +2022,9 @@ struct ImGuiContext
ImGuiWindow* NavWindow; // Focused window for navigation. Could be called 'FocusedWindow'
ImGuiID NavId; // Focused item for navigation
ImGuiID NavFocusScopeId; // Identify a selection scope (selection code often wants to "clear other items" when landing on an item of the selection set)
ImGuiID NavActivateId; // ~~ (g.ActiveId == 0) && (IsKeyPressed(ImGuiKey_Space) || IsKeyPressed(ImGuiKey_NavGamepadActivate)) ? NavId : 0, also set when calling ActivateItem()
ImGuiID NavActivateDownId; // ~~ IsKeyDown(ImGuiKey_Space) || IsKeyDown(ImGuiKey_NavGamepadActivate) ? NavId : 0
ImGuiID NavActivatePressedId; // ~~ IsKeyPressed(ImGuiKey_Space) || IsKeyPressed(ImGuiKey_NavGamepadActivate) ? NavId : 0 (no repeat)
ImGuiID NavActivateInputId; // ~~ IsKeyPressed(ImGuiKey_Enter) || IsKeyPressed(ImGuiKey_NavGamepadInput) ? NavId : 0; ImGuiActivateFlags_PreferInput will be set and NavActivateId will be 0.
ImGuiID NavActivateId; // ~~ (g.ActiveId == 0) && (IsKeyPressed(ImGuiKey_Space) || IsKeyDown(ImGuiKey_Enter) || IsKeyPressed(ImGuiKey_NavGamepadActivate)) ? NavId : 0, also set when calling ActivateItem()
ImGuiID NavActivateDownId; // ~~ IsKeyDown(ImGuiKey_Space) || IsKeyDown(ImGuiKey_Enter) || IsKeyDown(ImGuiKey_NavGamepadActivate) ? NavId : 0
ImGuiID NavActivatePressedId; // ~~ IsKeyPressed(ImGuiKey_Space) || IsKeyPressed(ImGuiKey_Enter) || IsKeyPressed(ImGuiKey_NavGamepadActivate) ? NavId : 0 (no repeat)
ImGuiActivateFlags NavActivateFlags;
ImGuiID NavJustMovedToId; // Just navigated to this id (result of a successfully MoveRequest).
ImGuiID NavJustMovedToFocusScopeId; // Just navigated to this focus scope id (result of a successfully MoveRequest).
@ -2181,6 +2189,7 @@ struct ImGuiContext
ImGuiDebugLogFlags DebugLogFlags;
ImGuiTextBuffer DebugLogBuf;
ImGuiTextIndex DebugLogIndex;
ImU8 DebugLogClipperAutoDisableFrames;
ImU8 DebugLocateFrames; // For DebugLocateItemOnHover(). This is used together with DebugLocateId which is in a hot/cached spot above.
bool DebugItemPickerActive; // Item picker is active (started with DebugStartItemPicker())
ImU8 DebugItemPickerMouseButton;
@ -2200,8 +2209,10 @@ struct ImGuiContext
ImVector<char> TempBuffer; // Temporary text buffer
ImGuiContext(ImFontAtlas* shared_font_atlas)
: InputTextState(this)
{
IO.Ctx = this;
InputTextState.Ctx = this;
Initialized = false;
ConfigFlagsCurrFrame = ConfigFlagsLastFrame = ImGuiConfigFlags_None;
FontAtlasOwnedByContext = shared_font_atlas ? false : true;
@ -2267,7 +2278,7 @@ struct ImGuiContext
ViewportFrontMostStampCount = 0;
NavWindow = NULL;
NavId = NavFocusScopeId = NavActivateId = NavActivateDownId = NavActivatePressedId = NavActivateInputId = 0;
NavId = NavFocusScopeId = NavActivateId = NavActivateDownId = NavActivatePressedId = 0;
NavJustMovedToId = NavJustMovedToFocusScopeId = NavNextActivateId = 0;
NavActivateFlags = NavNextActivateFlags = ImGuiActivateFlags_None;
NavJustMovedToKeyMods = ImGuiMod_None;
@ -2362,6 +2373,7 @@ struct ImGuiContext
DebugLogFlags = ImGuiDebugLogFlags_OutputToTTY;
DebugLocateId = 0;
DebugLogClipperAutoDisableFrames = 0;
DebugLocateFrames = 0;
DebugItemPickerActive = false;
DebugItemPickerMouseButton = ImGuiMouseButton_Left;
@ -2432,6 +2444,7 @@ struct IMGUI_API ImGuiWindowTempData
// Storage for one window
struct IMGUI_API ImGuiWindow
{
ImGuiContext* Ctx; // Parent UI context (needs to be set explicitly by parent).
char* Name; // Window name, owned by the window.
ImGuiID ID; // == ImHashStr(Name)
ImGuiWindowFlags Flags, FlagsPreviousFrame; // See enum ImGuiWindowFlags_
@ -2565,10 +2578,10 @@ public:
// We don't use g.FontSize because the window may be != g.CurrentWindow.
ImRect Rect() const { return ImRect(Pos.x, Pos.y, Pos.x + Size.x, Pos.y + Size.y); }
float CalcFontSize() const { ImGuiContext& g = *GImGui; float scale = g.FontBaseSize * FontWindowScale * FontDpiScale; if (ParentWindow) scale *= ParentWindow->FontWindowScale; return scale; }
float TitleBarHeight() const { ImGuiContext& g = *GImGui; return (Flags & ImGuiWindowFlags_NoTitleBar) ? 0.0f : CalcFontSize() + g.Style.FramePadding.y * 2.0f; }
float CalcFontSize() const { ImGuiContext& g = *Ctx; float scale = g.FontBaseSize * FontWindowScale * FontDpiScale; if (ParentWindow) scale *= ParentWindow->FontWindowScale; return scale; }
float TitleBarHeight() const { ImGuiContext& g = *Ctx; return (Flags & ImGuiWindowFlags_NoTitleBar) ? 0.0f : CalcFontSize() + g.Style.FramePadding.y * 2.0f; }
ImRect TitleBarRect() const { return ImRect(Pos, ImVec2(Pos.x + SizeFull.x, Pos.y + TitleBarHeight())); }
float MenuBarHeight() const { ImGuiContext& g = *GImGui; return (Flags & ImGuiWindowFlags_MenuBar) ? DC.MenuBarOffset.y + CalcFontSize() + g.Style.FramePadding.y * 2.0f : 0.0f; }
float MenuBarHeight() const { ImGuiContext& g = *Ctx; return (Flags & ImGuiWindowFlags_MenuBar) ? DC.MenuBarOffset.y + CalcFontSize() + g.Style.FramePadding.y * 2.0f : 0.0f; }
ImRect MenuBarRect() const { float y1 = Pos.y + TitleBarHeight(); return ImRect(Pos.x, y1, Pos.x + SizeFull.x, y1 + MenuBarHeight()); }
};
@ -3052,6 +3065,7 @@ namespace ImGui
// Parameter stacks (shared)
IMGUI_API void PushItemFlag(ImGuiItemFlags option, bool enabled);
IMGUI_API void PopItemFlag();
IMGUI_API const ImGuiDataVarInfo* GetStyleVarInfo(ImGuiStyleVar idx);
// Logging/Capture
IMGUI_API void LogBegin(ImGuiLogType type, int auto_open_depth); // -> BeginCapture() when we design v2 api, for now stay under the radar by using the old name.
@ -3476,7 +3490,7 @@ namespace ImGui
// Refactored focus/nav/tabbing system in 1.82 and 1.84. If you have old/custom copy-and-pasted widgets that used FocusableItemRegister():
// (Old) IMGUI_VERSION_NUM < 18209: using 'ItemAdd(....)' and 'bool tab_focused = FocusableItemRegister(...)'
// (Old) IMGUI_VERSION_NUM >= 18209: using 'ItemAdd(..., ImGuiItemAddFlags_Focusable)' and 'bool tab_focused = (GetItemStatusFlags() & ImGuiItemStatusFlags_Focused) != 0'
// (New) IMGUI_VERSION_NUM >= 18413: using 'ItemAdd(..., ImGuiItemFlags_Inputable)' and 'bool tab_focused = (GetItemStatusFlags() & ImGuiItemStatusFlags_FocusedTabbing) != 0 || g.NavActivateInputId == id' (WIP)
// (New) IMGUI_VERSION_NUM >= 18413: using 'ItemAdd(..., ImGuiItemFlags_Inputable)' and 'bool tab_focused = (GetItemStatusFlags() & ImGuiItemStatusFlags_FocusedTabbing) != 0 || (g.NavActivateId == id && (g.NavActivateFlags & ImGuiActivateFlags_PreferInput))' (WIP)
// Widget code are simplified as there's no need to call FocusableItemUnregister() while managing the transition from regular widget to TempInputText()
inline bool FocusableItemRegister(ImGuiWindow* window, ImGuiID id) { IM_ASSERT(0); IM_UNUSED(window); IM_UNUSED(id); return false; } // -> pass ImGuiItemAddFlags_Inputable flag to ItemAdd()
inline void FocusableItemUnregister(ImGuiWindow* window) { IM_ASSERT(0); IM_UNUSED(window); } // -> unnecessary: TempInputText() uses ImGuiInputTextFlags_MergedItem
@ -3516,14 +3530,15 @@ IMGUI_API void ImFontAtlasBuildMultiplyRectAlpha8(const unsigned char table
//-----------------------------------------------------------------------------
#ifdef IMGUI_ENABLE_TEST_ENGINE
extern void ImGuiTestEngineHook_ItemAdd(ImGuiContext* ctx, const ImRect& bb, ImGuiID id);
extern void ImGuiTestEngineHook_ItemAdd(ImGuiContext* ctx, ImGuiID id, const ImRect& bb, const ImGuiLastItemData* item_data); // item_data may be NULL
extern void ImGuiTestEngineHook_ItemInfo(ImGuiContext* ctx, ImGuiID id, const char* label, ImGuiItemStatusFlags flags);
extern void ImGuiTestEngineHook_Log(ImGuiContext* ctx, const char* fmt, ...);
extern const char* ImGuiTestEngine_FindItemDebugLabel(ImGuiContext* ctx, ImGuiID id);
#define IMGUI_TEST_ENGINE_ITEM_ADD(_BB,_ID) if (g.TestEngineHookItems) ImGuiTestEngineHook_ItemAdd(&g, _BB, _ID) // Register item bounding box
#define IMGUI_TEST_ENGINE_ITEM_INFO(_ID,_LABEL,_FLAGS) if (g.TestEngineHookItems) ImGuiTestEngineHook_ItemInfo(&g, _ID, _LABEL, _FLAGS) // Register item label and status flags (optional)
#define IMGUI_TEST_ENGINE_LOG(_FMT,...) if (g.TestEngineHookItems) ImGuiTestEngineHook_Log(&g, _FMT, __VA_ARGS__) // Custom log entry from user land into test log
// In IMGUI_VERSION_NUM >= 18934: changed IMGUI_TEST_ENGINE_ITEM_ADD(bb,id) to IMGUI_TEST_ENGINE_ITEM_ADD(id,bb,item_data);
#define IMGUI_TEST_ENGINE_ITEM_ADD(_ID,_BB,_ITEM_DATA) if (g.TestEngineHookItems) ImGuiTestEngineHook_ItemAdd(&g, _ID, _BB, _ITEM_DATA) // Register item bounding box
#define IMGUI_TEST_ENGINE_ITEM_INFO(_ID,_LABEL,_FLAGS) if (g.TestEngineHookItems) ImGuiTestEngineHook_ItemInfo(&g, _ID, _LABEL, _FLAGS) // Register item label and status flags (optional)
#define IMGUI_TEST_ENGINE_LOG(_FMT,...) if (g.TestEngineHookItems) ImGuiTestEngineHook_Log(&g, _FMT, __VA_ARGS__) // Custom log entry from user land into test log
#else
#define IMGUI_TEST_ENGINE_ITEM_ADD(_BB,_ID) ((void)0)
#define IMGUI_TEST_ENGINE_ITEM_INFO(_ID,_LABEL,_FLAGS) ((void)g)

View File

@ -498,8 +498,9 @@ bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool
g.HoveredWindow = window;
#ifdef IMGUI_ENABLE_TEST_ENGINE
// Alternate registration spot, for when caller didn't use ItemAdd()
if (id != 0 && g.LastItemData.ID != id)
IMGUI_TEST_ENGINE_ITEM_ADD(bb, id);
IMGUI_TEST_ENGINE_ITEM_ADD(id, bb, NULL);
#endif
bool pressed = false;
@ -609,10 +610,11 @@ bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool
bool nav_activated_by_inputs = (g.NavActivatePressedId == id);
if (!nav_activated_by_inputs && (flags & ImGuiButtonFlags_Repeat))
{
// Avoid pressing both keys from triggering double amount of repeat events
// Avoid pressing multiple keys from triggering excessive amount of repeat events
const ImGuiKeyData* key1 = GetKeyData(ImGuiKey_Space);
const ImGuiKeyData* key2 = GetKeyData(ImGuiKey_NavGamepadActivate);
const float t1 = ImMax(key1->DownDuration, key2->DownDuration);
const ImGuiKeyData* key2 = GetKeyData(ImGuiKey_Enter);
const ImGuiKeyData* key3 = GetKeyData(ImGuiKey_NavGamepadActivate);
const float t1 = ImMax(ImMax(key1->DownDuration, key2->DownDuration), key3->DownDuration);
nav_activated_by_inputs = CalcTypematicRepeatAmount(t1 - g.IO.DeltaTime, t1, g.IO.KeyRepeatDelay, g.IO.KeyRepeatRate) > 0;
}
if (nav_activated_by_code || nav_activated_by_inputs)
@ -2416,18 +2418,18 @@ bool ImGui::DragScalar(const char* label, ImGuiDataType data_type, void* p_data,
const bool input_requested_by_tabbing = temp_input_allowed && (g.LastItemData.StatusFlags & ImGuiItemStatusFlags_FocusedByTabbing) != 0;
const bool clicked = hovered && IsMouseClicked(0, id);
const bool double_clicked = (hovered && g.IO.MouseClickedCount[0] == 2 && TestKeyOwner(ImGuiKey_MouseLeft, id));
const bool make_active = (input_requested_by_tabbing || clicked || double_clicked || g.NavActivateId == id || g.NavActivateInputId == id);
const bool make_active = (input_requested_by_tabbing || clicked || double_clicked || g.NavActivateId == id);
if (make_active && (clicked || double_clicked))
SetKeyOwner(ImGuiKey_MouseLeft, id);
if (make_active && temp_input_allowed)
if (input_requested_by_tabbing || (clicked && g.IO.KeyCtrl) || double_clicked || g.NavActivateInputId == id)
if (input_requested_by_tabbing || (clicked && g.IO.KeyCtrl) || double_clicked || (g.NavActivateId == id && (g.NavActivateFlags & ImGuiActivateFlags_PreferInput)))
temp_input_is_active = true;
// (Optional) simple click (without moving) turns Drag into an InputText
if (g.IO.ConfigDragClickToInputText && temp_input_allowed && !temp_input_is_active)
if (g.ActiveId == id && hovered && g.IO.MouseReleased[0] && !IsMouseDragPastThreshold(0, g.IO.MouseDragThreshold * DRAG_MOUSE_THRESHOLD_FACTOR))
{
g.NavActivateId = g.NavActivateInputId = id;
g.NavActivateId = id;
g.NavActivateFlags = ImGuiActivateFlags_PreferInput;
temp_input_is_active = true;
}
@ -3008,11 +3010,11 @@ bool ImGui::SliderScalar(const char* label, ImGuiDataType data_type, void* p_dat
// Tabbing or CTRL-clicking on Slider turns it into an input box
const bool input_requested_by_tabbing = temp_input_allowed && (g.LastItemData.StatusFlags & ImGuiItemStatusFlags_FocusedByTabbing) != 0;
const bool clicked = hovered && IsMouseClicked(0, id);
const bool make_active = (input_requested_by_tabbing || clicked || g.NavActivateId == id || g.NavActivateInputId == id);
const bool make_active = (input_requested_by_tabbing || clicked || g.NavActivateId == id);
if (make_active && clicked)
SetKeyOwner(ImGuiKey_MouseLeft, id);
if (make_active && temp_input_allowed)
if (input_requested_by_tabbing || (clicked && g.IO.KeyCtrl) || g.NavActivateInputId == id)
if (input_requested_by_tabbing || (clicked && g.IO.KeyCtrl) || (g.NavActivateId == id && (g.NavActivateFlags & ImGuiActivateFlags_PreferInput)))
temp_input_is_active = true;
if (make_active && !temp_input_is_active)
@ -3170,7 +3172,7 @@ bool ImGui::VSliderScalar(const char* label, const ImVec2& size, ImGuiDataType d
const bool hovered = ItemHoverable(frame_bb, id);
const bool clicked = hovered && IsMouseClicked(0, id);
if (clicked || g.NavActivateId == id || g.NavActivateInputId == id)
if (clicked || g.NavActivateId == id)
{
if (clicked)
SetKeyOwner(ImGuiKey_MouseLeft, id);
@ -3847,7 +3849,7 @@ void ImGuiInputTextCallbackData::InsertChars(int pos, const char* new_text, cons
return;
// Contrary to STB_TEXTEDIT_INSERTCHARS() this is working in the UTF8 buffer, hence the mildly similar code (until we remove the U16 buffer altogether!)
ImGuiContext& g = *GImGui;
ImGuiContext& g = *Ctx;
ImGuiInputTextState* edit_state = &g.InputTextState;
IM_ASSERT(edit_state->ID != 0 && g.ActiveId == edit_state->ID);
IM_ASSERT(Buf == edit_state->TextA.Data);
@ -3951,8 +3953,9 @@ static bool InputTextFilterCharacter(unsigned int* p_char, ImGuiInputTextFlags f
// Custom callback filter
if (flags & ImGuiInputTextFlags_CallbackCharFilter)
{
ImGuiContext& g = *GImGui;
ImGuiInputTextCallbackData callback_data;
memset(&callback_data, 0, sizeof(ImGuiInputTextCallbackData));
callback_data.Ctx = &g;
callback_data.EventFlag = ImGuiInputTextFlags_CallbackCharFilter;
callback_data.EventChar = (ImWchar)c;
callback_data.Flags = flags;
@ -4097,7 +4100,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
ImGuiInputTextState* state = GetInputTextState(id);
const bool input_requested_by_tabbing = (item_status_flags & ImGuiItemStatusFlags_FocusedByTabbing) != 0;
const bool input_requested_by_nav = (g.ActiveId != id) && ((g.NavActivateInputId == id) || (g.NavActivateId == id && g.NavInputSource == ImGuiInputSource_Keyboard));
const bool input_requested_by_nav = (g.ActiveId != id) && ((g.NavActivateId == id) && ((g.NavActivateFlags & ImGuiActivateFlags_PreferInput) || (g.NavInputSource == ImGuiInputSource_Keyboard)));
const bool user_clicked = hovered && io.MouseClicked[0];
const bool user_scroll_finish = is_multiline && state != NULL && g.ActiveId == 0 && g.ActiveIdPreviousFrame == GetWindowScrollbarID(draw_window, ImGuiAxis_Y);
@ -4592,7 +4595,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
if (event_flag)
{
ImGuiInputTextCallbackData callback_data;
memset(&callback_data, 0, sizeof(ImGuiInputTextCallbackData));
callback_data.Ctx = &g;
callback_data.EventFlag = event_flag;
callback_data.Flags = flags;
callback_data.UserData = callback_user_data;
@ -4655,6 +4658,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
if (is_resizable)
{
ImGuiInputTextCallbackData callback_data;
callback_data.Ctx = &g;
callback_data.EventFlag = ImGuiInputTextFlags_CallbackResize;
callback_data.Flags = flags;
callback_data.Buf = buf;