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 
29     mpos = (
30         mat4.translation(
31             camPos.x+camCenter.x, 
32             camPos.y+camCenter.y, 
33             0
34         ) * 
35         mat4.scaling(
36             camScale.x, 
37             camScale.y, 
38             1
39         ).inverse() *
40         mat4.translation(
41             x, 
42             y, 
43             0
44         ) *
45         vec4(0, 0, 0, 1)
46     ).xy;
47 }
48 
49 /**
50     Gets the position of the mouse in the viewport
51 */
52 vec2 incInputGetMousePosition() {
53     return mpos;
54 }
55 
56 /**
57     Gets whether a mouse button is down
58 */
59 bool incInputIsMouseDown(int idx) {
60     return io.MouseDown[idx];
61 }
62 
63 /**
64     Gets whether a mouse button is down
65 */
66 bool incInputIsMouseClicked(ImGuiMouseButton idx) {
67     return igIsMouseClicked(idx, false);
68 }
69 
70 /**
71     Gets whether a mouse button is down
72 */
73 bool incInputIsMouseReleased(ImGuiMouseButton idx) {
74     return igIsMouseReleased(idx);
75 }
76 
77 /**
78     Gets whether a right click popup menu is requested by the user
79 */
80 bool incInputIsPopupRequested() {
81     return 
82         !incInputIsDragRequested() &&  // User can drag camera, make sure they aren't doing that 
83         incInputIsMouseReleased(ImGuiMouseButton.Right); // Check mouse button released
84 }
85 
86 /**
87     Gets whether the user has requested to drag something
88 */
89 bool incInputIsDragRequested(ImGuiMouseButton btn = ImGuiMouseButton.Right) {
90     ImVec2 dragDelta;
91     igGetMouseDragDelta(&dragDelta, btn);
92     return abs(dragDelta.x) > 0.1f && abs(dragDelta.y) > 0.1f;
93 }
94 
95 /**
96     Gets whether a key is held down
97 */
98 bool incInputIsKeyDown(ImGuiKey key) {
99     return igIsKeyDown(igGetKeyIndex(key));
100 }
101 
102 /**
103     Gets whether a key is held down
104 */
105 bool incInputIsKeyUp(ImGuiKey key) {
106     return !incInputIsKeyDown(key);
107 }
108 
109 /**
110     Gets whether a key is held down
111 */
112 bool incInputIsKeyPressed(ImGuiKey key) {
113     return igIsKeyPressed(igGetKeyIndex(key));
114 }
115 
116 uint incKeyScancode(string c) {
117     switch (c) {
118         case "A": return SDL_SCANCODE_A;
119         case "B": return SDL_SCANCODE_B;
120         case "C": return SDL_SCANCODE_C;
121         case "D": return SDL_SCANCODE_D;
122         case "E": return SDL_SCANCODE_E;
123         case "F": return SDL_SCANCODE_F;
124         case "G": return SDL_SCANCODE_G;
125         case "H": return SDL_SCANCODE_H;
126         case "I": return SDL_SCANCODE_I;
127         case "J": return SDL_SCANCODE_J;
128         case "K": return SDL_SCANCODE_K;
129         case "L": return SDL_SCANCODE_L;
130         case "M": return SDL_SCANCODE_M;
131         case "N": return SDL_SCANCODE_N;
132         case "O": return SDL_SCANCODE_O;
133         case "P": return SDL_SCANCODE_P;
134         case "Q": return SDL_SCANCODE_Q;
135         case "R": return SDL_SCANCODE_R;
136         case "S": return SDL_SCANCODE_S;
137         case "T": return SDL_SCANCODE_T;
138         case "U": return SDL_SCANCODE_U;
139         case "V": return SDL_SCANCODE_V;
140         case "W": return SDL_SCANCODE_W;
141         case "X": return SDL_SCANCODE_X;
142         case "Y": return SDL_SCANCODE_Y;
143         case "Z": return SDL_SCANCODE_Z;
144         case "0": return SDL_SCANCODE_0;
145         case "1": return SDL_SCANCODE_1;
146         case "2": return SDL_SCANCODE_2;
147         case "3": return SDL_SCANCODE_3;
148         case "4": return SDL_SCANCODE_4;
149         case "5": return SDL_SCANCODE_5;
150         case "6": return SDL_SCANCODE_6;
151         case "7": return SDL_SCANCODE_7;
152         case "8": return SDL_SCANCODE_8;
153         case "9": return SDL_SCANCODE_9;
154         case "F1": return SDL_SCANCODE_F1;
155         case "F2": return SDL_SCANCODE_F2;
156         case "F3": return SDL_SCANCODE_F3;
157         case "F4": return SDL_SCANCODE_F4;
158         case "F5": return SDL_SCANCODE_F5;
159         case "F6": return SDL_SCANCODE_F6;
160         case "F7": return SDL_SCANCODE_F7;
161         case "F8": return SDL_SCANCODE_F8;
162         case "F9": return SDL_SCANCODE_F9;
163         case "F10": return SDL_SCANCODE_F10;
164         case "F11": return SDL_SCANCODE_F11;
165         case "F12": return SDL_SCANCODE_F12;
166         case "Left": return SDL_SCANCODE_LEFT;
167         case "Right": return SDL_SCANCODE_RIGHT;
168         case "Up": return SDL_SCANCODE_UP;
169         case "Down": return SDL_SCANCODE_DOWN;
170         default: return SDL_SCANCODE_UNKNOWN;
171     }
172 }
173 
174 bool incShortcut(string s, bool repeat=false) {
175     auto io = igGetIO();
176 
177     if (startsWith(s, "Ctrl+")) {
178         if (!io.KeyCtrl) return false;
179         s = s[5..$];
180     }
181     if (startsWith(s, "Alt+")) {
182         if (!io.KeyAlt) return false;
183         s = s[4..$];
184     }
185     if (startsWith(s, "Shift+")) {
186         if (!io.KeyShift) return false;
187         s = s[6..$];
188     }
189 
190     uint scancode = incKeyScancode(s);
191     if (scancode == SDL_SCANCODE_UNKNOWN) return false;
192 
193     return igIsKeyPressed(scancode, repeat);
194 }