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.viewport;
8 import inochi2d;
9 import creator;
10 import creator.core;
11 import creator.core.input;
12 import bindbc.imgui;
13 import creator.viewport.model;
14 import creator.viewport.vertex;
15 import creator.viewport.anim;
16 import creator.viewport.test;
17 
18 /**
19     Draws the viewport contents
20 */
21 void incViewportDraw() {
22     auto camera = inGetCamera();
23     inBeginScene();
24     
25         switch(incEditMode) {
26             case EditMode.ModelEdit:
27                 incViewportModelDraw(camera);
28                 break;
29             case EditMode.VertexEdit:
30                 incViewportVertexDraw(camera);
31                 break;
32             case EditMode.AnimEdit:
33                 incViewportAnimDraw(camera);
34                 break;
35             case EditMode.ModelTest:
36                 incViewportTestDraw(camera);
37                 break;
38             default: assert(0);
39         }
40     inEndScene();
41 
42     if (incShouldPostProcess) {
43         inPostProcessScene();
44     }
45 }
46 
47 /**
48     Draws the viewport overlay (if any)
49 */
50 void incViewportDrawTools() {
51     switch(incEditMode) {
52         case EditMode.VertexEdit:
53             incViewportVertexTools();
54             break;
55         case EditMode.ModelEdit: 
56             incViewportModelTools(); 
57             break;
58         case EditMode.AnimEdit:
59         case EditMode.ModelTest:
60             break;
61         default: assert(0);
62     }
63 }
64 
65 void incViewportDrawOptions() {
66     switch(incEditMode) {
67         case EditMode.ModelEdit:
68             incViewportModelOptions();
69             break;
70         case EditMode.VertexEdit:
71             incViewportVertexOptions();
72             break;
73         case EditMode.AnimEdit:
74             incViewportAnimOverlay();
75             break;
76         case EditMode.ModelTest:
77             incViewportTestOverlay();
78             break;
79         default: assert(0);
80     }
81 }
82 
83 void incViewportDrawConfirmBar() {
84     switch(incEditMode) {
85         case EditMode.VertexEdit:
86             incViewportVertexConfirmBar();
87             break;
88         case EditMode.ModelEdit:
89             incViewportModelConfirmBar();
90             break;
91         case EditMode.AnimEdit:
92         case EditMode.ModelTest:
93             break;
94         default: assert(0);
95     }
96 }
97 
98 /**
99     Begins polling for viewport interactivity
100 */
101 void incViewportPoll() {
102     incInputPoll();
103     ImVec2 pos;
104     ImVec2 mpos;
105     igGetItemRectMin(&pos);
106     igGetMousePos(&mpos);
107     incInputSetViewportMouse(pos.x-mpos.x, pos.y-mpos.y);
108 }
109 
110 /**
111     Updates the viewport
112 */
113 void incViewportUpdate(bool localOnly = false) {
114     ImGuiIO* io = igGetIO();
115     auto camera = inGetCamera();
116 
117     // First update viewport movement
118     if (!localOnly) incViewportMovement(io, camera);
119 
120     // Then update sub-stuff
121     switch(incEditMode) {
122         case EditMode.ModelEdit:
123             incViewportModelUpdate(io, camera);
124             break;
125         case EditMode.VertexEdit:
126             incViewportVertexUpdate(io, camera);
127             break;
128         case EditMode.AnimEdit:
129             incViewportAnimUpdate(io, camera);
130             break;
131         case EditMode.ModelTest:
132             incViewportTestUpdate(io, camera);
133             break;
134         default: assert(0);
135     }
136 }
137 
138 /**
139     Updates the viewport toolbars
140 */
141 void incViewportToolbar() {
142     switch(incEditMode) {
143         case EditMode.ModelEdit:
144             incViewportModelToolbar();
145             break;
146         case EditMode.VertexEdit:
147             incViewportVertexToolbar();
148             break;
149         case EditMode.AnimEdit:
150             incViewportAnimToolbar();
151             break;
152         case EditMode.ModelTest:
153             incViewportTestToolbar();
154             break;
155         default: assert(0);
156     }
157 }
158 
159 /**
160     Called on editing mode present
161 */
162 void incViewportPresentMode(EditMode mode) {
163     switch(editMode_) {
164         case EditMode.ModelEdit:
165             incViewportModelPresent();
166             break;
167         case EditMode.VertexEdit:
168             incViewportVertexPresent();
169             break;
170         case EditMode.AnimEdit:
171             incViewportAnimPresent();
172             break;
173         case EditMode.ModelTest:
174             incViewportTestPresent();
175             break;
176         default: assert(0);
177     }
178 }
179 
180 /**
181     Called on editing mode withdraw
182 */
183 void incViewportWithdrawMode(EditMode mode) {
184     switch(editMode_) {
185         case EditMode.ModelEdit:
186             incViewportModelWithdraw();
187             break;
188         case EditMode.VertexEdit:
189             incViewportVertexWithdraw();
190             break;
191         case EditMode.AnimEdit:
192             incViewportAnimWithdraw();
193             break;
194         case EditMode.ModelTest:
195             incViewportTestWithdraw();
196             break;
197         default: assert(0);
198     }
199 }
200 
201 void incViewportMenu() {
202     switch(incEditMode) {
203         case EditMode.ModelEdit:
204             incViewportModelMenu();
205             break;
206         default: return;
207     }
208 }
209 
210 void incViewportMenuOpening() {
211     switch(incEditMode) {
212         case EditMode.ModelEdit:
213             incViewportModelMenuOpening();
214             break;
215         default: return;
216     }
217 }
218 
219 bool incViewportHasMenu() {
220     switch(incEditMode) {
221         case EditMode.ModelEdit: return true;
222         default: return false;
223     }
224 }
225 
226 /**
227     Updates the viewport tool settings
228 */
229 void incViewportToolSettings() {
230     switch(incEditMode) {
231         case EditMode.ModelEdit:
232             incViewportModelToolSettings();
233             break;
234         case EditMode.VertexEdit:
235             incViewportVertexToolSettings();
236             break;
237         default: 
238             incViewportToolSettingsNoTool();
239             break;
240     }
241 }
242 
243 bool incViewportAlwaysUpdate() {
244     switch(incEditMode) {
245         case EditMode.ModelTest:
246             return true;
247         default: return false;
248     }
249 }
250 
251 /// For when there's no tools for that view
252 void incViewportToolSettingsNoTool() {
253     import i18n : _;
254     import creator.widgets.label;
255     incText(_("No tool selected..."));
256 }
257 
258 bool incStartedDrag(int btn) {
259     return isDragging[btn];
260 }
261 
262 void incBeginDrag(int btn) {
263     isDragging[btn] = true;
264 }
265 
266 void incEndDrag(int btn) {
267     isDragging[btn] = false;
268 }
269 
270 bool incDragStartedInViewport(int btn) {
271     return isDraggingInViewport[btn];
272 }
273 
274 void incBeginDragInViewport(int btn) {
275     isDraggingInViewport[btn] = true;
276 }
277 
278 void incEndDragInViewport(int btn) {
279     isDraggingInViewport[btn] = false;
280 }
281 
282 //
283 //          VIEWPORT CAMERA HANDLING
284 //
285 
286 enum incVIEWPORT_ZOOM_MIN = 0.05;
287 enum incVIEWPORT_ZOOM_MAX = 12.0;
288 
289 /**
290     Target camera position in scene
291 */
292 vec2 incViewportTargetPosition = vec2(0);
293 
294 /**
295     Target camera zoom in scene
296 */
297 float incViewportTargetZoom = 1;
298 
299 /**
300     The actual zoom of the viewport
301 */
302 float incViewportZoom = 1;
303 
304 /**
305     Resets the viewport
306 */
307 void incViewportReset() {
308     incViewportTargetPosition = vec2(0);
309     incViewportTargetZoom = 1;
310 }
311 
312 
313 //
314 //          Internal Viewport Stuff(TM)
315 //
316 private {
317     bool[ImGuiMouseButton.COUNT] isDraggingInViewport;
318     bool[ImGuiMouseButton.COUNT] isDragging;
319     bool isMovingViewport;
320     float sx, sy;
321     float csx, csy;
322     bool isMovingPart;
323 
324     void incViewportMovement(ImGuiIO* io, Camera camera) {
325         float uiScale = incGetUIScale();
326         
327         // HANDLE MOVE VIEWPORT
328         if (!isMovingViewport && io.MouseDown[1] && incInputIsDragRequested()) {
329             isMovingViewport = true;
330             sx = io.MousePos.x;
331             sy = io.MousePos.y;
332             csx = camera.position.x;
333             csy = camera.position.y;
334         }
335 
336         if (isMovingViewport && !io.MouseDown[1]) {
337             isMovingViewport = false;
338         }
339 
340         if (isMovingViewport) {
341 
342             camera.position = vec2(
343                 csx+((io.MousePos.x-sx)/incViewportZoom)*uiScale,
344                 csy+((io.MousePos.y-sy)/incViewportZoom)*uiScale
345             );
346 
347             incViewportTargetPosition = camera.position;
348         }
349 
350         // HANDLE ZOOM
351         if (io.MouseWheel != 0) {
352             incViewportZoom += (io.MouseWheel/50)*incViewportZoom*uiScale;
353             incViewportZoom = clamp(incViewportZoom, incVIEWPORT_ZOOM_MIN, incVIEWPORT_ZOOM_MAX);
354             camera.scale = vec2(incViewportZoom);
355             incViewportTargetZoom = incViewportZoom;
356         }
357     }
358 }