I would like to animate some buttons moving into and out of the screen from the edges.
Currently imGui doesn't let me do that, because it automatically moves windows back into the visible area. Is there a possible work around? I can't find the code responsible for this behavior...
There's no way to disable it at the moment, tho it would be possible to add a flag for that purpose.
Look for DisplayWindowPadding and DisplaySafeAreaPadding.
I think in the common case the block you are looking for is:
// Clamp position so it stays visible
if (!(flags & ImGuiWindowFlags_ChildWindow) && !(flags & ImGuiWindowFlags_Tooltip))
{
if (!window_pos_set_by_api && window->AutoFitFramesX <= 0 && window->AutoFitFramesY <= 0 && g.IO.DisplaySize.x > 0.0f && g.IO.DisplaySize.y > 0.0f) // Ignore zero-sized display explicitly to avoid losing positions if a window manager reports zero-sized window when initializing or minimizing.
{
ImVec2 padding = ImMax(style.DisplayWindowPadding, style.DisplaySafeAreaPadding);
window->PosFloat = ImMax(window->PosFloat + window->Size, padding) - window->Size;
window->PosFloat = ImMin(window->PosFloat, g.IO.DisplaySize - padding);
}
}
So you could trivially add a new flag and test for it here.
Thank you! I didn't need a new flag: I used ImGuiWindowFlags_NoMove. It makes sense in a way. If I say NoMove, then don't move the window automatically to make it visible.
if (!(flags & ImGuiWindowFlags_ChildWindow) &&
!(flags & ImGuiWindowFlags_Tooltip) &&
!(flags & ImGuiWindowFlags_NoMove))
Hello @hamoid,
Sorry for my late answer. Looking at this today, I noticed that the code already test for !window_pos_set_by_api, in other words it is skipping the test if you called SetNextWindowPos() on the API which presumably is what you are already doing?
Under this condition perhaps ensuring that you call SetNextWindowPos() every frame would be enough and then we avoid introducing this extra meaning to ImGuiWindowFlags_NoMove. What do you think?
Hi @ocornut , thanks for looking at this. I'm using ImGui from October 2016, to which I applied the minor changes I needed including the NoMove check above, and it works fine. I prefer not to do changes now as I should release the app this week :)
Feel free to close the issue, as people can use what you suggested or what I did. Cheers!
Even if you aren't going to update I would appreciate your help in finding the right solution for imgui... I don't understand why using SetNextWindowPos() isn't enough, since supposedly you were using that.
Ok :) Looking at it, I see that I don't use SetNextWindowPos() in this case, but SetWindowPos() after calling Begin(). Is that maybe the issue?
I think in this case I could use SetNextWindowPos(). In other cases I used SetWindowPos() because I needed to know the size of the window to know where to position it, and it was using AutoResize. So I got used to that, and that's why I didn't use SetNextWindowPos().
I see, that makes sense. Interestingly yes, in that instance your SetWindowPos() position will be late by one frame and clamping will occur.
Nowadays SetNextWindowPos() has a pivot parameter which might help with alignment?
Sorry to take you time on this, I realize you don't have an immediate problem anymore with your hack, I'm just trying to make sure imgui can solve whatever is a legit problem.
Thanks for trying to make imgui powerful! :) I think pivot might help.
I don't know if my issue is too rare, but this is what I tried to do: Have four small ImGui windows at the corners of the screen, which can slide in and out, depending on the current app state.
To slide out the top-left one, you need to know the width of that window, so if its 80px wide, you animate it to (-80, 0).
It sounds like using SetNextWindowPos() makes this possible. The only remaining issue would be, what if the window size is not known when calling SetNextWindowPos().
Fair enough, I'll see what I can do, and may even try to implement it in the "simple overlay demo".
Ah, interestingly: one could animate the pivot from one side to the other. If you want to have constant time slide-in that would work.
Hello! I'd like to chime in on this issue as well!
We're using RemoteImGui to let users access our windows remotely. When a client is connected, I'd like to disable the clamping of window positions because the client display area can be larger (in the remote browser).
In our implementation, IO.DisplaySize is set to the size of the visible viewport in the engine, and IO.DisplayVisibleMax is set to the size of the remote client viewport if it's larger than IO.DisplaySize. That way primitives don't get clipped outside the viewport.
Maybe the solution would be to clamp the window position using IO.DisplayVisibleMax instead of IO.DisplaySize?
Something like this would work quite well:
if (!window_pos_set_by_api && window->AutoFitFramesX <= 0 && window->AutoFitFramesY <= 0 && g.IO.DisplaySize.x > 0.0f && g.IO.DisplaySize.y > 0.0f)
{
ImRect viewportRect = GetViewportRect(); // Use full viewport instead of DisplaySize
ImVec2 padding = ImMax(style.DisplayWindowPadding, style.DisplaySafeAreaPadding);
window->Pos = ImMax(window->Pos + window->Size, viewportRect.Min + padding) - window->Size;
window->Pos = ImMin(window->Pos, viewportRect.Max - padding);
}
This solution would be perfect because when the client disconnects, we reset IO.DisplayVisibleMax to the value of IO.DisplaySize, so any windows that have been moved offscreen will automatically be moved to the visible area.
Let me know what you think!
I just realized that the viewport rect can be smaller than DisplaySize, in which case my solution above won't work.
I think it's best to add new global variables in the IO settings to control window clamping:
ImVec2 WindowClampingMin; // <unset> (0.0f,0.0f)
ImVec2 WindowClampingMax; // <unset> (0.0f,0.0f)
Then the clamping code in ImGui::Begin() would look like this:
if (!window_pos_set_by_api && window->AutoFitFramesX <= 0 && window->AutoFitFramesY <= 0 && g.IO.DisplaySize.x > 0.0f && g.IO.DisplaySize.y > 0.0f)
{
ImRect clippingRect(ImVec2(0,0), g.IO.DisplaySize);
if (g.IO.WindowClampingMin.x != g.IO.WindowClampingMax.x && g.IO.WindowClampingMin.y != g.IO.WindowClampingMax.y)
{
clippingRect.Min = g.IO.WindowClampingMin;
clippingRect.Max = g.IO.WindowClampingMax;
}
ImVec2 padding = ImMax(style.DisplayWindowPadding, style.DisplaySafeAreaPadding);
window->Pos = ImMax(window->Pos + window->Size, clippingRect.Min + padding) - window->Size;
window->Pos = ImMin(window->Pos, clippingRect.Max - padding);
}
Oh well, I finally decided to fix my issue on my side without modifying ImGui,
I now set the IO.DisplaySize to the largest viewport size (local or remote), I keep IO.DisplayVisibleMax to its default value, and everything that needs the real local viewport size is handled outside ImGui (window docking, snapping to sides, etc).
It was a little more work, but it's much more flexible. When a client is connected, I now hide the local ImGui display and use the full size of the browser window to draw the interface!
Hello @ldecarufel ,
I now set the IO.DisplaySize to the largest viewport size (local or remote)
Yes that would be my suggestion. In fact, I don't really see a use for io.DisplayVisibleMin / io.DisplayVisibleMax and they've been obsoleted in the Viewport branch.
Using io.DisplaySize should work as fine, you'd want to setup a large virtual display.
One current drawback (that's not ideal) is when transferring the ImDrawData, the 1st draw command of each window will use a clipping rect covering the entire display size, so you cannot easily filter the draw data to send remotely. Ideally you would only remote transfer the data that is visible within the remote view. I intend down the line to maintain a per-command AABB in the ImDrawCmd which would solve this problem. (The AABB will be useful for other purpose.)
The problem gets a little more tricky and interesting in the Viewport branch (#1542).
As you are using remote viewers it would be interesting if you experimented with it and perhaps your feedback can drive the design forward as to how multi-viewports can accommodate for this remote usage situation.
By default:
But we could leverage viewport to improve the console/tablet shared experience:
I'll actually close this topic as the OP question was answered. If you have comments on the original topic feel free to answer here (we can continue this thread and re-open if same topic issues surface). If you are further comments on the Viewport branch you can post in #1542 or create a new topic.