浏览代码

Start collecting data for conversion

habeebweeb 4 年之前
父节点
当前提交
ff2067db64
共有 4 个文件被更改,包括 389 次插入12 次删除
  1. 7 0
      Converter/.vscode/settings.json
  2. 2 7
      Converter/.vscode/tasks.json
  3. 4 2
      Converter/Converter.csproj
  4. 376 3
      Converter/Program.cs

+ 7 - 0
Converter/.vscode/settings.json

@@ -0,0 +1,7 @@
+{
+    "[xml]": {
+        "editor.insertSpaces": true,
+        "editor.tabSize": 2,
+        "editor.autoIndent": "advanced"
+    }
+}

+ 2 - 7
Converter/.vscode/tasks.json

@@ -1,6 +1,4 @@
 {
-    // See https://go.microsoft.com/fwlink/?LinkId=733558
-    // for the documentation about the tasks.json format
     "version": "2.0.0",
     "tasks": [
         {
@@ -9,15 +7,12 @@
             "type": "shell",
             "args": [
                 "build",
-                // Ask dotnet build to generate full paths for file names.
                 "/property:GenerateFullPaths=true",
-                // Do not generate summary otherwise it leads to duplicate errors in Problems panel
-                "/consoleloggerparameters:NoSummary",
-                "/property:Configuration=Release"
+                "/consoleloggerparameters:NoSummary"
             ],
             "group": {
                 "kind": "build",
-                "isDefault": true,
+                "isDefault": true
             },
             "presentation": {
                 "reveal": "silent"

+ 4 - 2
Converter/Converter.csproj

@@ -1,8 +1,10 @@
 <Project Sdk="Microsoft.NET.Sdk">
-
   <PropertyGroup>
     <OutputType>Exe</OutputType>
     <TargetFramework>netcoreapp3.1</TargetFramework>
   </PropertyGroup>
-
+  <ItemGroup>
+    <Reference Include="..\lib\Ionic.Zlib.dll"/>
+    <Reference Include="..\lib\ExIni.dll"/>
+  </ItemGroup>
 </Project>

+ 376 - 3
Converter/Program.cs

@@ -1,12 +1,385 @@
 using System;
+using System.IO;
+using System.Collections.Generic;
+using System.Linq;
+using Ionic.Zlib;
+using ExIni;
 
 namespace Converter
 {
-    class Program
+    public class Program
     {
-        static void Main(string[] args)
+        private static StreamWriter writer;
+        public static void Main(string[] args)
         {
-            Console.WriteLine("Hello World!");
+            string writerPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "log.txt");
+            IniFile mmIniFile = IniFile.FromFile(args[0]);
+
+            IniSection sceneSection = mmIniFile.GetSection("scene");
+
+            using (writer = new StreamWriter(writerPath))
+            {
+                if (sceneSection != null)
+                {
+                    foreach (IniKey key in sceneSection.Keys)
+                    {
+                        ProcessScene(key);
+                    }
+                }
+            }
+        }
+
+        public static void ProcessScene(IniKey sceneKey)
+        {
+            if (sceneKey.Key.StartsWith("ss")) return;
+
+            string sceneData = sceneKey.Value;
+
+            if (string.IsNullOrEmpty(sceneData)) return;
+
+            writer.WriteLine($"Deserialize {sceneKey.Key}");
+
+            string[] strArray1 = sceneData.Split('_');
+            string[] strArray2 = strArray1[1].Split(';');
+            string[] strArray3 = strArray1[0].Split(',');
+            string[] strArray4 = null;
+            string[] strArray5 = null;
+            string[] strArray6 = null;
+            string[] strArray7 = null;
+
+            if (strArray1.Length >= 5)
+            {
+                strArray4 = strArray1[2].Split(',');
+                strArray5 = strArray1[3].Split(';');
+                strArray6 = strArray1[4].Split(';');
+            }
+
+            if (strArray1.Length >= 6)
+            {
+                strArray7 = strArray1[5].Split(';');
+            }
+
+            // Environment
+
+            int bgIndex;
+
+            string bgAsset = "Theater";
+
+            if (!int.TryParse(strArray3[2], out bgIndex))
+            {
+                bgAsset = strArray3[2].Replace(" ", "_");
+            }
+            else
+            {
+                writer.WriteLine($"No BG string: {bgIndex}");
+            }
+
+            Quaternion bgRotation = Quaternion.Euler(
+                float.Parse(strArray3[3]), float.Parse(strArray3[4]), float.Parse(strArray3[5])
+            );
+
+            Vector3 bgPosition = new Vector3(
+                float.Parse(strArray3[6]), float.Parse(strArray3[7]), float.Parse(strArray3[8])
+            );
+
+            Vector3 bgLocalScale = new Vector3(
+                float.Parse(strArray3[9]), float.Parse(strArray3[10]), float.Parse(strArray3[11])
+            );
+
+            if (strArray3.Length > 16)
+            {
+                Vector3 cameraTargetPos = new Vector3(
+                    float.Parse(strArray3[27]), float.Parse(strArray3[28]), float.Parse(strArray3[29])
+                );
+
+                float cameraDistance = float.Parse(strArray3[30]);
+
+                Quaternion cameraRotation = Quaternion.Euler(
+                    float.Parse(strArray3[31]), float.Parse(strArray3[32]), float.Parse(strArray3[33])
+                );
+            }
+
+            // Lights
+
+            if (strArray3.Length > 16)
+            {
+                // Main Light
+                /*
+                    0 = Directional
+                    1 = Spot
+                    2 = Point
+                    3 = Directional (Colour Mode)
+                */
+                int lightType = int.Parse(strArray3[17]);
+                Color lightColor = new Color(
+                    float.Parse(strArray3[18]), float.Parse(strArray3[19]), float.Parse(strArray3[20]), 1f
+                );
+
+                Quaternion lightRotation = Quaternion.Euler(
+                    float.Parse(strArray3[21]), float.Parse(strArray3[22]), float.Parse(strArray3[23])
+                );
+
+                // MM uses spotAngle for both range and spotAngle based on which light type is used
+                // TODO: assign value from spot angle appropriately 
+                float intensity = float.Parse(strArray3[24]);
+                float spotAngle = float.Parse(strArray3[25]);
+                float range = float.Parse(strArray3[26]);
+                float shadowStrength = 0.098f;
+                if (strArray4 != null) shadowStrength = float.Parse(strArray4[0]);
+                // lightKage[0] is the only value that's serialized
+            }
+
+            int lights = 1;
+
+            if (strArray5 != null)
+            {
+                int numberOfLights = strArray5.Length - 1;
+                lights += numberOfLights;
+
+                for (int i = 0; i < numberOfLights; i++)
+                {
+                    string[] lightProperties = strArray5[i].Split(',');
+
+                    int lightType = int.Parse(lightProperties[0]);
+
+                    Color lightColor = new Color(
+                        float.Parse(lightProperties[1]), float.Parse(lightProperties[1]),
+                        float.Parse(lightProperties[1]), 1f
+                    );
+
+                    Quaternion lightAngle = Quaternion.Euler(
+                        float.Parse(lightProperties[4]), float.Parse(lightProperties[5]), 18f
+                    );
+
+                    float intensity = float.Parse(lightProperties[6]);
+                    float spotAngle = float.Parse(lightProperties[7]);
+                    float range = spotAngle / 5f;
+                    float shadowStrength = 0.098f;
+                }
+            }
+
+            if (strArray7 != null)
+            {
+                for (int i = 0; i < lights; i++)
+                {
+                    string[] lightPosString = strArray7[i].Split(',');
+                    Vector3 lightPosition = new Vector3(
+                        float.Parse(lightPosString[0]), float.Parse(lightPosString[1]), float.Parse(lightPosString[2])
+                    );
+                }
+            }
+
+            // Message
+
+            if (strArray3.Length > 16)
+            {
+                bool showingMessage = int.Parse(strArray3[34]) == 1;
+                string name = strArray3[35];
+                string message = strArray3[36].Replace("&kaigyo", "\n");
+                // MM does not serialize message font size
+            }
+
+            // effect
+
+            if (strArray4 != null)
+            {
+                // bloom
+                bool bloomActive = int.Parse(strArray4[1]) == 1;
+                float bloomIntensity = float.Parse(strArray4[2]);
+                float bloomBlurIterations = float.Parse(strArray4[3]);
+                Color bloomColour = new Color(
+                    float.Parse(strArray4[4]), float.Parse(strArray4[5]), float.Parse(strArray4[6]), 1f
+                );
+                bool bloomHdr = int.Parse(strArray4[7]) == 1;
+
+                // vignetting
+                bool vignetteActive = int.Parse(strArray4[8]) == 1;
+                float vignetteIntensity = float.Parse(strArray4[9]);
+                float vignetteBlur = float.Parse(strArray4[10]);
+                float vignetteBlurSpread = float.Parse(strArray4[11]);
+                float vignetteChromaticAberration = float.Parse(strArray4[12]);
+
+                // bokashi (TODO: implement in MPS)
+                float bokashi = float.Parse(strArray4[13]);
+
+                if (strArray4.Length > 15)
+                {
+                    bool dofActive = int.Parse(strArray4[15]) == 1;
+                    float dofFocalLength = float.Parse(strArray4[16]);
+                    float dofFocalSize = float.Parse(strArray4[17]);
+                    float dofAperture = float.Parse(strArray4[18]);
+                    float dofMaxBlurSize = float.Parse(strArray4[19]);
+                    bool dofVisualizeFocus = int.Parse(strArray4[20]) == 1;
+
+                    bool fogActive = int.Parse(strArray4[21]) == 1;
+                    float fogStartDistance = float.Parse(strArray4[22]);
+                    float fogDensity = float.Parse(strArray4[23]);
+                    float fogHeightScale = float.Parse(strArray4[24]);
+                    float fogHeight = float.Parse(strArray4[25]);
+                    Color fogColor = new Color(
+                        float.Parse(strArray4[26]), float.Parse(strArray4[27]), float.Parse(strArray4[28]), 1f
+                    );
+                }
+            }
+
+            // prop
+            if (strArray3.Length > 37 && !string.IsNullOrEmpty(strArray3[37]))
+            {
+                // For the prop that spawns when you push (shift +) W
+                string assetName = strArray3[37].Replace(' ', '_');
+                Vector3 position = new Vector3(
+                    float.Parse(strArray3[41]), float.Parse(strArray3[42]), float.Parse(strArray3[43])
+                );
+                Quaternion rotation = Quaternion.Euler(
+                    float.Parse(strArray3[38]), float.Parse(strArray3[39]), float.Parse(strArray3[40])
+                );
+                Vector3 localScale = new Vector3(
+                    float.Parse(strArray3[44]), float.Parse(strArray3[45]), float.Parse(strArray3[46])
+                );
+            }
+
+            if (strArray6 != null)
+            {
+                for (int i = 0; i < strArray6.Length - 1; i++)
+                {
+                    string[] assetParts = strArray6[i].Split(',');
+                    string assetName = assetParts[0].Replace(' ', '_');
+
+                    if (assetName.StartsWith("creative_"))
+                    {
+                        // modifiedMM my room creative prop
+                        // modifiedMM serializes the prefabName rather than the ID.
+                        // TODO: Either write a special case for MPS or rewrite for use in game
+                        assetName.Replace("creative_", String.Empty);
+                        assetName = $"MYR_#{assetName}";
+                    }
+                    // else if (assetName.StartsWith("MYR_"))
+                    // {
+                    //     // MM 23.0+ my room creative prop
+                    //     assetName = assetName + "#";
+                    // }
+                    else if (assetName.Contains('#'))
+                    {
+                        if (assetName.Contains(".menu"))
+                        {
+                            // modifiedMM official mod prop
+                            string[] modComponents = assetParts[0].Split('#');
+                            string baseMenuFile = modComponents[0].Replace(' ', '_');
+                            string modItem = modComponents[1].Replace(' ', '_');
+                            assetName = $"{modComponents[0]}#{modComponents[1]}";
+                        }
+                        else
+                        {
+                            assetName = assetName.Split('#')[1].Replace(' ', '_');
+                        }
+                    }
+
+                    writer.WriteLine(assetName);
+
+                    Vector3 position = new Vector3(
+                        float.Parse(assetParts[4]), float.Parse(assetParts[5]), float.Parse(assetParts[6])
+                    );
+                    Quaternion rotation = Quaternion.Euler(
+                        float.Parse(assetParts[1]), float.Parse(assetParts[2]), float.Parse(assetParts[3])
+                    );
+                    Vector3 scale = new Vector3(
+                        float.Parse(assetParts[7]), float.Parse(assetParts[8]), float.Parse(assetParts[9])
+                    );
+                }
+            }
+
+            // meido
+
+            int numberOfMaids = strArray2.Length;
+
+            for (int i = 0; i < numberOfMaids; i++)
+            {
+                List<Quaternion> fingerRotation = new List<Quaternion>();
+                string[] maidData = strArray2[i].Split(':');
+                for (int j = 0; j < 40; j++)
+                {
+                    string fingerString = maidData[j];
+                    fingerRotation.Add(Quaternion.FromEulerString(fingerString));
+                }
+
+                // TODO: Other maid related things
+            }
+        }
+    }
+
+    public static class BinaryExtensions
+    {
+        public static void WriteVector3(this BinaryWriter binaryWriter, Vector3 vector3)
+        {
+            binaryWriter.Write(vector3.x);
+            binaryWriter.Write(vector3.y);
+            binaryWriter.Write(vector3.z);
+        }
+
+        public static void WriteQuaternion(this BinaryWriter binaryWriter, Quaternion quaternion)
+        {
+            binaryWriter.Write(quaternion.x);
+            binaryWriter.Write(quaternion.y);
+            binaryWriter.Write(quaternion.z);
+            binaryWriter.Write(quaternion.w);
+        }
+    }
+
+    public struct Vector3
+    {
+        public float x, y, z;
+        public Vector3(float x, float y, float z)
+        {
+            this.x = x;
+            this.y = y;
+            this.z = z;
+        }
+        public static Vector3 FromString(string vector3)
+        {
+            string[] data = vector3.Split(',');
+            return new Vector3(
+                float.Parse(data[0]), float.Parse(data[1]), float.Parse(data[2])
+            );
+        }
+    }
+
+    public struct Quaternion
+    {
+        public const float DegToRad = MathF.PI / 180f;
+        public float x, y, z, w;
+
+        public Quaternion(float x, float y, float z, float w)
+        {
+            this.x = x;
+            this.y = y;
+            this.z = z;
+            this.w = w;
+        }
+
+        public static Quaternion Euler(float x, float y, float z)
+        {
+            System.Numerics.Quaternion q = System.Numerics.Quaternion.CreateFromYawPitchRoll(
+                y * DegToRad, x * DegToRad, z * DegToRad
+            );
+            return new Quaternion(q.X, q.Y, q.Z, q.W);
+        }
+
+        public static Quaternion FromEulerString(string euler)
+        {
+            Vector3 components = Vector3.FromString(euler);
+            return Euler(components.x, components.y, components.z);
+        }
+    }
+
+    public struct Color
+    {
+        public float r, g, b, a;
+        public Color(float r, float g, float b, float a)
+        {
+            this.r = r;
+            this.g = g;
+            this.b = b;
+            this.a = a;
         }
     }
 }