Browse Source

Clean up menu file utilities

habeebweeb 4 years ago
parent
commit
55e44fda28

+ 6 - 9
COM3D2.MeidoPhotoStudio.Plugin/MeidoPhotoStudio/Managers/PropManager.cs

@@ -54,14 +54,11 @@ namespace COM3D2.MeidoPhotoStudio.Plugin
         public int CurrentDoguIndex { get; private set; }
         public DragPointDogu CurrentDogu => DoguCount == 0 ? null : doguList[CurrentDoguIndex];
 
-        static PropManager()
-        {
-            modItemsOnly = Configuration.Config.Bind(
-                "Prop", "ModItemsOnly",
-                false,
-                "Disable waiting for and loading base game clothing"
-            );
-        }
+        static PropManager() => modItemsOnly = Configuration.Config.Bind(
+            "Prop", "ModItemsOnly",
+            false,
+            "Disable waiting for and loading base game clothing"
+        );
 
         public PropManager(MeidoManager meidoManager)
         {
@@ -191,7 +188,7 @@ namespace COM3D2.MeidoPhotoStudio.Plugin
         {
             GameObject dogu = LoadModel(modItem);
             string name = modItem.MenuFile;
-            if (modItem.IsOfficialMod) name = Path.GetFileName(name);
+            if (modItem.IsOfficialMod) name = Path.GetFileName(name) + ".menu"; // Add '.menu' for partsedit support
             if (dogu != null) AttachDragPoint(dogu, modItem.ToString(), name, new Vector3(0f, 0f, 0.5f));
             return dogu != null;
         }

File diff suppressed because it is too large
+ 308 - 542
COM3D2.MeidoPhotoStudio.Plugin/MeidoPhotoStudio/MenuFileUtility.cs


+ 201 - 0
COM3D2.MeidoPhotoStudio.Plugin/MeidoPhotoStudio/ModelUtility.cs

@@ -0,0 +1,201 @@
+using System.IO;
+using System.Text;
+using System.Collections.Generic;
+using UnityEngine;
+using UnityEngine.Rendering;
+using System;
+using System.Linq;
+using Object = UnityEngine.Object;
+
+namespace COM3D2.MeidoPhotoStudio.Plugin
+{
+    public static partial class MenuFileUtility
+    {
+        private static GameObject CreateSeed() => Object.Instantiate(Resources.Load<GameObject>("seed"));
+
+        private static bool InstantiateModel(string modelFilename, out GameObject modelParent)
+        {
+            byte[] buffer;
+
+            modelParent = default;
+
+            try { buffer = ReadAFileBase(modelFilename); }
+            catch
+            {
+                Utility.LogError($"Could not load model file '{modelFilename}'");
+                return false;
+            }
+            
+            using var binaryReader = new BinaryReader(new MemoryStream(buffer), Encoding.UTF8);
+
+            if (binaryReader.ReadString() != "CM3D2_MESH")
+            {
+                Utility.LogError($"{modelFilename} is not a model file");
+                return false;
+            }
+
+            var modelVersion = binaryReader.ReadInt32();
+            var modelName = binaryReader.ReadString();
+            
+            modelParent = CreateSeed();
+            modelParent.layer = 1;
+            modelParent.name = "_SM_" + modelName;
+            
+            var rootName = binaryReader.ReadString();
+            var boneCount = binaryReader.ReadInt32();
+
+            var boneDict = new Dictionary<string, GameObject>();
+            var boneList = new List<GameObject>(boneCount);
+
+            GameObject rootBone = null;
+
+            try
+            {
+                // read bone data
+                for (var i = 0; i < boneCount; i++)
+                {
+                    GameObject bone = CreateSeed();
+                    bone.layer = 1;
+                    bone.name = binaryReader.ReadString();
+
+                    if (binaryReader.ReadByte() != 0)
+                    {
+                        GameObject otherBone = CreateSeed();
+                        otherBone.name = bone.name + "_SCL_";
+                        otherBone.transform.parent = bone.transform;
+                        boneDict[bone.name + "$_SCL_"] = otherBone;
+                    }
+
+                    boneList.Add(bone);
+                    boneDict[bone.name] = bone;
+
+                    if (bone.name == rootName) rootBone = bone;
+                }
+
+                for (var i = 0; i < boneCount; i++)
+                {
+                    var parentIndex = binaryReader.ReadInt32();
+                    boneList[i].transform.parent = parentIndex >= 0 
+                        ? boneList[parentIndex].transform 
+                        : modelParent.transform;
+                }
+
+                for (var i = 0; i < boneCount; i++)
+                {
+                    Transform transform = boneList[i].transform;
+                    transform.localPosition = binaryReader.ReadVector3();
+                    transform.localRotation = binaryReader.ReadQuaternion();
+                    if (modelVersion >= 2001 && binaryReader.ReadBoolean())
+                        transform.localScale = binaryReader.ReadVector3();
+                }
+                
+                // read mesh data
+                var meshRenderer = rootBone.AddComponent<SkinnedMeshRenderer>();
+                meshRenderer.updateWhenOffscreen = true;
+                meshRenderer.skinnedMotionVectors = false;
+                meshRenderer.lightProbeUsage = LightProbeUsage.Off;
+                meshRenderer.reflectionProbeUsage = ReflectionProbeUsage.Off;
+                meshRenderer.motionVectorGenerationMode = MotionVectorGenerationMode.ForceNoMotion;
+                
+                Mesh sharedMesh = meshRenderer.sharedMesh = new Mesh();
+                
+                var vertCount = binaryReader.ReadInt32();
+                var subMeshCount = binaryReader.ReadInt32();
+                var meshBoneCount = binaryReader.ReadInt32();
+
+                var meshBones = new Transform[meshBoneCount];
+                for (var i = 0; i < meshBoneCount; i++)
+                {
+                    var boneName = binaryReader.ReadString();
+                    
+                    if (!boneDict.ContainsKey(boneName)) Debug.LogError("nullbone= " + boneName);
+                    else
+                    {
+                        var keyName = boneName + "$_SCL_";
+                        GameObject bone = boneDict.ContainsKey(keyName) ? boneDict[keyName] : boneDict[boneName];
+                        meshBones[i] = bone.transform;
+                    }
+                }
+
+                meshRenderer.bones = meshBones;
+
+                var bindPoses = new Matrix4x4[meshBoneCount];
+                for (var i = 0; i < meshBoneCount; i++) bindPoses[i] = binaryReader.ReadMatrix4x4();
+                
+                sharedMesh.bindposes = bindPoses;
+
+                var vertices = new Vector3[vertCount];
+                var normals = new Vector3[vertCount];
+                var uv = new Vector2[vertCount];
+
+                for (var i = 0; i < vertCount; i++)
+                {
+                    vertices[i] = binaryReader.ReadVector3();
+                    normals[i] = binaryReader.ReadVector3();
+                    uv[i] = binaryReader.ReadVector2();
+                }
+
+                sharedMesh.vertices = vertices;
+                sharedMesh.normals = normals;
+                sharedMesh.uv = uv;
+
+                var tangentCount = binaryReader.ReadInt32();
+                if (tangentCount > 0)
+                {
+                    var tangents = new Vector4[tangentCount];
+                    for (var i = 0; i < tangentCount; i++) tangents[i] = binaryReader.ReadVector4();
+                    sharedMesh.tangents = tangents;
+                }
+
+                var boneWeights = new BoneWeight[vertCount];
+                for (var i = 0; i < vertCount; i++)
+                {
+                    boneWeights[i].boneIndex0 = binaryReader.ReadUInt16();
+                    boneWeights[i].boneIndex1 = binaryReader.ReadUInt16();
+                    boneWeights[i].boneIndex2 = binaryReader.ReadUInt16();
+                    boneWeights[i].boneIndex3 = binaryReader.ReadUInt16();
+                    boneWeights[i].weight0 = binaryReader.ReadSingle();
+                    boneWeights[i].weight1 = binaryReader.ReadSingle();
+                    boneWeights[i].weight2 = binaryReader.ReadSingle();
+                    boneWeights[i].weight3 = binaryReader.ReadSingle();
+                }
+
+                sharedMesh.boneWeights = boneWeights;
+                sharedMesh.subMeshCount = subMeshCount;
+
+                for (var i = 0; i < subMeshCount; i++)
+                {
+                    var pointCount = binaryReader.ReadInt32();
+                    var triangles = new int[pointCount];
+                    for (var j = 0; j < pointCount; j++) triangles[j] = binaryReader.ReadUInt16();
+                    sharedMesh.SetTriangles(triangles, i);
+                }
+
+                // read materials
+                var materialCount = binaryReader.ReadInt32();
+
+                var materials = new Material[materialCount];
+
+                for (var i = 0; i < materialCount; i++) materials[i] = ImportCM.ReadMaterial(binaryReader);
+
+                meshRenderer.materials = materials;
+
+                modelParent.AddComponent<Animation>();
+
+                return true;
+            }
+            catch (Exception e)
+            {
+                Utility.LogError($"Could not load mesh for '{modelFilename}' because {e.Message}\n{e.StackTrace}");
+
+                foreach (GameObject bone in boneList.Where(bone => bone)) Object.Destroy(bone);
+
+                if (modelParent) Object.Destroy(modelParent);
+
+                modelParent = null;
+
+                return false;
+            }
+        }
+    }
+}

+ 20 - 0
COM3D2.MeidoPhotoStudio.Plugin/MeidoPhotoStudio/Utility.cs

@@ -252,6 +252,11 @@ namespace COM3D2.MeidoPhotoStudio.Plugin
             binaryWriter.Write(vector3.z);
         }
 
