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.model;
8 import creator.viewport.model.deform;
9 import creator.widgets.tooltip;
10 import creator.widgets.label;
11 import creator.widgets.texture;
12 import creator.widgets.dummy;
13 import creator.widgets.dragdrop;
14 import creator.widgets.button;
15 import creator.core.input;
16 import creator.core;
17 import creator.viewport.vertex;
18 import creator;
19 import inochi2d;
20 import bindbc.imgui;
21 import i18n;
22 import std.stdio;
23 
24 private {
25     Part[] foundParts;
26 
27     enum ENTRY_SIZE = 48;
28 }
29 
30 void incViewportModelMenuOpening() {
31     foundParts.length = 0;
32 
33     vec2 mpos = incInputGetMousePosition()*-1;
34     mloop: foreach(ref Part part; incActivePuppet.getAllParts()) {
35         rect b = rect(part.bounds.x, part.bounds.y, part.bounds.z-part.bounds.x, part.bounds.w-part.bounds.y);
36         if (b.intersects(mpos)) {
37 
38             // Skip already selected parts
39             foreach(pn; incSelectedNodes()) {
40                 if (pn.uuid == part.uuid) continue mloop;
41             }
42             foundParts ~= part;
43         }
44     }
45 
46     import std.algorithm.sorting : sort;
47     import std.algorithm.mutation : SwapStrategy;
48     import std.math : cmp;
49     sort!((a, b) => cmp(
50         a.zSortNoOffset, 
51         b.zSortNoOffset) < 0, SwapStrategy.stable)(foundParts);
52 }
53 
54 void incViewportModelMenu() {
55     if (incSelectedNode() != incActivePuppet().root) {
56         if (igMenuItem(__("Focus Selected"))) {
57             incFocusCamera(incSelectedNode());
58         }
59     }
60     
61     if (igBeginChild("FOUND_PARTS", ImVec2(256, 256), false)) {
62         if (foundParts.length > 0) {
63             ImVec2 avail = incAvailableSpace();
64             ImVec2 cursorPos;
65             foreach(Part part; foundParts) {
66                 igPushID(part.uuid);
67                     ImVec2 nameSize = incMeasureString(part.name);
68 
69                     // Selectable
70                     igGetCursorPos(&cursorPos);
71                     if (igSelectable("###PartSelectable", false, ImGuiSelectableFlags.None, ImVec2(avail.x, ENTRY_SIZE))) {
72                         
73                         // Add selection if ctrl is down, otherwise set selection
74                         if (igIsKeyDown(ImGuiKey.LeftCtrl) || igIsKeyDown(ImGuiKey.RightCtrl)) incAddSelectNode(part);
75                         else incSelectNode(part);
76 
77                         // Escape early, we're already done.
78                         igPopID();
79                         igEndChild();
80                         igCloseCurrentPopup();
81                         return;
82                     }
83                     igSetItemAllowOverlap();
84 
85                     if(igBeginDragDropSource(ImGuiDragDropFlags.SourceAllowNullID)) {
86                         igSetDragDropPayload("_PUPPETNTREE", cast(void*)&part, (&part).sizeof, ImGuiCond.Always);
87                         incDragdropNodeList(part);
88                         igEndDragDropSource();
89                     }
90 
91                     // ICON
92                     igSetCursorPos(ImVec2(cursorPos.x+2, cursorPos.y+2));
93                     incTextureSlotUntitled("ICON", part.textures[0], ImVec2(ENTRY_SIZE-4, ENTRY_SIZE-4), 24, ImGuiWindowFlags.NoInputs);
94                     
95                     // Name
96                     igSetCursorPos(ImVec2(cursorPos.x + ENTRY_SIZE + 4, cursorPos.y + (ENTRY_SIZE/2) - (nameSize.y/2)));
97                     incText(part.name);
98 
99                     // Move to next line
100                     igSetCursorPos(ImVec2(cursorPos.x, cursorPos.y + ENTRY_SIZE + 3));
101                 igPopID();
102             }
103         } else {
104             incText(_("No parts found"));
105         }
106     }
107     igEndChild();
108 }
109 
110 void incViewportModelTools() {
111     if (incArmedParameter()) {
112         incViewportModelDeformTools();
113     }
114 }
115 
116 void incViewportModelConfirmBar() {
117 
118     // If parameter is armed we should *not* show the edit mesh button
119     if (incArmedParameter()) return;
120 
121     igPushStyleVar(ImGuiStyleVar.FramePadding, ImVec2(16, 4));
122         if (Drawable node = cast(Drawable)incSelectedNode()) {
123             if (igButton(__(" Edit Mesh"), ImVec2(0, 26))) {
124                 incVertexEditStartEditing(node);
125             }
126 
127             // Allow copying mesh data via drag n drop for now
128             if(igBeginDragDropTarget()) {
129                 incTooltip(_("Copy Mesh Data"));
130                 
131                 const(ImGuiPayload)* payload = igAcceptDragDropPayload("_PUPPETNTREE");
132                 if (payload !is null) {
133                     if (Drawable payloadDrawable = cast(Drawable)*cast(Node*)payload.Data) {
134                         incSetEditMode(EditMode.VertexEdit);
135                         incSelectNode(node);
136                         incVertexEditSetTarget(node);
137                         incFocusCamera(node, vec2(0, 0));
138                         incVertexEditCopyMeshDataToTarget(payloadDrawable.getMesh());
139                     }
140                 }
141                 igEndDragDropTarget();
142             } else {
143 
144 
145                 // Switches Inochi Creator over to Mesh Edit mode
146                 // and selects the mesh that you had selected previously
147                 // in Model Edit mode.
148                 incTooltip(_("Edit Mesh"));
149             }
150         }
151     igPopStyleVar();
152 }
153 
154 void incViewportModelOptions() {
155     igPushStyleVar(ImGuiStyleVar.ItemSpacing, ImVec2(0, 0));
156     igPushStyleVar(ImGuiStyleVar.WindowPadding, ImVec2(4, 4));
157         if (!incArmedParameter()) {
158             if(incBeginDropdownMenu("GIZMOS", "")) {
159 
160                 if (incButtonColored("", ImVec2(0, 0), incShowVertices ? ImVec4.init : ImVec4(0.6, 0.6, 0.6, 1))) {
161                     incShowVertices = !incShowVertices;
162                 }
163                 incTooltip(incShowVertices ? _("Hide Vertices") : _("Show Vertices"));
164                     
165                 igSameLine(0, 4);
166                 if (incButtonColored("", ImVec2(0, 0), incShowBounds ? ImVec4.init : ImVec4(0.6, 0.6, 0.6, 1))) {
167                     incShowBounds = !incShowBounds;
168                 }
169                 incTooltip(incShowBounds ? _("Hide Bounds") : _("Show Bounds"));
170 
171                 igSameLine(0, 4);
172                 if (incButtonColored("", ImVec2(0, 0), incShowOrientation ? ImVec4.init : ImVec4(0.6, 0.6, 0.6, 1))) {
173                     incShowOrientation = !incShowOrientation;
174                 }
175                 incTooltip(incShowOrientation ? _("Hide Orientation Gizmo") : _("Show Orientation Gizmo"));
176 
177                 incEndDropdownMenu();
178             }
179             incTooltip(_("Gizmos"));
180         }
181     igPopStyleVar(2);
182 }
183 
184 void incViewportModelNodeSelectionChanged() {
185     incViewportModelDeformNodeSelectionChanged();
186 }
187 
188 void incViewportModelUpdate(ImGuiIO* io, Camera camera) {
189     if (Parameter param = incArmedParameter()) {
190         incViewportModelDeformUpdate(io, camera, param);
191     }    
192 }
193 
194 void incViewportModelDraw(Camera camera) {
195     Parameter param = incArmedParameter();
196     incActivePuppet.update();
197     incActivePuppet.draw();
198 
199     if (param) {
200         incViewportModelDeformDraw(camera, param);
201     } else {
202         if (incSelectedNodes.length > 0) {
203             foreach(selectedNode; incSelectedNodes) {
204                 if (selectedNode is null) continue; 
205                 if (incShowOrientation) selectedNode.drawOrientation();
206                 if (incShowBounds) selectedNode.drawBounds();
207 
208 
209                 if (Drawable selectedDraw = cast(Drawable)selectedNode) {
210 
211                     if (incShowVertices || incEditMode != EditMode.ModelEdit) {
212                         selectedDraw.drawMeshLines();
213                         selectedDraw.drawMeshPoints();
214                     }
215                 }
216                 
217                 if (Driver selectedDriver = cast(Driver)selectedNode) {
218                     selectedDriver.drawDebug();
219                 }
220             }
221         }
222     }
223 }
224 
225 void incViewportModelToolSettings() {
226     incViewportModelDeformToolSettings();
227 }
228 
229 void incViewportModelPresent() {
230 
231 }
232 
233 void incViewportModelWithdraw() {
234 
235 }
236 
237 void incViewportModelToolbar() {
238     
239 }