Przeglądaj źródła

Start converter rewrite

habeebweeb 3 lat temu
rodzic
commit
ca7fd8d6ac

+ 7 - 0
src/MeidoPhotoStudio.Converter/Converters/IConverter.cs

@@ -0,0 +1,7 @@
+namespace MeidoPhotoStudio.Converter.Converters
+{
+    public interface IConverter
+    {
+        void Convert();
+    }
+}

+ 71 - 0
src/MeidoPhotoStudio.Converter/Converters/MMConverter.cs

@@ -0,0 +1,71 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using ExIni;
+using MeidoPhotoStudio.Converter.MultipleMaids;
+
+namespace MeidoPhotoStudio.Converter.Converters
+{
+    public class MMConverter : IConverter
+    {
+        private readonly string workingDirectory;
+
+        public MMConverter(string directory) => workingDirectory = directory;
+
+        public void Convert()
+        {
+            if (!Directory.Exists(workingDirectory))
+                Directory.CreateDirectory(workingDirectory);
+
+            foreach (var section in GetSceneSections(workingDirectory))
+            {
+                foreach (var key in section.Keys.Where(
+                    key => !key.Key.StartsWith("ss") && !string.IsNullOrEmpty(key.Value)
+                ))
+                {
+                    var data = key.Value;
+                    var screenshotKey = $"s{key.Key}";
+                    string? screenshotBase64 = null;
+
+                    if (section.HasKey(screenshotKey) && !string.IsNullOrEmpty(section[screenshotKey].Value))
+                        screenshotBase64 = section[screenshotKey].Value;
+
+                    var convertedData = MMSceneConverter.Convert(data);
+                    
+                }
+            }
+        }
+
+        private static void Convert(MMScene scene) { }
+
+        private static IEnumerable<IniSection> GetSceneSections(string directory) =>
+            Directory.GetFiles(directory, "*.ini", SearchOption.AllDirectories)
+                .Select(GetSceneSection)
+                .Where(section => section is not null)
+                .Select(section => section!);
+
+        private static IniSection? GetSceneSection(string filePath)
+        {
+            IniFile iniFile;
+
+            try
+            {
+                iniFile = IniFile.FromFile(filePath);
+            }
+            catch (Exception e)
+            {
+                Console.WriteLine($"Could not {(e is IOException ? "read" : "parse")} ini file {filePath}");
+                return null;
+            }
+
+            if (!iniFile.HasSection("scene"))
+            {
+                Console.WriteLine($"{filePath} is not a valid MM config because '[scene]' section is missing");
+                return null;
+            }
+
+            return iniFile.GetSection("scene");
+        }
+    }
+}

+ 31 - 0
src/MeidoPhotoStudio.Converter/MPSSceneSerializer.cs

@@ -0,0 +1,31 @@
+using System;
+using System.IO;
+using System.Text;
+using MeidoPhotoStudio.Plugin;
+
+namespace MeidoPhotoStudio.Converter
+{
+    internal class MPSSceneSerializer
+    {
+        private const string NoThumbBase64 =
+            "iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAIAAACRXR/mAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7D"
+            + "AcdvqGQAAAFOSURBVFhH3dJbjoMwEETRLIRP9r+zrCGpqJABY+x+2Ua5ys9EcteJNK/3sj7ws7E+j2ln8Q9+O7eE2Vjpq4kdJTsLTZRl"
+            + "jBMLTZFdDTkLDZYVAQUWGia7Wy+z0ABZZfqWhbrK6rs1Fuoka442WChcJllss1CgTDgnYqEQmXxLykJOmWpIwUJmmXZFx0IGmWFCzUKq"
+            + "J7b7FhYSvjIfN7JQ86Hnsp2FKm+dZ10sVHzuv+lloexCyMEAFkpHoq7FsBDuBJ76a1Y6EnXtT//li8/9N12sylvnWTur+dBz2cgSvjIf"
+            + "t7BUT2z31azePwOpWQYT064oWGYTUw1JWU4Tk2+JWCEmJpxrswJNTLLYYIWbWHO0xupkYvXdW1ZXE6tMl1kDTOxuvcAaZmJFQM4abGJX"
+            + "w4k1xcQyxs6aaGJHycaabmIJ82M9xMTo2VjP+izrF8NPHwq3SYqeAAAAAElFTkSuQmCC";
+
+        private static byte[]? noThumb;
+        public static byte[] NoThumb => noThumb ??= Convert.FromBase64String(NoThumbBase64);
+
+        public void SaveToFile(string filename, byte[] rawSceneData, string? thumbnail)
+        {
+            using var fileStream = File.Create(filename);
+
+            var rawThumbnail = thumbnail is null ? NoThumb : Convert.FromBase64String(thumbnail);
+
+            fileStream.Write(rawThumbnail, 0, rawThumbnail.Length);
+            fileStream.Write(rawSceneData, 0, rawSceneData.Length);
+        }
+    }
+}

