├── .gitignore ├── Assets ├── 01_MenuItems.meta ├── 01_MenuItems │ ├── 01.unity │ ├── 01.unity.meta │ ├── CubePrefab.prefab │ ├── CubePrefab.prefab.meta │ ├── Editor.meta │ ├── Editor │ │ ├── PlayerPrefsEditor.cs │ │ ├── PlayerPrefsEditor.cs.meta │ │ ├── SpecialPathEditor.cs │ │ ├── SpecialPathEditor.cs.meta │ │ ├── TextureProcessor.cs │ │ └── TextureProcessor.cs.meta │ ├── MyMonoBehaviour.cs │ ├── MyMonoBehaviour.cs.meta │ ├── a.png │ └── a.png.meta ├── 02_ScriptableWizard.meta ├── 02_ScriptableWizard │ ├── Editor.meta │ └── Editor │ │ ├── SelectAllOfTag.cs │ │ └── SelectAllOfTag.cs.meta ├── 03_EditorWindow.meta ├── 03_EditorWindow │ ├── Editor.meta │ ├── Editor │ │ ├── IHasCustomMenuWindow.cs │ │ ├── IHasCustomMenuWindow.cs.meta │ │ ├── MultipleWindow.cs │ │ ├── MultipleWindow.cs.meta │ │ ├── PopupWindow.cs │ │ ├── PopupWindow.cs.meta │ │ ├── PreferenceItemExample.cs │ │ ├── PreferenceItemExample.cs.meta │ │ ├── ShowAsDropDownWindow.cs │ │ ├── ShowAsDropDownWindow.cs.meta │ │ ├── ShowAuxWindow.cs │ │ ├── ShowAuxWindow.cs.meta │ │ ├── ShowPopupWindow.cs │ │ ├── ShowPopupWindow.cs.meta │ │ ├── SingleWindow.cs │ │ ├── SingleWindow.cs.meta │ │ ├── UtilityWindow.cs │ │ └── UtilityWindow.cs.meta │ ├── sprites.png │ └── sprites.png.meta ├── 04_SaveData.meta ├── 04_SaveData │ ├── Editor.meta │ └── Editor │ │ ├── EditorPrefsWindow.cs │ │ └── EditorPrefsWindow.cs.meta ├── 05_PropertyDrawer.meta ├── 05_PropertyDrawer │ ├── 05.unity │ ├── 05.unity.meta │ ├── DefaultPropertyDrawer.cs │ ├── DefaultPropertyDrawer.cs.meta │ ├── Editor.meta │ ├── Editor │ │ ├── PopupDrawer.cs │ │ ├── PopupDrawer.cs.meta │ │ ├── ScaledCurveDrawer.cs │ │ └── ScaledCurveDrawer.cs.meta │ ├── PopupAttribute.cs │ ├── PopupAttribute.cs.meta │ ├── PopupDrawerDemo.cs │ ├── PopupDrawerDemo.cs.meta │ ├── ScaledCurve.cs │ ├── ScaledCurve.cs.meta │ ├── ScaledCurveDemo.cs │ └── ScaledCurveDemo.cs.meta ├── 06_DecoratorDrawer.meta ├── 06_DecoratorDrawer │ ├── 06.unity │ ├── 06.unity.meta │ ├── ColorSpacer.cs │ ├── ColorSpacer.cs.meta │ ├── DecoratorDrawerDemo.cs │ ├── DecoratorDrawerDemo.cs.meta │ ├── Editor.meta │ └── Editor │ │ ├── ColorSpacerDrawer.cs │ │ └── ColorSpacerDrawer.cs.meta ├── 07_CustomEditor.meta ├── 07_CustomEditor │ ├── 07.unity │ ├── 07.unity.meta │ ├── Editor.meta │ ├── Editor │ │ ├── ExposeProperties.cs │ │ ├── ExposeProperties.cs.meta │ │ ├── MyPlayerEditor.cs │ │ ├── MyPlayerEditor.cs.meta │ │ ├── MyTypeEditor.cs │ │ ├── MyTypeEditor.cs.meta │ │ ├── PropertyInspectorEditor.cs │ │ ├── PropertyInspectorEditor.cs.meta │ │ ├── TransformEditor.cs │ │ └── TransformEditor.cs.meta │ ├── ExposePropertyAttribute.cs │ ├── ExposePropertyAttribute.cs.meta │ ├── MyPlayer.cs │ ├── MyPlayer.cs.meta │ ├── MyType.cs │ └── MyType.cs.meta ├── 08_Gizmos.meta ├── 08_Gizmos │ ├── 08.unity │ ├── 08.unity.meta │ ├── Editor.meta │ ├── Editor │ │ ├── GridEditor.cs │ │ └── GridEditor.cs.meta │ ├── GizmosDemo1.cs │ ├── GizmosDemo1.cs.meta │ ├── GizmosDemo2.cs │ ├── GizmosDemo2.cs.meta │ ├── Grid.cs │ ├── Grid.cs.meta │ ├── Tile.prefab │ └── Tile.prefab.meta ├── 09_SceneView.meta ├── 09_SceneView │ ├── 09.unity │ ├── 09.unity.meta │ ├── Editor.meta │ ├── Editor │ │ ├── EffectLayerCustom.cs │ │ ├── EffectLayerCustom.cs.meta │ │ ├── MeshVisualizeWindow.cs │ │ └── MeshVisualizeWindow.cs.meta │ ├── EffectLayer.cs │ └── EffectLayer.cs.meta ├── 10_Hierarchy.meta ├── 10_Hierarchy │ ├── 10.unity │ ├── 10.unity.meta │ ├── Editor.meta │ ├── Editor │ │ ├── HierarchyDemo.cs │ │ └── HierarchyDemo.cs.meta │ ├── HierarchyItem.cs │ └── HierarchyItem.cs.meta ├── ExplosionShape.meta └── ExplosionShape │ ├── BigExplode.asset │ ├── BigExplode.asset.meta │ ├── Editor.meta │ ├── Editor │ ├── ExplosionShapeEditor.cs │ └── ExplosionShapeEditor.cs.meta │ ├── ExplosionShape.cs │ ├── ExplosionShape.cs.meta │ ├── ExplosionShapeScene.unity │ ├── ExplosionShapeScene.unity.meta │ ├── SmallExplode.asset │ └── SmallExplode.asset.meta ├── ProjectSettings ├── AudioManager.asset ├── ClusterInputManager.asset ├── DynamicsManager.asset ├── EditorBuildSettings.asset ├── EditorSettings.asset ├── GraphicsSettings.asset ├── InputManager.asset ├── NavMeshAreas.asset ├── NetworkManager.asset ├── Physics2DSettings.asset ├── ProjectSettings.asset ├── ProjectVersion.txt ├── QualitySettings.asset ├── TagManager.asset ├── TimeManager.asset ├── UnityAdsSettings.asset └── UnityConnectSettings.asset └── readme.md /.gitignore: -------------------------------------------------------------------------------- 1 | /[Ll]ibrary/ 2 | /[Tt]emp/ 3 | /[Oo]bj/ 4 | /[Bb]uild/ 5 | /[Bb]uilds/ 6 | /Assets/AssetStoreTools* 7 | 8 | # Autogenerated VS/MD solution and project files 9 | ExportedObj/ 10 | *.csproj 11 | *.unityproj 12 | *.sln 13 | *.suo 14 | *.tmp 15 | *.user 16 | *.userprefs 17 | *.pidb 18 | *.booproj 19 | *.svd 20 | 21 | 22 | # Unity3D generated meta files 23 | *.pidb.meta 24 | 25 | # Unity3D Generated File On Crash Reports 26 | sysinfo.txt 27 | 28 | # Builds 29 | *.apk 30 | *.unitypackage 31 | -------------------------------------------------------------------------------- /Assets/01_MenuItems.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: b9a66dcd5ca3f4f0b94a2649c4fdc673 3 | folderAsset: yes 4 | timeCreated: 1482134846 5 | licenseType: Pro 6 | DefaultImporter: 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/01_MenuItems/01.unity: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/minhhh/unity-editorextension-manual/63f7107faba2791aea5832f87ea3a414fc2b46fc/Assets/01_MenuItems/01.unity -------------------------------------------------------------------------------- /Assets/01_MenuItems/01.unity.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: b72eba7826f384aecbea264a52cc1ac2 3 | timeCreated: 1482137858 4 | licenseType: Pro 5 | DefaultImporter: 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Assets/01_MenuItems/CubePrefab.prefab: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/minhhh/unity-editorextension-manual/63f7107faba2791aea5832f87ea3a414fc2b46fc/Assets/01_MenuItems/CubePrefab.prefab -------------------------------------------------------------------------------- /Assets/01_MenuItems/CubePrefab.prefab.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 823ef5c31b2d24ff0846f3cd3e07de24 3 | timeCreated: 1482143259 4 | licenseType: Pro 5 | NativeFormatImporter: 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Assets/01_MenuItems/Editor.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: c26bcf21fff5d4e1e853740d07254aec 3 | folderAsset: yes 4 | timeCreated: 1482135738 5 | licenseType: Pro 6 | DefaultImporter: 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/01_MenuItems/Editor/PlayerPrefsEditor.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using UnityEditor; 3 | 4 | public class MenuItems 5 | { 6 | [MenuItem ("Tools/Clear PlayerPrefs %g")] 7 | private static void ClearPlayerPrefs () 8 | { 9 | PlayerPrefs.DeleteAll (); 10 | } 11 | 12 | [MenuItem ("Tools/Option1", false, 1)] 13 | private static void NewMenuOption () 14 | { 15 | } 16 | 17 | [MenuItem ("Tools/Option2", false, 2)] 18 | private static void NewMenuOption2 () 19 | { 20 | } 21 | 22 | [MenuItem ("Tools/Option3", false, 3)] 23 | private static void NewMenuOption3 () 24 | { 25 | } 26 | 27 | [MenuItem ("Tools/Option4", false, 51)] 28 | private static void NewMenuOption4 () 29 | { 30 | } 31 | 32 | [MenuItem ("Tools/Option5", false, 52)] 33 | private static void NewMenuOption5 () 34 | { 35 | } 36 | } -------------------------------------------------------------------------------- /Assets/01_MenuItems/Editor/PlayerPrefsEditor.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 890af22919eaa47d397b1a6dc179e6a9 3 | timeCreated: 1482135727 4 | licenseType: Pro 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/01_MenuItems/Editor/SpecialPathEditor.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using System.Collections; 3 | using UnityEditor; 4 | 5 | public class SpecialPathEditor : MonoBehaviour 6 | { 7 | 8 | [MenuItem ("Assets/Load Additive Scene")] 9 | private static void LoadAdditiveScene () 10 | { 11 | var selected = Selection.activeObject; 12 | EditorApplication.OpenSceneAdditive (AssetDatabase.GetAssetPath (selected)); 13 | } 14 | 15 | // Adding a new menu item under Assets/Create 16 | 17 | [MenuItem ("Assets/Create/Add Configuration")] 18 | private static void AddConfig () 19 | { 20 | // Create and add a new ScriptableObject for storing configuration 21 | } 22 | 23 | // Add a new menu item that is accessed by right-clicking inside the RigidBody component 24 | 25 | [MenuItem ("CONTEXT/Rigidbody/New Option")] 26 | private static void NewOpenForRigidBody (MenuCommand menuCommand) 27 | { 28 | var rigid = menuCommand.context as Rigidbody; 29 | Debug.Log ("Change rigidbody " + rigid); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /Assets/01_MenuItems/Editor/SpecialPathEditor.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 1229701d0f9304d1a8ec51eaff588726 3 | timeCreated: 1482137811 4 | licenseType: Pro 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/01_MenuItems/Editor/TextureProcessor.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using System.Collections; 3 | using UnityEditor; 4 | 5 | public class TextureProcessor 6 | { 7 | [MenuItem ("Assets/ProcessTexture")] 8 | private static void DoSomethingWithTexture () 9 | { 10 | } 11 | 12 | // Note that we pass the same path, and also pass "true" to the second argument. 13 | [MenuItem ("Assets/ProcessTexture", true)] 14 | private static bool NewMenuOptionValidation () 15 | { 16 | // This returns true when the selected object is a Texture2D (the menu item will be disabled otherwise). 17 | return Selection.activeObject.GetType () == typeof(Texture2D); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /Assets/01_MenuItems/Editor/TextureProcessor.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 8e5ff0ae767404feebb10a01817cb202 3 | timeCreated: 1482142694 4 | licenseType: Pro 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/01_MenuItems/MyMonoBehaviour.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using System.Collections; 3 | 4 | [AddComponentMenu ("My/SuperMonoBehaviour")] 5 | public class MyMonoBehaviour : MonoBehaviour 6 | { 7 | [ContextMenuItem ("Reset", "ResetBiography")] 8 | public string playerBiography = ""; 9 | 10 | public string name = ""; 11 | 12 | [ContextMenu ("Reset Name")] 13 | private void ResetName () 14 | { 15 | name = string.Empty; 16 | } 17 | 18 | void ResetBiography () 19 | { 20 | playerBiography = ""; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Assets/01_MenuItems/MyMonoBehaviour.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: b345b096aea764c19b34015623d21142 3 | timeCreated: 1482136823 4 | licenseType: Pro 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/01_MenuItems/a.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/minhhh/unity-editorextension-manual/63f7107faba2791aea5832f87ea3a414fc2b46fc/Assets/01_MenuItems/a.png -------------------------------------------------------------------------------- /Assets/01_MenuItems/a.png.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: f5067733efc004c3c80db20ba5214e0d 3 | timeCreated: 1482143233 4 | licenseType: Pro 5 | TextureImporter: 6 | fileIDToRecycleName: {} 7 | serializedVersion: 2 8 | mipmaps: 9 | mipMapMode: 0 10 | enableMipMap: 1 11 | linearTexture: 0 12 | correctGamma: 0 13 | fadeOut: 0 14 | borderMipMap: 0 15 | mipMapFadeDistanceStart: 1 16 | mipMapFadeDistanceEnd: 3 17 | bumpmap: 18 | convertToNormalMap: 0 19 | externalNormalMap: 0 20 | heightScale: 0.25 21 | normalMapFilter: 0 22 | isReadable: 0 23 | grayScaleToAlpha: 0 24 | generateCubemap: 0 25 | cubemapConvolution: 0 26 | cubemapConvolutionSteps: 7 27 | cubemapConvolutionExponent: 1.5 28 | seamlessCubemap: 0 29 | textureFormat: -1 30 | maxTextureSize: 2048 31 | textureSettings: 32 | filterMode: -1 33 | aniso: -1 34 | mipBias: -1 35 | wrapMode: -1 36 | nPOTScale: 1 37 | lightmap: 0 38 | rGBM: 0 39 | compressionQuality: 50 40 | allowsAlphaSplitting: 0 41 | spriteMode: 0 42 | spriteExtrude: 1 43 | spriteMeshType: 1 44 | alignment: 0 45 | spritePivot: {x: 0.5, y: 0.5} 46 | spriteBorder: {x: 0, y: 0, z: 0, w: 0} 47 | spritePixelsToUnits: 100 48 | alphaIsTransparency: 0 49 | spriteTessellationDetail: -1 50 | textureType: -1 51 | buildTargetSettings: [] 52 | spriteSheet: 53 | serializedVersion: 2 54 | sprites: [] 55 | outline: [] 56 | spritePackingTag: 57 | userData: 58 | assetBundleName: 59 | assetBundleVariant: 60 | -------------------------------------------------------------------------------- /Assets/02_ScriptableWizard.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 887c50a702e154b52b1d5904b999fb36 3 | folderAsset: yes 4 | timeCreated: 1482204222 5 | licenseType: Pro 6 | DefaultImporter: 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/02_ScriptableWizard/Editor.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: fb9643e8f35fd40ba88e485fb9e5b880 3 | folderAsset: yes 4 | timeCreated: 1482204905 5 | licenseType: Pro 6 | DefaultImporter: 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/02_ScriptableWizard/Editor/SelectAllOfTag.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using System.Collections; 3 | using UnityEditor; 4 | using System; 5 | 6 | public class SelectAllOfTag : ScriptableWizard 7 | { 8 | public string searchTag = ""; 9 | 10 | [MenuItem ("Tools/Select All Of Tag")] 11 | public static void SelectAllOfTagWizard () 12 | { 13 | ScriptableWizard.DisplayWizard ("Select All of Tag...", "Reset", "Make Selection"); 14 | } 15 | 16 | void OnWizardCreate () 17 | { 18 | searchTag = ""; 19 | SelectGameObjectsByTag (searchTag); 20 | } 21 | 22 | void OnWizardOtherButton () 23 | { 24 | SelectGameObjectsByTag (searchTag); 25 | } 26 | 27 | void SelectGameObjectsByTag (string tag) 28 | { 29 | try { 30 | GameObject[] gameObjects = GameObject.FindGameObjectsWithTag (tag); 31 | Selection.objects = gameObjects; 32 | } catch (Exception e) { 33 | Selection.objects = new GameObject[0]; 34 | } 35 | 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /Assets/02_ScriptableWizard/Editor/SelectAllOfTag.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: eca2083cfad1d4c9e89edb960a0420ef 3 | timeCreated: 1482204866 4 | licenseType: Pro 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/03_EditorWindow.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: bc8ec5151950c4c7d9319a95fddaf70c 3 | folderAsset: yes 4 | timeCreated: 1482208598 5 | licenseType: Pro 6 | DefaultImporter: 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/03_EditorWindow/Editor.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: a6d236a9493114c48a58954bde677544 3 | folderAsset: yes 4 | timeCreated: 1482208605 5 | licenseType: Pro 6 | DefaultImporter: 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/03_EditorWindow/Editor/IHasCustomMenuWindow.cs: -------------------------------------------------------------------------------- 1 | using UnityEditor; 2 | using UnityEngine; 3 | 4 | public class IHasCustomMenuWindow : EditorWindow, IHasCustomMenu 5 | { 6 | bool locked = true; 7 | public void AddItemsToMenu (GenericMenu menu) 8 | { 9 | menu.AddItem (new GUIContent ("example"), false, () => { 10 | 11 | }); 12 | 13 | menu.AddItem (new GUIContent ("example2"), locked, () => { 14 | locked = !locked; 15 | }); 16 | } 17 | 18 | [MenuItem ("Window/IHasCustomMenuWindow")] 19 | static void Open () 20 | { 21 | GetWindow (); 22 | } 23 | } -------------------------------------------------------------------------------- /Assets/03_EditorWindow/Editor/IHasCustomMenuWindow.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 836b304af790c40399bdada1f9cf06d0 3 | timeCreated: 1482222343 4 | licenseType: Pro 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/03_EditorWindow/Editor/MultipleWindow.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using System.Collections; 3 | using UnityEditor; 4 | 5 | public class MultipleWindow : EditorWindow 6 | { 7 | [MenuItem ("Window/MultipleWindow")] 8 | static void Open () 9 | { 10 | var exampleWindow = CreateInstance (); 11 | exampleWindow.Show (); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /Assets/03_EditorWindow/Editor/MultipleWindow.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: aeadd1619930a471b85de954935ae6f2 3 | timeCreated: 1482208626 4 | licenseType: Pro 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/03_EditorWindow/Editor/PopupWindow.cs: -------------------------------------------------------------------------------- 1 | using UnityEditor; 2 | using UnityEngine; 3 | 4 | public class SamplePopupWindow : EditorWindow 5 | { 6 | [MenuItem ("Window/PopupWindow")] 7 | static void Open () 8 | { 9 | GetWindow (); 10 | } 11 | 12 | ExamplePupupContent popupContent = new ExamplePupupContent (); 13 | 14 | void OnGUI () 15 | { 16 | if (GUILayout.Button ("PopupContent", GUILayout.Width (128))) { 17 | var activatorRect = GUILayoutUtility.GetLastRect (); 18 | 19 | PopupWindow.Show (new Rect (activatorRect.x, activatorRect.y + 10, activatorRect.width, activatorRect.height), popupContent); 20 | } 21 | } 22 | } 23 | 24 | public class ExamplePupupContent : PopupWindowContent 25 | { 26 | public override void OnGUI (Rect rect) 27 | { 28 | EditorGUILayout.LabelField ("Label"); 29 | } 30 | 31 | public override void OnOpen () 32 | { 33 | Debug.Log ("OnOpen"); 34 | } 35 | 36 | public override void OnClose () 37 | { 38 | Debug.Log ("OnClose"); 39 | } 40 | 41 | public override Vector2 GetWindowSize () 42 | { 43 | return new Vector2 (300, 100); 44 | } 45 | } -------------------------------------------------------------------------------- /Assets/03_EditorWindow/Editor/PopupWindow.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 7389f399782564af8b8d423ccce77094 3 | timeCreated: 1482218709 4 | licenseType: Pro 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/03_EditorWindow/Editor/PreferenceItemExample.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using System.Collections; 3 | using UnityEditor; 4 | 5 | public class PreferenceItemExample : MonoBehaviour 6 | { 7 | [PreferenceItem ("Example")] 8 | static void OnPreferenceGUI () 9 | { 10 | 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Assets/03_EditorWindow/Editor/PreferenceItemExample.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: da9ba6dc2b5b143e5b7f64d631553cfe 3 | timeCreated: 1482220659 4 | licenseType: Pro 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/03_EditorWindow/Editor/ShowAsDropDownWindow.cs: -------------------------------------------------------------------------------- 1 | using UnityEditor; 2 | using UnityEngine; 3 | 4 | public class ShowAsDropDownWindow : EditorWindow 5 | { 6 | static ShowAsDropDownWindow exampleWindow; 7 | 8 | [MenuItem("Window/ShowAsDropDownWindow")] 9 | static void Open () 10 | { 11 | if (exampleWindow == null) { 12 | exampleWindow = CreateInstance (); 13 | } 14 | 15 | var buttonRect = new Rect (1800, 1300, 300, 100); 16 | var windowSize = new Vector2 (300, 100); 17 | exampleWindow.ShowAsDropDown (buttonRect, windowSize); 18 | } 19 | } -------------------------------------------------------------------------------- /Assets/03_EditorWindow/Editor/ShowAsDropDownWindow.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: f90ff2361ce4248efa6ecf807b389df7 3 | timeCreated: 1482220086 4 | licenseType: Pro 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/03_EditorWindow/Editor/ShowAuxWindow.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using System.Collections; 3 | using UnityEditor; 4 | 5 | public class ShowAuxWindow : EditorWindow 6 | { 7 | [MenuItem ("Window/AuxWindow")] 8 | static void Open () 9 | { 10 | var exampleWindow = CreateInstance (); 11 | exampleWindow.ShowAuxWindow (); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /Assets/03_EditorWindow/Editor/ShowAuxWindow.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: c2ca85bf7323b41d496f0ec69cae780d 3 | timeCreated: 1482219759 4 | licenseType: Pro 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/03_EditorWindow/Editor/ShowPopupWindow.cs: -------------------------------------------------------------------------------- 1 | using UnityEditor; 2 | using UnityEngine; 3 | 4 | public class ShowPopupWindow : EditorWindow 5 | { 6 | static ShowPopupWindow exampleWindow; 7 | 8 | [MenuItem ("Window/ShowPopupWindow")] 9 | static void Open () 10 | { 11 | if (exampleWindow == null) { 12 | exampleWindow = CreateInstance (); 13 | } 14 | exampleWindow.ShowPopup (); 15 | } 16 | 17 | 18 | void OnGUI () 19 | { 20 | if (Event.current.keyCode == KeyCode.Escape) { 21 | exampleWindow.Close (); 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /Assets/03_EditorWindow/Editor/ShowPopupWindow.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: f2b7fb42c58f74f5b8f420d4bf13eea2 3 | timeCreated: 1482209987 4 | licenseType: Pro 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/03_EditorWindow/Editor/SingleWindow.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using System.Collections; 3 | using UnityEditor; 4 | 5 | public class SingleWindow : EditorWindow 6 | { 7 | [MenuItem("Window/SingleWindow")] 8 | static void Open () 9 | { 10 | GetWindow (); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Assets/03_EditorWindow/Editor/SingleWindow.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 3959be38a0bca493ebb250e7ffa27f06 3 | timeCreated: 1482208845 4 | licenseType: Pro 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/03_EditorWindow/Editor/UtilityWindow.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using System.Collections; 3 | using UnityEditor; 4 | 5 | public class UtilityWindow : EditorWindow 6 | { 7 | [MenuItem ("Window/UtilityWindow")] 8 | static void Open () 9 | { 10 | GetWindow (true); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Assets/03_EditorWindow/Editor/UtilityWindow.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 061b9ef96a54c4b44a8540fff549d959 3 | timeCreated: 1482209336 4 | licenseType: Pro 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/03_EditorWindow/sprites.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/minhhh/unity-editorextension-manual/63f7107faba2791aea5832f87ea3a414fc2b46fc/Assets/03_EditorWindow/sprites.png -------------------------------------------------------------------------------- /Assets/03_EditorWindow/sprites.png.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 9da347109bf2047d0b46ef54275d720d 3 | timeCreated: 1482143233 4 | licenseType: Pro 5 | TextureImporter: 6 | fileIDToRecycleName: {} 7 | serializedVersion: 2 8 | mipmaps: 9 | mipMapMode: 0 10 | enableMipMap: 0 11 | linearTexture: 0 12 | correctGamma: 0 13 | fadeOut: 0 14 | borderMipMap: 0 15 | mipMapFadeDistanceStart: 1 16 | mipMapFadeDistanceEnd: 3 17 | bumpmap: 18 | convertToNormalMap: 0 19 | externalNormalMap: 0 20 | heightScale: 0.25 21 | normalMapFilter: 0 22 | isReadable: 0 23 | grayScaleToAlpha: 0 24 | generateCubemap: 0 25 | cubemapConvolution: 0 26 | cubemapConvolutionSteps: 7 27 | cubemapConvolutionExponent: 1.5 28 | seamlessCubemap: 0 29 | textureFormat: -1 30 | maxTextureSize: 2048 31 | textureSettings: 32 | filterMode: -1 33 | aniso: -1 34 | mipBias: -1 35 | wrapMode: -1 36 | nPOTScale: 1 37 | lightmap: 0 38 | rGBM: 0 39 | compressionQuality: 50 40 | allowsAlphaSplitting: 0 41 | spriteMode: 2 42 | spriteExtrude: 1 43 | spriteMeshType: 1 44 | alignment: 0 45 | spritePivot: {x: 0.5, y: 0.5} 46 | spriteBorder: {x: 0, y: 0, z: 0, w: 0} 47 | spritePixelsToUnits: 100 48 | alphaIsTransparency: 0 49 | spriteTessellationDetail: -1 50 | textureType: 5 51 | buildTargetSettings: [] 52 | spriteSheet: 53 | serializedVersion: 2 54 | sprites: [] 55 | outline: [] 56 | spritePackingTag: 57 | userData: 58 | assetBundleName: 59 | assetBundleVariant: 60 | -------------------------------------------------------------------------------- /Assets/04_SaveData.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 038d5dab4de86443a8e014f1b3bf4884 3 | folderAsset: yes 4 | timeCreated: 1482224533 5 | licenseType: Pro 6 | DefaultImporter: 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/04_SaveData/Editor.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 2ce6157a2d60d45bc8f7c13f512cd5e2 3 | folderAsset: yes 4 | timeCreated: 1482224540 5 | licenseType: Pro 6 | DefaultImporter: 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/04_SaveData/Editor/EditorPrefsWindow.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using UnityEditor; 3 | 4 | public class EditorPrefsWindow : EditorWindow 5 | { 6 | int someValue = 1; 7 | const string SOME_KEY = "KEY"; 8 | 9 | 10 | [MenuItem ("Window/EditorPrefsWindow")] 11 | static void Open () 12 | { 13 | GetWindow (); 14 | } 15 | 16 | void OnEnable () 17 | { 18 | someValue = EditorPrefs.GetInt (SOME_KEY, 1); 19 | } 20 | 21 | void OnGUI () 22 | { 23 | EditorGUI.BeginChangeCheck (); 24 | 25 | someValue = EditorGUILayout.IntSlider ("My Value", someValue, 1, 100); 26 | 27 | if (EditorGUI.EndChangeCheck ()) { 28 | EditorPrefs.SetInt (SOME_KEY, someValue); 29 | } 30 | 31 | } 32 | } -------------------------------------------------------------------------------- /Assets/04_SaveData/Editor/EditorPrefsWindow.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 36e01987d57664f45b43b846a110262d 3 | timeCreated: 1482224560 4 | licenseType: Pro 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/05_PropertyDrawer.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 8dfcd51c370354c81b8949641d008f3c 3 | folderAsset: yes 4 | timeCreated: 1482230215 5 | licenseType: Pro 6 | DefaultImporter: 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/05_PropertyDrawer/05.unity: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/minhhh/unity-editorextension-manual/63f7107faba2791aea5832f87ea3a414fc2b46fc/Assets/05_PropertyDrawer/05.unity -------------------------------------------------------------------------------- /Assets/05_PropertyDrawer/05.unity.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: d47faf8b50e904eb6b162496d30fd6e1 3 | timeCreated: 1482287712 4 | licenseType: Pro 5 | DefaultImporter: 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Assets/05_PropertyDrawer/DefaultPropertyDrawer.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using System.Collections; 3 | 4 | public class DefaultPropertyDrawer : MonoBehaviour 5 | { 6 | [Range (1, 10)] 7 | [Tooltip("Value between 1 and 10.")] 8 | public int num1; 9 | 10 | [Range (1, 10)] 11 | public float num2; 12 | 13 | [Multiline(5)] 14 | public string multiline; 15 | 16 | [TextArea(3, 5)] 17 | public string textArea; 18 | 19 | [ColorUsage (false)] 20 | public Color color2; 21 | 22 | [ColorUsage (true, true, 0, 8, 0.125f, 3)] 23 | public Color color3; 24 | 25 | [HideInInspector] 26 | public string str1; 27 | } 28 | -------------------------------------------------------------------------------- /Assets/05_PropertyDrawer/DefaultPropertyDrawer.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 17fc89ce28c294b529982bba02e50a57 3 | timeCreated: 1482287638 4 | licenseType: Pro 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/05_PropertyDrawer/Editor.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 2d84d9dd824c448c0b406b391158ea3c 3 | folderAsset: yes 4 | timeCreated: 1482287611 5 | licenseType: Pro 6 | DefaultImporter: 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/05_PropertyDrawer/Editor/PopupDrawer.cs: -------------------------------------------------------------------------------- 1 | using UnityEditor; 2 | using UnityEngine; 3 | using System; 4 | 5 | /// 6 | /// Taken from https://github.com/anchan828/property-drawer-collection/blob/master/Popup/PopupAttribute.cs 7 | /// 8 | [CustomPropertyDrawer (typeof(PopupAttribute))] 9 | public class PopupDrawer : PropertyDrawer 10 | { 11 | private Action setValue; 12 | private Func validateValue; 13 | protected string[] _list = null; 14 | 15 | public virtual string[] list { 16 | get { 17 | if (_list == null) { 18 | _list = new string[popupAttribute.list.Length]; 19 | 20 | for (int i = 0; i < popupAttribute.list.Length; i++) { 21 | _list [i] = popupAttribute.list [i].ToString (); 22 | } 23 | } 24 | 25 | return _list; 26 | } 27 | } 28 | 29 | public override void OnGUI (Rect position, SerializedProperty property, GUIContent label) 30 | { 31 | if (validateValue == null && setValue == null) 32 | SetUp (property); 33 | 34 | 35 | if (validateValue == null && setValue == null) { 36 | base.OnGUI (position, property, label); 37 | return; 38 | } 39 | 40 | int selectedIndex = 0; 41 | 42 | for (int i = 0; i < list.Length; i++) { 43 | selectedIndex = validateValue (i); 44 | 45 | if (selectedIndex != 0) 46 | break; 47 | } 48 | 49 | EditorGUI.BeginChangeCheck (); 50 | selectedIndex = EditorGUI.Popup (position, label.text, selectedIndex, list); 51 | 52 | if (EditorGUI.EndChangeCheck ()) { 53 | setValue (selectedIndex); 54 | } 55 | } 56 | 57 | void SetUp (SerializedProperty property) 58 | { 59 | if (variableType == typeof(string)) { 60 | 61 | validateValue = (index) => { 62 | return property.stringValue == list [index] ? index : 0; 63 | }; 64 | 65 | setValue = (index) => { 66 | property.stringValue = list [index]; 67 | }; 68 | } else if (variableType == typeof(int)) { 69 | 70 | validateValue = (index) => { 71 | return property.intValue == Convert.ToInt32 (list [index]) ? index : 0; 72 | }; 73 | 74 | setValue = (index) => { 75 | property.intValue = Convert.ToInt32 (list [index]); 76 | }; 77 | } else if (variableType == typeof(float)) { 78 | validateValue = (index) => { 79 | return Mathf.Approximately (property.floatValue, Convert.ToSingle (list [index])) ? index : 0; 80 | }; 81 | setValue = (index) => { 82 | property.floatValue = Convert.ToSingle (list [index]); 83 | }; 84 | } 85 | 86 | } 87 | 88 | PopupAttribute popupAttribute { 89 | get { return (PopupAttribute)attribute; } 90 | } 91 | 92 | private Type variableType { 93 | get { 94 | return list [0].GetType (); 95 | } 96 | } 97 | } -------------------------------------------------------------------------------- /Assets/05_PropertyDrawer/Editor/PopupDrawer.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: c33c6cd12d1e3435bb35f403ed738814 3 | timeCreated: 1482288630 4 | licenseType: Pro 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/05_PropertyDrawer/Editor/ScaledCurveDrawer.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using UnityEditor; 3 | 4 | [CustomPropertyDrawer (typeof(ScaledCurve))] 5 | public class ScaledCurveDrawer : PropertyDrawer 6 | { 7 | const int curveWidth = 50; 8 | const float min = 0; 9 | const float max = 1; 10 | 11 | public override void OnGUI (Rect pos, SerializedProperty prop, GUIContent label) 12 | { 13 | EditorGUI.BeginProperty (pos, label, prop); 14 | 15 | SerializedProperty scale = prop.FindPropertyRelative ("scale"); 16 | SerializedProperty curve = prop.FindPropertyRelative ("curve"); 17 | 18 | // Draw scale 19 | EditorGUI.Slider ( 20 | new Rect (pos.x, pos.y, pos.width - curveWidth, pos.height), 21 | scale, min, max, label); 22 | 23 | // Draw curve 24 | int indent = EditorGUI.indentLevel; 25 | EditorGUI.indentLevel = 0; 26 | EditorGUI.PropertyField ( 27 | new Rect (pos.width - curveWidth, pos.y, curveWidth, pos.height), 28 | curve, GUIContent.none); 29 | EditorGUI.indentLevel = indent; 30 | 31 | EditorGUI.EndProperty (); 32 | } 33 | 34 | } -------------------------------------------------------------------------------- /Assets/05_PropertyDrawer/Editor/ScaledCurveDrawer.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: dafa1dfa6232f4df2a18ddbb4140895b 3 | timeCreated: 1482291681 4 | licenseType: Pro 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/05_PropertyDrawer/PopupAttribute.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | 3 | public class PopupAttribute : PropertyAttribute 4 | { 5 | public object[] list; 6 | 7 | public PopupAttribute (params object[] list) 8 | { 9 | this.list = list; 10 | } 11 | } -------------------------------------------------------------------------------- /Assets/05_PropertyDrawer/PopupAttribute.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 50430b9faf0cc437c865de222135a832 3 | timeCreated: 1482288649 4 | licenseType: Pro 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/05_PropertyDrawer/PopupDrawerDemo.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using System.Collections; 3 | 4 | public class PopupDrawerDemo : MonoBehaviour 5 | { 6 | public string str1; 7 | 8 | [Popup ("value1", "value2", "value3")] 9 | public string str2; 10 | } 11 | -------------------------------------------------------------------------------- /Assets/05_PropertyDrawer/PopupDrawerDemo.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 865185afbfab34db89bfc7c98902fe04 3 | timeCreated: 1482288727 4 | licenseType: Pro 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/05_PropertyDrawer/ScaledCurve.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using System.Collections; 3 | 4 | // Custom serializable class 5 | [System.Serializable] 6 | public class ScaledCurve 7 | { 8 | public float scale = 1; 9 | public AnimationCurve curve = AnimationCurve.Linear (0, 0, 1, 1); 10 | } -------------------------------------------------------------------------------- /Assets/05_PropertyDrawer/ScaledCurve.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 10fdd0e9f97a7456e878e1defe1dc815 3 | timeCreated: 1482291712 4 | licenseType: Pro 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/05_PropertyDrawer/ScaledCurveDemo.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using System.Collections; 3 | 4 | public class ScaledCurveDemo : MonoBehaviour 5 | { 6 | public ScaledCurve myScaledCurve1; 7 | public ScaledCurve myScaledCurve2; 8 | } 9 | -------------------------------------------------------------------------------- /Assets/05_PropertyDrawer/ScaledCurveDemo.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: cfbaf86479984400da6dc6d653526019 3 | timeCreated: 1482291768 4 | licenseType: Pro 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/06_DecoratorDrawer.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 2495c6e1da13740d199024d324d35f27 3 | folderAsset: yes 4 | timeCreated: 1482293046 5 | licenseType: Pro 6 | DefaultImporter: 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/06_DecoratorDrawer/06.unity: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/minhhh/unity-editorextension-manual/63f7107faba2791aea5832f87ea3a414fc2b46fc/Assets/06_DecoratorDrawer/06.unity -------------------------------------------------------------------------------- /Assets/06_DecoratorDrawer/06.unity.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: bd9ae60e616674649a4fbf3433dd3d27 3 | timeCreated: 1482293934 4 | licenseType: Pro 5 | DefaultImporter: 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Assets/06_DecoratorDrawer/ColorSpacer.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using System.Collections; 3 | using UnityEditor; 4 | 5 | // This class defines the ColorSpacer attribute, so that 6 | // it can be used in your regular MonoBehaviour scripts: 7 | 8 | public class ColorSpacer : PropertyAttribute 9 | { 10 | public float spaceHeight; 11 | public float lineHeight; 12 | public float lineWidth; 13 | public Color lineColor = Color.red; 14 | 15 | public ColorSpacer (float spaceHeight, float lineHeight, float lineWidth, float r, float g, float b) 16 | { 17 | this.spaceHeight = spaceHeight; 18 | this.lineHeight = lineHeight; 19 | this.lineWidth = lineWidth; 20 | 21 | // unfortunately we can't pass a color through as a Color object 22 | // so we pass as 3 floats and make the object here 23 | this.lineColor = new Color (r, g, b); 24 | } 25 | } -------------------------------------------------------------------------------- /Assets/06_DecoratorDrawer/ColorSpacer.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 7752145268d97407ca655707b6e59d86 3 | timeCreated: 1482293280 4 | licenseType: Pro 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/06_DecoratorDrawer/DecoratorDrawerDemo.cs: -------------------------------------------------------------------------------- 1 |  2 | using UnityEngine; 3 | using System.Collections; 4 | 5 | public class DecoratorDrawerDemo : MonoBehaviour 6 | { 7 | public int a = 1; 8 | [Space(10)] 9 | public int b = 2; 10 | public int c = 3; 11 | 12 | // this shows our custom Decorator Drawer between the groups of properties 13 | [ColorSpacer (30, 3, 100, 1, 0, 0)] 14 | 15 | public string d = "d"; 16 | 17 | [Header ("New group")] 18 | public string e = "e"; 19 | public string f = "f"; 20 | 21 | } -------------------------------------------------------------------------------- /Assets/06_DecoratorDrawer/DecoratorDrawerDemo.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 36df1e1f2ff8b41b3bdc2d1dfb675071 3 | timeCreated: 1482293201 4 | licenseType: Pro 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/06_DecoratorDrawer/Editor.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: d93bf6615bff945f8a525050a718b48b 3 | folderAsset: yes 4 | timeCreated: 1482293052 5 | licenseType: Pro 6 | DefaultImporter: 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/06_DecoratorDrawer/Editor/ColorSpacerDrawer.cs: -------------------------------------------------------------------------------- 1 | // This defines how the ColorSpacer should be drawn 2 | // in the inspector, when inspecting a GameObject with 3 | // a MonoBehaviour which uses the ColorSpacer attribute 4 | using UnityEditor; 5 | using UnityEngine; 6 | 7 | [CustomPropertyDrawer (typeof(ColorSpacer))] 8 | public class ColorSpacerDrawer : DecoratorDrawer 9 | { 10 | 11 | ColorSpacer colorSpacer { 12 | get { return ((ColorSpacer)attribute); } 13 | } 14 | 15 | public override float GetHeight () 16 | { 17 | return base.GetHeight () + colorSpacer.spaceHeight; 18 | } 19 | 20 | public override void OnGUI (Rect position) 21 | { 22 | // calculate the rect values for where to draw the line in the inspector 23 | float lineX = (position.x + (position.width / 2)) - colorSpacer.lineWidth / 2; 24 | float lineY = position.y + (colorSpacer.spaceHeight / 2); 25 | float lineWidth = colorSpacer.lineWidth; 26 | float lineHeight = colorSpacer.lineHeight; 27 | 28 | // Draw the line in the calculated place in the inspector 29 | // (using the built in white pixel texture, tinted with GUI.color) 30 | Color oldGuiColor = GUI.color; 31 | GUI.color = colorSpacer.lineColor; 32 | EditorGUI.DrawPreviewTexture (new Rect (lineX, lineY, lineWidth, lineHeight), Texture2D.whiteTexture); 33 | GUI.color = oldGuiColor; 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /Assets/06_DecoratorDrawer/Editor/ColorSpacerDrawer.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: df8ded5181e9d464cadd3aa84b3f550c 3 | timeCreated: 1482293163 4 | licenseType: Pro 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/07_CustomEditor.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 431a3acaf4cd242618ac1f4227dd579a 3 | folderAsset: yes 4 | timeCreated: 1482317751 5 | licenseType: Pro 6 | DefaultImporter: 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/07_CustomEditor/07.unity: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/minhhh/unity-editorextension-manual/63f7107faba2791aea5832f87ea3a414fc2b46fc/Assets/07_CustomEditor/07.unity -------------------------------------------------------------------------------- /Assets/07_CustomEditor/07.unity.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 3d6323abf835441638e13a95e1362795 3 | timeCreated: 1482318275 4 | licenseType: Pro 5 | DefaultImporter: 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Assets/07_CustomEditor/Editor.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 0d6a66499e6694a578a6ec1e32f43911 3 | folderAsset: yes 4 | timeCreated: 1482317758 5 | licenseType: Pro 6 | DefaultImporter: 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/07_CustomEditor/Editor/ExposeProperties.cs: -------------------------------------------------------------------------------- 1 | using UnityEditor; 2 | using UnityEngine; 3 | using System; 4 | using System.Collections; 5 | using System.Collections.Generic; 6 | using System.Reflection; 7 | 8 | public static class ExposeProperties 9 | { 10 | public static void Expose (PropertyField[] properties) 11 | { 12 | var emptyOptions = new GUILayoutOption[0]; 13 | EditorGUILayout.BeginVertical (emptyOptions); 14 | foreach (PropertyField field in properties) { 15 | EditorGUILayout.BeginHorizontal (emptyOptions); 16 | if (field.Type == SerializedPropertyType.Integer) { 17 | var oldValue = (int)field.GetValue (); 18 | var newValue = EditorGUILayout.IntField (field.Name, oldValue, emptyOptions); 19 | if (oldValue != newValue) 20 | field.SetValue (newValue); 21 | } else if (field.Type == SerializedPropertyType.Float) { 22 | var oldValue = (float)field.GetValue (); 23 | var newValue = EditorGUILayout.FloatField (field.Name, oldValue, emptyOptions); 24 | if (Mathf.Approximately(oldValue, newValue)) 25 | field.SetValue (newValue); 26 | } else if (field.Type == SerializedPropertyType.Boolean) { 27 | var oldValue = (bool)field.GetValue (); 28 | var newValue = EditorGUILayout.Toggle (field.Name, oldValue, emptyOptions); 29 | if (oldValue != newValue) 30 | field.SetValue (newValue); 31 | } else if (field.Type == SerializedPropertyType.String) { 32 | var oldValue = (string)field.GetValue (); 33 | var newValue = EditorGUILayout.TextField (field.Name, oldValue, emptyOptions); 34 | if (oldValue != newValue) 35 | field.SetValue (newValue); 36 | } else if (field.Type == SerializedPropertyType.Vector2) { 37 | var oldValue = (Vector2)field.GetValue (); 38 | var newValue = EditorGUILayout.Vector2Field (field.Name, oldValue, emptyOptions); 39 | if (oldValue != newValue) 40 | field.SetValue (newValue); 41 | } else if (field.Type == SerializedPropertyType.Vector3) { 42 | var oldValue = (Vector3)field.GetValue (); 43 | var newValue = EditorGUILayout.Vector3Field (field.Name, oldValue, emptyOptions); 44 | if (oldValue != newValue) 45 | field.SetValue (newValue); 46 | } else if (field.Type == SerializedPropertyType.Enum) { 47 | var oldValue = (Enum)field.GetValue (); 48 | var newValue = EditorGUILayout.EnumPopup (field.Name, oldValue, emptyOptions); 49 | if (oldValue != newValue) 50 | field.SetValue (newValue); 51 | } 52 | EditorGUILayout.EndHorizontal (); 53 | } 54 | EditorGUILayout.EndVertical (); 55 | } 56 | 57 | public static PropertyField[] GetProperties (object obj) 58 | { 59 | var fields = new List (); 60 | 61 | PropertyInfo[] infos = obj.GetType ().GetProperties (BindingFlags.Public | BindingFlags.Instance); 62 | 63 | foreach (PropertyInfo info in infos) { 64 | if (!(info.CanRead && info.CanWrite)) 65 | continue; 66 | 67 | object[] attributes = info.GetCustomAttributes (true); 68 | 69 | bool isExposed = false; 70 | foreach (object o in attributes) 71 | if (o.GetType () == typeof(ExposePropertyAttribute)) { 72 | isExposed = true; 73 | break; 74 | } 75 | if (!isExposed) 76 | continue; 77 | 78 | var type = SerializedPropertyType.Integer; 79 | if (PropertyField.GetPropertyType (info, out type)) { 80 | var field = new PropertyField (obj, info, type); 81 | fields.Add (field); 82 | } 83 | } 84 | 85 | return fields.ToArray (); 86 | } 87 | } 88 | 89 | public class PropertyField 90 | { 91 | object obj; 92 | PropertyInfo info; 93 | SerializedPropertyType type; 94 | 95 | MethodInfo getter; 96 | MethodInfo setter; 97 | 98 | public SerializedPropertyType Type { 99 | get { return type; } 100 | } 101 | 102 | public String Name { 103 | get { return ObjectNames.NicifyVariableName (info.Name); } 104 | } 105 | 106 | public PropertyField (object obj, PropertyInfo info, SerializedPropertyType type) 107 | { 108 | this.obj = obj; 109 | this.info = info; 110 | this.type = type; 111 | 112 | getter = this.info.GetGetMethod (); 113 | setter = this.info.GetSetMethod (); 114 | } 115 | 116 | public object GetValue () 117 | { 118 | return getter.Invoke (obj, null); 119 | } 120 | 121 | public void SetValue (object value) 122 | { 123 | setter.Invoke (obj, new[] { value }); 124 | } 125 | 126 | public static bool GetPropertyType (PropertyInfo info, out SerializedPropertyType propertyType) 127 | { 128 | Type type = info.PropertyType; 129 | propertyType = SerializedPropertyType.Generic; 130 | if (type == typeof(int)) 131 | propertyType = SerializedPropertyType.Integer; 132 | else if (type == typeof(float)) 133 | propertyType = SerializedPropertyType.Float; 134 | else if (type == typeof(bool)) 135 | propertyType = SerializedPropertyType.Boolean; 136 | else if (type == typeof(string)) 137 | propertyType = SerializedPropertyType.String; 138 | else if (type == typeof(Vector2)) 139 | propertyType = SerializedPropertyType.Vector2; 140 | else if (type == typeof(Vector3)) 141 | propertyType = SerializedPropertyType.Vector3; 142 | else if (type.IsEnum) 143 | propertyType = SerializedPropertyType.Enum; 144 | 145 | return propertyType != SerializedPropertyType.Generic; 146 | } 147 | } -------------------------------------------------------------------------------- /Assets/07_CustomEditor/Editor/ExposeProperties.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 9ad56d9b3c23b4f0e89b5f8d54a95b6b 3 | timeCreated: 1482320955 4 | licenseType: Pro 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/07_CustomEditor/Editor/MyPlayerEditor.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using UnityEditor; 3 | using System.Collections; 4 | 5 | [CustomEditor (typeof(MyPlayer))] 6 | [CanEditMultipleObjects] 7 | public class MyPlayerEditor : Editor 8 | { 9 | 10 | SerializedProperty damageProp; 11 | SerializedProperty armorProp; 12 | SerializedProperty gunProp; 13 | 14 | 15 | void OnEnable () 16 | { 17 | // Setup the SerializedProperties 18 | damageProp = serializedObject.FindProperty ("damage"); 19 | armorProp = serializedObject.FindProperty ("armor"); 20 | gunProp = serializedObject.FindProperty ("gun"); 21 | } 22 | 23 | public override void OnInspectorGUI () 24 | { 25 | // Update the serializedProperty - always do this in the beginning of OnInspectorGUI. 26 | serializedObject.Update (); 27 | // Show the custom GUI controls 28 | EditorGUILayout.IntSlider (damageProp, 0, 100, new GUIContent ("Damage")); 29 | // Only show the damage progress bar if all the objects have the same damage value: 30 | if (!damageProp.hasMultipleDifferentValues) 31 | ProgressBar (damageProp.intValue / 100.0f, "Damage"); 32 | EditorGUILayout.IntSlider (armorProp, 0, 100, new GUIContent ("Armor")); 33 | // Only show the armor progress bar if all the objects have the same armor value: 34 | if (!armorProp.hasMultipleDifferentValues) 35 | ProgressBar (armorProp.intValue / 100.0f, "Armor"); 36 | EditorGUILayout.PropertyField (gunProp, new GUIContent ("Gun Object")); 37 | // Apply changes to the serializedProperty - always do this in the end of OnInspectorGUI. 38 | serializedObject.ApplyModifiedProperties (); 39 | } 40 | 41 | // Custom GUILayout progress bar. 42 | void ProgressBar (float value, string label) 43 | { 44 | // Get a rect for the progress bar using the same margins as a textfield: 45 | Rect rect = GUILayoutUtility.GetRect (18, 18, "TextField"); 46 | EditorGUI.ProgressBar (rect, value, label); 47 | EditorGUILayout.Space (); 48 | } 49 | } -------------------------------------------------------------------------------- /Assets/07_CustomEditor/Editor/MyPlayerEditor.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: fe89b3c309ba744af9f6744f8b6dc9e4 3 | timeCreated: 1482319130 4 | licenseType: Pro 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/07_CustomEditor/Editor/MyTypeEditor.cs: -------------------------------------------------------------------------------- 1 | using UnityEditor; 2 | 3 | [CustomEditor (typeof(MyType), true)] 4 | public class MyTypeEditor : PropertyInspectorEditor 5 | { 6 | } 7 | -------------------------------------------------------------------------------- /Assets/07_CustomEditor/Editor/MyTypeEditor.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: c27ee9ec08ec743d2a5925b6001a3072 3 | timeCreated: 1482322589 4 | licenseType: Pro 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/07_CustomEditor/Editor/PropertyInspectorEditor.cs: -------------------------------------------------------------------------------- 1 | using UnityEditor; 2 | using UnityEngine; 3 | using System.Collections; 4 | 5 | public class PropertyInspectorEditor : Editor where T : MonoBehaviour 6 | { 7 | T m_Instance; 8 | PropertyField[] m_fields; 9 | 10 | public void OnEnable () 11 | { 12 | m_Instance = target as T; 13 | m_fields = ExposeProperties.GetProperties (m_Instance); 14 | } 15 | 16 | public override void OnInspectorGUI () 17 | { 18 | if (m_Instance == null) 19 | return; 20 | 21 | this.DrawDefaultInspector (); 22 | 23 | ExposeProperties.Expose (m_fields); 24 | 25 | EditorUtility.SetDirty (m_Instance); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Assets/07_CustomEditor/Editor/PropertyInspectorEditor.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 0793db4e47ee94391aa404770335ae5c 3 | timeCreated: 1482321059 4 | licenseType: Pro 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/07_CustomEditor/Editor/TransformEditor.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using UnityEditor; 3 | using System.Collections; 4 | 5 | [CustomEditor (typeof(Transform))] 6 | public class TransformInspector : Editor 7 | { 8 | 9 | public bool showTools; 10 | public bool copyPosition; 11 | public bool copyRotation; 12 | public bool copyScale; 13 | public bool pastePosition; 14 | public bool pasteRotation; 15 | public bool pasteScale; 16 | public bool selectionNullError; 17 | 18 | public override void OnInspectorGUI () 19 | { 20 | 21 | Transform t = (Transform)target; 22 | 23 | // Replicate the standard transform inspector gui 24 | EditorGUI.indentLevel = 0; 25 | Vector3 position = EditorGUILayout.Vector3Field ("Position", t.localPosition); 26 | Vector3 eulerAngles = EditorGUILayout.Vector3Field ("Rotation", t.localEulerAngles); 27 | Vector3 scale = EditorGUILayout.Vector3Field ("Scale", t.localScale); 28 | 29 | // 30 | if (GUILayout.Button ((showTools) ? "Hide Transform Tools" : "Show Transform Tools")) { 31 | showTools = !showTools; 32 | EditorPrefs.SetBool ("ShowTools", showTools); 33 | } 34 | // START TRANSFORM TOOLS FOLD DOWN // 35 | if (showTools) { 36 | if (!copyPosition && !copyRotation && !copyScale) { 37 | selectionNullError = true; 38 | } else { 39 | selectionNullError = false; 40 | } 41 | EditorGUILayout.BeginHorizontal (); 42 | if (GUILayout.Button (selectionNullError ? "Nothing Selected" : "Copy Transform")) { 43 | if (copyPosition) { 44 | EditorPrefs.SetFloat ("LocalPosX", t.localPosition.x); 45 | EditorPrefs.SetFloat ("LocalPosY", t.localPosition.y); 46 | EditorPrefs.SetFloat ("LocalPosZ", t.localPosition.z); 47 | } 48 | if (copyRotation) { 49 | EditorPrefs.SetFloat ("LocalRotX", t.localEulerAngles.x); 50 | EditorPrefs.SetFloat ("LocalRotY", t.localEulerAngles.y); 51 | EditorPrefs.SetFloat ("LocalRotZ", t.localEulerAngles.z); 52 | } 53 | if (copyScale) { 54 | EditorPrefs.SetFloat ("LocalScaleX", t.localScale.x); 55 | EditorPrefs.SetFloat ("LocalScaleY", t.localScale.y); 56 | EditorPrefs.SetFloat ("LocalScaleZ", t.localScale.z); 57 | } 58 | 59 | Debug.Log ("LP: " + t.localPosition + " LT: (" + t.localEulerAngles.x + ", " + t.localEulerAngles.y + ", " + t.localEulerAngles.z + ") LS: " + t.localScale); 60 | } 61 | if (GUILayout.Button ("Paste Transform")) { 62 | Vector3 tV3 = new Vector3 (); 63 | if (pastePosition) { 64 | tV3.x = EditorPrefs.GetFloat ("LocalPosX", 0.0f); 65 | tV3.y = EditorPrefs.GetFloat ("LocalPosY", 0.0f); 66 | tV3.z = EditorPrefs.GetFloat ("LocalPosZ", 0.0f); 67 | t.localPosition = tV3; 68 | } 69 | if (pasteRotation) { 70 | tV3.x = EditorPrefs.GetFloat ("LocalRotX", 0.0f); 71 | tV3.y = EditorPrefs.GetFloat ("LocalRotY", 0.0f); 72 | tV3.z = EditorPrefs.GetFloat ("LocalRotZ", 0.0f); 73 | t.localEulerAngles = tV3; 74 | } 75 | if (pasteScale) { 76 | tV3.x = EditorPrefs.GetFloat ("LocalScaleX", 1.0f); 77 | tV3.y = EditorPrefs.GetFloat ("LocalScaleY", 1.0f); 78 | tV3.z = EditorPrefs.GetFloat ("LocalScaleZ", 1.0f); 79 | t.localScale = tV3; 80 | } 81 | 82 | Debug.Log ("LP: " + t.localPosition + " LT: " + t.localEulerAngles + " LS: " + t.localScale); 83 | } 84 | EditorGUILayout.EndHorizontal (); 85 | 86 | EditorGUIUtility.LookLikeControls (); 87 | EditorGUILayout.BeginHorizontal (); 88 | GUILayout.Label ("Position", GUILayout.Width (75)); 89 | GUILayout.Label ("Rotation", GUILayout.Width (75)); 90 | GUILayout.Label ("Scale", GUILayout.Width (50)); 91 | if (GUILayout.Button ("All", GUILayout.MaxWidth (40))) 92 | TransformCopyAll (); 93 | EditorGUILayout.EndHorizontal (); 94 | EditorGUILayout.BeginHorizontal (); 95 | GUILayout.Space (20); 96 | copyPosition = EditorGUILayout.Toggle (copyPosition, GUILayout.Width (75)); 97 | copyRotation = EditorGUILayout.Toggle (copyRotation, GUILayout.Width (65)); 98 | copyScale = EditorGUILayout.Toggle (copyScale, GUILayout.Width (45)); 99 | if (GUILayout.Button ("None", GUILayout.MaxWidth (40))) 100 | TransformCopyNone (); 101 | EditorGUILayout.EndHorizontal (); 102 | EditorGUIUtility.LookLikeInspector (); 103 | } 104 | // END TRANSFORM TOOLS FOLD DOWN // 105 | 106 | if (GUI.changed) { 107 | SetCopyPasteBools (); 108 | Undo.RegisterUndo (t, "Transform Change"); 109 | 110 | t.localPosition = FixIfNaN (position); 111 | t.localEulerAngles = FixIfNaN (eulerAngles); 112 | t.localScale = FixIfNaN (scale); 113 | } 114 | } 115 | 116 | private Vector3 FixIfNaN (Vector3 v) 117 | { 118 | if (float.IsNaN (v.x)) { 119 | v.x = 0; 120 | } 121 | if (float.IsNaN (v.y)) { 122 | v.y = 0; 123 | } 124 | if (float.IsNaN (v.z)) { 125 | v.z = 0; 126 | } 127 | return v; 128 | } 129 | 130 | void OnEnable () 131 | { 132 | showTools = EditorPrefs.GetBool ("ShowTools", false); 133 | copyPosition = EditorPrefs.GetBool ("Copy Position", true); 134 | copyRotation = EditorPrefs.GetBool ("Copy Rotation", true); 135 | copyScale = EditorPrefs.GetBool ("Copy Scale", true); 136 | pastePosition = EditorPrefs.GetBool ("Paste Position", true); 137 | pasteRotation = EditorPrefs.GetBool ("Paste Rotation", true); 138 | pasteScale = EditorPrefs.GetBool ("Paste Scale", true); 139 | } 140 | 141 | void TransformCopyAll () 142 | { 143 | copyPosition = true; 144 | copyRotation = true; 145 | copyScale = true; 146 | GUI.changed = true; 147 | } 148 | 149 | void TransformCopyNone () 150 | { 151 | copyPosition = false; 152 | copyRotation = false; 153 | copyScale = false; 154 | GUI.changed = true; 155 | } 156 | 157 | void SetCopyPasteBools () 158 | { 159 | pastePosition = copyPosition; 160 | pasteRotation = copyRotation; 161 | pasteScale = copyScale; 162 | 163 | EditorPrefs.SetBool ("Copy Position", copyPosition); 164 | EditorPrefs.SetBool ("Copy Rotation", copyRotation); 165 | EditorPrefs.SetBool ("Copy Scale", copyScale); 166 | EditorPrefs.SetBool ("Paste Position", pastePosition); 167 | EditorPrefs.SetBool ("Paste Rotation", pasteRotation); 168 | EditorPrefs.SetBool ("Paste Scale", pasteScale); 169 | } 170 | } -------------------------------------------------------------------------------- /Assets/07_CustomEditor/Editor/TransformEditor.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 7cabd9885806d416fa63aa69611aefa8 3 | timeCreated: 1482319765 4 | licenseType: Pro 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/07_CustomEditor/ExposePropertyAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | [AttributeUsage (AttributeTargets.Property)] public class ExposePropertyAttribute : Attribute 4 | { 5 | } -------------------------------------------------------------------------------- /Assets/07_CustomEditor/ExposePropertyAttribute.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 4da41a4a5cb024284a9f06f8611616bb 3 | timeCreated: 1482320915 4 | licenseType: Pro 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/07_CustomEditor/MyPlayer.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using System.Collections; 3 | 4 | public class MyPlayer : MonoBehaviour 5 | { 6 | 7 | public int armor; 8 | 9 | public int damage; 10 | public GameObject gun; 11 | 12 | } -------------------------------------------------------------------------------- /Assets/07_CustomEditor/MyPlayer.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: e08436eec492641459a6ec139eaefb90 3 | timeCreated: 1482318988 4 | licenseType: Pro 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/07_CustomEditor/MyType.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | 3 | public class MyType : MonoBehaviour 4 | { 5 | [HideInInspector, SerializeField] int m_SomeInt; 6 | [HideInInspector, SerializeField] float m_SomeFloat; 7 | [HideInInspector, SerializeField] bool m_SomeBool; 8 | [HideInInspector, SerializeField] string m_Etc; 9 | 10 | [ExposeProperty] public int SomeInt { 11 | get { return m_SomeInt; } 12 | set { m_SomeInt = value; } 13 | } 14 | 15 | [ExposeProperty] public float SomeFloat { 16 | get { return m_SomeFloat; } 17 | set { m_SomeFloat = value; } 18 | } 19 | 20 | [ExposeProperty] public bool SomeBool { 21 | get { return m_SomeBool; } 22 | set { m_SomeBool = value; } 23 | } 24 | 25 | [ExposeProperty] public string SomeString { 26 | get { return m_Etc; } 27 | set { m_Etc = value; } 28 | } 29 | } -------------------------------------------------------------------------------- /Assets/07_CustomEditor/MyType.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 0bfa63c0fc83843a182f9c3e58a16dc1 3 | timeCreated: 1482321046 4 | licenseType: Pro 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/08_Gizmos.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 7be0b2967b66e4ed9917aeb6d8ed3369 3 | folderAsset: yes 4 | timeCreated: 1482293956 5 | licenseType: Pro 6 | DefaultImporter: 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/08_Gizmos/08.unity: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/minhhh/unity-editorextension-manual/63f7107faba2791aea5832f87ea3a414fc2b46fc/Assets/08_Gizmos/08.unity -------------------------------------------------------------------------------- /Assets/08_Gizmos/08.unity.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: ecbc957e65593425bad886f7a1ad49c7 3 | timeCreated: 1482302692 4 | licenseType: Pro 5 | DefaultImporter: 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Assets/08_Gizmos/Editor.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 5329e247640a340cf97853f1e6bc58a6 3 | folderAsset: yes 4 | timeCreated: 1482305105 5 | licenseType: Pro 6 | DefaultImporter: 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/08_Gizmos/Editor/GridEditor.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using System.Collections; 3 | using UnityEditor; 4 | 5 | [CustomEditor (typeof(Grid))] 6 | public class GridEditor : Editor 7 | { 8 | Grid grid; 9 | 10 | public void OnEnable () 11 | { 12 | grid = (Grid)target; 13 | 14 | SceneView.onSceneGUIDelegate += OnSceneGUI; 15 | } 16 | 17 | public override void OnInspectorGUI () 18 | { 19 | GUILayout.BeginHorizontal (); 20 | GUILayout.Label (" Grid Width "); 21 | grid.width = EditorGUILayout.FloatField (grid.width, GUILayout.Width (50)); 22 | GUILayout.EndHorizontal (); 23 | 24 | GUILayout.BeginHorizontal (); 25 | GUILayout.Label (" Grid Height "); 26 | grid.height = EditorGUILayout.FloatField (grid.height, GUILayout.Width (50)); 27 | GUILayout.EndHorizontal (); 28 | 29 | SceneView.RepaintAll (); 30 | } 31 | 32 | void OnSceneGUI (SceneView sceneview) 33 | { 34 | Event e = Event.current; 35 | Ray r = Camera.current.ScreenPointToRay (new Vector3 (e.mousePosition.x, -e.mousePosition.y + Camera.current.pixelHeight)); 36 | Vector3 mousePos = r.origin; 37 | 38 | if (e.isKey && e.character == 'a') { 39 | GameObject obj; 40 | Object prefab = EditorUtility.GetPrefabParent (Selection.activeObject); 41 | 42 | if (prefab) { 43 | obj = (GameObject)EditorUtility.InstantiatePrefab (prefab); 44 | Vector3 aligned = new Vector3 (Mathf.Floor (mousePos.x / grid.width) * grid.width + grid.width / 2.0f, 45 | Mathf.Floor (mousePos.y / grid.height) * grid.height + grid.height / 2.0f, 0.0f); 46 | obj.transform.position = aligned; 47 | } 48 | } else if (e.isKey && e.character == 'd') { 49 | foreach (GameObject obj in Selection.gameObjects) 50 | DestroyImmediate (obj); 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /Assets/08_Gizmos/Editor/GridEditor.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 64ccd988131af4e408f60508e2c246af 3 | timeCreated: 1482305113 4 | licenseType: Pro 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/08_Gizmos/GizmosDemo1.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using System.Collections; 3 | 4 | public class GizmosDemo1 : MonoBehaviour 5 | { 6 | 7 | void OnDrawGizmosSelected () 8 | { 9 | Gizmos.color = new Color32 (255, 0, 255, 255); 10 | Gizmos.DrawWireCube (transform.position, transform.lossyScale); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Assets/08_Gizmos/GizmosDemo1.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: a0deed5b5a5f6432299b1ec3159eb43f 3 | timeCreated: 1482303326 4 | licenseType: Pro 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/08_Gizmos/GizmosDemo2.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using System.Collections; 3 | 4 | public class GizmosDemo2 : MonoBehaviour 5 | { 6 | 7 | void OnDrawGizmos () 8 | { 9 | Gizmos.color = new Color32 (255, 0, 255, 255); 10 | Gizmos.DrawWireCube (transform.position, transform.lossyScale); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Assets/08_Gizmos/GizmosDemo2.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 9b81a87cc34b1445a809bb3936a683bf 3 | timeCreated: 1482303326 4 | licenseType: Pro 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/08_Gizmos/Grid.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using System.Collections; 3 | 4 | #if UNITY_EDITOR 5 | using UnityEditor; 6 | #endif 7 | 8 | public class Grid : MonoBehaviour 9 | { 10 | public float width = 1.0f; 11 | public float height = 1.0f; 12 | 13 | void Start () 14 | { 15 | } 16 | 17 | void Update () 18 | { 19 | } 20 | 21 | void OnDrawGizmos () 22 | { 23 | Vector3 pos = Camera.current.transform.position; 24 | 25 | for (float y = pos.y - 800.0f; y < pos.y + 800.0f; y += height) { 26 | Gizmos.DrawLine (new Vector3 (-1000000.0f, Mathf.Floor (y / height) * height, 0.0f), 27 | new Vector3 (1000000.0f, Mathf.Floor (y / height) * height, 0.0f)); 28 | } 29 | 30 | for (float x = pos.x - 1200.0f; x < pos.x + 1200.0f; x += width) { 31 | Gizmos.DrawLine (new Vector3 (Mathf.Floor (x / width) * width, -1000000.0f, 0.0f), 32 | new Vector3 (Mathf.Floor (x / width) * width, 1000000.0f, 0.0f)); 33 | } 34 | } 35 | 36 | } -------------------------------------------------------------------------------- /Assets/08_Gizmos/Grid.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 9308f418508d54d01b03d7e2a5c9d825 3 | timeCreated: 1482304216 4 | licenseType: Pro 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/08_Gizmos/Tile.prefab: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/minhhh/unity-editorextension-manual/63f7107faba2791aea5832f87ea3a414fc2b46fc/Assets/08_Gizmos/Tile.prefab -------------------------------------------------------------------------------- /Assets/08_Gizmos/Tile.prefab.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 5987b0e279e214bc3869f56a0c57c8e4 3 | timeCreated: 1482304735 4 | licenseType: Pro 5 | NativeFormatImporter: 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Assets/09_SceneView.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 5b205b490427641d7974a55197b08c2e 3 | folderAsset: yes 4 | timeCreated: 1482308688 5 | licenseType: Pro 6 | DefaultImporter: 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/09_SceneView/09.unity: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/minhhh/unity-editorextension-manual/63f7107faba2791aea5832f87ea3a414fc2b46fc/Assets/09_SceneView/09.unity -------------------------------------------------------------------------------- /Assets/09_SceneView/09.unity.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: db3ee45c1db8646a9b7c596ff46e78ee 3 | timeCreated: 1482309579 4 | licenseType: Pro 5 | DefaultImporter: 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Assets/09_SceneView/Editor.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: ed182116ccb9b48b891cba26c6d5ab74 3 | folderAsset: yes 4 | timeCreated: 1482309778 5 | licenseType: Pro 6 | DefaultImporter: 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/09_SceneView/Editor/EffectLayerCustom.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using System.Collections; 3 | using UnityEditor; 4 | 5 | [CustomEditor (typeof(EffectLayer))] 6 | public class EffectLayerCustom : Editor 7 | { 8 | EffectLayer layer; 9 | 10 | void OnEnable () 11 | { 12 | layer = target as EffectLayer; 13 | } 14 | 15 | public void OnSceneGUI () 16 | { 17 | 18 | Rect r = new Rect (Screen.width - 160, Screen.height - 120, 160, 80); 19 | 20 | Vector2 mouse = Event.current.mousePosition; 21 | 22 | Rect r2 = r; 23 | r2.yMin -= 30; 24 | r2.xMin -= 10; 25 | r2.xMax += 10; 26 | r2.yMax += 10; 27 | 28 | if (r2.Contains (mouse) && Event.current.type == EventType.Layout) { 29 | int controlID = GUIUtility.GetControlID (1024, FocusType.Passive); 30 | HandleUtility.AddControl (controlID, 0F); 31 | } 32 | 33 | Handles.BeginGUI (); 34 | GUILayout.BeginArea (r, layer.gameObject.name, "Window"); 35 | 36 | layer.myBool = GUILayout.Toggle (layer.myBool, "Check Box?"); 37 | 38 | EditorGUIUtility.labelWidth = 110f; 39 | layer.myFloat = EditorGUILayout.FloatField ("Some Float: ", layer.myFloat); 40 | EditorGUIUtility.labelWidth = 0f; 41 | 42 | EditorGUILayout.BeginHorizontal(); 43 | if (GUILayout.Button ("Play")) { 44 | } 45 | 46 | if (GUILayout.Button ("Reset")) { 47 | layer.myFloat = 0; 48 | layer.myInt = 0; 49 | layer.myStr = ""; 50 | } 51 | EditorGUILayout.EndHorizontal (); 52 | 53 | 54 | GUILayout.EndArea (); 55 | 56 | Handles.EndGUI (); 57 | 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /Assets/09_SceneView/Editor/EffectLayerCustom.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 17f0239e4ff264c6187cc700f83098bc 3 | timeCreated: 1482314209 4 | licenseType: Pro 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/09_SceneView/Editor/MeshVisualizeWindow.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using UnityEditor; 3 | using System.Collections; 4 | using System; 5 | 6 | public class MeshVisualizeWindow : EditorWindow 7 | { 8 | [MenuItem ("Window/Mesh visualizer")] 9 | public static void OpenWindow () 10 | { 11 | GetWindow ().Focus (); 12 | } 13 | 14 | private Mesh selectedMesh; 15 | private Vector3[] selectedVertices, selectedNormals; 16 | private Color[] selectedColors, randomColors; 17 | private int[] selectedTriangles; 18 | 19 | private int startVertIndex, endVertIndex, startTriIndex, endTriIndex; 20 | 21 | private bool shouldVisualizeVertices = true, shouldVisualizeTriangles = false; 22 | private bool useVertexColors = true; 23 | 24 | private bool hasVertexColors { get { return selectedMesh.colors != null && selectedMesh.colors.Length > 0; } } 25 | 26 | void OnEnable () 27 | { 28 | SceneView.onSceneGUIDelegate -= OnSceneGUI; 29 | SceneView.onSceneGUIDelegate += OnSceneGUI; 30 | 31 | init (); 32 | randomColors = generateColors (255); 33 | } 34 | 35 | void OnDisable () 36 | { 37 | SceneView.onSceneGUIDelegate -= OnSceneGUI; 38 | 39 | } 40 | 41 | void OnSelectionChange () 42 | { 43 | init (); 44 | //Force to repaint UI, otherwise the new values arent visible until you interact with the window 45 | Repaint (); 46 | } 47 | 48 | //Initialises the variables for the current selection. 49 | private void init () 50 | { 51 | //Reset to default 52 | selectedMesh = null; 53 | 54 | if (Selection.activeGameObject == null) 55 | return; 56 | 57 | MeshFilter mFilter; 58 | SkinnedMeshRenderer mSkinRender; 59 | 60 | if ((mFilter = Selection.activeGameObject.GetComponent ()) != null) 61 | selectedMesh = mFilter.sharedMesh; 62 | 63 | if ((mSkinRender = Selection.activeGameObject.GetComponent ()) != null) 64 | selectedMesh = mSkinRender.sharedMesh; 65 | 66 | if (selectedMesh == null || (selectedVertices != null && selectedMesh.vertices.Length == selectedVertices.Length)) 67 | return; 68 | 69 | selectedVertices = selectedMesh.vertices; 70 | selectedNormals = selectedMesh.normals; 71 | selectedTriangles = selectedMesh.triangles; 72 | selectedColors = validateColors (selectedMesh.colors); 73 | if (!hasVertexColors || !useVertexColors) 74 | selectedColors = generateColors (selectedVertices.Length); 75 | 76 | startVertIndex = 0; 77 | endVertIndex = selectedVertices.Length; 78 | endTriIndex = selectedTriangles.Length / 3; 79 | } 80 | 81 | private Color[] validateColors (Color[] colors) 82 | { 83 | for (int i = 0; i < colors.Length; i++) { 84 | if (colors [i].a < .5f) 85 | colors [i].a = 1f; 86 | } 87 | 88 | return colors; 89 | } 90 | 91 | private Color[] generateColors (int size) 92 | { 93 | Color[] cols = new Color[size]; 94 | for (int i = 0; i < cols.Length; i++) 95 | cols [i] = new Color (UnityEngine.Random.value, UnityEngine.Random.value, UnityEngine.Random.value); 96 | return cols; 97 | } 98 | 99 | 100 | #region GUI 101 | 102 | void OnGUI () 103 | { 104 | if (selectedMesh == null) { 105 | EditorGUILayout.HelpBox ("Please select a meshfilter or skinnedmeshrenderer!", MessageType.Error); 106 | return; 107 | } 108 | 109 | drawGeneralGUI (); 110 | EditorGUILayout.Space (); 111 | drawVertexGUI (); 112 | EditorGUILayout.Space (); 113 | drawTriangleGUI (); 114 | 115 | if (GUI.changed) 116 | SceneView.RepaintAll (); 117 | } 118 | 119 | private void drawGeneralGUI () 120 | { 121 | EditorGUILayout.LabelField ("General settings", EditorStyles.boldLabel); 122 | 123 | EditorGUI.indentLevel++; 124 | EditorGUILayout.LabelField (string.Format ("Vertex count: {0}, triangle count: {1}", selectedVertices.Length, selectedMesh.triangles.Length / 3)); 125 | 126 | if (hasVertexColors) { 127 | useVertexColors = EditorGUILayout.Toggle ("Use vertex colors", useVertexColors); 128 | 129 | if (GUI.changed && useVertexColors) 130 | selectedColors = validateColors (selectedMesh.colors); 131 | else if (GUI.changed && !useVertexColors) 132 | selectedColors = generateColors (selectedVertices.Length); 133 | } 134 | 135 | EditorGUI.indentLevel--; 136 | } 137 | 138 | private void drawVertexGUI () 139 | { 140 | shouldVisualizeVertices = EditorGUILayout.BeginToggleGroup ("Show vertices", shouldVisualizeVertices); 141 | 142 | EditorGUI.indentLevel++; 143 | EditorGUILayout.LabelField ("Visualise from index: " + startVertIndex + " to " + endVertIndex); 144 | 145 | //Lame, MinMaxSlider only has a float version! 146 | float tmpStart = startVertIndex, tmpEnd = endVertIndex; 147 | EditorGUILayout.MinMaxSlider (ref tmpStart, ref tmpEnd, 0, selectedVertices.Length); 148 | startVertIndex = (int)tmpStart; 149 | endVertIndex = (int)tmpEnd; 150 | 151 | EditorGUILayout.BeginHorizontal (); 152 | EditorGUILayout.LabelField ("Min"); 153 | 154 | if (GUILayout.Button ("-")) 155 | startVertIndex = Mathf.Clamp (startVertIndex - 1, 0, endVertIndex); 156 | if (GUILayout.Button ("+")) 157 | startVertIndex = Mathf.Clamp (startVertIndex + 1, 0, endVertIndex); 158 | 159 | EditorGUILayout.EndHorizontal (); 160 | 161 | EditorGUILayout.BeginHorizontal (); 162 | EditorGUILayout.LabelField ("Max"); 163 | 164 | if (GUILayout.Button ("-")) 165 | endVertIndex = Mathf.Clamp (endVertIndex - 1, startVertIndex, selectedVertices.Length); 166 | if (GUILayout.Button ("+")) 167 | endVertIndex = Mathf.Clamp (endVertIndex + 1, startVertIndex, selectedVertices.Length); 168 | 169 | EditorGUILayout.EndHorizontal (); 170 | 171 | EditorGUILayout.EndToggleGroup (); 172 | 173 | EditorGUI.indentLevel--; 174 | } 175 | 176 | private void drawTriangleGUI () 177 | { 178 | shouldVisualizeTriangles = EditorGUILayout.BeginToggleGroup ("Show triangles", shouldVisualizeTriangles); 179 | 180 | EditorGUILayout.LabelField ("Visualise from index: " + startTriIndex + " to " + endTriIndex); 181 | EditorGUI.indentLevel++; 182 | 183 | //Lame, MinMaxSlider only has a float version! 184 | float tmpStart = startTriIndex, tmpEnd = endTriIndex; 185 | EditorGUILayout.MinMaxSlider (ref tmpStart, ref tmpEnd, 0, selectedTriangles.Length / 3f); 186 | startTriIndex = (int)tmpStart; 187 | endTriIndex = (int)tmpEnd; 188 | 189 | EditorGUILayout.BeginHorizontal (); 190 | EditorGUILayout.LabelField ("Min"); 191 | 192 | if (GUILayout.Button ("-")) 193 | startTriIndex = Mathf.Clamp (startTriIndex - 1, 0, endTriIndex); 194 | if (GUILayout.Button ("+")) 195 | startTriIndex = Mathf.Clamp (startTriIndex + 1, 0, endTriIndex); 196 | 197 | EditorGUILayout.EndHorizontal (); 198 | 199 | EditorGUILayout.BeginHorizontal (); 200 | EditorGUILayout.LabelField ("Max"); 201 | 202 | if (GUILayout.Button ("-")) 203 | endTriIndex = Mathf.Clamp (endTriIndex - 1, startTriIndex, selectedTriangles.Length / 3); 204 | if (GUILayout.Button ("+")) 205 | endTriIndex = Mathf.Clamp (endTriIndex + 1, startTriIndex, selectedTriangles.Length / 3); 206 | 207 | EditorGUILayout.EndHorizontal (); 208 | 209 | EditorGUILayout.EndToggleGroup (); 210 | EditorGUI.indentLevel--; 211 | } 212 | 213 | #endregion 214 | 215 | #region Scene 216 | 217 | private void OnSceneGUI (SceneView sceneView) 218 | { 219 | if (selectedMesh == null || Selection.activeGameObject == null) 220 | return; 221 | //Everything we do is in local space 222 | Handles.matrix = Selection.activeGameObject.transform.localToWorldMatrix; 223 | 224 | if (shouldVisualizeVertices) 225 | visualizeVertices (); 226 | 227 | if (shouldVisualizeTriangles) 228 | visualizeTriangles (); 229 | 230 | } 231 | 232 | private void visualizeVertices () 233 | { 234 | for (int i = startVertIndex; i < endVertIndex; i++) { 235 | Handles.color = selectedColors [i]; 236 | 237 | DrawRay (selectedVertices [i], selectedNormals [i]); 238 | Handles.Label (selectedVertices [i] + selectedNormals [i] * 1.1f, i.ToString ()); 239 | } 240 | } 241 | 242 | private void visualizeTriangles () 243 | { 244 | for (int i = startTriIndex * 3; i < endTriIndex * 3; i += 3) { 245 | Handles.color = randomColors [i % randomColors.Length]; 246 | Vector3 p1 = selectedVertices [selectedTriangles [i + 0]], 247 | p2 = selectedVertices [selectedTriangles [i + 1]], 248 | p3 = selectedVertices [selectedTriangles [i + 2]]; 249 | 250 | DrawArrow (p1, p2 - p1); 251 | DrawArrow (p2, p3 - p2); 252 | DrawArrow (p3, p1 - p3); 253 | 254 | Handles.Label ((p1 + p2 + p3) / 3f, (i / 3).ToString ()); 255 | } 256 | 257 | } 258 | 259 | //Draws an arrow in the handles. `arrowatpercent` determines where the arrow cap is, 1 means at the end 0 at the beginning 260 | static void DrawArrow (Vector3 origin, Vector3 direction, float arrowAtPercent = .8f) 261 | { 262 | DrawRay (origin, direction); 263 | DrawRay (origin + direction * arrowAtPercent, Quaternion.LookRotation (direction) * Quaternion.Euler (0, 200f, 0) * Vector3.forward * 0.1f); 264 | DrawRay (origin + direction * arrowAtPercent, Quaternion.LookRotation (direction) * Quaternion.Euler (0, 160f, 0) * Vector3.forward * 0.1f); 265 | } 266 | //Draws a line that starts at origin and ends at origin+direction 267 | static void DrawRay (Vector3 origin, Vector3 direction) 268 | { 269 | Handles.DrawLine (origin, origin + direction); 270 | } 271 | 272 | #endregion 273 | } -------------------------------------------------------------------------------- /Assets/09_SceneView/Editor/MeshVisualizeWindow.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 765cf524aa2bf4e7ea5e0d9ab6e27072 3 | timeCreated: 1482302805 4 | licenseType: Pro 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/09_SceneView/EffectLayer.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using System.Collections; 3 | 4 | public class EffectLayer : MonoBehaviour 5 | { 6 | public string myStr; 7 | public int myInt; 8 | public float myFloat; 9 | public bool myBool; 10 | } 11 | -------------------------------------------------------------------------------- /Assets/09_SceneView/EffectLayer.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 4b11858d41e7843c2979e5bb47ad4a0b 3 | timeCreated: 1482314248 4 | licenseType: Pro 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/10_Hierarchy.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 6864d47dfc5314e77acdf2da1f23431c 3 | folderAsset: yes 4 | timeCreated: 1482311714 5 | licenseType: Pro 6 | DefaultImporter: 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/10_Hierarchy/10.unity: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/minhhh/unity-editorextension-manual/63f7107faba2791aea5832f87ea3a414fc2b46fc/Assets/10_Hierarchy/10.unity -------------------------------------------------------------------------------- /Assets/10_Hierarchy/10.unity.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 9e902f5cf7f8344f3a3e6d7aa7a41b0b 3 | timeCreated: 1482312113 4 | licenseType: Pro 5 | DefaultImporter: 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Assets/10_Hierarchy/Editor.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 84bb227ff9fd4472eb6d66592386988c 3 | folderAsset: yes 4 | timeCreated: 1482311939 5 | licenseType: Pro 6 | DefaultImporter: 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/10_Hierarchy/Editor/HierarchyDemo.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using System.Collections; 3 | using UnityEditor; 4 | 5 | public static class HierarchyDemo 6 | { 7 | [InitializeOnLoadMethod] 8 | private static void DrawToHierarchy () 9 | { 10 | EditorApplication.hierarchyWindowItemOnGUI += OnGUI; 11 | } 12 | 13 | const int WIDTH = 40; 14 | const int LABEL_WIDTH = 40; 15 | static Color labelColor = Color.green; 16 | 17 | private static void OnGUI (int instanceID, Rect rect) 18 | { 19 | var go = EditorUtility.InstanceIDToObject (instanceID) as GameObject; 20 | 21 | if (go == null) { 22 | return; 23 | } 24 | 25 | var hierarchyItem = go.GetComponent (); 26 | 27 | if (hierarchyItem == null) { 28 | return; 29 | } 30 | 31 | 32 | var posButton = rect; 33 | posButton.x = posButton.xMax - WIDTH; 34 | posButton.width = WIDTH; 35 | 36 | var pos = posButton; 37 | pos.x = posButton.x - WIDTH; 38 | pos.width = WIDTH; 39 | 40 | var posLabel = pos; 41 | posLabel.x = pos.x - LABEL_WIDTH; 42 | posLabel.width = LABEL_WIDTH; 43 | 44 | GUIStyle guiStyleLabel = new GUIStyle (); 45 | GUIStyleState styleState = new GUIStyleState (); 46 | styleState.textColor = labelColor; 47 | guiStyleLabel.normal = styleState; 48 | 49 | if (GUI.Button (posButton, "Play")) { 50 | 51 | } 52 | 53 | GUI.Label (posLabel, "myStr:", guiStyleLabel); 54 | hierarchyItem.myStr = EditorGUI.TextField (pos, hierarchyItem.myStr); 55 | 56 | } 57 | 58 | } 59 | -------------------------------------------------------------------------------- /Assets/10_Hierarchy/Editor/HierarchyDemo.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 3e646251e5b9349b090dc6d2066eaccf 3 | timeCreated: 1482311879 4 | licenseType: Pro 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/10_Hierarchy/HierarchyItem.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using System.Collections; 3 | 4 | public class HierarchyItem : MonoBehaviour 5 | { 6 | public string myStr; 7 | 8 | 9 | } 10 | -------------------------------------------------------------------------------- /Assets/10_Hierarchy/HierarchyItem.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 5e1440b8e682b48708dc97daaaadb37e 3 | timeCreated: 1482312099 4 | licenseType: Pro 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/ExplosionShape.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 3c78ae8895f3341de829209b0ca92b90 3 | folderAsset: yes 4 | timeCreated: 1482374485 5 | licenseType: Pro 6 | DefaultImporter: 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/ExplosionShape/BigExplode.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!114 &11400000 4 | MonoBehaviour: 5 | m_ObjectHideFlags: 0 6 | m_PrefabParentObject: {fileID: 0} 7 | m_PrefabInternal: {fileID: 0} 8 | m_GameObject: {fileID: 0} 9 | m_Enabled: 1 10 | m_EditorHideFlags: 0 11 | m_Script: {fileID: 11500000, guid: b1a44d4a91cfb8d4e844e48f246a1b25, type: 3} 12 | m_Name: BigExplode 13 | m_EditorClassIdentifier: 14 | m_width: 5 15 | m_height: 5 16 | m_data: 00000000000000000100000000000000000000000000000002000000030000000200000000000000010000000300000005000000030000000100000000000000020000000300000002000000000000000000000000000000010000000000000000000000 17 | -------------------------------------------------------------------------------- /Assets/ExplosionShape/BigExplode.asset.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 6f94723e15d399544af1c32573c0cc20 3 | NativeFormatImporter: 4 | userData: 5 | assetBundleName: 6 | assetBundleVariant: 7 | -------------------------------------------------------------------------------- /Assets/ExplosionShape/Editor.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: c15e77c89a88541cd810ad0b18ad5268 3 | folderAsset: yes 4 | timeCreated: 1482374485 5 | licenseType: Pro 6 | DefaultImporter: 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/ExplosionShape/Editor/ExplosionShapeEditor.cs: -------------------------------------------------------------------------------- 1 | using UnityEditor; 2 | using UnityEngine; 3 | using System.Text.RegularExpressions; 4 | 5 | [CustomEditor (typeof(ExplosionShape)), CanEditMultipleObjects] 6 | public class ExplosionShapeEditor : Editor 7 | { 8 | // Creating New Explosions 9 | [MenuItem ("Teaching/Create Explosion Shape")] 10 | static void CreatePuzzle () 11 | { 12 | string path = EditorUtility.SaveFilePanel ("Create Explosion Shape", "Assets/", "explode.asset", "asset"); 13 | if (path == "") 14 | return; 15 | 16 | path = FileUtil.GetProjectRelativePath (path); 17 | 18 | ExplosionShape es = CreateInstance (); 19 | AssetDatabase.CreateAsset (es, path); 20 | AssetDatabase.SaveAssets (); 21 | } 22 | 23 | // Editing Explosions 24 | public override void OnInspectorGUI () 25 | { 26 | if (Event.current.type == EventType.Layout) { 27 | return; 28 | } 29 | 30 | Rect position = new Rect (0, 31 | 50, // Accounts for Header 32 | Screen.width, 33 | Screen.height - 32); 34 | 35 | foreach (var item in targets) { 36 | ExplosionShape pw = item as ExplosionShape; 37 | Rect usedRect = InspectExplodeShape (position, pw); 38 | position.y += usedRect.height; 39 | } 40 | } 41 | 42 | // Editing Single Explosion 43 | public static Rect InspectExplodeShape (Rect position, ExplosionShape tarPuz) 44 | { 45 | GUI.changed = false; 46 | Rect saveOrig = position; 47 | 48 | // Size 49 | int newWidth = EditorGUI.IntField (new Rect (position.x, 50 | position.y, 51 | position.width * 0.5f, 52 | EditorGUIUtility.singleLineHeight), 53 | "width", 54 | tarPuz.m_width); 55 | 56 | position.y += EditorGUIUtility.singleLineHeight; 57 | 58 | int newHeight = EditorGUI.IntField (new Rect (position.x, 59 | position.y, 60 | position.width * 0.5f, 61 | EditorGUIUtility.singleLineHeight), 62 | "height", 63 | tarPuz.m_height); 64 | position.y += EditorGUIUtility.singleLineHeight; 65 | 66 | // Resize 67 | if ((newWidth != tarPuz.m_width) || (newHeight != tarPuz.m_height)) { 68 | int[] newData = new int[newWidth * newHeight]; 69 | 70 | for (int x = 0; (x < newWidth) && (x < tarPuz.m_width); x++) 71 | for (int y = 0; (y < newHeight) && (y < tarPuz.m_height); y++) 72 | newData [x + y * newWidth] = tarPuz.m_data [x + y * tarPuz.m_width]; 73 | 74 | tarPuz.m_width = newWidth; 75 | tarPuz.m_height = newHeight; 76 | tarPuz.m_data = newData; 77 | } 78 | 79 | 80 | // Setup Block Size and Font 81 | float xWidth = Mathf.Min (position.width * 0.5f / Mathf.Max (1, tarPuz.m_width), 82 | position.height / Mathf.Max (1, tarPuz.m_height)); 83 | GUIStyle myFontStyle = new GUIStyle (EditorStyles.textField); 84 | myFontStyle.fontSize = Mathf.FloorToInt (xWidth * 0.7f); 85 | 86 | // Edit Blocks 87 | for (int x = 0; x < tarPuz.m_width; x++) { 88 | for (int y = 0; y < tarPuz.m_height; y++) { 89 | tarPuz.m_data [x + y * tarPuz.m_width] = 90 | EditorGUI.IntField (new Rect (position.x + xWidth * x, 91 | position.y + xWidth * y, 92 | xWidth, 93 | xWidth), 94 | tarPuz.m_data [x + y * tarPuz.m_width], myFontStyle); 95 | 96 | } 97 | } 98 | 99 | if (GUI.changed) 100 | EditorUtility.SetDirty (tarPuz); 101 | 102 | return new Rect (saveOrig.x, saveOrig.y, saveOrig.width, EditorGUIUtility.singleLineHeight + (tarPuz.m_height * xWidth)); 103 | } 104 | 105 | // Preview Explosion 106 | public override bool HasPreviewGUI () 107 | { 108 | return true; 109 | } 110 | 111 | public override void OnPreviewGUI (Rect tarRect, GUIStyle background) 112 | { 113 | ExplosionShape exShape = target as ExplosionShape; 114 | 115 | // Get Size 116 | float blockSize = Mathf.Min (tarRect.width / exShape.m_width, tarRect.height / exShape.m_height); 117 | float offX = (tarRect.width - blockSize * exShape.m_width) / 2 + tarRect.x; 118 | float offY = (tarRect.height - blockSize * exShape.m_height) / 2 + tarRect.y; 119 | 120 | // Get Max 121 | int maxExplode = Mathf.Max (exShape.m_data); 122 | float maxExDiv = 1.0f / (float)maxExplode; 123 | 124 | // Draw Blocks 125 | for (int x = 0; x < exShape.m_width; ++x) 126 | for (int y = 0; y < exShape.m_height; ++y) 127 | if (exShape.m_data [x + y * exShape.m_width] > 0) 128 | EditorGUI.DrawRect (new Rect (offX + x * blockSize + 1, 129 | offY + y * blockSize + 1, 130 | blockSize - 2, 131 | blockSize - 2), 132 | new Color (0, 0, 0, exShape.m_data [x + y * exShape.m_width] * maxExDiv)); 133 | 134 | } 135 | 136 | // For Static Thumbnails 137 | public override Texture2D RenderStaticPreview (string assetPath, Object[] subAssets, int TexWidth, int TexHeight) 138 | { 139 | ExplosionShape exShape = target as ExplosionShape; 140 | Texture2D staticPreview = new Texture2D (TexWidth, TexHeight); 141 | 142 | // Get Size 143 | int blockSize = Mathf.FloorToInt (Mathf.Min (TexWidth / exShape.m_width, TexHeight / exShape.m_height)); 144 | int offX = (TexWidth - blockSize * exShape.m_width) / 2; 145 | int offY = (TexHeight - blockSize * exShape.m_height) / 2; 146 | 147 | // Get Max 148 | int maxExplode = Mathf.Max (exShape.m_data); 149 | float maxExDiv = 1.0f / (float)maxExplode; 150 | 151 | // Blank Slate 152 | Color blankCol = new Color (0, 0, 0, 0); 153 | Color[] colBlock = new Color[TexWidth * TexHeight]; 154 | for (int i = 0; i < colBlock.Length; ++i) 155 | colBlock [i] = blankCol; 156 | staticPreview.SetPixels (0, 0, TexWidth, TexHeight, colBlock); 157 | 158 | // Draw Blocks 159 | for (int x = 0; x < exShape.m_width; ++x) { 160 | for (int y = 0; y < exShape.m_height; ++y) { 161 | if (exShape.m_data [x + y * exShape.m_width] > 0) { 162 | int subX = offX + x * blockSize; 163 | int subY = TexHeight - (offY + y * blockSize) - blockSize; 164 | Color blockColour = new Color (0, 0, 0, exShape.m_data [x + y * exShape.m_width] * maxExDiv); 165 | for (int px = 0; px < blockSize; ++px) 166 | for (int py = 0; py < blockSize; ++py) 167 | staticPreview.SetPixel (subX + px, subY + py, blockColour); 168 | } 169 | } 170 | } 171 | 172 | staticPreview.Apply (); 173 | return staticPreview; 174 | } 175 | } -------------------------------------------------------------------------------- /Assets/ExplosionShape/Editor/ExplosionShapeEditor.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 6b6f882a88f642248adbcbe7aaef18a7 3 | MonoImporter: 4 | serializedVersion: 2 5 | defaultReferences: [] 6 | executionOrder: 0 7 | icon: {instanceID: 0} 8 | userData: 9 | assetBundleName: 10 | assetBundleVariant: 11 | -------------------------------------------------------------------------------- /Assets/ExplosionShape/ExplosionShape.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using System.Collections; 3 | 4 | [System.Serializable] 5 | public class ExplosionShape : ScriptableObject 6 | { 7 | public int m_width; 8 | public int m_height; 9 | public int[] m_data; 10 | 11 | public ExplosionShape () 12 | { 13 | m_width = 8; 14 | m_height = 8; 15 | m_data = new int[m_width * m_height]; 16 | for (int i = 0; i < m_data.Length; i++) 17 | m_data [i] = 0; 18 | } 19 | }; -------------------------------------------------------------------------------- /Assets/ExplosionShape/ExplosionShape.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: b1a44d4a91cfb8d4e844e48f246a1b25 3 | MonoImporter: 4 | serializedVersion: 2 5 | defaultReferences: [] 6 | executionOrder: 0 7 | icon: {instanceID: 0} 8 | userData: 9 | assetBundleName: 10 | assetBundleVariant: 11 | -------------------------------------------------------------------------------- /Assets/ExplosionShape/ExplosionShapeScene.unity: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!29 &1 4 | SceneSettings: 5 | m_ObjectHideFlags: 0 6 | m_PVSData: 7 | m_PVSObjectsArray: [] 8 | m_PVSPortalsArray: [] 9 | m_OcclusionBakeSettings: 10 | smallestOccluder: 5 11 | smallestHole: .25 12 | backfaceThreshold: 100 13 | --- !u!104 &2 14 | RenderSettings: 15 | m_Fog: 0 16 | m_FogColor: {r: .5, g: .5, b: .5, a: 1} 17 | m_FogMode: 3 18 | m_FogDensity: .00999999978 19 | m_LinearFogStart: 0 20 | m_LinearFogEnd: 300 21 | m_AmbientLight: {r: .200000003, g: .200000003, b: .200000003, a: 1} 22 | m_SkyboxMaterial: {fileID: 0} 23 | m_HaloStrength: .5 24 | m_FlareStrength: 1 25 | m_FlareFadeSpeed: 3 26 | m_HaloTexture: {fileID: 0} 27 | m_SpotCookie: {fileID: 0} 28 | m_ObjectHideFlags: 0 29 | --- !u!127 &3 30 | LevelGameManager: 31 | m_ObjectHideFlags: 0 32 | --- !u!157 &4 33 | LightmapSettings: 34 | m_ObjectHideFlags: 0 35 | m_LightProbes: {fileID: 0} 36 | m_Lightmaps: [] 37 | m_LightmapsMode: 1 38 | m_BakedColorSpace: 0 39 | m_UseDualLightmapsInForward: 0 40 | m_LightmapEditorSettings: 41 | m_Resolution: 50 42 | m_LastUsedResolution: 0 43 | m_TextureWidth: 1024 44 | m_TextureHeight: 1024 45 | m_BounceBoost: 1 46 | m_BounceIntensity: 1 47 | m_SkyLightColor: {r: .860000014, g: .930000007, b: 1, a: 1} 48 | m_SkyLightIntensity: 0 49 | m_Quality: 0 50 | m_Bounces: 1 51 | m_FinalGatherRays: 1000 52 | m_FinalGatherContrastThreshold: .0500000007 53 | m_FinalGatherGradientThreshold: 0 54 | m_FinalGatherInterpolationPoints: 15 55 | m_AOAmount: 0 56 | m_AOMaxDistance: .100000001 57 | m_AOContrast: 1 58 | m_LODSurfaceMappingDistance: 1 59 | m_Padding: 0 60 | m_TextureCompression: 0 61 | m_LockAtlas: 0 62 | --- !u!196 &5 63 | NavMeshSettings: 64 | m_ObjectHideFlags: 0 65 | m_BuildSettings: 66 | agentRadius: .5 67 | agentHeight: 2 68 | agentSlope: 45 69 | agentClimb: .400000006 70 | ledgeDropHeight: 0 71 | maxJumpAcrossDistance: 0 72 | accuratePlacement: 0 73 | minRegionArea: 2 74 | widthInaccuracy: 16.666666 75 | heightInaccuracy: 10 76 | m_NavMesh: {fileID: 0} 77 | --- !u!1 &408564867 78 | GameObject: 79 | m_ObjectHideFlags: 0 80 | m_PrefabParentObject: {fileID: 0} 81 | m_PrefabInternal: {fileID: 0} 82 | serializedVersion: 4 83 | m_Component: 84 | - 4: {fileID: 408564871} 85 | - 33: {fileID: 408564870} 86 | - 23: {fileID: 408564868} 87 | - 54: {fileID: 408564872} 88 | - 65: {fileID: 408564869} 89 | m_Layer: 0 90 | m_Name: Floor 91 | m_TagString: Untagged 92 | m_Icon: {fileID: 0} 93 | m_NavMeshLayer: 0 94 | m_StaticEditorFlags: 4294967295 95 | m_IsActive: 1 96 | --- !u!23 &408564868 97 | Renderer: 98 | m_ObjectHideFlags: 0 99 | m_PrefabParentObject: {fileID: 0} 100 | m_PrefabInternal: {fileID: 0} 101 | m_GameObject: {fileID: 408564867} 102 | m_Enabled: 1 103 | m_CastShadows: 1 104 | m_ReceiveShadows: 1 105 | m_LightmapIndex: 255 106 | m_LightmapTilingOffset: {x: 1, y: 1, z: 0, w: 0} 107 | m_Materials: 108 | - {fileID: 10302, guid: 0000000000000000f000000000000000, type: 0} 109 | m_SubsetIndices: 110 | m_StaticBatchRoot: {fileID: 0} 111 | m_UseLightProbes: 0 112 | m_LightProbeAnchor: {fileID: 0} 113 | m_ScaleInLightmap: 1 114 | m_SortingLayer: 0 115 | m_SortingOrder: 0 116 | m_SortingLayerID: 0 117 | --- !u!65 &408564869 118 | BoxCollider: 119 | m_ObjectHideFlags: 0 120 | m_PrefabParentObject: {fileID: 0} 121 | m_PrefabInternal: {fileID: 0} 122 | m_GameObject: {fileID: 408564867} 123 | m_Material: {fileID: 0} 124 | m_IsTrigger: 0 125 | m_Enabled: 1 126 | serializedVersion: 2 127 | m_Size: {x: 1, y: 1.00000024, z: .100000001} 128 | m_Center: {x: 0, y: 0, z: 0} 129 | --- !u!33 &408564870 130 | MeshFilter: 131 | m_ObjectHideFlags: 0 132 | m_PrefabParentObject: {fileID: 0} 133 | m_PrefabInternal: {fileID: 0} 134 | m_GameObject: {fileID: 408564867} 135 | m_Mesh: {fileID: 10210, guid: 0000000000000000e000000000000000, type: 0} 136 | --- !u!4 &408564871 137 | Transform: 138 | m_ObjectHideFlags: 0 139 | m_PrefabParentObject: {fileID: 0} 140 | m_PrefabInternal: {fileID: 0} 141 | m_GameObject: {fileID: 408564867} 142 | m_LocalRotation: {x: .707106829, y: 0, z: 0, w: .707106829} 143 | m_LocalPosition: {x: 0, y: 0, z: 0} 144 | m_LocalScale: {x: 20, y: 20, z: 1} 145 | m_Children: [] 146 | m_Father: {fileID: 0} 147 | --- !u!54 &408564872 148 | Rigidbody: 149 | m_ObjectHideFlags: 0 150 | m_PrefabParentObject: {fileID: 0} 151 | m_PrefabInternal: {fileID: 0} 152 | m_GameObject: {fileID: 408564867} 153 | serializedVersion: 2 154 | m_Mass: 1 155 | m_Drag: 0 156 | m_AngularDrag: .0500000007 157 | m_UseGravity: 0 158 | m_IsKinematic: 1 159 | m_Interpolate: 0 160 | m_Constraints: 0 161 | m_CollisionDetection: 0 162 | --- !u!1 &445856243 163 | GameObject: 164 | m_ObjectHideFlags: 0 165 | m_PrefabParentObject: {fileID: 0} 166 | m_PrefabInternal: {fileID: 0} 167 | serializedVersion: 4 168 | m_Component: 169 | - 4: {fileID: 445856245} 170 | - 108: {fileID: 445856244} 171 | m_Layer: 0 172 | m_Name: Point light 173 | m_TagString: Untagged 174 | m_Icon: {fileID: 0} 175 | m_NavMeshLayer: 0 176 | m_StaticEditorFlags: 0 177 | m_IsActive: 1 178 | --- !u!108 &445856244 179 | Light: 180 | m_ObjectHideFlags: 0 181 | m_PrefabParentObject: {fileID: 0} 182 | m_PrefabInternal: {fileID: 0} 183 | m_GameObject: {fileID: 445856243} 184 | m_Enabled: 1 185 | serializedVersion: 3 186 | m_Type: 2 187 | m_Color: {r: 1, g: .669117689, b: .669117689, a: 1} 188 | m_Intensity: 1 189 | m_Range: 24.4038944 190 | m_SpotAngle: 30 191 | m_CookieSize: 10 192 | m_Shadows: 193 | m_Type: 0 194 | m_Resolution: -1 195 | m_Strength: 1 196 | m_Bias: .0500000007 197 | m_Softness: 4 198 | m_SoftnessFade: 1 199 | m_Cookie: {fileID: 0} 200 | m_DrawHalo: 0 201 | m_ActuallyLightmapped: 0 202 | m_Flare: {fileID: 0} 203 | m_RenderMode: 0 204 | m_CullingMask: 205 | serializedVersion: 2 206 | m_Bits: 4294967295 207 | m_Lightmapping: 1 208 | m_ShadowSamples: 1 209 | m_ShadowRadius: 0 210 | m_ShadowAngle: 0 211 | m_IndirectIntensity: 1 212 | m_AreaSize: {x: 1, y: 1} 213 | --- !u!4 &445856245 214 | Transform: 215 | m_ObjectHideFlags: 0 216 | m_PrefabParentObject: {fileID: 0} 217 | m_PrefabInternal: {fileID: 0} 218 | m_GameObject: {fileID: 445856243} 219 | m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} 220 | m_LocalPosition: {x: -5.60648966, y: 6.04319859, z: 0} 221 | m_LocalScale: {x: 1, y: 1, z: 1} 222 | m_Children: [] 223 | m_Father: {fileID: 0} 224 | --- !u!1 &698710236 225 | GameObject: 226 | m_ObjectHideFlags: 0 227 | m_PrefabParentObject: {fileID: 0} 228 | m_PrefabInternal: {fileID: 0} 229 | serializedVersion: 4 230 | m_Component: 231 | - 4: {fileID: 698710241} 232 | - 20: {fileID: 698710240} 233 | - 92: {fileID: 698710239} 234 | - 124: {fileID: 698710238} 235 | - 81: {fileID: 698710237} 236 | - 114: {fileID: 698710242} 237 | m_Layer: 0 238 | m_Name: Main Camera 239 | m_TagString: MainCamera 240 | m_Icon: {fileID: 0} 241 | m_NavMeshLayer: 0 242 | m_StaticEditorFlags: 0 243 | m_IsActive: 1 244 | --- !u!81 &698710237 245 | AudioListener: 246 | m_ObjectHideFlags: 0 247 | m_PrefabParentObject: {fileID: 0} 248 | m_PrefabInternal: {fileID: 0} 249 | m_GameObject: {fileID: 698710236} 250 | m_Enabled: 1 251 | --- !u!124 &698710238 252 | Behaviour: 253 | m_ObjectHideFlags: 0 254 | m_PrefabParentObject: {fileID: 0} 255 | m_PrefabInternal: {fileID: 0} 256 | m_GameObject: {fileID: 698710236} 257 | m_Enabled: 1 258 | --- !u!92 &698710239 259 | Behaviour: 260 | m_ObjectHideFlags: 0 261 | m_PrefabParentObject: {fileID: 0} 262 | m_PrefabInternal: {fileID: 0} 263 | m_GameObject: {fileID: 698710236} 264 | m_Enabled: 1 265 | --- !u!20 &698710240 266 | Camera: 267 | m_ObjectHideFlags: 0 268 | m_PrefabParentObject: {fileID: 0} 269 | m_PrefabInternal: {fileID: 0} 270 | m_GameObject: {fileID: 698710236} 271 | m_Enabled: 1 272 | serializedVersion: 2 273 | m_ClearFlags: 1 274 | m_BackGroundColor: {r: .192156866, g: .301960796, b: .474509805, a: .0196078438} 275 | m_NormalizedViewPortRect: 276 | serializedVersion: 2 277 | x: 0 278 | y: 0 279 | width: 1 280 | height: 1 281 | near clip plane: .300000012 282 | far clip plane: 1000 283 | field of view: 60 284 | orthographic: 0 285 | orthographic size: 5 286 | m_Depth: -1 287 | m_CullingMask: 288 | serializedVersion: 2 289 | m_Bits: 4294967295 290 | m_RenderingPath: -1 291 | m_TargetTexture: {fileID: 0} 292 | m_HDR: 0 293 | m_OcclusionCulling: 1 294 | --- !u!4 &698710241 295 | Transform: 296 | m_ObjectHideFlags: 0 297 | m_PrefabParentObject: {fileID: 0} 298 | m_PrefabInternal: {fileID: 0} 299 | m_GameObject: {fileID: 698710236} 300 | m_LocalRotation: {x: .285854965, y: 0, z: 0, w: .958272934} 301 | m_LocalPosition: {x: 0, y: 7.94120026, z: -10.5392399} 302 | m_LocalScale: {x: 1, y: 1, z: 1} 303 | m_Children: [] 304 | m_Father: {fileID: 0} 305 | --- !u!114 &698710242 306 | MonoBehaviour: 307 | m_ObjectHideFlags: 0 308 | m_PrefabParentObject: {fileID: 0} 309 | m_PrefabInternal: {fileID: 0} 310 | m_GameObject: {fileID: 698710236} 311 | m_Enabled: 1 312 | m_EditorHideFlags: 0 313 | m_Script: {fileID: 11500000, guid: 9c60fe7ee361a1943b5d56be1fc6ea1f, type: 3} 314 | m_Name: 315 | m_EditorClassIdentifier: 316 | m_SmilePrefab: {fileID: 100000, guid: c6bc3f583d66b804ba6365e2fc0556bc, type: 2} 317 | m_SmileExplosionSmall: {fileID: 11400000, guid: b1e32f47ec702c742bdc4e980fa56cc1, 318 | type: 2} 319 | m_SmileExplosionBig: {fileID: 11400000, guid: 6f94723e15d399544af1c32573c0cc20, 320 | type: 2} 321 | --- !u!1 &797868126 322 | GameObject: 323 | m_ObjectHideFlags: 0 324 | m_PrefabParentObject: {fileID: 0} 325 | m_PrefabInternal: {fileID: 0} 326 | serializedVersion: 4 327 | m_Component: 328 | - 4: {fileID: 797868128} 329 | - 108: {fileID: 797868127} 330 | m_Layer: 0 331 | m_Name: Point light 332 | m_TagString: Untagged 333 | m_Icon: {fileID: 0} 334 | m_NavMeshLayer: 0 335 | m_StaticEditorFlags: 0 336 | m_IsActive: 1 337 | --- !u!108 &797868127 338 | Light: 339 | m_ObjectHideFlags: 0 340 | m_PrefabParentObject: {fileID: 0} 341 | m_PrefabInternal: {fileID: 0} 342 | m_GameObject: {fileID: 797868126} 343 | m_Enabled: 1 344 | serializedVersion: 3 345 | m_Type: 2 346 | m_Color: {r: .644538224, g: .985294104, b: .536115944, a: 1} 347 | m_Intensity: 1 348 | m_Range: 24.8288364 349 | m_SpotAngle: 30 350 | m_CookieSize: 10 351 | m_Shadows: 352 | m_Type: 0 353 | m_Resolution: -1 354 | m_Strength: 1 355 | m_Bias: .0500000007 356 | m_Softness: 4 357 | m_SoftnessFade: 1 358 | m_Cookie: {fileID: 0} 359 | m_DrawHalo: 0 360 | m_ActuallyLightmapped: 0 361 | m_Flare: {fileID: 0} 362 | m_RenderMode: 0 363 | m_CullingMask: 364 | serializedVersion: 2 365 | m_Bits: 4294967295 366 | m_Lightmapping: 1 367 | m_ShadowSamples: 1 368 | m_ShadowRadius: 0 369 | m_ShadowAngle: 0 370 | m_IndirectIntensity: 1 371 | m_AreaSize: {x: 1, y: 1} 372 | --- !u!4 &797868128 373 | Transform: 374 | m_ObjectHideFlags: 0 375 | m_PrefabParentObject: {fileID: 0} 376 | m_PrefabInternal: {fileID: 0} 377 | m_GameObject: {fileID: 797868126} 378 | m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} 379 | m_LocalPosition: {x: 7.60588598, y: 6.04319859, z: 0} 380 | m_LocalScale: {x: 1, y: 1, z: 1} 381 | m_Children: [] 382 | m_Father: {fileID: 0} 383 | -------------------------------------------------------------------------------- /Assets/ExplosionShape/ExplosionShapeScene.unity.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 82d49eb8b85ecc14d86db6dfb2580080 3 | DefaultImporter: 4 | userData: 5 | assetBundleName: 6 | assetBundleVariant: 7 | -------------------------------------------------------------------------------- /Assets/ExplosionShape/SmallExplode.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/minhhh/unity-editorextension-manual/63f7107faba2791aea5832f87ea3a414fc2b46fc/Assets/ExplosionShape/SmallExplode.asset -------------------------------------------------------------------------------- /Assets/ExplosionShape/SmallExplode.asset.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: b1e32f47ec702c742bdc4e980fa56cc1 3 | NativeFormatImporter: 4 | userData: 5 | assetBundleName: 6 | assetBundleVariant: 7 | -------------------------------------------------------------------------------- /ProjectSettings/AudioManager.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/minhhh/unity-editorextension-manual/63f7107faba2791aea5832f87ea3a414fc2b46fc/ProjectSettings/AudioManager.asset -------------------------------------------------------------------------------- /ProjectSettings/ClusterInputManager.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/minhhh/unity-editorextension-manual/63f7107faba2791aea5832f87ea3a414fc2b46fc/ProjectSettings/ClusterInputManager.asset -------------------------------------------------------------------------------- /ProjectSettings/DynamicsManager.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/minhhh/unity-editorextension-manual/63f7107faba2791aea5832f87ea3a414fc2b46fc/ProjectSettings/DynamicsManager.asset -------------------------------------------------------------------------------- /ProjectSettings/EditorBuildSettings.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/minhhh/unity-editorextension-manual/63f7107faba2791aea5832f87ea3a414fc2b46fc/ProjectSettings/EditorBuildSettings.asset -------------------------------------------------------------------------------- /ProjectSettings/EditorSettings.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/minhhh/unity-editorextension-manual/63f7107faba2791aea5832f87ea3a414fc2b46fc/ProjectSettings/EditorSettings.asset -------------------------------------------------------------------------------- /ProjectSettings/GraphicsSettings.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/minhhh/unity-editorextension-manual/63f7107faba2791aea5832f87ea3a414fc2b46fc/ProjectSettings/GraphicsSettings.asset -------------------------------------------------------------------------------- /ProjectSettings/InputManager.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/minhhh/unity-editorextension-manual/63f7107faba2791aea5832f87ea3a414fc2b46fc/ProjectSettings/InputManager.asset -------------------------------------------------------------------------------- /ProjectSettings/NavMeshAreas.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/minhhh/unity-editorextension-manual/63f7107faba2791aea5832f87ea3a414fc2b46fc/ProjectSettings/NavMeshAreas.asset -------------------------------------------------------------------------------- /ProjectSettings/NetworkManager.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/minhhh/unity-editorextension-manual/63f7107faba2791aea5832f87ea3a414fc2b46fc/ProjectSettings/NetworkManager.asset -------------------------------------------------------------------------------- /ProjectSettings/Physics2DSettings.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/minhhh/unity-editorextension-manual/63f7107faba2791aea5832f87ea3a414fc2b46fc/ProjectSettings/Physics2DSettings.asset -------------------------------------------------------------------------------- /ProjectSettings/ProjectSettings.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/minhhh/unity-editorextension-manual/63f7107faba2791aea5832f87ea3a414fc2b46fc/ProjectSettings/ProjectSettings.asset -------------------------------------------------------------------------------- /ProjectSettings/ProjectVersion.txt: -------------------------------------------------------------------------------- 1 | m_EditorVersion: 5.4.3f1 2 | m_StandardAssetsVersion: 0 3 | -------------------------------------------------------------------------------- /ProjectSettings/QualitySettings.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/minhhh/unity-editorextension-manual/63f7107faba2791aea5832f87ea3a414fc2b46fc/ProjectSettings/QualitySettings.asset -------------------------------------------------------------------------------- /ProjectSettings/TagManager.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/minhhh/unity-editorextension-manual/63f7107faba2791aea5832f87ea3a414fc2b46fc/ProjectSettings/TagManager.asset -------------------------------------------------------------------------------- /ProjectSettings/TimeManager.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/minhhh/unity-editorextension-manual/63f7107faba2791aea5832f87ea3a414fc2b46fc/ProjectSettings/TimeManager.asset -------------------------------------------------------------------------------- /ProjectSettings/UnityAdsSettings.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/minhhh/unity-editorextension-manual/63f7107faba2791aea5832f87ea3a414fc2b46fc/ProjectSettings/UnityAdsSettings.asset -------------------------------------------------------------------------------- /ProjectSettings/UnityConnectSettings.asset: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/minhhh/unity-editorextension-manual/63f7107faba2791aea5832f87ea3a414fc2b46fc/ProjectSettings/UnityConnectSettings.asset -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # Custom Extension Manual 2 | 3 | The Unity Editor offers many APIs for extending its functionality in various ways. It helps bring extreme flexibility to your workflow as a developer, designer or artist. 4 | 5 | In this manual, I will explore the options for creating Unity Editor extensions. The examples are drawn from the code of plenty of tutorials on the Internet, open-source projects and Unity plugins. 6 | 7 | ## Menu Items 8 | 9 | Unity Editor Extensions allow adding custom menus for commonly used functionality that is frequently accessed. 10 | 11 | ### Adding Menu Items 12 | 13 | 1. Create `Editor` script 14 | 1. Create static methods that are marked with the `MenuItem` attribute. 15 | 16 | **Example** 17 | 18 | ``` 19 | using UnityEngine; 20 | using UnityEditor; 21 | 22 | public class MenuItems 23 | { 24 | [MenuItem ("Tools/Clear PlayerPrefs")] 25 | private static void ClearPlayerPrefs () 26 | { 27 | PlayerPrefs.DeleteAll (); 28 | } 29 | } 30 | ``` 31 | 32 | It is sometimes preferable to collect all custom menu items in a single class, such as shown in [https://github.com/EsotericSoftware/spine-runtimes/blob/36000e3c550a80c712afcf65a73103c7d29c9f5f/spine-unity/Assets/spine-unity/Editor/Menus.cs](https://github.com/EsotericSoftware/spine-runtimes/blob/36000e3c550a80c712afcf65a73103c7d29c9f5f/spine-unity/Assets/spine-unity/Editor/Menus.cs). 33 | 34 | ### Hotkeys 35 | 36 | Hotkey can be added to the menus as follows: 37 | 38 | ``` 39 | [MenuItem("Tools/New Option %#a")] 40 | private static void NewMenuOption() 41 | { 42 | } 43 | 44 | // Add a new menu item with hotkey CTRL-G 45 | 46 | [MenuItem("Tools/Item %g")] 47 | private static void NewNestedOption() 48 | { 49 | } 50 | 51 | // Add a new menu item with hotkey G 52 | [MenuItem("Tools/Item2 _g")] 53 | private static void NewOptionWithHotkey() 54 | { 55 | } 56 | ``` 57 | 58 | [These are the supported keys](https://docs.unity3d.com/ScriptReference/MenuItem.html): 59 | 60 | % – CTRL on Windows / CMD on OSX 61 | # – Shift 62 | & – Alt 63 | LEFT/RIGHT/UP/DOWN – Arrow keys 64 | F1...F2 – F keys 65 | HOME, END, PGUP, PGDN 66 | 67 | ### Component Menu Items 68 | Unity does not allow you to add items to `Component` menu with `MenuItem` attribute. Instead, you have to use a different attribute, `AddComponentMenu`, on the MonoBehaviour class itself. 69 | 70 | **Examples** 71 | 72 | ``` 73 | using UnityEngine; 74 | using System.Collections; 75 | 76 | [AddComponentMenu ("My/SuperMonoBehaviour")] 77 | public class MyMonoBehaviour : MonoBehaviour 78 | { 79 | } 80 | ``` 81 | 82 | A real-world example is [https://github.com/EsotericSoftware/spine-runtimes/blob/master/spine-unity/Assets/spine-unity/SkeletonUtility/SkeletonUtilityBone.cs](https://github.com/EsotericSoftware/spine-runtimes/blob/master/spine-unity/Assets/spine-unity/SkeletonUtility/SkeletonUtilityBone.cs) 83 | 84 | ### Special Paths 85 | 86 | Unity has a few “special” paths that act as context menus (menus that are accessible using right-click): 87 | 88 | Assets – items will be available under the “Assets” menu, as well using right-click inside the project view. 89 | Assets/Create – items will be listed when clicking on the “Create” button in the project view (useful when adding new types that can be added to the project) 90 | CONTEXT/ComponentName – items will be available by right-clicking inside the inspector of the given component. 91 | 92 | **MenuCommand** 93 | 94 | When adding a new menu item to an inspector (using `CONTEXT/Component`, as described above), sometimes it is necessary to get a reference to the actual component (e.g: to modify its data). 95 | 96 | This can be done by adding a MenuCommand argument to the static method that defines the new menu item: 97 | 98 | ``` 99 | [MenuItem ("CONTEXT/Rigidbody/New Option")] 100 | private static void NewOpenForRigidBody (MenuCommand menuCommand) 101 | { 102 | var rigid = menuCommand.context as Rigidbody; 103 | Debug.Log ("Change rigidbody " + rigid); 104 | } 105 | ``` 106 | 107 | **ContextMenu** 108 | 109 | This is similar to defining `MenuItem` with a path that starts with `CONTEXT/...` 110 | 111 | Examples 112 | 113 | ``` 114 | public class MyMonoBehaviour : MonoBehaviour 115 | { 116 | public string name = ""; 117 | 118 | [ContextMenu ("Reset Name")] 119 | private void ResetName () 120 | { 121 | name = string.Empty; 122 | } 123 | } 124 | ``` 125 | 126 | A real world example is [this](https://github.com/EsotericSoftware/spine-runtimes/blob/9c21942482701ccf28778a210fef03f3cae151e6/spine-unity/Assets/Examples/Getting%20Started/Scripts/SpineboyBeginnerView.cs). 127 | 128 | 129 | **ContextMenuItem** 130 | 131 | This attribute is added to fields of a component (MonoBehaviour) class, to allow adding context menus at a finer resolution 132 | 133 | Example 134 | 135 | ``` 136 | using UnityEngine; 137 | using System.Collections; 138 | 139 | public class ExampleClass : MonoBehaviour { 140 | [ContextMenuItem("Reset", "ResetBiography")] 141 | [Multiline(8)] 142 | public string playerBiography = ""; 143 | void ResetBiography() { 144 | playerBiography = ""; 145 | } 146 | } 147 | ``` 148 | 149 | ### Validation 150 | 151 | Some menu items should only be available if certain conditions are met, and should not be available otherwise. Enabling/disabling menu items according to their usage context is done by adding validation methods. 152 | 153 | **Example** 154 | 155 | ``` 156 | [MenuItem("Assets/ProcessTexture")] 157 | private static void DoSomethingWithTexture() 158 | { 159 | } 160 | 161 | // Note that we pass the same path, and also pass "true" to the second argument. 162 | [MenuItem("Assets/ProcessTexture", true)] 163 | private static bool NewMenuOptionValidation() 164 | { 165 | // This returns true when the selected object is a Texture2D (the menu item will be disabled otherwise). 166 | return Selection.activeObject.GetType() == typeof(Texture2D); 167 | } 168 | ``` 169 | 170 | A real world example is [this](https://github.com/EsotericSoftware/spine-runtimes/blob/a6d9915c95b3f0c0db050b603fa3d5fd868f1346/spine-unity/Assets/spine-unity/Editor/BoneFollowerInspector.cs). 171 | 172 | ### Controlling Order with Priority 173 | Priority is a number that can be assigned to a MenuItem attribute that controls the ordering of menu items under the root menu. Menu items are also automatically grouped according to their assigned priority in increments of 50. 174 | 175 | **Example** 176 | 177 | ``` 178 | [MenuItem("NewMenu/Option1", false, 1)] 179 | private static void NewMenuOption() 180 | { 181 | } 182 | 183 | [MenuItem("NewMenu/Option2", false, 2)] 184 | private static void NewMenuOption2() 185 | { 186 | } 187 | 188 | [MenuItem("NewMenu/Option3", false, 3)] 189 | private static void NewMenuOption3() 190 | { 191 | } 192 | 193 | [MenuItem("NewMenu/Option4", false, 51)] 194 | private static void NewMenuOption4() 195 | { 196 | } 197 | 198 | [MenuItem("NewMenu/Option5", false, 52)] 199 | private static void NewMenuOption5() 200 | { 201 | } 202 | ``` 203 | 204 | 205 | **References** 206 | * [Unity Editor Extensions – Menu Items](http://www.tallior.com/unity-editor-extensions-menu-items/) 207 | * [Guide to Extending Unity Editor’s Menus](https://blog.redbluegames.com/guide-to-extending-unity-editors-menus-b2de47a746db#.5lwjprjv8) 208 | 209 | 210 | ## ScriptableWizard 211 | One of the simplest forms of custom editor windows. It opens like a dialog box, you set some values in it, then hit a button to execute some action. 212 | 213 | Editor wizards are typically opened using a menu item. 214 | 215 | ``` 216 | using System.Collections; 217 | using UnityEditor; 218 | using System; 219 | 220 | public class SelectAllOfTag : ScriptableWizard 221 | { 222 | public string searchTag = ""; 223 | 224 | [MenuItem ("Tools/Select All Of Tag")] 225 | public static void SelectAllOfTagWizard () 226 | { 227 | ScriptableWizard.DisplayWizard ("Select All of Tag...", "Reset", "Make Selection"); 228 | } 229 | 230 | void OnWizardCreate () 231 | { 232 | searchTag = ""; 233 | SelectGameObjectsByTag (searchTag); 234 | } 235 | 236 | void OnWizardOtherButton () 237 | { 238 | SelectGameObjectsByTag (searchTag); 239 | } 240 | 241 | void SelectGameObjectsByTag (string tag) 242 | { 243 | try { 244 | GameObject[] gameObjects = GameObject.FindGameObjectsWithTag (tag); 245 | Selection.objects = gameObjects; 246 | } catch (Exception e) { 247 | Selection.objects = new GameObject[0]; 248 | } 249 | 250 | } 251 | 252 | } 253 | ``` 254 | 255 | **References** 256 | * [Creating Basic Editor Tools](https://www.youtube.com/watch?v=L24GKk1qQD4) 257 | 258 | ## Custom EditorWindow 259 | 260 | Create your own custom editor window that can float free or be docked as a tab, just like the native windows: Scene Window, Game Window, Inspector Window in the Unity interface. 261 | 262 | EditorWindow are typically opened using a menu item. 263 | 264 | **Example** 265 | 266 | ``` 267 | public class MultipleWindow : EditorWindow 268 | { 269 | [MenuItem ("Window/MultipleWindow")] 270 | static void Open () 271 | { 272 | var exampleWindow = CreateInstance (); 273 | exampleWindow.Show (); 274 | } 275 | } 276 | ``` 277 | 278 | Using `CreateInstance`, we can create multiple instances of the EditorWindow. However, most of the time, we would only want 1 instance of the EditorWindow to do specific tasks. In that case, we will use `EditorWindow.GetWindow` 279 | 280 | ``` 281 | public class SingleWindow : EditorWindow 282 | { 283 | [MenuItem("Window/SingleWindow")] 284 | static void Open () 285 | { 286 | GetWindow (); 287 | } 288 | } 289 | ``` 290 | 291 | ### Showing Windows 292 | 293 | There are several ways to show the EditorWindow 294 | 295 | **Show** 296 | 297 | This is the default way, using `EditorWindow.Show`. The default call to `EditorWindow.GetWindow` also use this method internally. Windows shown in this way can be docked as a tab to a DockArea 298 | 299 | **ShowUtility** 300 | 301 | If you want the window to be always on top of other windows, and not dockable, you can use `EditorWindow.ShowUtility` or `EditorWindow.GetWindow (true)`. 302 | 303 | **ShowPopup** 304 | 305 | This is a Window with no window title and no Close button. You have to implement the Close function yourself. 306 | 307 | The `Slice` menu in the `SpriteEditor` window is implemented using this approach. 308 | 309 | **PopupWindow** 310 | 311 | This is similar to `ShowPopup` 312 | 313 | **ShowAuxWindow** 314 | 315 | Create a window that can not be set as Tab Window. It is similar to `ShowUtility`, but if you focus on another window, this window will be deleted. 316 | 317 | **ShowAsDropDown** 318 | 319 | Similar to `ShowPopup` except that it will always be displayed within the visible area of the screen 320 | 321 | 322 | ### Preference Item 323 | 324 | `PreferenceItem` is a way to add menus to Unity Preferences 325 | 326 | ``` 327 | public class PreferenceItemExample : MonoBehaviour 328 | { 329 | [PreferenceItem ("Example")] 330 | static void OnPreferenceGUI () 331 | { 332 | } 333 | } 334 | ``` 335 | 336 | Real world example: [BitStrapPreferences](https://bitbucket.org/Bitcake-Studio/bitstrap/src/4999a15ed7af5a2f6786c38d57733e1a5871579f/Assets/BitStrap/Plugins/Preferences/Editor/BitStrapPreferences.cs?at=default&fileviewer=file-view-default) 337 | 338 | ### IHasCustomMenu 339 | 340 | You can implement this interface to add more item to the Context Menu of the EditorWindow 341 | 342 | ``` 343 | public class IHasCustomMenuWindow : EditorWindow, IHasCustomMenu 344 | { 345 | bool locked = true; 346 | public void AddItemsToMenu (GenericMenu menu) 347 | { 348 | menu.AddItem (new GUIContent ("example"), false, () => { 349 | 350 | }); 351 | 352 | menu.AddItem (new GUIContent ("example2"), locked, () => { 353 | locked = !locked; 354 | }); 355 | } 356 | 357 | [MenuItem ("Window/IHasCustomMenuWindow")] 358 | static void Open () 359 | { 360 | GetWindow (); 361 | } 362 | } 363 | ``` 364 | 365 | ## Saving Data 366 | When using Editor Extension, there are 4 options 367 | 368 | ### EditorPrefs 369 | 370 | EditorPrefs is a simple way to store key-value tuple in Unity Editor environment. 371 | 372 | Example 373 | 374 | ``` 375 | public class EditorPrefsWindow : EditorWindow 376 | { 377 | int someValue = 1; 378 | const string SOME_KEY = "KEY"; 379 | 380 | 381 | [MenuItem ("Window/EditorPrefsWindow")] 382 | static void Open () 383 | { 384 | GetWindow (); 385 | } 386 | 387 | void OnEnable () 388 | { 389 | someValue = EditorPrefs.GetInt (SOME_KEY, 1); 390 | } 391 | 392 | void OnGUI () 393 | { 394 | EditorGUI.BeginChangeCheck (); 395 | 396 | someValue = EditorGUILayout.IntSlider ("My Value", someValue, 1, 100); 397 | 398 | if (EditorGUI.EndChangeCheck ()) { 399 | EditorPrefs.SetInt (SOME_KEY, someValue); 400 | } 401 | 402 | } 403 | } 404 | ``` 405 | 406 | ### EditorUserSettings 407 | 408 | It's a way to save data only for the current project. The data will be stored in `Library/EditorUserSettings.asset`. 409 | 410 | It can be used to save sensitive information such as password or oauth accesss token. The values will be encrypted. 411 | 412 | ### ScriptableObject 413 | 414 | This is the main form of saving shared data in Unity. You can save various kinds of data, and you can read back these data easily from outside Editor Script. 415 | 416 | 417 | ### JSON 418 | Finally, one can use `JSON` format to save settings. 419 | 420 | There are many ways to serialize Unity Objects to JSON, including Unity's `JsonUtility`, `EditorJsonUtility` and other third-party libraries such as `MiniJSON` or `SimpleJSON`. 421 | 422 | ## Property Drawer 423 | 424 | `PropertyDrawer` is a great way to create custom drawer for your Serializable class. Another use is to customize the GUI of script members with custom `PropertyAttribute` 425 | 426 | ### CustomPropertyDrawer with PropertyAttribute 427 | 428 | Unity already provides CustomPropertyDrawer for several `PropertyAttribute` including: `Range, Multiline, TextArea, ColorUsage, HideInInspector, Tooltip` 429 | 430 | Example 431 | 432 | ``` 433 | [CustomPropertyDrawer (typeof (MyAttribute))] 434 | public class MyAttributeDrawer : PropertyDrawer { 435 | 436 | // Draw the property inside the given rect 437 | public override void OnGUI (Rect position, SerializedProperty property, GUIContent label) { 438 | ... 439 | ``` 440 | 441 | Real world examples: [property-drawer-collection](https://github.com/anchan828/property-drawer-collection) 442 | 443 | ### CustomPropertyDrawer for a class 444 | 445 | You can override the default property drawer for a class, similarly to a `PropertyAttribute` 446 | 447 | ``` 448 | [CustomPropertyDrawer (typeof (MyClass))] 449 | public class MyClassDrawer : PropertyDrawer { 450 | 451 | // Draw the property inside the given rect 452 | public override void OnGUI (Rect position, SerializedProperty property, GUIContent label) { 453 | ... 454 | ``` 455 | 456 | **References** 457 | 458 | * [Property Drawers & Custom Inspectors](https://unity3d.com/learn/tutorials/topics/interface-essentials/property-drawers-custom-inspectors) 459 | 460 | ## DecoratorDrawer 461 | A DecoratorDrawer is similar to a PropertyDrawer, except that it doesn't draw a property but rather draws decorative elements based purely on the data it gets from its corresponding PropertyAttribute. 462 | 463 | Some built-in DecoratorDrawer includes: Header, Space 464 | 465 | Example 466 | 467 | ``` 468 | [CustomPropertyDrawer(typeof(MyAttribute))] 469 | public class MyAttributeDrawer : DecoratorDrawer 470 | { 471 | public override void OnGUI(Rect position) 472 | { 473 | ... 474 | ``` 475 | 476 | [Unity example](https://docs.unity3d.com/ScriptReference/DecoratorDrawer.html) 477 | 478 | ## Custom Editor 479 | 480 | Unity allows creating a custom inspector for built-in classes or your custom classes. 481 | 482 | To create a new inspector, create a new `EditorClass` and decorate it with `CustomEditor` attribute. 483 | 484 | ``` 485 | [CustomEditor(typeof(MySettingsClass))] 486 | public class MySettingsEditor : Editor 487 | { 488 | public override void OnInspectorGUI() 489 | { 490 | } 491 | 492 | public override void OnSceneGUI() 493 | { 494 | } 495 | 496 | public override void OnPreviewGUI (Rect r, GUIStyle background) 497 | { 498 | } 499 | } 500 | ``` 501 | 502 | Real world example of Custom Inspector: (https://github.com/EsotericSoftware/spine-runtimes/blob/master/spine-unity/Assets/spine-unity/Editor/SkeletonRendererInspector.cs) 503 | 504 | Example of OnPreviewGUI: [Unity: ScriptableObject and AssetDatabase](https://www.youtube.com/watch?v=74Ph6y0rR-g) 505 | 506 | ### SceneView 507 | 508 | You can draw GUI stuff on the Scene View with `SceneView.onSceneGUIDelegate += OnSceneGUI;`. Inside a CustomEditor, you can use the function `OnSceneGUI`. 509 | 510 | Example 511 | 512 | ``` 513 | public void OnSceneGUI () 514 | { 515 | Handles.BeginGUI (); 516 | ... 517 | Handles.EndGUI (); 518 | } 519 | ``` 520 | 521 | Real world example of using Scene View: [Editor Scripting from the real world](https://www.youtube.com/watch?v=s1o0gZwJS-4), SplineEditor of [Xffect Editor](https://www.assetstore.unity3d.com/en/#!/content/3810), and [MeshVisualizeWindow.cs](https://gist.github.com/TJHeuvel/c4f8d218a0d774682560a8f348a90dff) 522 | 523 | 524 | **References** 525 | 526 | * [Property Drawers & Custom Inspectors](https://unity3d.com/learn/tutorials/topics/interface-essentials/property-drawers-custom-inspectors) 527 | * [Unity Editor Extensions](http://www.tallior.com/unity-editor-extensions/) 528 | * [Expose property in inspector](http://wiki.unity3d.com/index.php?title=Expose_properties_in_inspector) 529 | * [ScriptableObject and AssetDatabase](https://www.youtube.com/watch?v=74Ph6y0rR-g) 530 | 531 | 532 | ## Gizmos 533 | Gizmos are used to give visual debugging or setup aids in the scene view. 534 | 535 | ### Gizmos setup in Inspector 536 | 537 | You can setup the Gizmos added to GameObject in the Inspector. 538 | 539 | 540 | ### Drawing Gizmos 541 | 542 | All gizmo drawing has to be done in either OnDrawGizmos or OnDrawGizmosSelected functions of the script. 543 | 544 | ``` 545 | void OnDrawGizmos () 546 | { 547 | Gizmos.color = new Color32 (255, 0, 255, 255); 548 | Gizmos.DrawWireCube (transform.position, transform.lossyScale); 549 | } 550 | ``` 551 | 552 | **References** 553 | 554 | * [How to Add Your Own Tools to Unity’s Editor](https://code.tutsplus.com/tutorials/how-to-add-your-own-tools-to-unitys-editor--active-10047) 555 | * [Gizmos](https://docs.unity3d.com/ScriptReference/Gizmos.html) 556 | 557 | 558 | ## EditorApplication.hierarchyWindowItemOnGUI 559 | Delegate for OnGUI events for every visible list item in the HierarchyWindow. 560 | 561 | Example 562 | 563 | ``` 564 | public static class HierarchyDemo 565 | { 566 | [InitializeOnLoadMethod] 567 | private static void DrawToHierarchy () 568 | { 569 | EditorApplication.hierarchyWindowItemOnGUI += OnGUI; 570 | } 571 | 572 | private static void OnGUI (int instanceID, Rect rect) 573 | { 574 | 575 | } 576 | ``` 577 | 578 | ## AssetPostProcessor 579 | AssetPostprocessor lets you hook into the import pipeline and run scripts prior or after importing assets. 580 | 581 | Example: [Property Drawers & Custom Inspectors](https://unity3d.com/learn/tutorials/topics/interface-essentials/property-drawers-custom-inspectors) 582 | 583 | Real world example: [unity-dither4444](https://github.com/keijiro/unity-dither4444) 584 | 585 | ## Miscs 586 | * [Editor Default Resources](http://anchan828.github.io/editor-manual/web/part2-beginner.html) 587 | 588 | ## Tips and Tricks 589 | 590 | 591 | ## References 592 | * [Unity Editor Extensions](http://www.tallior.com/unity-editor-extensions/) 593 | * [Editor Scripting from the real world](https://www.youtube.com/watch?v=s1o0gZwJS-4) 594 | * [Property Drawers & Custom Inspectors](https://unity3d.com/learn/tutorials/topics/interface-essentials/property-drawers-custom-inspectors) 595 | * [Editor Manual](http://anchan828.github.io/editor-manual/web/index.html) 596 | --------------------------------------------------------------------------------