From 5242505dae5e4c8ca3d033f104a4dc66a606ae33 Mon Sep 17 00:00:00 2001 From: jellejurre Date: Thu, 12 Sep 2024 19:04:36 +0200 Subject: [PATCH] Add instance any package functionality --- Instancer.cs | 114 +++++++++++++++++++++++++++++++++++++++++---------- Readme.md | 8 ++++ 2 files changed, 101 insertions(+), 21 deletions(-) diff --git a/Instancer.cs b/Instancer.cs index 69477f3..2a82581 100644 --- a/Instancer.cs +++ b/Instancer.cs @@ -32,6 +32,62 @@ public static bool RenameInstancesToggleValidate() return true; } + [MenuItem("VRLabs/Create Instance/Any Package")] + public static void CreateInstanceAnyPackageStart() + { + string sourceFolder = EditorUtility.OpenFolderPanel("Select Directory To Copy Assets From", "Assets/", ""); + + if (sourceFolder == "" || sourceFolder == null) + { + Debug.LogError("No folder selected, please select a folder to copy the assets to."); + return; + } + + 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; + } + + if (!targetFolder.Contains(Application.dataPath)) + { + Debug.LogError("Selected folder is not in the Assets folder, please select a folder in the Assets directory."); + return; + } + + if (renameInstances) + { + EnterValueWindow.Open("", "Enter Old Package name", (oldName) => + { + EnterValueWindow.Open(oldName, "Enter New Instance name", (newName) => + { + FinishInstancing(oldName, "Assets" + sourceFolder.Replace(Application.dataPath, ""), new[] + { + ".*\\.cs", + ".*\\.asmdef", + ".*\\.shader", + "package.json" + }, targetFolder, newName, null, true); + }); + }); + } + else + { + EnterValueWindow.Open("", "Enter New Instance name", (newName) => + { + FinishInstancing(newName, "Assets" + sourceFolder.Replace(Application.dataPath, ""), new[] + { + ".*\\.cs", + ".*\\.asmdef", + ".*\\.shader", + "package.json" + }, targetFolder, null, null, true); + }); + } + } + public static void Instance(string packageName, string installFilePath, string[] excludeRegexs) { InstanceWithCallback(packageName, installFilePath, excludeRegexs, null); @@ -56,7 +112,7 @@ public static void InstanceWithCallback(string packageName, string installFilePa if (renameInstances) { - EnterValueWindow.Open(packageName, (newName) => FinishInstancing(packageName, installFilePath, excludeRegexs, targetFolder, newName, callBack)); + EnterValueWindow.Open(packageName, "Enter new Instance Name",(newName) => FinishInstancing(packageName, installFilePath, excludeRegexs, targetFolder, newName, callBack)); return; } @@ -65,11 +121,11 @@ public static void InstanceWithCallback(string packageName, string installFilePa // 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) + string targetFolder, string newInstanceName = null, Action callBack = null, bool isAnyPackage = false) { - targetFolder = PrepareTargetFolderPath(targetFolder, packageName); + targetFolder = PrepareTargetFolderPath(targetFolder, newInstanceName != null ? newInstanceName : packageName); - string sourceFolder = GetSourceFolder(installFilePath); + string sourceFolder = isAnyPackage ? installFilePath : GetSourceFolder(installFilePath); string[] localAssetPaths = GetLocalAssetPaths(sourceFolder, excludeRegexs); @@ -190,18 +246,26 @@ static void FixReferences(string[] localAssetPaths, string sourceFolder, string foreach (string localAssetPath in localAssetPaths) { string targetAssetPath = targetFolder + localAssetPath; - UnityEngine.Object[] targetAssets = AssetDatabase.LoadAllAssetsAtPath(targetAssetPath); + UnityEngine.Object[] targetAssets = AssetDatabase.LoadAllAssetsAtPath(targetAssetPath).Where(x => x != null).ToArray(); foreach (var targetAsset in targetAssets) { SerializedObject serializedObject = new SerializedObject(targetAsset); SerializedProperty property = serializedObject.GetIterator(); + bool changed = false; + bool newChanged = false; do { if (property.propertyType == SerializedPropertyType.ObjectReference) { if (property.objectReferenceValue != null) { - property.objectReferenceValue = GetTargetVersion(sourceFolder, targetFolder, property.objectReferenceValue); + Object newObject; + (newObject, newChanged) = GetTargetVersion(sourceFolder, targetFolder, property.objectReferenceValue); + if (newChanged) + { + changed = true; + property.objectReferenceValue = newObject; + } } } @@ -209,12 +273,18 @@ static void FixReferences(string[] localAssetPaths, string sourceFolder, string { if (property.exposedReferenceValue != null) { - property.exposedReferenceValue = GetTargetVersion(sourceFolder, targetFolder, property.exposedReferenceValue); + Object newObject; + (newObject, newChanged) = GetTargetVersion(sourceFolder, targetFolder, property.exposedReferenceValue); + if (newChanged) + { + changed = true; + property.exposedReferenceValue = newObject; + } } } } while (property.Next(true)); - serializedObject.ApplyModifiedProperties(); + if (changed) serializedObject.ApplyModifiedProperties(); } } } @@ -224,8 +294,8 @@ static void RenameInstance(string[] localAssetPaths, string targetFolder, string foreach (string localAssetPath in localAssetPaths) { string targetAssetPath = targetFolder + localAssetPath; - UnityEngine.Object[] targetAssets = AssetDatabase.LoadAllAssetsAtPath(targetAssetPath); - + UnityEngine.Object[] targetAssets = AssetDatabase.LoadAllAssetsAtPath(targetAssetPath).Where(x => x != null).ToArray(); + if (targetAssets.Length == 0) continue; string[] possibleNames = new []{packageName, packageName.Replace("-", ""), packageName.Replace("-", " ")}; String fileName = Path.GetFileName(targetAssetPath); @@ -249,7 +319,7 @@ static void RenameInstance(string[] localAssetPaths, string targetFolder, string { string value = property.stringValue; if (value == null) continue; - + foreach (string possibleName in possibleNames) { if (value.StartsWith(possibleName) && !value.StartsWith(newInstanceName)) @@ -270,41 +340,43 @@ 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) + private static (Object, bool) GetTargetVersion(string sourceFolder, string targetFolder, Object target) { string targetPath = AssetDatabase.GetAssetPath(target); if (targetPath.StartsWith(sourceFolder)) { - string newTargetPath = targetFolder + targetPath.Remove(0, sourceFolder.Length); - return AssetDatabase.LoadAllAssetsAtPath(newTargetPath).Where(obj => obj.GetType() == target.GetType()).FirstOrDefault(x => x.name == target.name); + string newTargetPath = targetFolder + targetPath.Remove(0, sourceFolder.Length); + Object newObject = AssetDatabase.LoadAllAssetsAtPath(newTargetPath).Where(obj => obj.GetType() == target.GetType()).FirstOrDefault(x => x.name == target.name); + return (newObject, newObject != null); } - return target; + return (target, false); } } public class EnterValueWindow : EditorWindow { private string value = ""; + private string windowTitle; private Action callBack; - public static void Open(string packageName, Action callBack) + public static void Open(string packageName, string windowTitle, Action callBack) { - var window = GetWindow("Enter new Instance Name"); + var window = GetWindow(windowTitle); + window.windowTitle = windowTitle; 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); + EditorGUILayout.LabelField(windowTitle, EditorStyles.boldLabel); value = EditorGUILayout.TextField(value); if (GUILayout.Button("Submit")) - { - callBack(value); + { Close(); + callBack(value); } } } diff --git a/Readme.md b/Readme.md index 927c98c..4a294b5 100644 --- a/Readme.md +++ b/Readme.md @@ -33,6 +33,14 @@ VRLabs' Instancing system that copies files over for use in the Assets directory * Click the `VRLabs/[PackageName]` button in the toolbar and select an output folder to copy to. +### Instance Any Package + +* You can use the `VRLabs/Instance Any Package` button to instance and rename any package in the Assets folder. +* It will ask you for the package name and the new instance name. + * Note that it will only rename things that start with the package name, so if you have e.g. controller parameters that start with a different name, they wont be renamed and will clash with the initial package. + * Note that materials will reference shaders from the original package as shaders are not copied over. + * Note that big packages might crash your Unity Editor and cancel the renames, so notall packages will work. + ## Contributors * [Jelle](https://jellejurre.dev)