+ 2 - 0
src/MeidoPhotoStudio.Converter/MeidoPhotoStudio.Converter.csproj

@@ -3,6 +3,8 @@
     <TargetFramework>net35</TargetFramework>
     <FrameworkPathOverride Condition="'$(TargetFramework)' == 'net35'">$(MSBuildProgramFiles32)\Reference Assemblies\Microsoft\Framework\.NETFramework\v3.5\Profile\Client</FrameworkPathOverride>
     <ProjectGuid>{19D28B0C-3537-4FEE-B7B3-1ABF70B16D5E}</ProjectGuid>
+    <LangVersion>9</LangVersion>
+    <Nullable>enable</Nullable>
   </PropertyGroup>
   <ItemGroup>
     <Reference Include="..\..\lib\Assembly-CSharp.dll" />

+ 20 - 0
src/MeidoPhotoStudio.Converter/MultipleMaids/ConversionUtility.cs

@@ -0,0 +1,20 @@
+using UnityEngine;
+
+namespace MeidoPhotoStudio.Converter.MultipleMaids
+{
+    internal static class ConversionUtility
+    {
+        public static Quaternion ParseEulerAngle(string euler)
+        {
+            var data = euler.Split(',');
+
+            return Quaternion.Euler(float.Parse(data[0]), float.Parse(data[1]), float.Parse(data[2]));
+        }
+
+        public static Vector3 ParseVector3(string vector3)
+        {
+            var data = vector3.Split(',');
+            return new(float.Parse(data[0]), float.Parse(data[1]), float.Parse(data[2]));
+        }
+    }
+}

+ 37 - 0
src/MeidoPhotoStudio.Converter/MultipleMaids/MMConstants.cs

@@ -0,0 +1,37 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using MyRoomCustom;
+
+namespace MeidoPhotoStudio.Converter.MultipleMaids
+{
+    public static class MMConstants
+    {
+        public static readonly string[] FaceKeys =
+        {
+            "eyeclose", "eyeclose2", "eyeclose3", "eyeclose6", "hitomih", "hitomis", "mayuha",
+            "mayuup", "mayuv", "mayuvhalf", "moutha", "mouths", "mouthdw", "mouthup", "tangout",
+            "tangup", "eyebig", "eyeclose5", "mayuw", "mouthhe", "mouthc", "mouthi", "mouthuphalf",
+            "tangopen",
+            "namida", "tear1", "tear2", "tear3", "shock", "yodare", "hoho", "hoho2", "hohos", "hohol",
+            "toothoff", "nosefook",
+        };
+
+        public static readonly string[] MpnAttachProps =
+        {
+            /* "", "", "", "", "", "", "", "", "", */
+            "kousokuu_tekaseone_i_.menu", "kousokuu_tekasetwo_i_.menu", "kousokul_ashikaseup_i_.menu",
+            "kousokuu_tekasetwo_i_.menu", "kousokul_ashikasedown_i_.menu", "kousokuu_tekasetwodown_i_.menu",
+            "kousokuu_ushirode_i_.menu", "kousokuu_smroom_haritsuke_i_.menu",
+        };
+
+        private static Dictionary<string, PlacementData.Data>? myrAssetNameToData;
+        public static Dictionary<string, PlacementData.Data> MyrAssetNameToData =>
+            myrAssetNameToData ??= PlacementData.GetAllDatas(false)
+                .ToDictionary(
+                    data => string.IsNullOrEmpty(data.assetName) ? data.resourceName : data.assetName,
+                    data => data,
+                    StringComparer.InvariantCultureIgnoreCase
+                );
+    }
+}

+ 14 - 0
src/MeidoPhotoStudio.Converter/MultipleMaids/MMScene.cs

