├── ReportInstanceID.cs ├── ReportSelectedObjectType.cs ├── SelectEditorGUISkin.cs ├── SaveEditorGUISkinToAssetDatabase.cs ├── ReplaceSelectedSceneObjectsWithSelectedPrefab.cs ├── ResetTransformsOfSelectedObjects.cs ├── ReportBoundsOfSelectedObjects.cs ├── ApplyImportSettingsToSelectedAssets.cs ├── README.md └── GroundSelectedObjects.cs /ReportInstanceID.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using UnityEditor; 3 | 4 | namespace EditorFormulas.Formulas 5 | { 6 | public static class ReportInstanceID { 7 | 8 | [FormulaAttribute ("Report Instance ID", "Reports the instanceID of the selected object", "VoxelBoy")] 9 | public static void Run() 10 | { 11 | if(Selection.activeObject != null) 12 | { 13 | Debug.Log(Selection.activeObject.GetInstanceID()); 14 | } 15 | } 16 | 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /ReportSelectedObjectType.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using UnityEditor; 3 | 4 | namespace EditorFormulas.Formulas 5 | { 6 | public static class ReportSelectedObjectType { 7 | 8 | [FormulaAttribute("Report Selected Object Type", "Reports the System.Type of the selected object in the Editor", "VoxelBoy")] 9 | public static void Run() 10 | { 11 | if(Selection.activeObject == null) 12 | { 13 | return; 14 | } 15 | Debug.Log(Selection.activeObject.GetType().FullName); 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /SelectEditorGUISkin.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using UnityEditor; 3 | using System.Reflection; 4 | 5 | namespace EditorFormulas.Formulas 6 | { 7 | public static class SelectEditorGUISkin { 8 | 9 | [FormulaAttribute("Select Editor GUI Skin", "Selects the GUISkin object used by the Editor", "VoxelBoy")] 10 | public static void Run() 11 | { 12 | Selection.activeObject = typeof(GUISkin).GetField("current", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static).GetValue(null) as GUISkin; 13 | } 14 | 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /SaveEditorGUISkinToAssetDatabase.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using UnityEditor; 3 | using System.Reflection; 4 | 5 | namespace EditorFormulas.Formulas 6 | { 7 | public static class SaveEditorGUISkinToAssetDatabase { 8 | 9 | [FormulaAttribute ("Save Editor GUISkin To Asset Database", "Saves the GUISkin used by the Editor to your Project. Useful for trying to replicate Editor controls in your own tools.", "VoxelBoy")] 10 | public static void Run() 11 | { 12 | var currentGUISkin = typeof(GUISkin).GetField("current", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static).GetValue(null) as GUISkin; 13 | 14 | var newGUISkin = Object.Instantiate(currentGUISkin); 15 | newGUISkin.hideFlags = HideFlags.None; 16 | 17 | var assetPath = AssetDatabase.GenerateUniqueAssetPath("Assets/EditorGUISkin.guiskin"); 18 | 19 | AssetDatabase.CreateAsset (newGUISkin, assetPath); 20 | AssetDatabase.SaveAssets (); 21 | AssetDatabase.Refresh(); 22 | } 23 | 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /ReplaceSelectedSceneObjectsWithSelectedPrefab.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using UnityEditor; 3 | using System.Collections.Generic; 4 | 5 | namespace EditorFormulas.Formulas 6 | { 7 | public static class ReplaceSelectedSceneObjectsWithSelectedPrefab { 8 | 9 | [FormulaAttribute ("Replace Selected Scene Objects With Selected Prefab", "Replaces selected scene objects with the prefab selected in Project view while maintaining the objects' world transforms", "VoxelBoy")] 10 | public static void Run() 11 | { 12 | var prefab = new List(Selection.GetFiltered(typeof(GameObject), SelectionMode.Assets)).Find(x => AssetDatabase.IsMainAsset (x)) as GameObject; 13 | if(prefab == null) 14 | { 15 | Debug.LogError("No prefab found among selected objects."); 16 | return; 17 | } 18 | 19 | var sceneTransforms = Selection.GetFiltered(typeof(Transform), SelectionMode.ExcludePrefab); 20 | foreach(Transform t in sceneTransforms) 21 | { 22 | var instantiatedPrefab = PrefabUtility.InstantiatePrefab(prefab) as GameObject; 23 | Undo.RegisterCreatedObjectUndo(instantiatedPrefab, "Instantiate prefab " + instantiatedPrefab.name); 24 | instantiatedPrefab.transform.parent = t.parent; 25 | instantiatedPrefab.transform.localPosition = t.localPosition; 26 | instantiatedPrefab.transform.localRotation = t.localRotation; 27 | instantiatedPrefab.transform.localScale = t.localScale; 28 | Undo.DestroyObjectImmediate(t.gameObject); 29 | } 30 | } 31 | } 32 | } -------------------------------------------------------------------------------- /ResetTransformsOfSelectedObjects.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using UnityEditor; 3 | 4 | namespace EditorFormulas.Formulas 5 | { 6 | public static class ResetTransformsOfSelectedObjects { 7 | 8 | [FormulaAttribute("Reset Transforms Of Selected Objects", "Reset the position, rotation, or scale of selected transforms", "VoxelBoy")] 9 | public static void Run (bool resetPosition, bool resetRotation, bool resetScale, bool useWorldSpace) 10 | { 11 | var selection = Selection.GetFiltered(typeof(Transform), SelectionMode.Editable | SelectionMode.ExcludePrefab); 12 | if(selection.Length == 0) 13 | { 14 | Debug.Log("No transforms found in selection."); 15 | return; 16 | } 17 | 18 | foreach(var obj in selection) 19 | { 20 | var t = obj as Transform; 21 | if(resetPosition) 22 | { 23 | if(useWorldSpace) 24 | { 25 | t.position = Vector3.zero; 26 | } 27 | else 28 | { 29 | t.localPosition = Vector3.zero; 30 | } 31 | } 32 | if(resetRotation) 33 | { 34 | if(useWorldSpace) 35 | { 36 | t.rotation = Quaternion.identity; 37 | } 38 | else 39 | { 40 | t.localRotation = Quaternion.identity; 41 | } 42 | } 43 | if(resetScale) 44 | { 45 | if(useWorldSpace) 46 | { 47 | var parent = t.parent; 48 | t.SetParent(null, true); 49 | t.localScale = Vector3.one; 50 | t.SetParent(parent, true); 51 | } 52 | else 53 | { 54 | t.localScale = Vector3.one; 55 | } 56 | } 57 | } 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /ReportBoundsOfSelectedObjects.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using UnityEditor; 3 | using System.Collections.Generic; 4 | 5 | namespace EditorFormulas.Formulas 6 | { 7 | public static class ReportBoundsOfSelectedObjects { 8 | 9 | [FormulaAttribute ("Report Bounds Of Selected Objects", "Reports the renderer or colliders bounds of the selected objects", "VoxelBoy")] 10 | public static void Run(bool reportRendererBounds, bool reportColliderBounds, bool encapsulateChildren) 11 | { 12 | var selection = Selection.objects; 13 | if(selection.Length == 0) { return; } 14 | foreach(GameObject go in selection) 15 | { 16 | if(reportRendererBounds) 17 | { 18 | var bounds = new Bounds(go.transform.position, Vector3.zero); 19 | var rendererOnObject = go.GetComponent(); 20 | if(rendererOnObject != null) 21 | { 22 | bounds = rendererOnObject.bounds; 23 | } 24 | if(encapsulateChildren) 25 | { 26 | var renderersInChildren = go.GetComponentsInChildren(); 27 | foreach(var rend in renderersInChildren) 28 | { 29 | bounds.Encapsulate(rend.bounds); 30 | } 31 | } 32 | 33 | Debug.Log(string.Format("Renderer bounds of {0} is center:{1} size:{2}", 34 | go.name, 35 | FullVector3String_ReportBoundsOfSelectedObjects(bounds.center), 36 | FullVector3String_ReportBoundsOfSelectedObjects(bounds.size))); 37 | } 38 | if(reportColliderBounds) 39 | { 40 | var bounds = new Bounds(go.transform.position, Vector3.zero); 41 | var colliderOnObject = go.GetComponent(); 42 | if(colliderOnObject != null) 43 | { 44 | bounds = colliderOnObject.bounds; 45 | } 46 | if(encapsulateChildren) 47 | { 48 | var collidersInChildren = go.GetComponentsInChildren(); 49 | foreach(var col in collidersInChildren) 50 | { 51 | bounds.Encapsulate(col.bounds); 52 | } 53 | } 54 | 55 | Debug.Log(string.Format("Collider bounds of {0} is center:{1} size:{2}", 56 | go.name, 57 | FullVector3String_ReportBoundsOfSelectedObjects(bounds.center), 58 | FullVector3String_ReportBoundsOfSelectedObjects(bounds.size))); 59 | } 60 | } 61 | } 62 | 63 | private static string FullVector3String_ReportBoundsOfSelectedObjects(Vector3 vector) 64 | { 65 | return string.Format("({0},{1},{2})", vector.x, vector.y, vector.z); 66 | } 67 | } 68 | } -------------------------------------------------------------------------------- /ApplyImportSettingsToSelectedAssets.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using UnityEditor; 3 | using System.Reflection; 4 | 5 | namespace EditorFormulas.Formulas 6 | { 7 | public static class ApplyImportSettingsToSelectedAssets { 8 | 9 | [FormulaAttribute ("Apply Import Settings To Selected Assets", "Applies the import settings of the originalAsset to the selected assets in Project view", "VoxelBoy")] 10 | public static void Run(Object originalAsset) 11 | { 12 | if(originalAsset == null) 13 | { 14 | return; 15 | } 16 | if(!AssetDatabase.Contains(originalAsset)) 17 | { 18 | Debug.LogError("The object given as the original asset is not in the asset database. Make sure you've specified an actual asset and not a scene object."); 19 | return; 20 | } 21 | 22 | var originalAssetPath = AssetDatabase.GetAssetPath(originalAsset); 23 | var originalAssetImporter = AssetImporter.GetAtPath(originalAssetPath); 24 | if(originalAssetImporter == null) 25 | { 26 | Debug.LogError("There is no valid importer for the given asset."); 27 | } 28 | 29 | var selectedObjects = Selection.objects; 30 | foreach(var obj in selectedObjects) 31 | { 32 | if(obj == null) 33 | { 34 | continue; 35 | } 36 | if(!AssetDatabase.Contains(obj)) 37 | { 38 | Debug.LogError("The selected object " + obj.name + " is not in the asset database", obj); 39 | continue; 40 | } 41 | var objAssetPath = AssetDatabase.GetAssetPath(obj); 42 | var objAssetImporter = AssetImporter.GetAtPath(objAssetPath); 43 | if(objAssetImporter == null) 44 | { 45 | Debug.LogError("The selected object " + obj.name + " has no valid importer.", obj); 46 | continue; 47 | } 48 | if(objAssetImporter.GetType() != originalAssetImporter.GetType()) 49 | { 50 | Debug.LogError("The selected object's asset importer is not of the same type as the original object's asset importer."); 51 | continue; 52 | } 53 | 54 | //Get all public properties of original asset importer and apply them to objAssetImporter 55 | var properties = originalAssetImporter.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance); 56 | 57 | foreach(var property in properties) 58 | { 59 | if(property.GetGetMethod() != null && property.GetSetMethod() != null) 60 | { 61 | var val = property.GetValue(originalAssetImporter, null); 62 | property.SetValue(objAssetImporter, val, null); 63 | } 64 | } 65 | objAssetImporter.SaveAndReimport(); 66 | } 67 | 68 | AssetDatabase.Refresh(); 69 | } 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## Editor Formulas 2 | 3 | All community submitted Editor Formulas are gathered here. 4 | 5 | A "Formula" is a single static method that has no return value but can have zero to many parameters. 6 | 7 | ### Writing Formulas 8 | 9 | Here is a simple Formula template: 10 | ``` 11 | using UnityEngine; 12 | 13 | namespace EditorFormulas.Formulas 14 | { 15 | public static class AddOneAndLog 16 | { 17 | [FormulaAttribute ("Add One and Log", "Adds one to the given number and prints it out", "GenericAuthor")] 18 | public static void Run (int number) 19 | { 20 | Debug.Log(number + 1); 21 | } 22 | } 23 | } 24 | ``` 25 | 26 | When loaded in Editor Formulas Window, this Formula will show up like this: 27 | 28 | Add One Formula 29 | 30 | There are several hard requirements for how Formulas must be written: 31 | * The name of the file and the class must match exactly. 32 | * The name must be unique among all other formulas. 33 | * A FormulaAttribute must be added to the entry method for the formula. 34 | * The entry method must be public and static. 35 | * The class should be inside the EditorFormulas.Formulas namespace. 36 | 37 | A FormulaTemplate.cs file is provided in the [Editor Formulas Window repository](https://github.com/VoxelBoy/EditorFormulasWindow) to make it easier to create a new formula that meets these requirements. 38 | 39 | If you're working on a complex Formula and you're having trouble implementing everything within a single method, you can use additional *private static* methods, *static* variables, and even *nested classes*. 40 | 41 | ### Supported parameter types 42 | 43 | * Int 44 | * Float 45 | * String 46 | * Bool 47 | * Rect 48 | * RectOffset 49 | * Vector2 50 | * Vector3 51 | * Vector4 52 | * Color 53 | * UnityEngine.Object 54 | * Enum 55 | * LayerMask 56 | * More to come soon 57 | 58 | ### Submitting Formulas 59 | 1. Create a copy of the FormulaTemplate.cs file that you can find in the [Editor Formulas Window repository](https://github.com/VoxelBoy/EditorFormulasWindow). 60 | 2. Choose a unique name for your Formula that's descriptive of what it does. Rename the file and the class with the CamelCase version of your Formula name. 61 | 3. Modify the FormulaAttribute on the already existing Run method to pass it the formula name, tooltip, and author name. 62 | 4. Fork this repository and submit your Formula as a pull request. 63 | 5. Your Formula will be quickly reviewed. If it's not directly accepted, you will be contacted to correct any issues found. 64 | -------------------------------------------------------------------------------- /GroundSelectedObjects.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using UnityEditor; 3 | using System.Collections.Generic; 4 | 5 | namespace EditorFormulas.Formulas 6 | { 7 | public static class GroundSelectedObjects { 8 | 9 | //Assumes gravity in -Y direction 10 | //Does 4 raycasts, one from each corner of the bottom of the bounds 11 | [FormulaAttribute ("Ground Selected Objects", "Tries to place the selected objects on whatever surface is beneath them", "VoxelBoy")] 12 | public static void Run(float distanceFromGround, LayerMask raycastLayerMask) 13 | { 14 | var selectedSceneObjects = Selection.GetFiltered(typeof(Transform), SelectionMode.Editable | SelectionMode.ExcludePrefab); 15 | if(selectedSceneObjects.Length == 0) 16 | { 17 | Debug.Log("No transforms among selected objects."); 18 | return; 19 | } 20 | foreach(Transform t in selectedSceneObjects) 21 | { 22 | var colliders = new List(); 23 | //Add the colliders on the root game object 24 | var collidersOnRoot = t.GetComponents(); 25 | colliders.AddRange(collidersOnRoot); 26 | //Add the colliders in the children 27 | t.GetComponentsInChildren(colliders); 28 | if(colliders.Count == 0) 29 | { 30 | Debug.Log("Skipping because no colliders found on " + t.name); 31 | continue; 32 | } 33 | //Start with the first collider's bounds 34 | Bounds bounds = colliders[0].bounds; 35 | for(int i=1; i