1 /*
2     Copyright © 2022, Inochi2D Project
3     Distributed under the 2-Clause BSD License, see LICENSE file.
4     
5     Authors: Luna Nielsen
6 */
7 module creator.widgets.viewport;
8 import creator.widgets;
9 import inochi2d.math;
10 
11 private {
12     struct ViewportToolAreaData {
13         ImVec2 contentSize;
14     }
15 }
16 
17 /**
18     Starts a generalized tool area that resizes to fit its contents
19 */
20 void incBeginViewportToolArea(string id_str, ImGuiDir hdir, ImGuiDir vdir = ImGuiDir.Up, bool pad = true) {
21     igSetItemAllowOverlap();
22     igPushID(id_str.ptr, id_str.ptr+id_str.length);
23     auto storage = igGetStateStorage();
24     auto win = igGetCurrentWindow();
25     auto style = igGetStyle();
26     auto id = igGetID("CONTENT_SIZE");
27 
28     // NOTE: Since this data is needed *before* we enter the child window
29     // we need to access it now, when we're writing to the values later
30     // we'll want to end the child FIRST before accessing it.
31     ViewportToolAreaData* data = cast(ViewportToolAreaData*)ImGuiStorage_GetVoidPtr(storage, id);
32     if (!data) {
33         data = cast(ViewportToolAreaData*)igMemAlloc(ViewportToolAreaData.sizeof);
34         data.contentSize = ImVec2(1, 1);
35         ImGuiStorage_SetVoidPtr(storage, id, data);
36     }
37 
38     float paddingX = pad ? style.FramePadding.x : 0;
39     float paddingY = pad ? style.FramePadding.y : 0; 
40 
41     // Depending on whether we're on the right or the left we want the tool area to display slightly offset
42     // on the top left or top right, this ensures that.
43     igSetCursorScreenPos(
44         ImVec2(
45             hdir == ImGuiDir.Right ? win.InnerRect.Min.x - (paddingX+data.contentSize.x) : win.InnerRect.Max.x + paddingX,
46             vdir == ImGuiDir.Down ? win.InnerRect.Min.y - (paddingY+data.contentSize.y) : win.InnerRect.Max.y + paddingY,   
47         )
48     );
49 
50     igPushStyleVar(ImGuiStyleVar.FrameRounding, 0);
51 
52     enum FLAGS = ImGuiWindowFlags.NoScrollbar | ImGuiWindowFlags.NoScrollWithMouse;
53     igBeginChild("CONTENT_CHILD", ImVec2(data.contentSize.x, data.contentSize.y), false, FLAGS);
54 }
55 
56 void incEndViewportToolArea() {
57     auto win = igGetCurrentWindow();
58     
59     // End the child
60     igEndChild();
61 
62     // Pop style vars
63     igPopStyleVar();
64 
65     // NOTE: now that we're outside the child we can actually set the ViewportToolAreaData.
66     // Since we set the state storage outside of the child in the beginning
67     auto storage = igGetStateStorage();
68     auto id = igGetID("CONTENT_SIZE");
69     ViewportToolAreaData* data = cast(ViewportToolAreaData*)ImGuiStorage_GetVoidPtr(storage, id);
70     if (data) data.contentSize = ImVec2(clamp(win.ContentSize.x, 1, float.max), clamp(win.ContentSize.y, 1, float.max));
71     
72     // Finally pop the user specified ID which the state storage is stored inside
73     igPopID();
74 }