@@ -0,0 +1,14 @@
+namespace MeidoPhotoStudio.Converter.MultipleMaids
+{
+    public class MMScene
+    {
+        public readonly string Data;
+        public readonly string? ScreenshotBase64;
+
+        public MMScene(string data, string? screenshotBase64)
+        {
+            Data = data;
+            ScreenshotBase64 = screenshotBase64;
+        }
+    }
+}

+ 158 - 0
src/MeidoPhotoStudio.Converter/MultipleMaids/MMSceneConverter.cs

@@ -0,0 +1,158 @@
+using System.IO;
+using System.Text;
+using MeidoPhotoStudio.Plugin;
+using UnityEngine;
+
+namespace MeidoPhotoStudio.Converter.MultipleMaids
+{
+    public static class MMSceneConverter
+    {
+        private static readonly int[] bodyRotations =
+        {
+            71, 44, 40, 41, 42, 43, 57, 68, 69, 46, 49, 47, 50, 52, 55, 53, 56, 92, 94, 93, 95, 45, 48, 51, 54,
+        };
+        private static SimpleSerializer<PoseInfo> PoseInfoSerializer => Serialization.GetSimple<PoseInfo>();
+        private static SimpleSerializer<TransformDTO> TransformDtoSerializer => Serialization.GetSimple<TransformDTO>();
+
+        public static byte[] Convert(string data, bool environment = false)
+        {
+            var dataSegments = data.Split('_');
+
+            using var memoryStream = new MemoryStream();
+            using var dataWriter = new BinaryWriter(memoryStream, Encoding.UTF8);
+
+            if (!environment)
+            {
+                ConvertMeido(dataSegments, dataWriter);
+                ConvertMessage(dataSegments, dataWriter);
+                ConvertCamera(dataSegments, dataWriter);
+            }
+
+            ConvertLight(dataSegments, dataWriter);
+            ConvertEffect(dataSegments, dataWriter);
+            ConvertEnvironment(dataSegments, dataWriter);
+            ConvertProps(dataSegments, dataWriter);
+
+            dataWriter.Write("END");
+
+            return memoryStream.ToArray();
+        }
+
+        private static void ConvertMeido(string[] data, BinaryWriter writer)
+        {
+            var strArray2 = data[1].Split(';');
+
+            writer.Write(MeidoManager.header);
+            writer.WriteVersion(1);
+
+            var meidoCount = strArray2.Length;
+
+            writer.Write(meidoCount);
+
+            var gravityEnabled = false;
+
+            var transformSerializer = TransformDtoSerializer;
+
+            foreach (var rawData in strArray2)
+            {
+                using var memoryStream = new MemoryStream();
+                using var tempWriter = new BinaryWriter(memoryStream, Encoding.UTF8);
+
+                var maidData = rawData.Split(':');
+
+                tempWriter.WriteVersion(1);
+
+                transformSerializer.Serialize(
+                    new()
+                    {
+                        Position = ConversionUtility.ParseVector3(maidData[59]),
+                        Rotation = ConversionUtility.ParseEulerAngle(maidData[58]),
+                        LocalScale = ConversionUtility.ParseVector3(maidData[60]),
+                    }, writer
+                );
+
+                ConvertHead(maidData, tempWriter);
+                ConvertBody(maidData, tempWriter);
+                ConvertClothing(maidData, tempWriter);
+            
+                writer.Write(memoryStream.Length);
+                writer.Write(memoryStream.ToArray());
+            }
+
+            static void ConvertHead(string[] maidData, BinaryWriter writer)
+            {
+                writer.WriteVersion(1);
+
+                // eye direction
+                writer.Write(Quaternion.identity);
+                writer.Write(Quaternion.identity);
+
+                // free look
+                if (maidData.Length == 64)
+                {
+                    writer.Write(false);
+                    writer.Write(new Vector3(0f, 1f, 0f));
+                }
+                else
+                {
+                    var freeLookData = maidData[64].Split(',');
+                    var isFreeLook = int.Parse(freeLookData[0]) == 1;
+
+                    writer.Write(isFreeLook);
+
+                    var offsetTarget = isFreeLook
+                        ? new(float.Parse(freeLookData[2]), 1f, float.Parse(freeLookData[1]))
+                        : new Vector3(0f, 1f, 0f);
+
+                    writer.Write(offsetTarget);
+                }
+
+                // HeadEulerAngle is unknown and also ignored for converted scenes
+                writer.Write(Vector3.zero);
+
+                // head/eye to camera (Not changed by MM so always true)
+                writer.Write(true);
+                writer.Write(true);
+
+                // face
+                var faceValues = maidData[63].Split(',');
+                writer.Write(faceValues.Length);
+
+                for (var i = 0; i < MMConstants.FaceKeys.Length - 1; i++)
+                {
+                    writer.Write(MMConstants.FaceKeys[i]);
+                    writer.Write(float.Parse(faceValues[i]));
+                }
+
+                // nosefook
+                if (faceValues.Length > 35)
+                    writer.Write(float.Parse(faceValues[35]));
+            }
+
+            static void ConvertBody(string[] maidData, BinaryWriter writer)
+            {
+                writer.WriteVersion(1);
+
+                for (var i = 0; i < 40; i++)
+                    writer.Write(ConversionUtility.ParseEulerAngle(maidData[i]));
+            }
+
+            static void ConvertClothing(string[] maidData, BinaryWriter writer)
+            {
+                writer.WriteVersion(1);
+            }
+        }
+
+        private static void ConvertMessage(string[] data, BinaryWriter writer) { }
+
+        private static void ConvertCamera(string[] data, BinaryWriter writer) { }
+
+        private static void ConvertLight(string[] data, BinaryWriter writer) { }
+
+        private static void ConvertEffect(string[] data, BinaryWriter writer) { }
+
+        private static void ConvertEnvironment(string[] data, BinaryWriter writer) { }
+
+        private static void ConvertProps(string[] data, BinaryWriter writer) { }
+    }
+}

