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.vertex;
8 import i18n;
9 import creator.viewport;
10 import creator.viewport.common.mesh;
11 import creator.viewport.common.mesheditor;
12 import creator.core.input;
13 import creator.widgets;
14 import creator;
15 import inochi2d;
16 import bindbc.imgui;
17 import std.stdio;
18 import bindbc.opengl;
19 
20 private {
21     IncMeshEditor editor;
22 }
23 
24 void incViewportVertexInspector(Drawable node) {
25 
26     
27 
28 }
29 
30 void incViewportVertexTools() {
31     editor.viewportTools();
32 }
33 
34 void incViewportVertexOptions() {
35     igPushStyleVar(ImGuiStyleVar.ItemSpacing, ImVec2(0, 0));
36     igPushStyleVar(ImGuiStyleVar.WindowPadding, ImVec2(4, 4));
37         igBeginGroup();
38             if (igButton("")) editor.mesh.flipHorz();
39             incTooltip(_("Flip Horizontally"));
40 
41             igSameLine(0, 0);
42 
43             if (igButton("")) editor.mesh.flipVert();
44             incTooltip(_("Flip Vertically"));
45         igEndGroup();
46 
47         igSameLine(0, 4);
48 
49         igBeginGroup();
50             if (incButtonColored("", ImVec2(0, 0), editor.mirrorHoriz ? ImVec4.init : ImVec4(0.6, 0.6, 0.6, 1))) {
51                 editor.mirrorHoriz = !editor.mirrorHoriz;
52                 editor.refreshMesh();
53             }
54             incTooltip(_("Mirror Horizontally"));
55 
56             igSameLine(0, 0);
57 
58             if (incButtonColored("", ImVec2(0, 0), editor.mirrorVert ? ImVec4.init : ImVec4(0.6, 0.6, 0.6, 1))) {
59                 editor.mirrorVert = !editor.mirrorVert;
60                 editor.refreshMesh();
61             }
62             incTooltip(_("Mirror Vertically"));
63         igEndGroup();
64 
65         igSameLine(0, 4);
66 
67         igBeginGroup();
68             if (incButtonColored("", ImVec2(0, 0),
69                 editor.previewTriangulate ? ImVec4(1, 1, 0, 1) : ImVec4.init)) {
70                 editor.previewTriangulate = !editor.previewTriangulate;
71                 editor.refreshMesh();
72             }
73             incTooltip(_("Triangulate vertices"));
74 
75             if (incBeginDropdownMenu("TRIANGULATE_SETTINGS")) {
76                 incDummyLabel("TODO: Options Here", ImVec2(0, 192));
77 
78                 // Button which bakes some auto generated content
79                 // In this case, a mesh is baked from the triangulation.
80                 if (incButtonColored(__("Bake"), ImVec2(incAvailableSpace().x, 0),
81                     editor.previewingTriangulation() ? ImVec4.init : ImVec4(0.6, 0.6, 0.6, 1))) {
82                     if (editor.previewingTriangulation()) {
83                         editor.applyPreview();
84                         editor.refreshMesh();
85                     }
86                 }
87                 incTooltip(_("Bakes the triangulation, applying it to the mesh."));
88                 
89                 incEndDropdownMenu();
90             }
91             incTooltip(_("Triangulation Options"));
92 
93         igEndGroup();
94     igPopStyleVar(2);
95 }
96 
97 void incViewportVertexConfirmBar() {
98     Drawable target = editor.getTarget();
99     igPushStyleVar(ImGuiStyleVar.FramePadding, ImVec2(16, 4));
100         if (igButton(__(" Apply"), ImVec2(0, 26))) {
101             if (incMeshEditGetIsApplySafe()) {
102                 incMeshEditApply();
103             } else {
104                 incDialog(
105                     "CONFIRM_VERTEX_APPLY", 
106                     __("Are you sure?"), 
107                     _("The layout of the mesh has changed, all deformations to this mesh will be deleted if you continue."),
108                     DialogLevel.Warning,
109                     DialogButtons.Yes | DialogButtons.No
110                 );
111             }
112         }
113 
114         // In case of a warning popup preventing application.
115         if (incDialogButtonSelected("CONFIRM_VERTEX_APPLY") == DialogButtons.Yes) {
116             incMeshEditApply();
117         }
118         incTooltip(_("Apply"));
119         
120         igSameLine(0, 0);
121 
122         if (igButton(__(" Cancel"), ImVec2(0, 26))) {
123             if (igGetIO().KeyShift) {
124                 incMeshEditReset();
125             } else {
126                 incMeshEditClear();
127             }
128 
129             incSetEditMode(EditMode.ModelEdit);
130             incSelectNode(target);
131             incFocusCamera(target);
132         }
133         incTooltip(_("Cancel"));
134     igPopStyleVar();
135 }
136 
137 void incViewportVertexUpdate(ImGuiIO* io, Camera camera) {
138     editor.update(io, camera);
139 }
140 
141 void incViewportVertexDraw(Camera camera) {
142     // Draw the part that is currently being edited
143     auto target = editor.getTarget();
144     if (target !is null) {
145         if (Part part = cast(Part)target) {
146 
147             // Draw albedo texture at 0, 0
148             inDrawTextureAtPosition(part.textures[0], vec2(0, 0));
149         }
150     }
151 
152     editor.draw(camera);
153 }
154 
155 void incViewportVertexToolbar() { }
156 
157 void incViewportVertexToolSettings() { }
158 
159 void incViewportVertexPresent() {
160     editor = new IncMeshEditor(false);
161 }
162 
163 void incViewportVertexWithdraw() {
164     editor = null;
165 }
166 
167 Drawable incVertexEditGetTarget() {
168     return editor.getTarget();
169 }
170 
171 void incVertexEditStartEditing(Drawable target) {
172     incSetEditMode(EditMode.VertexEdit);
173     incSelectNode(target);
174     incVertexEditSetTarget(target);
175     incFocusCamera(target, vec2(0, 0));
176 }
177 
178 void incVertexEditSetTarget(Drawable target) {
179     editor.setTarget(target);
180 }
181 
182 void incVertexEditCopyMeshDataToTarget(MeshData data) {
183     editor.importMesh(data);
184 }
185 
186 bool incMeshEditGetIsApplySafe() {
187     Drawable target = cast(Drawable)editor.getTarget();
188     return !(
189         editor.mesh.getVertexCount() != target.getMesh().vertices.length &&
190         incActivePuppet().getIsNodeBound(target)
191     );
192 }
193 
194 /**
195     Applies the mesh edits
196 */
197 void incMeshEditApply() {
198     Node target = editor.getTarget();
199     
200     // Automatically apply triangulation
201     if (editor.previewingTriangulation()) {
202         editor.applyPreview();
203         editor.refreshMesh();
204     }
205 
206     if (editor.mesh.getVertexCount() < 3 || editor.mesh.getEdgeCount() < 3) {
207         incDialog(__("Error"), _("Cannot apply invalid mesh\nAt least 3 vertices forming a triangle is needed."));
208         return;
209     }
210 
211     // Apply to target
212     editor.applyToTarget();
213 
214     // Switch mode
215     incSetEditMode(EditMode.ModelEdit);
216     incSelectNode(target);
217     incFocusCamera(target);
218 }
219 
220 /**
221     Resets the mesh edits
222 */
223 void incMeshEditClear() {
224     editor.mesh.clear();
225 }
226 
227 
228 /**
229     Resets the mesh edits
230 */
231 void incMeshEditReset() {
232     editor.mesh.reset();
233 }