using UnityEngine; using System; using System.Linq; using System.Collections.Generic; using System.Text; using System.IO; using Util; namespace CM3D2.MultipleMaids.Plugin { public partial class MultipleMaids { private static readonly byte[] pngEnd = Encoding.ASCII.GetBytes("IEND"); private static string sceneData; private const string baseDirectoryName = "< Base Directory >"; private string saveScenePath = Path.Combine(Path.GetFullPath(".\\"), "Mod\\MultipleMaidsSave"); private List saveScenes = new List(50); private GUIStyle selectedButtonStyle; private string[] directoryList; private Texture2D frame; private Rect saveManagerRect; private Rect saveModalRect; private Rect resizeManagerRect; private Vector2 saveManagerScrollPos = Vector2.zero; private Vector2 dirListScrollPos = Vector2.zero; private bool saveManagerInitialize = false; private bool loadSaveFlag = false; private bool overwriteFlag = false; private bool createSaveFlag = false; private bool manageSaveFlag = false; private bool createDirectory = false; private bool deleteDirectoryFlag = false; private bool deleteFileFlag = false; private bool resizeManager = false; private int selectedSave = 0; private int selectedDirectory = 0; private string currentDirectory = ""; private string textFieldValue = ""; public void InitializeSaveManager() { frame = MakeTex(2, 2, Color.white); if (!Directory.Exists(saveScenePath)) { Directory.CreateDirectory(saveScenePath); } selectedButtonStyle = new GUIStyle("button"); selectedButtonStyle.normal.background = MakeTex(1, 1, new Color(0.5f, 0.5f, 0.5f, 0.4f)); selectedButtonStyle.normal.textColor = Color.white; GetSaveDirectories(); InitializeSaveList(); saveManagerInitialize = true; } private void RefreshSaveManager() { SwitchDirectory(currentDirectory); GetSaveDirectories(); InitializeSaveList(); } private void InitializeSaveList() { saveScenes.Clear(); string workingPath = Path.Combine(saveScenePath, currentDirectory); DirectoryInfo info = new DirectoryInfo(workingPath); foreach (var save in info.GetFiles("*.png")) { Texture2D screenshot = new Texture2D(1, 1, TextureFormat.ARGB32, false); screenshot.LoadImage(File.ReadAllBytes(save.FullName)); saveScenes.Add(new SavePng(save, screenshot)); } selectedSave = saveScenes.Count == 0 ? 0 : saveScenes.Count - 1; saveScenes.Sort((a, b) => a.info.LastWriteTime.CompareTo(b.info.LastWriteTime)); saveManagerScrollPos.y = 0; } private void GetSaveDirectories() { DirectoryInfo[] directoryInfo = new DirectoryInfo(saveScenePath).GetDirectories(); directoryList = new string[directoryInfo.Length + 1]; directoryList[0] = baseDirectoryName; for (int i = 0; i < directoryInfo.Length; i++) { directoryList[i + 1] = directoryInfo[i].Name; } } private void SwitchDirectory(string target) { if (target.Equals(baseDirectoryName)) target = ""; string targetDirectory = Path.Combine(saveScenePath, target); if (!Directory.Exists(targetDirectory)) { currentDirectory = ""; selectedDirectory = 0; GetSaveDirectories(); } else { selectedDirectory = Array.FindIndex(directoryList, d => d.Equals(target, StringComparison.OrdinalIgnoreCase)); selectedDirectory = selectedDirectory == -1 ? 0 : selectedDirectory; if (target == currentDirectory) return; currentDirectory = target; } InitializeSaveList(); } private void LoadSave() { string filePath = saveScenes[selectedSave].info.FullName; if (!File.Exists(filePath)) { InitializeSaveList(); sceneData = null; return; } using (FileStream fileStream = File.OpenRead(filePath)) { byte[] buffer = new byte[pngEnd.Length]; long position = 0; while (true) { int bytesRead = fileStream.Read(buffer, 0, buffer.Length); if (bytesRead != pngEnd.Length) { sceneData = null; return; } if (BytesEqual(buffer, pngEnd)) { fileStream.Position += 4; break; } fileStream.Position = ++position; } using (MemoryStream sceneStream = LZMA.Decompress(fileStream)) { sceneData = Encoding.Unicode.GetString(sceneStream.ToArray()); } } SavePng temp = saveScenes[selectedSave]; saveScenes.RemoveAt(selectedSave); saveScenes.Add(temp); saveManagerScrollPos.y = 0; } private void Overwrite() { string filePath = saveScenes[selectedSave].info.FullName; if (!File.Exists(filePath)) { RefreshSaveManager(); } else { File.Delete(filePath); saveScenes.RemoveAt(selectedSave); saveManagerScrollPos.y = 0; } } private void MakeNewDirectory(string directoryName) { directoryName = string.Join("", directoryName.Split(Path.GetInvalidFileNameChars())); string newDirectory = Path.Combine(saveScenePath, directoryName); if (!Directory.Exists(newDirectory)) { Directory.CreateDirectory(newDirectory); } GetSaveDirectories(); SwitchDirectory(directoryName); } private void DeleteDirectory() { string directory = Path.Combine(saveScenePath, directoryList[selectedDirectory]); if (Directory.Exists(directory)) { DirectoryInfo dirInfo = new DirectoryInfo(directory); foreach (var finfo in dirInfo.GetFiles()) { finfo.Delete(); } dirInfo.Delete(); } RefreshSaveManager(); } private void DeleteFile() { string file = saveScenes[selectedSave].info.FullName; if (File.Exists(file)) { saveScenes[selectedSave].info.Delete(); saveScenes.RemoveAt(selectedSave); } RefreshSaveManager(); } private void SaveScene() { string saveDirectory = Path.Combine(saveScenePath, currentDirectory); if (!Directory.Exists(saveDirectory)) { thum_byte_to_base64_ = ""; thum_file_path_ = ""; RefreshSaveManager(); return; } string sceneString = SerializeScene(true); #region MM GUI stuff Texture2D screenshot = new Texture2D(1, 1, TextureFormat.ARGB32, false); screenshot.LoadImage(File.ReadAllBytes(thum_file_path_)); float num2 = screenshot.width / (float)screenshot.height; Vector2 vector2 = new Vector2(480f, 270f); int newWidth = screenshot.width; int newHeight = screenshot.height; if (vector2.x < (double)screenshot.width && vector2.y < (double)screenshot.height) { newWidth = (int)vector2.x; newHeight = Mathf.RoundToInt(newWidth / num2); if (vector2.y < (double)newHeight) { newHeight = (int)vector2.y; newWidth = Mathf.RoundToInt(newHeight * num2); } } else if (vector2.x < (double)screenshot.width) { newWidth = (int)vector2.x; newHeight = Mathf.RoundToInt(newWidth / num2); } else if (vector2.y < (double)screenshot.height) { newHeight = (int)vector2.y; newWidth = Mathf.RoundToInt(newHeight * num2); } TextureScale.Bilinear(screenshot, newWidth, newHeight); #endregion thum_byte_to_base64_ = ""; thum_file_path_ = ""; string filePath = Path.Combine(saveDirectory, $"mmsave{DateTime.Now:yyyyMMddHHmmss}.png"); using (FileStream fileStream = File.Create(filePath)) using (MemoryStream sceneStream = new MemoryStream(Encoding.Unicode.GetBytes(sceneString))) { byte[] screenshotBuffer = screenshot.EncodeToPNG(); byte[] sceneBuffer = LZMA.Compress(sceneStream); fileStream.Write(screenshotBuffer, 0, screenshotBuffer.Length); fileStream.Write(sceneBuffer, 0, sceneBuffer.Length); } saveScenes.Add(new SavePng(new FileInfo(filePath), screenshot)); selectedSave = saveScenes.Count - 1; } private static bool BytesEqual(byte[] a, byte[] b) { if (a.Length != b.Length) return false; for (int i = 0; i < a.Length; i++) { if (a[i] != b[i]) return false; } return true; } class SavePng { public FileInfo info { get; } public Texture2D screenshot { get; } public SavePng(FileInfo info, Texture2D screenshot) { this.info = info; this.screenshot = screenshot; } } } }