Merge branch 'viewport' into docking

# Conflicts:
#	imgui.h
This commit is contained in:
omar
2018-12-20 17:03:21 +01:00
7 changed files with 272 additions and 228 deletions

134
imgui.cpp
View File

@ -43,6 +43,7 @@ DOCUMENTATION
- How can I load multiple fonts?
- How can I display and input non-latin characters such as Chinese, Japanese, Korean, Cyrillic?
- How can I use the drawing facilities without an ImGui window? (using ImDrawList API)
- How can I use Dear ImGui on a platform that doesn't have a mouse or a keyboard? (input share, remoting, gamepad)
- I integrated Dear ImGui in my engine and the text or lines are blurry..
- I integrated Dear ImGui in my engine and some elements are clipping or disappearing when I move windows around..
- How can I help?
@ -835,6 +836,21 @@ CODE
- You can create your own ImDrawList instance. You'll need to initialize them ImGui::GetDrawListSharedData(), or create your own ImDrawListSharedData,
and then call your rendered code with your own ImDrawList or ImDrawData data.
Q: How can I use this without a mouse, without a keyboard or without a screen? (gamepad, input share, remote display)
A: - You can control Dear ImGui with a gamepad. Read about navigation in "Using gamepad/keyboard navigation controls".
(short version: map gamepad inputs into the io.NavInputs[] array + set io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad)
- You can share your computer mouse seamlessly with your console/tablet/phone using Synergy (https://symless.com/synergy)
This is the preferred solution for developer productivity.
In particular, the "micro-synergy-client" repository (https://github.com/symless/micro-synergy-client) has simple
and portable source code (uSynergy.c/.h) for a small embeddable client that you can use on any platform to connect
to your host computer, based on the Synergy 1.x protocol. Make sure you download the Synergy 1 server on your computer.
Console SDK also sometimes provide equivalent tooling or wrapper for Synergy-like protocols.
- You may also use a third party solution such as Remote ImGui (https://github.com/JordiRos/remoteimgui) which sends
the vertices to render over the local network, allowing you to use Dear ImGui even on a screen-less machine.
- For touch inputs, you can increase the hit box of widgets (via the style.TouchPadding setting) to accommodate
for the lack of precision of touch inputs, but it is recommended you use a mouse or gamepad to allow optimizing
for screen real-estate and precision.
Q: I integrated Dear ImGui in my engine and the text or lines are blurry..
A: In your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f).
Also make sure your orthographic projection matrix and io.DisplaySize matches your actual framebuffer dimension.
@ -1123,6 +1139,7 @@ ImGuiIO::ImGuiIO()
// Platform Functions
BackendPlatformName = BackendRendererName = NULL;
BackendPlatformUserData = BackendRendererUserData = BackendLanguageUserData = NULL;
GetClipboardTextFn = GetClipboardTextFn_DefaultImpl; // Platform dependent default implementations
SetClipboardTextFn = SetClipboardTextFn_DefaultImpl;
ClipboardUserData = NULL;
@ -4249,6 +4266,8 @@ bool ImGui::IsMousePosValid(const ImVec2* mouse_pos)
return mouse_pos->x >= MOUSE_INVALID && mouse_pos->y >= MOUSE_INVALID;
}
// Return the delta from the initial clicking position.
// 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(). Back-ends in theory should always keep mouse position valid when dragging even outside the client window.
ImVec2 ImGui::GetMouseDragDelta(int button, float lock_threshold)
{
@ -4428,6 +4447,10 @@ static bool ImGui::BeginChildEx(const char* name, ImGuiID id, const ImVec2& size
child_window->ChildId = id;
child_window->AutoFitChildAxises = auto_fit_axises;
// Set the cursor to handle case where the user called SetNextWindowPos()+BeginChild() manually.
// While this is not really documented/defined, it seems that the expected thing to do.
parent_window->DC.CursorPos = child_window->Pos;
// Process navigation-in immediately so NavInit can run on first frame
if (g.NavActivateId == id && !(flags & ImGuiWindowFlags_NavFlattened) && (child_window->DC.NavLayerActiveMask != 0 || child_window->DC.NavHasScroll))
{
@ -6673,10 +6696,10 @@ ImVec2 ImGui::GetCursorScreenPos()
return window->DC.CursorPos;
}
void ImGui::SetCursorScreenPos(const ImVec2& screen_pos)
void ImGui::SetCursorScreenPos(const ImVec2& pos)
{
ImGuiWindow* window = GetCurrentWindow();
window->DC.CursorPos = screen_pos;
window->DC.CursorPos = pos;
window->DC.CursorMaxPos = ImMax(window->DC.CursorMaxPos, window->DC.CursorPos);
}
@ -6714,12 +6737,12 @@ void ImGui::SetScrollY(float scroll_y)
window->ScrollTargetCenterRatio.y = 0.0f;
}
void ImGui::SetScrollFromPosY(float pos_y, float center_y_ratio)
void ImGui::SetScrollFromPosY(float local_y, float center_y_ratio)
{
// We store a target position so centering can occur on the next frame when we are guaranteed to have a known window size
ImGuiWindow* window = GetCurrentWindow();
IM_ASSERT(center_y_ratio >= 0.0f && center_y_ratio <= 1.0f);
window->ScrollTarget.y = (float)(int)(pos_y + window->Scroll.y);
window->ScrollTarget.y = (float)(int)(local_y + window->Scroll.y);
window->ScrollTargetCenterRatio.y = center_y_ratio;
}
@ -7875,7 +7898,8 @@ static void ImGui::UpdateSelectWindowViewport(ImGuiWindow* window)
window->ViewportId = window->Viewport->ID;
}
// Called by imgui at the end of the main loop, after EndFrame()
// Called by user at the end of the main loop, after EndFrame()
// This will handle the creation/update of all OS windows via function defined in the ImGuiPlatformIO api.
void ImGui::UpdatePlatformWindows()
{
ImGuiContext& g = *GImGui;
@ -7903,34 +7927,34 @@ void ImGui::UpdatePlatformWindows()
if (viewport->LastFrameActive < g.FrameCount)
continue;
// New windows that appears directly in a new viewport won't always have a size on their frame
// New windows that appears directly in a new viewport won't always have a size on their first frame
if (viewport->Size.x <= 0 || viewport->Size.y <= 0)
continue;
// Update common viewport flags for owned viewports
if (viewport->Window != NULL)
if (ImGuiWindow* window = viewport->Window)
{
ImGuiViewportFlags flags = viewport->Flags & ~(ImGuiViewportFlags_TopMost | ImGuiViewportFlags_NoTaskBarIcon | ImGuiViewportFlags_NoDecoration);
if (viewport->Window->Flags & ImGuiWindowFlags_Tooltip)
if (window->Flags & ImGuiWindowFlags_Tooltip)
flags |= ImGuiViewportFlags_TopMost;
if ((g.IO.ConfigFlags & ImGuiConfigFlags_ViewportsNoTaskBarIcon) != 0 || (viewport->Window->Flags & (ImGuiWindowFlags_ChildMenu | ImGuiWindowFlags_Tooltip | ImGuiWindowFlags_Popup)) != 0)
if ((g.IO.ConfigFlags & ImGuiConfigFlags_ViewportsNoTaskBarIcon) != 0 || (window->Flags & (ImGuiWindowFlags_ChildMenu | ImGuiWindowFlags_Tooltip | ImGuiWindowFlags_Popup)) != 0)
flags |= ImGuiViewportFlags_NoTaskBarIcon;
if ((g.IO.ConfigFlags & ImGuiConfigFlags_ViewportsDecoration) == 0 || (viewport->Window->Flags & (ImGuiWindowFlags_ChildMenu | ImGuiWindowFlags_Tooltip | ImGuiWindowFlags_Popup)) != 0)
if ((g.IO.ConfigFlags & ImGuiConfigFlags_ViewportsDecoration) == 0 || (window->Flags & (ImGuiWindowFlags_ChildMenu | ImGuiWindowFlags_Tooltip | ImGuiWindowFlags_Popup)) != 0)
flags |= ImGuiViewportFlags_NoDecoration;
viewport->Flags = flags;
}
// Create window
bool is_new_window = (viewport->PlatformWindowCreated == false);
if (is_new_window)
bool is_new_platform_window = (viewport->PlatformWindowCreated == false);
if (is_new_platform_window)
{
//IMGUI_DEBUG_LOG("Create Platform Window %08X (%s)\n", viewport->ID, viewport->Window ? viewport->Window->Name : "n/a");
g.PlatformIO.Platform_CreateWindow(viewport);
if (g.PlatformIO.Renderer_CreateWindow != NULL)
g.PlatformIO.Renderer_CreateWindow(viewport);
viewport->LastNameHash = 0;
viewport->LastPlatformPos = viewport->LastPlatformSize = ImVec2(FLT_MAX, FLT_MAX); // By clearing those we'll enforce a call to Platform_SetWindowPos/Platform_SetWindowSize before Platform_ShowWindow
viewport->LastRendererSize = viewport->Size;
viewport->LastPlatformPos = viewport->LastPlatformSize = ImVec2(FLT_MAX, FLT_MAX); // By clearing those we'll enforce a call to Platform_SetWindowPos/Size below, before Platform_ShowWindow (FIXME: Is that necessary?)
viewport->LastRendererSize = viewport->Size; // We don't need to call Renderer_SetWindowSize() as it is expected Renderer_CreateWindow() already did it.
viewport->PlatformWindowCreated = true;
}
@ -7953,29 +7977,32 @@ void ImGui::UpdatePlatformWindows()
if (viewport->LastNameHash != title_hash)
{
char title_end_backup_c = *title_end;
*title_end = 0; // Cut existing buffer short instead of doing an alloc/free
*title_end = 0; // Cut existing buffer short instead of doing an alloc/free, no small gain.
g.PlatformIO.Platform_SetWindowTitle(viewport, title_begin);
*title_end = title_end_backup_c;
viewport->LastNameHash = title_hash;
}
}
// Update alpha
// Update alpha (if it changed)
if (viewport->LastAlpha != viewport->Alpha && g.PlatformIO.Platform_SetWindowAlpha)
g.PlatformIO.Platform_SetWindowAlpha(viewport, viewport->Alpha);
viewport->LastAlpha = viewport->Alpha;
// Show window. On startup ensure platform window don't get focus
if (is_new_window)
if (is_new_platform_window)
{
if (g.FrameCount < 3) // Give a few frames for the application to stabilize (nested contents may lead to viewport being created a few frames late)
// On startup ensure new platform window don't steal focus (give it a few frames, as nested contents may lead to viewport being created a few frames late)
if (g.FrameCount < 3)
viewport->Flags |= ImGuiViewportFlags_NoFocusOnAppearing;
g.PlatformIO.Platform_ShowWindow(viewport);
}
// Even without focus, we assume the window becomes front-most. This is used by our platform z-order heuristic when io.MouseHoveredViewport is not available.
if (is_new_window && viewport->LastFrontMostStampCount != g.WindowsFrontMostStampCount)
viewport->LastFrontMostStampCount = ++g.WindowsFrontMostStampCount;
// Show window
g.PlatformIO.Platform_ShowWindow(viewport);
// Even without focus, we assume the window becomes front-most.
// This is useful for our platform z-order heuristic when io.MouseHoveredViewport is not available.
if (viewport->LastFrontMostStampCount != g.WindowsFrontMostStampCount)
viewport->LastFrontMostStampCount = ++g.WindowsFrontMostStampCount;
}
// Clear request flags
viewport->PlatformRequestClose = viewport->PlatformRequestMove = viewport->PlatformRequestResize = false;
@ -8002,6 +8029,34 @@ void ImGui::UpdatePlatformWindows()
}
}
// This is a default/basic function for performing the rendering/swap of multiple Platform Windows.
// Custom renderers may prefer to not call this function at all, and instead iterate the publicly exposed platform data and handle rendering/sync themselves.
// The Render/Swap functions stored in ImGuiPlatformIO are merely here to allow for this helper to exist, but you can do it yourself:
//
// ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
// for (int i = 1; i < platform_io.Viewports.Size; i++)
// MyRenderFunction(platform_io.Viewports[i], my_args);
// for (int i = 1; i < platform_io.Viewports.Size; i++)
// MySwapBufferFunction(platform_io.Viewports[i], my_args);
//
void ImGui::RenderPlatformWindowsDefault(void* platform_render_arg, void* renderer_render_arg)
{
// Skip the main viewport (index 0), which is always fully handled by the application!
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
for (int i = 1; i < platform_io.Viewports.Size; i++)
{
ImGuiViewport* viewport = platform_io.Viewports[i];
if (platform_io.Platform_RenderWindow) platform_io.Platform_RenderWindow(viewport, platform_render_arg);
if (platform_io.Renderer_RenderWindow) platform_io.Renderer_RenderWindow(viewport, renderer_render_arg);
}
for (int i = 1; i < platform_io.Viewports.Size; i++)
{
ImGuiViewport* viewport = platform_io.Viewports[i];
if (platform_io.Platform_SwapBuffers) platform_io.Platform_SwapBuffers(viewport, platform_render_arg);
if (platform_io.Renderer_SwapBuffers) platform_io.Renderer_SwapBuffers(viewport, renderer_render_arg);
}
}
static int ImGui::FindPlatformMonitorForPos(const ImVec2& pos)
{
ImGuiContext& g = *GImGui;
@ -8043,37 +8098,6 @@ static int ImGui::FindPlatformMonitorForRect(const ImRect& rect)
return best_monitor_n;
}
// This is a default/basic function for performing the rendering/swap of multiple platform windows.
// Custom renderers may prefer to not call this function at all, and instead iterate the publicly exposed platform data and handle rendering/sync themselves.
// The Render/Swap functions stored in ImGuiPlatformIO are merely here to allow for this helper to exist, but you can do it yourself:
//
// ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
// for (int i = 1; i < platform_io.Viewports.Size; i++)
// MyRenderFunction(platform_io.Viewports[i], my_args);
// for (int i = 1; i < platform_io.Viewports.Size; i++)
// MySwapBufferFunction(platform_io.Viewports[i], my_args);
//
void ImGui::RenderPlatformWindowsDefault(void* platform_render_arg, void* renderer_render_arg)
{
if (!(ImGui::GetIO().ConfigFlags & ImGuiConfigFlags_ViewportsEnable))
return;
// Skip the main viewport (index 0), which is always fully handled by the application!
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
for (int i = 1; i < platform_io.Viewports.Size; i++)
{
ImGuiViewport* viewport = platform_io.Viewports[i];
if (platform_io.Platform_RenderWindow) platform_io.Platform_RenderWindow(viewport, platform_render_arg);
if (platform_io.Renderer_RenderWindow) platform_io.Renderer_RenderWindow(viewport, renderer_render_arg);
}
for (int i = 1; i < platform_io.Viewports.Size; i++)
{
ImGuiViewport* viewport = platform_io.Viewports[i];
if (platform_io.Platform_SwapBuffers) platform_io.Platform_SwapBuffers(viewport, platform_render_arg);
if (platform_io.Renderer_SwapBuffers) platform_io.Renderer_SwapBuffers(viewport, renderer_render_arg);
}
}
void ImGui::DestroyPlatformWindow(ImGuiViewportP* viewport)
{
ImGuiContext& g = *GImGui;