diff --git a/source/creator/medit/mesh.d b/source/creator/medit/mesh.d new file mode 100644 index 000000000..00ef6776f --- /dev/null +++ b/source/creator/medit/mesh.d @@ -0,0 +1,110 @@ +module creator.medit.mesh; +import inochi2d; +import inochi2d.core.dbg; +import bindbc.opengl; + +struct MeshVertex { + vec2 position; + MeshVertex*[] connections; + + bool isConnectedTo(MeshVertex* other) { + if (other == null) return false; + + foreach(conn; other.connections) { + if (*conn == this) return true; + } + return false; + } + + void connect(MeshVertex* other) { + this.connections ~= other; + other.connections ~= &this; + } +} + +class IncMesh { +private: + MeshData* data; + MeshVertex*[] vertices; + bool changed; + + vec3[] pData; + vec3[] pDataSel; // TODO: selection + void pRegen() { + pData = new vec3[vertices.length]; + foreach(i, point; vertices) { + pData[i] = vec3(point.position, 0); + } + inDbgSetBuffer(pData); + } + + vec3[] lData; + ushort[] lIndices; + void lRegen() { + + } + + void mImport(ref MeshData data) { + // Reset vertex length + vertices.length = 0; + + // Iterate over flat mesh and extract it in to + // vertices and "connections" + MeshVertex*[ushort] iVertices; + foreach(i; 0..data.indices.length/3) { + auto index = data.indices[i*3]; + auto nindex = data.indices[(i*3)+1]; + auto nnindex = data.indices[(i*3)+2]; + if (nnindex !in iVertices) iVertices[nnindex] = new MeshVertex(data.vertices[nnindex], []); + if (nindex !in iVertices) iVertices[nindex] = new MeshVertex(data.vertices[nindex], []); + if (index !in iVertices) iVertices[index] = new MeshVertex(data.vertices[index], []); + + if (!iVertices[index].isConnectedTo(iVertices[nindex])) iVertices[index].connect(iVertices[nindex]); + if (!iVertices[nindex].isConnectedTo(iVertices[nnindex])) iVertices[nindex].connect(iVertices[nnindex]); + if (!iVertices[index].isConnectedTo(iVertices[nnindex])) iVertices[index].connect(iVertices[nnindex]); + } + + foreach(vertex; iVertices) { + vertices ~= vertex; + } + + pRegen(); + lRegen(); + } + + MeshData mExport() { + + return *data; + } + +public: + + /** + Constructs a new IncMesh + */ + this(ref MeshData mesh) { + data = &mesh; + mImport(mesh); + } + + /** + Exports the working mesh to a MeshData object. + */ + MeshData export_() { + return mExport(); + } + + /** + Resets mesh to prior state + */ + void reset() { + mImport(*data); + } + + /** + Removes all vertices from the mesh + */ + void clear() { + vertices.length = 0; + } +} \ No newline at end of file diff --git a/source/creator/medit/package.d b/source/creator/medit/package.d new file mode 100644 index 000000000..0fb3871f0 --- /dev/null +++ b/source/creator/medit/package.d @@ -0,0 +1,75 @@ +module creator.medit; +import creator.core; +import inochi2d; +import std.exception; +import bindbc.opengl; +public import creator.medit.mesh; + +private { + Drawable target; + MeshData editingData; + bool hasEdited; + + GLuint vboPoints; + GLuint vboSegments; + + IncMesh editingMesh; +} + +void incMeshEditSetTarget(Drawable target_) { + target = target_; + editingMesh = new IncMesh(target_.getMesh()); +} + +void incMeshEditReset() { + editingData = target.getMesh.copy(); +} + +/** + Maps UV coordinates from world-space to texture space +*/ +void incMeshEditMapUV(ref vec2 uv) { + uv -= vec2(incMeshEditWorldPos()); + if (Part part = cast(Part)target) { + + // Texture 0 is always albedo texture + auto tex = part.textures[0]; + + // By dividing by width and height we should get the values in UV coordinate space. + uv.x /= cast(float)tex.width; + uv.y /= cast(float)tex.height; + } +} + +void incMeshEditBarrier() { + //if () +} + +void incMeshEditDbg() { + editingData.dbg(); +} + +bool incMeshEditCanTriangulate() { + return false; +} + +bool incMeshEditCanApply() { + return editingData.isReady(); +} + +void incMeshEditApply() { + enforce(editingData.isReady(), "Mesh is incomplete and cannot be applied."); + hasEdited = false; + + // Fix winding order + editingData.fixWinding(); + target.getMesh() = editingData; +} + +bool incMeshEditIsEdited() { + return hasEdited; +} + +vec3 incMeshEditWorldPos() { + return vec3(target.transform.matrix() * vec4(1, 1, 1, 1)); +} \ No newline at end of file diff --git a/source/creator/ver.d b/source/creator/ver.d index 2c2a96e00..2cb7dde40 100644 --- a/source/creator/ver.d +++ b/source/creator/ver.d @@ -4,6 +4,6 @@ module creator.ver; /** Inochi Creator Version, autogenerated with gitver */ -enum INC_VERSION = "v0.5.6-beta.1-6-gad82e22"; +enum INC_VERSION = "v0.6.0"; // trans rights \ No newline at end of file diff --git a/source/creator/widgets/titlebar.d b/source/creator/widgets/titlebar.d index 7adfb000e..4a617fe9b 100644 --- a/source/creator/widgets/titlebar.d +++ b/source/creator/widgets/titlebar.d @@ -85,7 +85,7 @@ void incTitlebar(string title) { ImGuiWindowFlags.NoScrollbar | ImGuiWindowFlags.MenuBar; - SDL_Window* window = cast(SDL_Window*)igGetWindowViewport().PlatformHandle; + SDL_Window* window = incGetWindowPtr(); if (incGetDarkMode()) igPushStyleColor(ImGuiCol.MenuBarBg, ImVec4(0.1, 0.1, 0.1, 1)); else igPushStyleColor(ImGuiCol.MenuBarBg, ImVec4(0.9, 0.9, 0.9, 1));