using Pumkin.AvatarTools; using Pumkin.DataStructures; using Pumkin.HelperFunctions; using System; using System.Collections; using System.Collections.Generic; using System.IO; using System.Linq; using UnityEditor; using UnityEngine; namespace Pumkin.Presets { public abstract class PumkinPreset : ScriptableObject { public new string name; public abstract bool ApplyPreset(GameObject avatar); public override string ToString() { return name; } } public static class PumkinsPresetManager { public static readonly string resourcePresetsPath = "Presets/"; public static readonly string resourceCamerasPath = resourcePresetsPath + "Cameras"; public static readonly string resourcePosesPath = resourcePresetsPath + "Poses"; public static readonly string resourceBlendshapesPath = resourcePresetsPath + "Blendshapes"; public static readonly string localPresetsPath = PumkinsAvatarTools.MainFolderPathLocal + "/resources/" + resourcePresetsPath; public static readonly string localCamerasPath = PumkinsAvatarTools.MainFolderPathLocal + "/resources/" + resourceCamerasPath; public static readonly string localPosesPath = PumkinsAvatarTools.MainFolderPathLocal + "/resources/" + resourcePosesPath; public static readonly string localBlendshapesPath = PumkinsAvatarTools.MainFolderPathLocal + "/resources/" + resourceBlendshapesPath; static string cameraPresetScriptGUID = null; static string blendshapePresetScriptGUID = null; static string posePresetScriptGUID = null; static List _cameraPresets; static List _humanPosePresets; static List _blendshapePresets; public static List CameraPresets { get { if(_cameraPresets == null) { _cameraPresets = new List(); LoadPresets(); } return _cameraPresets; } private set { _cameraPresets = value; } } public static List PosePresets { get { if(_humanPosePresets == null) { _humanPosePresets = new List(); LoadPresets(); } return _humanPosePresets; } private set { _humanPosePresets = value; } } public static List BlendshapePresets { get { if(_blendshapePresets == null) { _blendshapePresets = new List(); LoadPresets(); } return _blendshapePresets; } private set { _blendshapePresets = value; } } /// /// Destroys loose preset objects that live in memory and not in assets /// public static void CleanupPresetsOfType() where T : PumkinPreset { var tools = PumkinsAvatarTools.Instance; string typeName = typeof(T).Name; var presets = GameObject.FindObjectsOfType(); Type t = typeof(T); Type tP = typeof(PumkinPreset); foreach(var preset in presets) { if(preset && !Helpers.IsAssetInAssets(preset)) { PumkinsAvatarTools.LogVerbose($"Destroying orphanned {typeName}"); Helpers.DestroyAppropriate(preset); } } if(typeof(T) == typeof(PumkinsCameraPreset) || t == tP) CameraPresets.RemoveAll(o => o == default(PumkinsCameraPreset) || !Helpers.IsAssetInAssets(o)); if(typeof(T) == typeof(PumkinsPosePreset) || t == tP) PosePresets.RemoveAll(o => o == default(PumkinsPosePreset) || !Helpers.IsAssetInAssets(o)); if(typeof(T) == typeof(PumkinsBlendshapePreset) || t == tP) BlendshapePresets.RemoveAll(o => o == default(PumkinsBlendshapePreset) || !Helpers.IsAssetInAssets(o)); PumkinsAvatarTools.RefreshPresetIndex(); } public static void LoadPresets() where T : PumkinPreset { Type t = typeof(T); Type pT = typeof(PumkinPreset); FixScriptReferences(); if(t == typeof(PumkinsCameraPreset) || t == pT) { Resources.LoadAll(resourceCamerasPath); CameraPresets = Resources.FindObjectsOfTypeAll().ToList(); CleanupPresetsOfType(); } if(typeof(T) == typeof(PumkinsPosePreset) || t == pT) { Resources.LoadAll(resourcePosesPath); PosePresets = Resources.FindObjectsOfTypeAll().ToList(); CleanupPresetsOfType(); } if(typeof(T) == typeof(PumkinsBlendshapePreset) || t == pT) { Resources.LoadAll(resourceBlendshapesPath); BlendshapePresets = Resources.FindObjectsOfTypeAll().ToList(); CleanupPresetsOfType(); } } public static int GetPresetIndex(T preset) where T : PumkinPreset { int i = -1; if(typeof(T) == typeof(PumkinsCameraPreset)) i = CameraPresets.IndexOf(preset as PumkinsCameraPreset); else if(typeof(T) == typeof(PumkinsPosePreset)) i = PosePresets.IndexOf(preset as PumkinsPosePreset); else if(typeof(T) == typeof(PumkinsBlendshapePreset)) i = BlendshapePresets.IndexOf(preset as PumkinsBlendshapePreset); return i; } public static int GetPresetIndex(string name) where T : PumkinPreset { int i = -1; if(typeof(T) == typeof(PumkinsCameraPreset)) i = CameraPresets.FindIndex(o => o.name.ToLower() == name.ToLower()); else if(typeof(T) == typeof(PumkinsPosePreset)) i = PosePresets.FindIndex(o => o.name.ToLower() == name.ToLower()); else if(typeof(T) == typeof(PumkinsBlendshapePreset)) i = BlendshapePresets.FindIndex(o => o.name.ToLower() == name.ToLower()); return i; } public static string GetPresetName(int index) where T : PumkinPreset { if(typeof(T) == typeof(PumkinsCameraPreset)) { if(CameraPresets[index]) return CameraPresets[index].name; } else if(typeof(T) == typeof(PumkinsPosePreset)) { if(PosePresets[index]) return PosePresets[index].name; } else if(typeof(T) == typeof(PumkinsBlendshapePreset)) { if(BlendshapePresets[index]) return BlendshapePresets[index].name; } return ""; } public static T FindPreset(string name) where T : PumkinPreset { object preset = null; if(typeof(T) == typeof(PumkinsCameraPreset)) preset = CameraPresets.Find(o => o.name.ToLower() == name.ToLower()); else if(typeof(T) == typeof(PumkinsCameraPreset)) preset = PosePresets.Find(o => o.name.ToLower() == name.ToLower()); else if(typeof(T) == typeof(PumkinsBlendshapePreset)) preset = BlendshapePresets.Find(o => o.name.ToLower() == name.ToLower()); return (T)preset; } public static int GetPresetCountOfType() where T : PumkinPreset { if(typeof(T) == typeof(PumkinsCameraPreset)) return CameraPresets.Count; else if(typeof(T) == typeof(PumkinsPosePreset)) return PosePresets.Count; else if(typeof(T) == typeof(PumkinsBlendshapePreset)) return BlendshapePresets.Count; return -1; } public static void SelectPresetInToolWindow(T preset, bool openWindow = true) where T : PumkinPreset { int index = GetPresetIndex(preset.name); if(index != -1) { PumkinsAvatarTools.PresetToolbarOptions toolbarOption = PumkinsAvatarTools.PresetToolbarOptions.Camera; if(openWindow) { _PumkinsAvatarToolsWindow.ShowWindow(); PumkinsAvatarTools.Instance._info_expand = false; PumkinsAvatarTools.Instance._tools_expand = false; PumkinsAvatarTools.Instance._thumbnails_expand = true; } if(typeof(T) == typeof(PumkinsCameraPreset)) { PumkinsAvatarTools.Instance._selectedCameraPresetString = preset.name; PumkinsAvatarTools.Instance._selectedCameraPresetIndex = index; toolbarOption = PumkinsAvatarTools.PresetToolbarOptions.Camera; } else if(typeof(T) == typeof(PumkinsPosePreset)) { PumkinsAvatarTools.Instance._selectedPosePresetString = preset.name; PumkinsAvatarTools.Instance._selectedPosePresetIndex = index; toolbarOption = PumkinsAvatarTools.PresetToolbarOptions.Pose; } else if(typeof(T) == typeof(PumkinsBlendshapePreset)) { PumkinsAvatarTools.Instance._selectedBlendshapePresetString = preset.name; PumkinsAvatarTools.Instance._selectedBlendshapePresetIndex = index; toolbarOption = PumkinsAvatarTools.PresetToolbarOptions.Blendshape; } if(openWindow) PumkinsAvatarTools.Instance.SelectThumbnailPresetToolbarOption(toolbarOption); } } static void SetupGUID() where T : PumkinPreset { if(typeof(T) == typeof(PumkinPreset)) { SetupAllGUIDs(); // bad redirect to setup all return; } string typeName = typeof(T).Name; var guids = AssetDatabase.FindAssets(typeName); string guid = null; string path = null; foreach(var g in guids) { path = AssetDatabase.GUIDToAssetPath(g); if(!path.EndsWith($"{typeName}.cs")) continue; guid = g; break; } if(typeof(T) == typeof(PumkinsBlendshapePreset)) blendshapePresetScriptGUID = guid; else if(typeof(T) == typeof(PumkinsCameraPreset)) cameraPresetScriptGUID = guid; else if(typeof(T) == typeof(PumkinsPosePreset)) posePresetScriptGUID = guid; else return; PumkinsAvatarTools.LogVerbose($"Set GUID of {typeof(T).Name} script at {path} to {guid}"); } static void SetupAllGUIDs() { SetupGUID(); SetupGUID(); SetupGUID(); } public static void FixScriptReferences() where T : PumkinPreset { SetupGUID(); Type t = typeof(T); Type pT = typeof(PumkinPreset); var pathsGuids = new Dictionary(); if(t == typeof(PumkinsBlendshapePreset) || t == pT) pathsGuids.Add(Helpers.LocalAssetsPathToAbsolutePath(localBlendshapesPath), blendshapePresetScriptGUID); if(t == typeof(PumkinsCameraPreset) || t == pT) pathsGuids.Add(Helpers.LocalAssetsPathToAbsolutePath(localCamerasPath), cameraPresetScriptGUID); if(t == typeof(PumkinsPosePreset) || t == pT) pathsGuids.Add(Helpers.LocalAssetsPathToAbsolutePath(localPosesPath), posePresetScriptGUID); foreach(var kv in pathsGuids) { var path = kv.Key; var guid = kv.Value; if(!Directory.Exists(path)) { PumkinsAvatarTools.LogVerbose($"Directory {path} doesn't exist. Can't fix references"); continue; } var files = Directory.GetFiles($"{path}", "*.asset", SearchOption.AllDirectories); foreach(var file in files) { if(ReplacePresetGUIDTemp(file, guid)) AssetDatabase.ImportAsset(Helpers.AbsolutePathToLocalAssetsPath(file), ImportAssetOptions.ForceUpdate); } PumkinsAvatarTools.LogVerbose($"Fixed references for type {typeof(T).Name}"); } } public static void FixAllPresetScriptReferences() { SetupAllGUIDs(); FixScriptReferences(); FixScriptReferences(); FixScriptReferences(); } /// /// TODO: Replace with one that reads only the needed lines /// static bool ReplacePresetGUIDTemp(string filePath, string newGUID) { filePath = Helpers.AbsolutePathToLocalAssetsPath(filePath); if(Helpers.StringIsNullOrWhiteSpace(filePath) || Helpers.StringIsNullOrWhiteSpace(newGUID)) { PumkinsAvatarTools.LogVerbose($"Filepath ({filePath}) or GUID ({newGUID}) is empty", LogType.Warning); return false; } else if(!File.Exists(filePath)) { PumkinsAvatarTools.Log($"File {filePath} doesn't exist. Can't fix preset references", LogType.Warning); return false; } var lines = File.ReadAllLines(filePath); for(int i = 0; i < lines.Length; i++) { var line = lines[i]; if(!line.Contains("m_Script")) continue; lines[i] = Helpers.ReplaceGUIDInLine(line, newGUID, out bool replaced); if(replaced) { File.WriteAllLines(filePath, lines); return true; } break; } return false; } } }