diff --git a/Instancer.cs b/Instancer.cs index f2765af..69477f3 100644 --- a/Instancer.cs +++ b/Instancer.cs @@ -1,6 +1,4 @@ using System; -using System.Collections; -using System.Collections.Generic; using System.IO; using System.Linq; using System.Text.RegularExpressions; @@ -10,26 +8,67 @@ namespace VRLabs.Instancer { + [InitializeOnLoad] public class Instancer : MonoBehaviour { - public static string Instance(string packageName, string installFilePath, string[] excludeRegexs) + static bool renameInstances; + + static Instancer() + { + renameInstances = PlayerPrefs.GetString("VRLabs.Instancer.RenameInstances", "True") == "True"; ; + } + + [MenuItem("VRLabs/Rename new Instances", priority = 1)] + public static void RenameInstancesToggle() + { + renameInstances = !renameInstances; + PlayerPrefs.SetString("VRLabs.Instancer.RenameInstances", renameInstances.ToString()); + } + + [MenuItem("VRLabs/Rename new Instances", true)] + public static bool RenameInstancesToggleValidate() + { + Menu.SetChecked("VRLabs/Rename new Instances", renameInstances); + return true; + } + + public static void Instance(string packageName, string installFilePath, string[] excludeRegexs) + { + InstanceWithCallback(packageName, installFilePath, excludeRegexs, null); + } + + // Done this way because existing packages call the Instance method with 3 parameters + public static void InstanceWithCallback(string packageName, string installFilePath, string[] excludeRegexs, Action callBack = null) { string targetFolder = EditorUtility.OpenFolderPanel("Select Directory To Copy Assets To", "Assets/", ""); if (targetFolder == "" || targetFolder == null) { Debug.LogError("No folder selected, please select a folder to copy the assets to."); - return null; + return; } if (!targetFolder.Contains(Application.dataPath)) { Debug.LogError("Selected folder is not in the Assets folder, please select a folder in the Assets directory."); - return null; + return; } - targetFolder = PrepareTargetFolderPath(targetFolder, packageName); + if (renameInstances) + { + EnterValueWindow.Open(packageName, (newName) => FinishInstancing(packageName, installFilePath, excludeRegexs, targetFolder, newName, callBack)); + return; + } + FinishInstancing(packageName, installFilePath, excludeRegexs, targetFolder, callBack: callBack); + } + + // Done this way because we need the unity editor to continue running during the rename popup window. + public static void FinishInstancing(string packageName, string installFilePath, string[] excludeRegexs, + string targetFolder, string newInstanceName = null, Action callBack = null) + { + targetFolder = PrepareTargetFolderPath(targetFolder, packageName); + string sourceFolder = GetSourceFolder(installFilePath); string[] localAssetPaths = GetLocalAssetPaths(sourceFolder, excludeRegexs); @@ -39,18 +78,17 @@ public static string Instance(string packageName, string installFilePath, string CopyFiles(localAssetPaths, sourceFolder, targetFolder); AssetDatabase.Refresh(); - + FixReferences(localAssetPaths, sourceFolder, targetFolder); - + + if (newInstanceName != null) + { + RenameInstance(localAssetPaths, targetFolder, packageName, newInstanceName); + } + AssetDatabase.Refresh(); - return targetFolder; - } - - public static void Install(string packageName, string installFilePath, string[] excludeRegexs, Action callBack) - { - string instancePath = Instance(packageName, installFilePath, excludeRegexs); - callBack(instancePath); + callBack?.Invoke(targetFolder); } static string PrepareTargetFolderPath(string folderPath, string packageName) @@ -161,7 +199,6 @@ static void FixReferences(string[] localAssetPaths, string sourceFolder, string { if (property.propertyType == SerializedPropertyType.ObjectReference) { - // Debug.Log($"O{property.name}, {property.displayName}, {property.objectReferenceValue}"); if (property.objectReferenceValue != null) { property.objectReferenceValue = GetTargetVersion(sourceFolder, targetFolder, property.objectReferenceValue); @@ -170,7 +207,6 @@ static void FixReferences(string[] localAssetPaths, string sourceFolder, string if (property.propertyType == SerializedPropertyType.ExposedReference) { - // Debug.Log($"E{property.name}, {property.displayName}, {property.exposedReferenceValue}"); if (property.exposedReferenceValue != null) { property.exposedReferenceValue = GetTargetVersion(sourceFolder, targetFolder, property.exposedReferenceValue); @@ -182,7 +218,58 @@ static void FixReferences(string[] localAssetPaths, string sourceFolder, string } } } + + static void RenameInstance(string[] localAssetPaths, string targetFolder, string packageName, string newInstanceName) + { + foreach (string localAssetPath in localAssetPaths) + { + string targetAssetPath = targetFolder + localAssetPath; + UnityEngine.Object[] targetAssets = AssetDatabase.LoadAllAssetsAtPath(targetAssetPath); + + string[] possibleNames = new []{packageName, packageName.Replace("-", ""), packageName.Replace("-", " ")}; + String fileName = Path.GetFileName(targetAssetPath); + foreach (string possibleName in possibleNames) + { + if (fileName.StartsWith(possibleName)) + { + fileName = ReplaceAtStart(fileName, possibleName, newInstanceName); + AssetDatabase.RenameAsset(targetAssetPath, fileName); + break; + } + } + + foreach (var targetAsset in targetAssets) + { + SerializedObject serializedObject = new SerializedObject(targetAsset); + SerializedProperty property = serializedObject.GetIterator(); + do + { + if (property.propertyType == SerializedPropertyType.String) + { + string value = property.stringValue; + if (value == null) continue; + + foreach (string possibleName in possibleNames) + { + if (value.StartsWith(possibleName) && !value.StartsWith(newInstanceName)) + { + property.stringValue = ReplaceAtStart(value, possibleName, newInstanceName); + break; + } + } + } + } while (property.Next(true)); + + serializedObject.ApplyModifiedProperties(); + } + } + } + + public static string ReplaceAtStart(string str, string oldValue, string newValue) + { + return newValue + str.Substring(oldValue.Length); + } private static Object GetTargetVersion(string sourceFolder, string targetFolder, Object target) { string targetPath = AssetDatabase.GetAssetPath(target); @@ -195,4 +282,30 @@ private static Object GetTargetVersion(string sourceFolder, string targetFolder, return target; } } + + public class EnterValueWindow : EditorWindow + { + private string value = ""; + private Action callBack; + public static void Open(string packageName, Action callBack) + { + var window = GetWindow("Enter new Instance Name"); + window.value = packageName; + window.callBack = callBack; + window.position = new Rect(Screen.width / 2, Screen.height / 2, 250, 100); + window.Show(); + } + + private void OnGUI() + { + EditorGUILayout.LabelField("New Instance Name:", EditorStyles.boldLabel); + value = EditorGUILayout.TextField(value); + + if (GUILayout.Button("Submit")) + { + callBack(value); + Close(); + } + } + } }