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.controller;
8 import creator.widgets;
9 import inochi2d;
10 
11 bool incController(string str_id, ref Parameter param, ImVec2 size) {
12     ImGuiWindow* window = igGetCurrentWindow();
13     if (window.SkipItems) return false;
14 
15     ImVec2 avail;
16     igGetContentRegionAvail(&avail);
17     if (size.x <= 0) size.x = avail.x-size.x;
18     if (!param.isVec2) size.y = 32;
19     else if (size.y <= 0) size.y = avail.y-size.y;
20 
21     ImGuiContext* ctx = igGetCurrentContext();
22     ImGuiStyle style = ctx.Style;
23     ImGuiID id = ImGuiWindow_GetID_Str(window, str_id.ptr, str_id.ptr+str_id.length);
24     ImGuiStorage* storage = igGetStateStorage();
25     
26     // Handle padding
27     ImVec2 pos = window.DC.CursorPos;
28     size.x -= style.FramePadding.x*2;
29 
30     // Apply size to "canvas"
31     ImRect bb = ImRect(pos, ImVec2(pos.x+size.x, pos.y+size.y));
32     ImRect inner_bb = ImRect(ImVec2(pos.x+8, pos.y+8), ImVec2(pos.x+size.x-8, pos.y+size.y-8));
33     ImRect clamp_bb = ImRect(
34         ImVec2(inner_bb.Min.x+4, inner_bb.Min.y+4),
35         ImVec2(inner_bb.Max.x-4, inner_bb.Max.y-4)
36     );
37     igItemSize_Rect(bb, style.FramePadding.y);
38     if (!igItemAdd(bb, id, null))
39         return false;
40     ImDrawList* drawList = igGetWindowDrawList();
41 
42     if (igIsItemHovered()) {
43         if (igIsMouseClicked(ImGuiMouseButton.Left, false)) {
44             ImGuiStorage_SetBool(storage, id, true);
45         }
46     }
47     
48     if (!igIsMouseDown(ImGuiMouseButton.Left)) {
49         ImGuiStorage_SetBool(storage, id, false);
50     }
51 
52     // Get clamped mouse position
53     ImVec2 mpos;
54     igGetMousePos(&mpos);
55     mpos.x = clamp(mpos.x, clamp_bb.Min.x, clamp_bb.Max.x);
56     mpos.y = clamp(mpos.y, clamp_bb.Min.y, clamp_bb.Max.y);
57 
58     if (param.isVec2) {
59         float oldSize = style.FrameBorderSize;
60         igPushStyleVar_Float(ImGuiStyleVar.FrameBorderSize, 1);
61             igRenderFrameBorder(inner_bb.Min, inner_bb.Max, style.FrameRounding);
62         igPopStyleVar(1);
63 
64         if (ImGuiStorage_GetBool(storage, id, false)) {
65 
66                 // Calculate the proper value
67                 param.handle.x = (((mpos.x-clamp_bb.Min.x)/clamp_bb.Max.x)*2);
68                 param.handle.y = (((mpos.y-clamp_bb.Min.y)/clamp_bb.Max.y)*2);
69                 param.handle = clamp(param.handle, vec2(-1, -1), vec2(1, 1));
70         }
71 
72         // Draw our selector circle
73         ImDrawList_AddCircleFilled(
74             drawList, 
75             ImVec2(
76                 clamp_bb.Min.x + (clamp_bb.Max.x*((param.handle.x+1)/2)), 
77                 clamp_bb.Min.y + (clamp_bb.Max.y*((param.handle.y+1)/2))
78             ), 
79             4, 
80             igGetColorU32_Vec4(ImVec4(1, 0, 0, 1)), 
81             12
82         );
83     } else {
84         ImDrawList_AddLine(
85             drawList, 
86             ImVec2(
87                 inner_bb.Min.x,
88                 inner_bb.Min.y
89             ),
90             ImVec2(
91                 inner_bb.Min.x,
92                 inner_bb.Max.y
93             ),
94             igGetColorU32_Col(ImGuiCol.Border, 1),
95             2
96         );
97 
98         ImDrawList_AddLine(
99             drawList, 
100             ImVec2(
101                 inner_bb.Min.x,
102                 pos.y+(size.y/2)
103             ),
104             ImVec2(
105                 inner_bb.Max.x,
106                 pos.y+(size.y/2)
107             ),
108             igGetColorU32_Col(ImGuiCol.Border, 1),
109             2
110         );
111 
112         ImDrawList_AddLine(
113             drawList, 
114             ImVec2(
115                 inner_bb.Max.x,
116                 inner_bb.Min.y
117             ),
118             ImVec2(
119                 inner_bb.Max.x,
120                 inner_bb.Max.y
121             ),
122             igGetColorU32_Col(ImGuiCol.Border, 1),
123             2
124         );
125 
126         if (ImGuiStorage_GetBool(storage, id, false)) {
127             
128             // Calculate the proper value
129             param.handle.x = (
130                 (
131                     (mpos.x-clamp_bb.Min.x)/clamp_bb.Max.x
132                 )*2)-1;
133             param.handle = clamp(param.handle, vec2(-1, -1), vec2(1, 1));
134         }
135 
136         // Draw our selector circle
137         ImDrawList_AddCircleFilled(
138             drawList, 
139             ImVec2(
140                 clamp_bb.Min.x + (clamp_bb.Max.x*((param.handle.x+1)/2)), 
141                 pos.y+(size.y/2)
142             ), 
143             4, 
144             igGetColorU32_Vec4(ImVec4(1, 0, 0, 1)), 
145             12
146         );
147     }
148     return true;
149 }