+        public static Vector2 ReadVector2(this BinaryReader binaryReader)
+        {
+            return new Vector2(binaryReader.ReadSingle(), binaryReader.ReadSingle());
+        }
+
         public static Vector3 ReadVector3(this BinaryReader binaryReader)
         {
             return new Vector3(
@@ -259,6 +264,14 @@ namespace COM3D2.MeidoPhotoStudio.Plugin
             );
         }
 
+        public static Vector4 ReadVector4(this BinaryReader binaryReader)
+        {
+            return new Vector4(
+                binaryReader.ReadSingle(), binaryReader.ReadSingle(),
+                binaryReader.ReadSingle(), binaryReader.ReadSingle()
+            );
+        }
+
         public static void WriteQuaternion(this BinaryWriter binaryWriter, Quaternion quaternion)
         {
             binaryWriter.Write(quaternion.x);
@@ -292,5 +305,12 @@ namespace COM3D2.MeidoPhotoStudio.Plugin
                 binaryReader.ReadSingle(), binaryReader.ReadSingle()
             );
         }
+
+        public static Matrix4x4 ReadMatrix4x4(this BinaryReader binaryReader)
+        {
+            Matrix4x4 matrix = default;
+            for (var i = 0; i < 16; i++) matrix[i] = binaryReader.ReadSingle();
+            return matrix;
+        }
     }
 }