+ 40 - 0
src/MeidoPhotoStudio.Converter/Plugin.cs

@@ -0,0 +1,40 @@
+using System.IO;
+using BepInEx;
+using BepInEx.Logging;
+using UnityEngine;
+using UnityEngine.SceneManagement;
+
+namespace MeidoPhotoStudio.Converter
+{
+    [BepInPlugin(PluginGuid, PluginName, PluginVersion)]
+    public class Plugin : BaseUnityPlugin
+    {
+        private const string PluginGuid = "com.habeebweeb.com3d2.meidophotostudio.converter";
+        public const string PluginName = "MeidoPhotoStudio Converter";
+        public const string PluginVersion = "0.0.0";
+
+        private readonly PluginCore pluginCore;
+        private readonly UI ui;
+
+        public static Plugin? Instance { get; private set; }
+        public new ManualLogSource Logger { get; private set; }
+
+        public Plugin()
+        {
+            pluginCore = new(); // Path.Combine(Paths.ConfigPath, PluginName)
+            ui = new();
+        }
+
+        private void Awake()
+        {
+            DontDestroyOnLoad(this);
+
+            Instance = this;
+            Logger = base.Logger;
+
+            SceneManager.sceneLoaded += (scene, _) => ui.Visible = scene.buildIndex is 3 or 9;
+        }
+
+        private void OnGUI() => ui.Draw();
+    }
+}

+ 21 - 0
src/MeidoPhotoStudio.Converter/PluginCore.cs

@@ -0,0 +1,21 @@
+namespace MeidoPhotoStudio.Converter
+{
+    public class PluginCore
+    {
+        // private readonly string workingDirectory;
+        // public Core(string directory)
+        // {
+        //     workingDirectory = directory;
+        // }
+        //
+        // public void ProcessMMConfigurations()
+        // {
+        //     if (!Directory.Exists(workingDirectory))
+        //         Directory.CreateDirectory(workingDirectory);
+        //
+        //     var mmScenes = GetMMScenes(workingDirectory);
+        //
+        //     foreach (var scene in mmScenes) { }
+        // }
+    }
+}

Plik diff jest za duży
+ 773 - 792
src/MeidoPhotoStudio.Converter/Program.cs


+ 19 - 0
src/MeidoPhotoStudio.Converter/UI.cs

@@ -0,0 +1,19 @@
+namespace MeidoPhotoStudio.Converter
+{
+    public class UI
+    {
+        public bool Visible;
+        
+        public void Draw()
+        {
+            if (!Visible) return;
+            
+            
+        }
+
+        private void GUIFunc(int windowId)
+        {
+            
+        }
+    }
+}