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 }