1 module creator.core.input;
2 import creator.core;
3 import inochi2d.core;
4 import inochi2d.math;
5 import bindbc.imgui;
6 import bindbc.sdl;
7 import std.algorithm;
8 
9 private {
10     vec2 mpos;
11     ImGuiIO* io;
12 }
13 
14 /**
15     Begins a UI input pass
16 */
17 void incInputPoll() {
18     io = igGetIO();
19 }
20 
21 /**
22     Sets the mouse within the viewport
23 */
24 void incInputSetViewportMouse(float x, float y) {
25     vec2 camPos = inGetCamera().position;
26     vec2 camScale = inGetCamera().scale;
27     vec2 camCenter = inGetCamera().getCenterOffset();
28     float uiScale = incGetUIScale();
29 
30     mpos = (
31         mat4.translation(
32             camPos.x+camCenter.x, 
33             camPos.y+camCenter.y, 
34             0
35         ) * 
36         mat4.scaling(
37             camScale.x, 
38             camScale.y, 
39             1
40         ).inverse() *
41         mat4.translation(
42             x*uiScale, 
43             y*uiScale, 
44             0
45         ) *
46         vec4(0, 0, 0, 1)
47     ).xy;
48 }
49 
50 /**
51     Gets the position of the mouse in the viewport
52 */
53 vec2 incInputGetMousePosition() {
54     return mpos;
55 }
56 
57 /**
58     Gets whether a mouse button is down
59 */
60 bool incInputIsMouseDown(int idx) {
61     return io.MouseDown[idx];
62 }
63 
64 /**
65     Gets whether a mouse button is down
66 */
67 bool incInputIsMouseClicked(ImGuiMouseButton idx) {
68     return igIsMouseClicked(idx, false);
69 }
70 
71 /**
72     Gets whether a mouse button is down
73 */
74 bool incInputIsMouseReleased(ImGuiMouseButton idx) {
75     return igIsMouseReleased(idx);
76 }
77 
78 /**
79     Gets whether a right click popup menu is requested by the user
80 */
81 bool incInputIsPopupRequested() {
82     return 
83         !incInputIsDragRequested() &&  // User can drag camera, make sure they aren't doing that 
84         incInputIsMouseReleased(ImGuiMouseButton.Right); // Check mouse button released
85 }
86 
87 /**
88     Gets whether the user has requested to drag something
89 */
90 bool incInputIsDragRequested(ImGuiMouseButton btn = ImGuiMouseButton.Right) {
91     ImVec2 dragDelta;
92     igGetMouseDragDelta(&dragDelta, btn);
93     return abs(dragDelta.x) > 0.1f && abs(dragDelta.y) > 0.1f;
94 }
95 
96 /**
97     Gets whether a key is held down
98 */
99 bool incInputIsKeyDown(ImGuiKey key) {
100     return igIsKeyDown(key);
101 }
102 
103 /**
104     Gets whether a key is held down
105 */
106 bool incInputIsKeyUp(ImGuiKey key) {
107     return !incInputIsKeyDown(key);
108 }
109 
110 /**
111     Gets whether a key is held down
112 */
113 bool incInputIsKeyPressed(ImGuiKey key) {
114     return igIsKeyPressed(key);
115 }
116 
117 ImGuiKey incKeyScancode(string c) {
118     switch (c) {
119         case "A": return ImGuiKey.A;
120         case "B": return ImGuiKey.B;
121         case "C": return ImGuiKey.C;
122         case "D": return ImGuiKey.D;
123         case "E": return ImGuiKey.E;
124         case "F": return ImGuiKey.F;
125         case "G": return ImGuiKey.G;
126         case "H": return ImGuiKey.H;
127         case "I": return ImGuiKey.I;
128         case "J": return ImGuiKey.J;
129         case "K": return ImGuiKey.K;
130         case "L": return ImGuiKey.L;
131         case "M": return ImGuiKey.M;
132         case "N": return ImGuiKey.N;
133         case "O": return ImGuiKey.O;
134         case "P": return ImGuiKey.P;
135         case "Q": return ImGuiKey.Q;
136         case "R": return ImGuiKey.R;
137         case "S": return ImGuiKey.S;
138         case "T": return ImGuiKey.T;
139         case "U": return ImGuiKey.U;
140         case "V": return ImGuiKey.V;
141         case "W": return ImGuiKey.W;
142         case "X": return ImGuiKey.X;
143         case "Y": return ImGuiKey.Y;
144         case "Z": return ImGuiKey.Z;
145         case "0": return ImGuiKey.n0;
146         case "1": return ImGuiKey.n1;
147         case "2": return ImGuiKey.n2;
148         case "3": return ImGuiKey.n3;
149         case "4": return ImGuiKey.n4;
150         case "5": return ImGuiKey.n5;
151         case "6": return ImGuiKey.n6;
152         case "7": return ImGuiKey.n7;
153         case "8": return ImGuiKey.n8;
154         case "9": return ImGuiKey.n9;
155         case "F1": return ImGuiKey.F1;
156         case "F2": return ImGuiKey.F2;
157         case "F3": return ImGuiKey.F3;
158         case "F4": return ImGuiKey.F4;
159         case "F5": return ImGuiKey.F5;
160         case "F6": return ImGuiKey.F6;
161         case "F7": return ImGuiKey.F7;
162         case "F8": return ImGuiKey.F8;
163         case "F9": return ImGuiKey.F9;
164         case "F10": return ImGuiKey.F10;
165         case "F11": return ImGuiKey.F11;
166         case "F12": return ImGuiKey.F12;
167         case "Left": return ImGuiKey.LeftArrow;
168         case "Right": return ImGuiKey.RightArrow;
169         case "Up": return ImGuiKey.UpArrow;
170         case "Down": return ImGuiKey.DownArrow;
171         default: return ImGuiKey.None;
172     }
173 }
174 
175 bool incShortcut(string s, bool repeat=false) {
176     auto io = igGetIO();
177 
178     if(io.KeyCtrl && io.KeyAlt) return false;
179 
180     if (startsWith(s, "Ctrl+Shift+")) {
181         if (!(io.KeyCtrl && !io.KeyAlt && io.KeyShift)) return false;
182         s = s[11..$];
183     }
184     if (startsWith(s, "Ctrl+")) {
185         if (!(io.KeyCtrl && !io.KeyAlt && !io.KeyShift)) return false;
186         s = s[5..$];
187     }
188     if (startsWith(s, "Alt+")) {
189         if (!(!io.KeyCtrl && io.KeyAlt && !io.KeyShift)) return false;
190         s = s[4..$];
191     }
192     if (startsWith(s, "Shift+")) {
193         if (!(!io.KeyCtrl && !io.KeyAlt && io.KeyShift)) return false;
194         s = s[6..$];
195     }
196 
197     ImGuiKey scancode = incKeyScancode(s);
198     if (scancode == ImGuiKey.None) return false;
199 
200     return igIsKeyPressed(scancode, repeat);
201 }