1 /*
2     Copyright © 2020, Inochi2D Project
3     Distributed under the 2-Clause BSD License, see LICENSE file.
4     
5     Authors: Luna Nielsen
6 */
7 module creator.widgets.progress;
8 import creator.widgets;
9 import inochi2d.math;
10 
11 //
12 //  BORROWED AND MODIFIED FROM
13 //  https://github.com/ocornut/imgui/issues/1901
14 //
15 
16 bool incBufferBar(string label, float value, ImVec2 size, ImU32 bgColor, ImU32 fgColor) {
17     ImGuiWindow* window = igGetCurrentWindow();
18     if (window.SkipItems) return false;
19 
20     ImVec2 avail;
21     igGetContentRegionAvail(&avail);
22     if (size.x <= 0) size.x = avail.x-size.x;
23     if (size.y == 0) size.y = 64;
24 
25     value = clamp(value, 0, 1);
26     
27 
28     ImGuiContext* ctx = igGetCurrentContext();
29     ImGuiStyle style = ctx.Style;
30     ImGuiID id = ImGuiWindow_GetID_Str(window, label.ptr, label.ptr+label.length);
31 
32     ImVec2 pos = window.DC.CursorPos;
33     size.x -= style.FramePadding.x*2;
34 
35     ImRect bb = ImRect(ImVec2(pos.x, pos.y+((size.y/2)-2)), ImVec2(pos.x+size.x, pos.y+((size.y/2)+2)));
36     ImRect obb = ImRect(pos, ImVec2(pos.x+size.x, pos.y+size.y));
37     igItemSize_Rect(obb, style.FramePadding.y);
38     if (!igItemAdd(obb, id, null))
39         return false;
40     
41     float circleStart = size.x; // * 0.7f;
42     float circleEnd = size.x;
43     float circleWidth = circleEnd-circleStart;
44 
45     ImDrawList_AddRectFilled(igGetWindowDrawList(), bb.Min, ImVec2(pos.x + circleStart, bb.Max.y), bgColor, 8, ImDrawFlags.RoundCornersAll);
46     ImDrawList_AddRectFilled(igGetWindowDrawList(), bb.Min, ImVec2(pos.x + circleStart*value, bb.Max.y), fgColor, 8, ImDrawFlags.RoundCornersAll);
47     
48     
49     igNewLine();
50     return false;
51 }
52 
53 /**
54     Creates a spinner
55 */
56 bool incSpinner(string label, float radius, int thickness, ImU32 color) {
57     ImGuiWindow* window = igGetCurrentWindow();
58     if (window.SkipItems) return false;
59 
60     // If radius less or equal to 0 is passed do normal imgui behaviour
61     ImVec2 avail;
62     igGetContentRegionAvail(&avail);
63     if (radius <= 0) radius = (min(avail.x, avail.y)/2) - radius;
64 
65 
66     ImGuiContext* ctx = igGetCurrentContext();
67     ImGuiStyle style = ctx.Style;
68     ImGuiID id = ImGuiWindow_GetID_Str(window, label.ptr, label.ptr+label.length);
69 
70     ImVec2 pos = ImVec2(window.DC.CursorPos.x, window.DC.CursorPos.y);
71     ImVec2 size = ImVec2((radius*2), ((radius+style.FramePadding.y)*2));
72     ImRect bb = ImRect(pos, ImVec2(pos.x+size.x, pos.y+size.y));
73     igItemSize_Rect(bb, style.FramePadding.y);
74     if (!igItemAdd(bb, id))
75         return false;
76 
77     // Render
78     ImDrawList_PathClear(igGetWindowDrawList());
79 
80     enum SEGMENTS = 45;
81     float start = abs(sin(ctx.Time*1.4f)*(SEGMENTS-5));
82 
83     const float aMin = PI*2 * (cast(float)start / cast(float)SEGMENTS);
84     const float aMax = PI*2 * ((cast(float)SEGMENTS-3) / cast(float)SEGMENTS);
85 
86     ImVec2 center = ImVec2(pos.x+radius, pos.y+radius+style.FramePadding.y);
87 
88     for (int i = 0; i < SEGMENTS; i++) {
89         const float a = aMin + (cast(float)i / cast(float)SEGMENTS) * (aMax-aMin);
90         ImDrawList_PathLineTo(igGetWindowDrawList(), ImVec2(
91             center.x + cos(a+ctx.Time*8) * (radius-thickness),
92             center.y + sin(a+ctx.Time*8) * (radius-thickness)
93         ));
94     }
95 
96     ImDrawList_PathStroke(igGetWindowDrawList(), color, ImDrawFlags.None, thickness);
97     igNewLine();
98     return false;
99 }