|
@@ -70,6 +70,7 @@ CODE
|
|
|
// [SECTION] STYLING
|
|
|
// [SECTION] RENDER HELPERS
|
|
|
// [SECTION] MAIN CODE (most of the code! lots of stuff, needs tidying up!)
|
|
|
+// [SECTION] INPUTS
|
|
|
// [SECTION] ERROR CHECKING
|
|
|
// [SECTION] LAYOUT
|
|
|
// [SECTION] SCROLLING
|
|
@@ -295,6 +296,7 @@ CODE
|
|
|
// TODO: Setup viewport covering 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 }, fragment 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++)
|
|
|
{
|
|
|
const ImDrawList* cmd_list = draw_data->CmdLists[n];
|
|
@@ -309,9 +311,11 @@ CODE
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
- // The texture for the draw call is specified by pcmd->GetTexID().
|
|
|
- // The vast majority of draw calls will use the Dear ImGui texture atlas, which value you have set yourself during initialization.
|
|
|
- MyEngineBindTexture((MyTexture*)pcmd->GetTexID());
|
|
|
+ // Project scissor/clipping rectangles into framebuffer space
|
|
|
+ ImVec2 clip_min(pcmd->ClipRect.x - clip_off.x, pcmd->ClipRect.y - clip_off.y);
|
|
|
+ ImVec2 clip_max(pcmd->ClipRect.z - clip_off.x, pcmd->ClipRect.w - clip_off.y);
|
|
|
+ if (clip_max.x <= clip_min.x || clip_max.y <= clip_min.y)
|
|
|
+ continue;
|
|
|
|
|
|
// 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 ignore this at first. You will get some small glitches
|
|
@@ -322,14 +326,16 @@ CODE
|
|
|
// - In the interest of supporting multi-viewport applications (see 'docking' branch on github),
|
|
|
// always subtract draw_data->DisplayPos from clipping bounds to convert them to your viewport space.
|
|
|
// - Note that pcmd->ClipRect contains Min+Max bounds. Some graphics API may use Min+Max, other may use Min+Size (size being Max-Min)
|
|
|
- ImVec2 pos = draw_data->DisplayPos;
|
|
|
- MyEngineScissor((int)(pcmd->ClipRect.x - pos.x), (int)(pcmd->ClipRect.y - pos.y), (int)(pcmd->ClipRect.z - pos.x), (int)(pcmd->ClipRect.w - pos.y));
|
|
|
+ MyEngineSetScissor(clip_min.x, clip_min.y, clip_max.x, clip_max.y);
|
|
|
+
|
|
|
+ // The texture for the draw call is specified by pcmd->GetTexID().
|
|
|
+ // The vast majority of draw calls will use the Dear ImGui texture atlas, which value you have set yourself during initialization.
|
|
|
+ MyEngineBindTexture((MyTexture*)pcmd->GetTexID());
|
|
|
|
|
|
// 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.
|
|
|
- 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_buffer, pcmd->VtxOffset);
|
|
|
}
|
|
|
- idx_buffer += pcmd->ElemCount;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
@@ -387,9 +393,8 @@ CODE
|
|
|
you may use GetMainViewport()->Pos to offset hard-coded positions, e.g. SetNextWindowPos(GetMainViewport()->Pos)
|
|
|
- likewise io.MousePos and GetMousePos() will use OS coordinates.
|
|
|
If you query mouse positions to interact with non-imgui coordinates you will need to offset them, e.g. subtract GetWindowViewport()->Pos.
|
|
|
- - 2021/XX/XX (1.XX) - Moved IME support functions from io.ImeSetInputScreenPosFn, io.ImeWindowHandle to the PlatformIO api.
|
|
|
-
|
|
|
|
|
|
+ - 2022/03/05 (1.87) - removed io.ImeSetInputScreenPosFn() in favor of more flexible io.SetPlatformImeDataFn(). Removed 'void* io.ImeWindowHandle' in favor of writing to 'void* ImGuiViewport::PlatformHandleRaw'.
|
|
|
- 2022/03/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::SetNextItemOpen()
|
|
|
- ImGui::GetContentRegionAvailWidth() -> use ImGui::GetContentRegionAvail().x
|
|
@@ -927,6 +932,7 @@ static void WindowSettingsHandler_WriteAll(ImGuiContext*, ImGuiSetti
|
|
|
// 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 void SetPlatformImeDataFn_DefaultImpl(ImGuiViewport* viewport, ImGuiPlatformImeData* data);
|
|
|
|
|
|
namespace ImGui
|
|
|
{
|
|
@@ -1167,6 +1173,7 @@ ImGuiIO::ImGuiIO()
|
|
|
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);
|
|
@@ -3879,62 +3886,63 @@ static bool IsWindowActiveAndVisible(ImGuiWindow* window)
|
|
|
static void ImGui::UpdateMouseInputs()
|
|
|
{
|
|
|
ImGuiContext& g = *GImGui;
|
|
|
+ ImGuiIO& io = g.IO;
|
|
|
|
|
|
// Round mouse position to avoid spreading non-rounded position (e.g. UpdateManualResize doesn't support them well)
|
|
|
- if (IsMousePosValid(&g.IO.MousePos))
|
|
|
- g.IO.MousePos = g.MouseLastValidPos = ImFloor(g.IO.MousePos);
|
|
|
+ if (IsMousePosValid(&io.MousePos))
|
|
|
+ io.MousePos = g.MouseLastValidPos = ImFloor(io.MousePos);
|
|
|
|
|
|
// If mouse just appeared or disappeared (usually denoted by -FLT_MAX components) we cancel out movement in MouseDelta
|
|
|
- if (IsMousePosValid(&g.IO.MousePos) && IsMousePosValid(&g.IO.MousePosPrev))
|
|
|
- g.IO.MouseDelta = g.IO.MousePos - g.IO.MousePosPrev;
|
|
|
+ if (IsMousePosValid(&io.MousePos) && IsMousePosValid(&io.MousePosPrev))
|
|
|
+ io.MouseDelta = io.MousePos - io.MousePosPrev;
|
|
|
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 gamepad/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.IO.MousePosPrev = g.IO.MousePos;
|
|
|
- for (int i = 0; i < IM_ARRAYSIZE(g.IO.MouseDown); i++)
|
|
|
+ io.MousePosPrev = io.MousePos;
|
|
|
+ for (int i = 0; i < IM_ARRAYSIZE(io.MouseDown); i++)
|
|
|
{
|
|
|
- g.IO.MouseClicked[i] = g.IO.MouseDown[i] && g.IO.MouseDownDuration[i] < 0.0f;
|
|
|
- g.IO.MouseClickedCount[i] = 0; // Will be filled below
|
|
|
- g.IO.MouseReleased[i] = !g.IO.MouseDown[i] && g.IO.MouseDownDuration[i] >= 0.0f;
|
|
|
- g.IO.MouseDownDurationPrev[i] = g.IO.MouseDownDuration[i];
|
|
|
- g.IO.MouseDownDuration[i] = g.IO.MouseDown[i] ? (g.IO.MouseDownDuration[i] < 0.0f ? 0.0f : g.IO.MouseDownDuration[i] + g.IO.DeltaTime) : -1.0f;
|
|
|
- if (g.IO.MouseClicked[i])
|
|
|
+ io.MouseClicked[i] = io.MouseDown[i] && io.MouseDownDuration[i] < 0.0f;
|
|
|
+ io.MouseClickedCount[i] = 0; // Will be filled below
|
|
|
+ io.MouseReleased[i] = !io.MouseDown[i] && io.MouseDownDuration[i] >= 0.0f;
|
|
|
+ io.MouseDownDurationPrev[i] = io.MouseDownDuration[i];
|
|
|
+ io.MouseDownDuration[i] = io.MouseDown[i] ? (io.MouseDownDuration[i] < 0.0f ? 0.0f : io.MouseDownDuration[i] + io.DeltaTime) : -1.0f;
|
|
|
+ if (io.MouseClicked[i])
|
|
|
{
|
|
|
bool is_repeated_click = false;
|
|
|
- if ((float)(g.Time - g.IO.MouseClickedTime[i]) < g.IO.MouseDoubleClickTime)
|
|
|
+ if ((float)(g.Time - io.MouseClickedTime[i]) < io.MouseDoubleClickTime)
|
|
|
{
|
|
|
- ImVec2 delta_from_click_pos = IsMousePosValid(&g.IO.MousePos) ? (g.IO.MousePos - g.IO.MouseClickedPos[i]) : ImVec2(0.0f, 0.0f);
|
|
|
- if (ImLengthSqr(delta_from_click_pos) < g.IO.MouseDoubleClickMaxDist * g.IO.MouseDoubleClickMaxDist)
|
|
|
+ ImVec2 delta_from_click_pos = IsMousePosValid(&io.MousePos) ? (io.MousePos - io.MouseClickedPos[i]) : ImVec2(0.0f, 0.0f);
|
|
|
+ if (ImLengthSqr(delta_from_click_pos) < io.MouseDoubleClickMaxDist * io.MouseDoubleClickMaxDist)
|
|
|
is_repeated_click = true;
|
|
|
}
|
|
|
if (is_repeated_click)
|
|
|
- g.IO.MouseClickedLastCount[i]++;
|
|
|
+ io.MouseClickedLastCount[i]++;
|
|
|
else
|
|
|
- g.IO.MouseClickedLastCount[i] = 1;
|
|
|
- g.IO.MouseClickedTime[i] = g.Time;
|
|
|
- g.IO.MouseClickedPos[i] = g.IO.MousePos;
|
|
|
- g.IO.MouseClickedCount[i] = g.IO.MouseClickedLastCount[i];
|
|
|
- g.IO.MouseDragMaxDistanceAbs[i] = ImVec2(0.0f, 0.0f);
|
|
|
- g.IO.MouseDragMaxDistanceSqr[i] = 0.0f;
|
|
|
+ io.MouseClickedLastCount[i] = 1;
|
|
|
+ io.MouseClickedTime[i] = g.Time;
|
|
|
+ io.MouseClickedPos[i] = io.MousePos;
|
|
|
+ io.MouseClickedCount[i] = io.MouseClickedLastCount[i];
|
|
|
+ io.MouseDragMaxDistanceAbs[i] = ImVec2(0.0f, 0.0f);
|
|
|
+ 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
|
|
|
- ImVec2 delta_from_click_pos = IsMousePosValid(&g.IO.MousePos) ? (g.IO.MousePos - g.IO.MouseClickedPos[i]) : ImVec2(0.0f, 0.0f);
|
|
|
- g.IO.MouseDragMaxDistanceSqr[i] = ImMax(g.IO.MouseDragMaxDistanceSqr[i], ImLengthSqr(delta_from_click_pos));
|
|
|
- g.IO.MouseDragMaxDistanceAbs[i].x = ImMax(g.IO.MouseDragMaxDistanceAbs[i].x, delta_from_click_pos.x < 0.0f ? -delta_from_click_pos.x : delta_from_click_pos.x);
|
|
|
- g.IO.MouseDragMaxDistanceAbs[i].y = ImMax(g.IO.MouseDragMaxDistanceAbs[i].y, delta_from_click_pos.y < 0.0f ? -delta_from_click_pos.y : delta_from_click_pos.y);
|
|
|
+ ImVec2 delta_from_click_pos = IsMousePosValid(&io.MousePos) ? (io.MousePos - io.MouseClickedPos[i]) : ImVec2(0.0f, 0.0f);
|
|
|
+ io.MouseDragMaxDistanceSqr[i] = ImMax(io.MouseDragMaxDistanceSqr[i], ImLengthSqr(delta_from_click_pos));
|
|
|
+ io.MouseDragMaxDistanceAbs[i].x = ImMax(io.MouseDragMaxDistanceAbs[i].x, delta_from_click_pos.x < 0.0f ? -delta_from_click_pos.x : delta_from_click_pos.x);
|
|
|
+ io.MouseDragMaxDistanceAbs[i].y = ImMax(io.MouseDragMaxDistanceAbs[i].y, delta_from_click_pos.y < 0.0f ? -delta_from_click_pos.y : delta_from_click_pos.y);
|
|
|
}
|
|
|
|
|
|
// 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 been deactivated by gamepad/keyboard navigation
|
|
|
- if (g.IO.MouseClicked[i])
|
|
|
+ if (io.MouseClicked[i])
|
|
|
g.NavDisableMouseHover = false;
|
|
|
}
|
|
|
}
|
|
@@ -4283,8 +4291,10 @@ void ImGui::NewFrame()
|
|
|
|
|
|
g.MouseCursor = ImGuiMouseCursor_Arrow;
|
|
|
g.WantCaptureMouseNextFrame = g.WantCaptureKeyboardNextFrame = g.WantTextInputNextFrame = -1;
|
|
|
- g.PlatformImePos = ImVec2(1.0f, 1.0f); // OS Input Method Editor showing on top-left of our window by default
|
|
|
- g.PlatformImePosViewport = NULL;
|
|
|
+
|
|
|
+ // Platform IME data: reset for the frame
|
|
|
+ g.PlatformImeDataPrev = g.PlatformImeData;
|
|
|
+ g.PlatformImeData.WantVisible = false;
|
|
|
|
|
|
// Mouse wheel scrolling, scale
|
|
|
UpdateMouseWheel();
|
|
@@ -4759,14 +4769,12 @@ void ImGui::EndFrame()
|
|
|
|
|
|
ErrorCheckEndFrameSanityChecks();
|
|
|
|
|
|
- // Notify OS when our Input Method Editor cursor has moved (e.g. CJK inputs using Microsoft IME)
|
|
|
- if (g.PlatformIO.Platform_SetImeInputPos && (g.PlatformImeLastPos.x == FLT_MAX || ImLengthSqr(g.PlatformImePos - g.PlatformImeLastPos) > 0.0001f))
|
|
|
- if (g.PlatformImePosViewport && g.PlatformImePosViewport->PlatformWindowCreated)
|
|
|
- {
|
|
|
- g.PlatformIO.Platform_SetImeInputPos(g.PlatformImePosViewport, g.PlatformImePos);
|
|
|
- g.PlatformImeLastPos = g.PlatformImePos;
|
|
|
- g.PlatformImePosViewport = NULL;
|
|
|
- }
|
|
|
+ // Notify Platform/OS when our Input Method Editor cursor has moved (e.g. CJK inputs using Microsoft IME)
|
|
|
+ if (g.IO.SetPlatformImeDataFn && memcmp(&g.PlatformImeData, &g.PlatformImeDataPrev, sizeof(ImGuiPlatformImeData)) != 0)
|
|
|
+ {
|
|
|
+ ImGuiViewport* viewport = FindViewportByID(g.PlatformImeViewport);
|
|
|
+ g.IO.SetPlatformImeDataFn(viewport ? viewport : GetMainViewport(), &g.PlatformImeData);
|
|
|
+ }
|
|
|
|
|
|
// Hide implicit/fallback "Debug" window if it hasn't been used
|
|
|
g.WithinFrameScopeWithImplicitWindow = false;
|
|
@@ -5010,240 +5018,6 @@ static void FindHoveredWindow()
|
|
|
g.MovingWindow->Viewport = moving_window_viewport;
|
|
|
}
|
|
|
|
|
|
-// 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 clip)
|
|
|
-{
|
|
|
- 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, rect_clipped.Max + g.Style.TouchExtraPadding);
|
|
|
- if (!rect_for_touch.Contains(g.IO.MousePos))
|
|
|
- return false;
|
|
|
- if (!g.MouseViewport->GetMainRect().Overlaps(rect_clipped))
|
|
|
- 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 into 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, float 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_rate)
|
|
|
-{
|
|
|
- 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.KeyRepeatRate) > 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[user_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 doubling the repeat rate, which made it an ok rate for repeat on mouse hold.
|
|
|
- int amount = CalcTypematicRepeatAmount(t - g.IO.DeltaTime, t, g.IO.KeyRepeatDelay, 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 during the MouseReleased frame.
|
|
|
-// [Internal] This doesn't test if the button is pressed
|
|
|
-bool ImGui::IsMouseDragPastThreshold(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;
|
|
|
- return g.IO.MouseDragMaxDistanceSqr[button] >= lock_threshold * lock_threshold;
|
|
|
-}
|
|
|
-
|
|
|
-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 position.
|
|
|
-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 analyzer 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 threshold 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_threshold)
|
|
|
- if (IsMousePosValid(&g.IO.MousePos) && IsMousePosValid(&g.IO.MouseClickedPos[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()
|
|
|
{
|
|
|
ImGuiContext& g = *GImGui;
|
|
@@ -8043,6 +7817,249 @@ bool ImGui::IsRectVisible(const ImVec2& rect_min, const ImVec2& 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 clip)
|
|
|
+{
|
|
|
+ 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, rect_clipped.Max + g.Style.TouchExtraPadding);
|
|
|
+ if (!rect_for_touch.Contains(g.IO.MousePos))
|
|
|
+ return false;
|
|
|
+ if (!g.MouseViewport->GetMainRect().Overlaps(rect_clipped))
|
|
|
+ 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 into 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, float 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_rate)
|
|
|
+{
|
|
|
+ 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.KeyRepeatRate) > 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[user_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 doubling the repeat rate, which made it an ok rate for repeat on mouse hold.
|
|
|
+ int amount = CalcTypematicRepeatAmount(t - g.IO.DeltaTime, t, g.IO.KeyRepeatDelay, 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 during the MouseReleased frame.
|
|
|
+// [Internal] This doesn't test if the button is pressed
|
|
|
+bool ImGui::IsMouseDragPastThreshold(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;
|
|
|
+ return g.IO.MouseDragMaxDistanceSqr[button] >= lock_threshold * lock_threshold;
|
|
|
+}
|
|
|
+
|
|
|
+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 position.
|
|
|
+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 analyzer 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 threshold 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_threshold)
|
|
|
+ if (IsMousePosValid(&g.IO.MousePos) && IsMousePosValid(&g.IO.MouseClickedPos[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;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
//-----------------------------------------------------------------------------
|
|
|
// [SECTION] ERROR CHECKING
|
|
|
//-----------------------------------------------------------------------------
|
|
@@ -16905,6 +16922,49 @@ static void SetClipboardTextFn_DefaultImpl(void*, const char* text)
|
|
|
|
|
|
#endif
|
|
|
|
|
|
+// Win32 API IME support (for Asian languages, etc.)
|
|
|
+#if defined(_WIN32) && !defined(IMGUI_DISABLE_WIN32_FUNCTIONS) && !defined(IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS)
|
|
|
+
|
|
|
+#include <imm.h>
|
|
|
+#ifdef _MSC_VER
|
|
|
+#pragma comment(lib, "imm32")
|
|
|
+#endif
|
|
|
+
|
|
|
+static void SetPlatformImeDataFn_DefaultImpl(ImGuiViewport* viewport, ImGuiPlatformImeData* data)
|
|
|
+{
|
|
|
+ // 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;
|
|
|
+
|
|
|
+ ::ImmAssociateContextEx(hwnd, NULL, data->WantVisible ? IACE_DEFAULT : 0);
|
|
|
+
|
|
|
+ if (HIMC himc = ::ImmGetContext(hwnd))
|
|
|
+ {
|
|
|
+ COMPOSITIONFORM composition_form = {};
|
|
|
+ composition_form.ptCurrentPos.x = (LONG)(data->InputPos.x - viewport->Pos.x);
|
|
|
+ composition_form.ptCurrentPos.y = (LONG)(data->InputPos.y - viewport->Pos.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 - viewport->Pos.x);
|
|
|
+ candidate_form.ptCurrentPos.y = (LONG)(data->InputPos.y - viewport->Pos.y);
|
|
|
+ ::ImmSetCandidateWindow(himc, &candidate_form);
|
|
|
+ ::ImmReleaseContext(hwnd, himc);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+#else
|
|
|
+
|
|
|
+static void SetPlatformImeDataFn_DefaultImpl(ImGuiViewport*, ImGuiPlatformImeData*) {}
|
|
|
+
|
|
|
+#endif
|
|
|
+
|
|
|
//-----------------------------------------------------------------------------
|
|
|
// [SECTION] METRICS/DEBUGGER WINDOW
|
|
|
//-----------------------------------------------------------------------------
|