├── Assets ├── EdNotes │ ├── README.txt.meta │ ├── Scripts │ │ ├── Note.cs │ │ ├── Editor.meta │ │ ├── Editor │ │ │ ├── NotesAsset.asset.meta │ │ │ ├── EditorNotes.cs.meta │ │ │ ├── NoteWindow.cs.meta │ │ │ ├── NotesAsset.cs.meta │ │ │ ├── EditorNotesSettings.cs.meta │ │ │ ├── NotesAsset.asset │ │ │ ├── NotesAsset.cs │ │ │ ├── EditorNotes.cs │ │ │ ├── NoteWindow.cs │ │ │ └── EditorNotesSettings.cs │ │ ├── Note.cs.meta │ │ ├── NotesContainer.cs.meta │ │ └── NotesContainer.cs │ ├── Scripts.meta │ └── README.txt └── EdNotes.meta ├── .gitignore ├── README.md └── UNLICENSE /Assets/EdNotes/README.txt.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 02ea673c1803cb6498e88d5444338b05 3 | timeCreated: 1505894805 4 | licenseType: Free 5 | TextScriptImporter: 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Assets/EdNotes.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 774ea463344f6d24ea34616b3efe3b50 3 | folderAsset: yes 4 | timeCreated: 1505810532 5 | licenseType: Free 6 | DefaultImporter: 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/EdNotes/Scripts/Note.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | 3 | 4 | namespace EdNotes 5 | { 6 | [System.Serializable] 7 | public class Note 8 | { 9 | public Object targetObj; 10 | public string targetGUID; 11 | public string text; 12 | } 13 | } -------------------------------------------------------------------------------- /Assets/EdNotes/Scripts.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 903c5457b6403a84f9743f73a91b1581 3 | folderAsset: yes 4 | timeCreated: 1505823672 5 | licenseType: Free 6 | DefaultImporter: 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/EdNotes/Scripts/Editor.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 4372671519a9ef14c9c9faacd7838a21 3 | folderAsset: yes 4 | timeCreated: 1505810537 5 | licenseType: Free 6 | DefaultImporter: 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/EdNotes/Scripts/Editor/NotesAsset.asset.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 7bf30532836ebd04f924c12ab9b8f83c 3 | timeCreated: 1505902982 4 | licenseType: Free 5 | NativeFormatImporter: 6 | mainObjectFileID: 11400000 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | -------------------------------------------------------------------------------- /Assets/EdNotes/Scripts/Note.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 6c75670d45336e24ca022d80fc3aec21 3 | timeCreated: 1505811019 4 | licenseType: Free 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/EdNotes/Scripts/Editor/EditorNotes.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 5421b9ab8f5ad2f49b43f7198e39519f 3 | timeCreated: 1505811019 4 | licenseType: Free 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/EdNotes/Scripts/Editor/NoteWindow.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 2b44ed70405a7234db4f23430c7d8655 3 | timeCreated: 1505817201 4 | licenseType: Free 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/EdNotes/Scripts/Editor/NotesAsset.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 8de00777c8f8c1c44bbc70fb25461a21 3 | timeCreated: 1505810581 4 | licenseType: Free 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/EdNotes/Scripts/NotesContainer.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: d2c03a706958d0045a2a966ac965a214 3 | timeCreated: 1505819056 4 | licenseType: Free 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/EdNotes/Scripts/Editor/EditorNotesSettings.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: d40f3e0862da7fd408aff9037e56dca1 3 | timeCreated: 1505813027 4 | licenseType: Free 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/EdNotes/Scripts/Editor/NotesAsset.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: 8de00777c8f8c1c44bbc70fb25461a21, type: 3} 12 | m_Name: NotesAsset 13 | m_EditorClassIdentifier: 14 | iconName: sv_icon_dot4_pix16_gizmo 15 | notes: [] 16 | labelExpandWidth: 0100 17 | iconPos: 0000000002000000 18 | iconOffs: 19 | - 0 20 | - 0 21 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /[Ll]ibrary/ 2 | /[Tt]emp/ 3 | /[Oo]bj/ 4 | /[Bb]uild/ 5 | /[Bb]uilds/ 6 | /Assets/AssetStoreTools* 7 | /ProjectSettings/ 8 | /_build/ 9 | /_work/ 10 | 11 | # Visual Studio 2015 cache directory 12 | /.vs/ 13 | 14 | # Autogenerated VS/MD/Consulo solution and project files 15 | ExportedObj/ 16 | .consulo/ 17 | *.csproj 18 | *.unityproj 19 | *.sln 20 | *.suo 21 | *.tmp 22 | *.user 23 | *.userprefs 24 | *.pidb 25 | *.booproj 26 | *.svd 27 | *.pdb 28 | 29 | # Unity3D generated meta files 30 | *.pidb.meta 31 | 32 | # Unity3D Generated File On Crash Reports 33 | sysinfo.txt 34 | 35 | # Builds 36 | *.apk 37 | *.unitypackage 38 | -------------------------------------------------------------------------------- /Assets/EdNotes/Scripts/NotesContainer.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using UnityEngine; 3 | 4 | 5 | namespace EdNotes 6 | { 7 | public class NotesContainer : MonoBehaviour 8 | { 9 | [HideInInspector] public List notes = new List(); 10 | 11 | private Dictionary _cache = null; 12 | public Dictionary Cache { get { return _cache ?? UpdateCache(); } } 13 | 14 | public Dictionary UpdateCache() 15 | { 16 | if (_cache == null) _cache = new Dictionary(); 17 | else _cache.Clear(); 18 | 19 | foreach (Note n in notes) 20 | if (n.targetObj != null) _cache.Add(n.targetObj.GetInstanceID(), n); 21 | 22 | return _cache; 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /Assets/EdNotes/README.txt: -------------------------------------------------------------------------------- 1 | # Unity Editor Notes 2 | 3 | A simple tool to add notes to GameObject in the Hierarchy or Objects in the Project panel. The notes data in the scene are kept in a hidden object tagged as `EditorOnly` so the data will not end up in your final builds. The data concerning project objects are kept in an asset next to the this tool's scripts by default. 4 | 5 | Open the Note panel via menu: `Window > Notes`. Enter some text and press [Save]. 6 | 7 | Click on the gear icon to show the Editor Notes settings where you can change the icon to use to indicate that an object has a note attached. 8 | 9 | - Label Expand: if you choose a Label icon then this determine if the colour expands full width or only object name length. 10 | - Icon Position: select where icon should be shown if using icon type indicator. 11 | + Left/Right edge of panel 12 | + To Left/Right of the object's name 13 | - Icon Offset: can be used to move the icon from the selected position -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Unity Editor Notes 2 | 3 | A simple tool to add notes to GameObject in the Hierarchy or Objects in the Project panel. The notes data in the scene are kept in a hidden object tagged as `EditorOnly` so the data will not end up in your final builds. The data concerning project objects are kept in an asset next to the this tool's scripts by default. 4 | 5 | Open the Note panel via menu: `Window > Notes`. Enter some text and press [Save]. 6 | 7 | Click on the gear icon to show the Editor Notes settings where you can change the icon to use to indicate that an object has a note attached. 8 | 9 | - Label Expand: if you choose a Label icon then this determine if the colour expands full width or only object name length. 10 | - Icon Position: select where icon should be shown if using icon type indicator. 11 | + Left/Right edge of panel 12 | + To Left/Right of the object's name 13 | - Icon Offset: can be used to move the icon from the selected position 14 | 15 | ![screenshot](https://user-images.githubusercontent.com/837362/30640573-bb962954-9e03-11e7-88e9-1d03f2379195.png) 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /UNLICENSE: -------------------------------------------------------------------------------- 1 | This is free and unencumbered software released into the public domain. 2 | 3 | Anyone is free to copy, modify, publish, use, compile, sell, or 4 | distribute this software, either in source code form or as a compiled 5 | binary, for any purpose, commercial or non-commercial, and by any 6 | means. 7 | 8 | In jurisdictions that recognize copyright laws, the author or authors 9 | of this software dedicate any and all copyright interest in the 10 | software to the public domain. We make this dedication for the benefit 11 | of the public at large and to the detriment of our heirs and 12 | successors. We intend this dedication to be an overt act of 13 | relinquishment in perpetuity of all present and future rights to this 14 | software under copyright law. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19 | IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 20 | OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 | OTHER DEALINGS IN THE SOFTWARE. 23 | 24 | For more information, please refer to 25 | -------------------------------------------------------------------------------- /Assets/EdNotes/Scripts/Editor/NotesAsset.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using UnityEngine; 3 | using UnityEditor; 4 | 5 | 6 | namespace EdNotes 7 | { 8 | public class NotesAsset : ScriptableObject 9 | { 10 | public enum IconPos { Left, Right, LeftName, RightName } 11 | 12 | [SerializeField, HideInInspector] private string iconName = "sv_icon_dot4_pix16_gizmo"; //"sv_label_4"; 13 | [HideInInspector] public List notes = new List(); 14 | [HideInInspector] public bool[] labelExpandWidth = { false, false }; 15 | [HideInInspector] public IconPos[] iconPos = { IconPos.Left, IconPos.LeftName }; 16 | [HideInInspector] public float[] iconOffs = { 0f, 0f }; 17 | 18 | public GUIStyle Style { get; private set; } 19 | public GUIContent Icon { get; private set; } 20 | public bool IsLabelIcon { get; private set; } 21 | 22 | private Dictionary _cache = null; 23 | public Dictionary Cache { get { return _cache ?? UpdateCache(); } } 24 | 25 | public string IconName 26 | { 27 | get { return iconName; } 28 | set { iconName = value; UpdateIcon(); } 29 | } 30 | 31 | public Dictionary UpdateCache() 32 | { 33 | if (_cache == null) _cache = new Dictionary(); 34 | else _cache.Clear(); 35 | 36 | foreach (Note n in notes) 37 | if (n.targetObj != null) _cache.Add(n.targetGUID, n); 38 | 39 | return _cache; 40 | } 41 | 42 | public void UpdateIcon() 43 | { 44 | Icon = null; 45 | IsLabelIcon = false; 46 | if (!string.IsNullOrEmpty(iconName)) 47 | { 48 | Icon = EditorGUIUtility.IconContent(iconName); 49 | if (Icon.image == null) 50 | { 51 | Icon = null; 52 | } 53 | else 54 | { 55 | if (IconName.Contains("sv_label")) IsLabelIcon = true; 56 | 57 | if (IsLabelIcon) 58 | { 59 | Style = new GUIStyle() 60 | { 61 | stretchWidth = false, 62 | border = new RectOffset(6, 6, 0, 0), 63 | padding = new RectOffset(5, 5, 0, 0), 64 | normal = { background = (Texture2D)Icon.image } 65 | }; 66 | } 67 | } 68 | } 69 | } 70 | 71 | // ------------------------------------------------------------------------------------------------------------ 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /Assets/EdNotes/Scripts/Editor/EditorNotes.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using UnityEditor; 3 | using UnityEngine; 4 | using UnityEngine.SceneManagement; 5 | using UnityEditor.SceneManagement; 6 | 7 | 8 | namespace EdNotes 9 | { 10 | [InitializeOnLoad] 11 | public static class EditorNotes 12 | { 13 | public static readonly string NotesContainerObjName = "_EdNotes_K2JB5LWK4E3B_"; 14 | 15 | private static NotesAsset _settings = null; 16 | public static NotesAsset Settings { get { return _settings ?? LoadNotesAsset(); } } 17 | 18 | public static Dictionary cache = null; 19 | 20 | // ------------------------------------------------------------------------------------------------------------ 21 | 22 | static EditorNotes() 23 | { 24 | EditorApplication.hierarchyWindowItemOnGUI += HierarchyOnGUI; 25 | EditorApplication.projectWindowItemOnGUI += ProjectWindowItemCallback; 26 | EditorSceneManager.sceneOpened += SceneOpened; 27 | EditorSceneManager.sceneClosed += SceneClosed; 28 | } 29 | 30 | public static NotesContainer GetContainer(Scene scene) 31 | { 32 | if (cache == null) 33 | { 34 | cache = new Dictionary(); 35 | UpdateSceneCache(); 36 | } 37 | 38 | NotesContainer c; 39 | if (cache.TryGetValue(scene, out c)) return c; 40 | return null; 41 | } 42 | 43 | public static void UpdateSceneCache() 44 | { 45 | Object[] objs = Object.FindObjectsOfType(); 46 | foreach (NotesContainer c in objs) 47 | { 48 | if (!cache.ContainsKey(c.gameObject.scene)) cache.Add(c.gameObject.scene, c); 49 | } 50 | } 51 | 52 | private static void SceneOpened(Scene scene, OpenSceneMode mode) 53 | { 54 | UpdateSceneCache(); 55 | } 56 | 57 | private static void SceneClosed(Scene scene) 58 | { 59 | if (cache.ContainsKey(scene)) cache.Remove(scene); 60 | } 61 | 62 | private static void HierarchyOnGUI(int instanceID, Rect rect) 63 | { 64 | if (Settings.Icon == null || Event.current.type != EventType.Repaint) return; 65 | GameObject go = EditorUtility.InstanceIDToObject(instanceID) as GameObject; 66 | if (go == null) return; // skip the "Scene" entry 67 | 68 | NotesContainer c = GetContainer(go.scene); 69 | if (c == null || !c.Cache.ContainsKey(instanceID)) return; 70 | 71 | if (Settings.IsLabelIcon) DrawLabel(0, rect, go.name); 72 | else DrawIcon(0, rect, go.name); 73 | } 74 | 75 | private static void ProjectWindowItemCallback(string guid, Rect rect) 76 | { 77 | if (Settings.Icon == null || Event.current.type != EventType.Repaint) return; 78 | if (!Settings.Cache.ContainsKey(guid)) return; 79 | 80 | string name = AssetDatabase.GUIDToAssetPath(guid); 81 | int i = name.LastIndexOf('/') + 1; 82 | if (i > 0) name = name.Substring(i); 83 | i = name.LastIndexOf('.'); 84 | if (i > 0) name = name.Substring(0, i); 85 | 86 | if (Settings.IsLabelIcon) 87 | { 88 | rect.x += 16f; 89 | DrawLabel(1, rect, name); 90 | } 91 | else DrawIcon(1, rect, name); 92 | } 93 | 94 | private static void DrawLabel(int idx, Rect rect, string name) 95 | { 96 | GUIContent gc = TempGUIContent(name); 97 | 98 | if (!Settings.labelExpandWidth[idx]) 99 | rect.width = Settings.Style.CalcSize(gc).x; 100 | 101 | GUI.Label(rect, gc, Settings.Style); 102 | } 103 | 104 | private static void DrawIcon(int idx, Rect rect, string name) 105 | { 106 | if (Settings.iconPos[idx] == NotesAsset.IconPos.Left) 107 | { 108 | rect.x = Settings.iconOffs[idx]; 109 | } 110 | else if (Settings.iconPos[idx] == NotesAsset.IconPos.Right) 111 | { 112 | rect.x = rect.xMax - 18f - Settings.iconOffs[idx]; 113 | } 114 | else if (Settings.iconPos[idx] == NotesAsset.IconPos.LeftName) 115 | { 116 | rect.y -= 3f; 117 | rect.x = rect.x - 7f + Settings.iconOffs[idx]; 118 | } 119 | else if (Settings.iconPos[idx] == NotesAsset.IconPos.RightName) 120 | { 121 | GUIContent gc = TempGUIContent(name); 122 | rect.x = rect.x + GUI.skin.label.CalcSize(gc).x - 5f + Settings.iconOffs[idx]; 123 | if (idx == 1) rect.x += 18f; 124 | } 125 | 126 | rect.width = 16; 127 | GUI.Label(rect, Settings.Icon); 128 | } 129 | 130 | private static NotesAsset LoadNotesAsset() 131 | { 132 | string[] guids = AssetDatabase.FindAssets("t:NotesAsset"); 133 | string fn = (guids.Length > 0 ? AssetDatabase.GUIDToAssetPath(guids[0]) : GetPackageFolder() + "NotesAsset.asset"); 134 | _settings = AssetDatabase.LoadAssetAtPath(fn); 135 | if (_settings == null) 136 | { 137 | _settings = ScriptableObject.CreateInstance(); 138 | AssetDatabase.CreateAsset(_settings, fn); 139 | AssetDatabase.SaveAssets(); 140 | } 141 | 142 | _settings.UpdateIcon(); 143 | return _settings; 144 | } 145 | 146 | private static string GetPackageFolder() 147 | { 148 | try 149 | { 150 | string[] res = System.IO.Directory.GetFiles(Application.dataPath, "EditorNotes.cs", System.IO.SearchOption.AllDirectories); 151 | if (res.Length > 0) return "Assets" + res[0].Replace(Application.dataPath, "").Replace("EditorNotes.cs", "").Replace("\\", "/"); 152 | } 153 | catch (System.Exception ex) 154 | { 155 | Debug.LogException(ex); 156 | } 157 | 158 | return "Assets/"; 159 | } 160 | 161 | private static GUIContent GC_Temp = new GUIContent(); 162 | private static GUIContent TempGUIContent(string label) 163 | { 164 | GC_Temp.text = label; 165 | return GC_Temp; 166 | } 167 | 168 | // ------------------------------------------------------------------------------------------------------------ 169 | } 170 | } -------------------------------------------------------------------------------- /Assets/EdNotes/Scripts/Editor/NoteWindow.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using UnityEngine; 3 | using UnityEditor; 4 | using UnityEditor.SceneManagement; 5 | 6 | 7 | namespace EdNotes 8 | { 9 | public class NoteWindow : EditorWindow 10 | { 11 | private static readonly GUIContent GC_Save = new GUIContent("Save"); 12 | private static readonly GUIContent GC_Close = new GUIContent("Close"); 13 | private static readonly GUIContent GC_Delete = new GUIContent("X", "Remove this note"); 14 | private static readonly GUIContent GC_IconHead = new GUIContent("Icon: "); 15 | private static readonly GUIContent GC_Head = new GUIContent(); 16 | private static GUIContent GC_Settings = null; 17 | 18 | [System.NonSerialized] private Object targetObj; 19 | [System.NonSerialized] private GameObject targetGO; 20 | [System.NonSerialized] private string targetGUID; 21 | [System.NonSerialized] private NotesContainer container; 22 | [System.NonSerialized] private Note note; 23 | [System.NonSerialized] private bool inScene; 24 | [System.NonSerialized] private bool isNew; 25 | [System.NonSerialized] private bool dirty; 26 | [System.NonSerialized] private string text; 27 | [System.NonSerialized] private EditorNotesSettings iconSelector = new EditorNotesSettings(); 28 | 29 | // ------------------------------------------------------------------------------------------------------------ 30 | 31 | //[MenuItem("Assets/Notes", false, 0), MenuItem("GameObject/Notes", false, 11)] 32 | [MenuItem("Window/Notes", false)] 33 | public static void ShowNoteWindow() 34 | { 35 | GetWindow("Note").UpdateNoteWidow(); 36 | } 37 | 38 | private void OnSelectionChange() 39 | { 40 | UpdateNoteWidow(); 41 | } 42 | 43 | private void UpdateNoteWidow() 44 | { 45 | if (dirty && targetObj != null && targetObj != Selection.activeObject) 46 | { 47 | if (EditorUtility.DisplayDialog("EdNotes", "Unsaved changes in the object's notes. Save now?", "Yes", "No")) 48 | { 49 | Save(); 50 | } 51 | } 52 | 53 | Repaint(); 54 | inScene = false; 55 | dirty = false; 56 | isNew = false; 57 | container = null; 58 | note = null; 59 | text = ""; 60 | GC_Head.text = ""; 61 | 62 | if (Selection.activeObject == null) 63 | { 64 | return; 65 | } 66 | 67 | targetObj = Selection.activeObject; 68 | targetGUID = AssetDatabase.AssetPathToGUID(AssetDatabase.GetAssetPath(targetObj)); 69 | targetGO = Selection.activeGameObject; 70 | GC_Head.text = targetObj.name; 71 | 72 | if (targetGO != null && targetGO.scene.IsValid()) 73 | { 74 | inScene = true; 75 | container = EditorNotes.GetContainer(targetGO.scene); 76 | if (container != null) 77 | { 78 | foreach (Note n in container.notes) 79 | if (n.targetObj == targetGO) { note = n; break; } 80 | } 81 | 82 | } 83 | else 84 | { 85 | List notesList = EditorNotes.Settings.notes; 86 | if (notesList != null) 87 | { 88 | foreach (Note n in notesList) 89 | if (n.targetGUID == targetGUID) { note = n; break; } 90 | } 91 | } 92 | 93 | if (note == null) 94 | { 95 | isNew = true; 96 | note = new Note() 97 | { 98 | targetObj = targetObj, 99 | targetGUID = targetGUID, 100 | text = "" 101 | }; 102 | } 103 | 104 | text = note.text; 105 | } 106 | 107 | private void OnGUI() 108 | { 109 | if (targetObj == null || note == null) 110 | { 111 | GUIUtility.ExitGUI(); 112 | return; 113 | } 114 | 115 | if (GC_Settings == null) 116 | { 117 | GC_Settings = EditorGUIUtility.IconContent("_Popup"); 118 | GC_Settings.tooltip = "EdNotes Settings"; 119 | } 120 | 121 | GUILayout.Label(GC_Head, EditorStyles.boldLabel); 122 | 123 | EditorGUI.BeginChangeCheck(); 124 | text = EditorGUILayout.TextArea(text, GUILayout.ExpandHeight(true)); 125 | if (EditorGUI.EndChangeCheck()) dirty = true; 126 | 127 | EditorGUILayout.BeginHorizontal(); 128 | { 129 | GUILayout.FlexibleSpace(); 130 | Rect r = GUILayoutUtility.GetRect(GC_Settings, GUI.skin.button, GUILayout.Width(30)); 131 | if (GUI.Button(r, GC_Settings)) PopupWindow.Show(r, iconSelector); 132 | GUI.enabled = !isNew; 133 | if (GUILayout.Button(GC_Delete, GUILayout.Width(25))) Delete(); 134 | GUI.enabled = dirty; 135 | if (GUILayout.Button(GC_Save, GUILayout.Width(80))) Save(); 136 | GUI.enabled = true; 137 | //if (GUILayout.Button(GC_Close, GUILayout.Width(80))) { if (!dirty || EditorUtility.DisplayDialog("EdNotes", "Unsaved changes. Close?", "Yes", "Cancel")) Close(); } 138 | GUILayout.FlexibleSpace(); 139 | } 140 | EditorGUILayout.EndHorizontal(); 141 | } 142 | 143 | private void Save() 144 | { 145 | dirty = false; 146 | note.text = text; 147 | 148 | if (text.Length == 0 && !isNew) 149 | { 150 | Delete(); 151 | return; 152 | } 153 | 154 | if (!inScene) 155 | { 156 | if (isNew) 157 | { 158 | isNew = false; 159 | EditorNotes.Settings.notes.Add(note); 160 | EditorNotes.Settings.UpdateCache(); 161 | EditorApplication.RepaintProjectWindow(); 162 | } 163 | 164 | EditorUtility.SetDirty(EditorNotes.Settings); 165 | } 166 | else 167 | { 168 | if (container == null) 169 | { 170 | GameObject go = new GameObject(EditorNotes.NotesContainerObjName) 171 | { 172 | tag = "EditorOnly", 173 | hideFlags = HideFlags.HideInHierarchy 174 | }; 175 | container = go.AddComponent(); 176 | if (go.scene != targetGO.scene) EditorSceneManager.MoveGameObjectToScene(go, targetGO.scene); 177 | EditorNotes.UpdateSceneCache(); 178 | } 179 | 180 | if (isNew) 181 | { 182 | isNew = false; 183 | container.notes.Add(note); 184 | container.UpdateCache(); 185 | EditorApplication.RepaintHierarchyWindow(); 186 | } 187 | 188 | EditorSceneManager.MarkSceneDirty(container.gameObject.scene); 189 | } 190 | } 191 | 192 | private void Delete() 193 | { 194 | GUIUtility.keyboardControl = 0; 195 | isNew = true; 196 | note.text = text = ""; 197 | 198 | if (!inScene) 199 | { 200 | EditorNotes.Settings.notes.Remove(note); 201 | 202 | if (EditorNotes.Settings.notes.Count > 0) 203 | { 204 | for (int i = EditorNotes.Settings.notes.Count - 1; i >= 0; i--) 205 | { 206 | if (EditorNotes.Settings.notes[i].targetObj == null || string.IsNullOrEmpty(EditorNotes.Settings.notes[i].text)) 207 | EditorNotes.Settings.notes.RemoveAt(i); 208 | } 209 | } 210 | 211 | EditorNotes.Settings.UpdateCache(); 212 | EditorUtility.SetDirty(EditorNotes.Settings); 213 | EditorApplication.RepaintProjectWindow(); 214 | 215 | } 216 | else 217 | { 218 | container.notes.Remove(note); 219 | 220 | if (container.notes.Count > 0) 221 | { 222 | for (int i = container.notes.Count - 1; i >= 0; i--) 223 | { 224 | if (container.notes[i].targetObj == null || string.IsNullOrEmpty(container.notes[i].text)) 225 | container.notes.RemoveAt(i); 226 | } 227 | } 228 | 229 | container.UpdateCache(); 230 | EditorSceneManager.MarkSceneDirty(targetGO.scene); 231 | EditorApplication.RepaintHierarchyWindow(); 232 | } 233 | 234 | } 235 | 236 | // ------------------------------------------------------------------------------------------------------------ 237 | } 238 | } 239 | -------------------------------------------------------------------------------- /Assets/EdNotes/Scripts/Editor/EditorNotesSettings.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using UnityEngine; 3 | using UnityEditor; 4 | 5 | 6 | namespace EdNotes 7 | { 8 | public class EditorNotesSettings : PopupWindowContent 9 | { 10 | private class StyleDefs 11 | { 12 | public GUIStyle Background = "sv_iconselector_back"; 13 | public GUIStyle Seperator = "sv_iconselector_sep"; 14 | public GUIStyle Selection = "sv_iconselector_selection"; 15 | public GUIStyle SelectionLabel = "sv_iconselector_labelselection"; 16 | public GUIStyle NoneButton = "sv_iconselector_button"; 17 | } 18 | 19 | private static readonly GUIContent GC_Hierarchy = new GUIContent("Hierarchy"); 20 | private static readonly GUIContent GC_Project = new GUIContent("Project Panel"); 21 | private static readonly GUIContent GC_LabelExpand = new GUIContent("Label Expand"); 22 | private static readonly GUIContent GC_IconPos = new GUIContent("Icon Position"); 23 | private static readonly GUIContent GC_IconOffs = new GUIContent("Icon Offset"); 24 | 25 | private static readonly Vector2 sz = new Vector2(140f, 260f); 26 | private static int HashIconSelector = "IconSelectorPopup".GetHashCode(); 27 | 28 | private static GUIContent[] GC_LabelIconsL = null; 29 | private static GUIContent[] GC_LabelIcons = null; 30 | private static GUIContent[] GC_SmallIcons = null; 31 | private static GUIContent[] GC_LargeIcons = null; 32 | private static GUIContent GC_NoneButton; 33 | 34 | private StyleDefs Styles = null; 35 | private Texture2D selectedTexture = null; 36 | 37 | // ------------------------------------------------------------------------------------------------------------ 38 | 39 | public override Vector2 GetWindowSize() 40 | { 41 | return sz; 42 | } 43 | 44 | public override void OnOpen() 45 | { 46 | base.OnOpen(); 47 | Init(); 48 | } 49 | 50 | public override void OnClose() 51 | { 52 | base.OnClose(); 53 | } 54 | 55 | public override void OnGUI(Rect rect) 56 | { 57 | if (Styles == null) Styles = new StyleDefs(); 58 | if (Event.current.type == EventType.KeyDown && Event.current.keyCode == KeyCode.Escape) CloseWindow(); 59 | 60 | GUI.BeginGroup(new Rect(0f, 0f, editorWindow.position.width, editorWindow.position.height), Styles.Background); 61 | 62 | // --- 63 | GUI.Label(new Rect(6f, 4f, 110f, 20f), "Select Icon"); 64 | if (GUI.Button(new Rect(93f, 6f, 43f, 12f), GC_NoneButton, Styles.NoneButton)) 65 | { 66 | selectedTexture = null; 67 | EditorNotes.Settings.IconName = ""; 68 | EditorUtility.SetDirty(EditorNotes.Settings); 69 | EditorApplication.RepaintHierarchyWindow(); 70 | EditorApplication.RepaintProjectWindow(); 71 | } 72 | 73 | // --- 74 | GUILayout.Space(22f); 75 | GUILayout.Label(GUIContent.none, Styles.Seperator); 76 | GUILayout.Space(3f); 77 | 78 | // --- 79 | GUILayout.BeginHorizontal(); 80 | GUILayout.Space(6f); 81 | for (int i = 0; i < GC_LabelIcons.Length / 2; i++) DoButton(GC_LabelIcons[i], true); 82 | GUILayout.EndHorizontal(); 83 | GUILayout.Space(5f); 84 | GUILayout.BeginHorizontal(); 85 | GUILayout.Space(6f); 86 | for (int j = GC_LabelIcons.Length / 2; j < GC_LabelIcons.Length; j++) DoButton(GC_LabelIcons[j], true); 87 | GUILayout.EndHorizontal(); 88 | 89 | // --- 90 | GUILayout.Space(3f); 91 | GUILayout.Label(GUIContent.none, Styles.Seperator); 92 | GUILayout.Space(3f); 93 | 94 | // --- 95 | GUILayout.BeginHorizontal(); 96 | GUILayout.Space(9f); 97 | for (int k = 0; k < GC_SmallIcons.Length / 2; k++) DoButton(GC_SmallIcons[k], false); 98 | GUILayout.Space(3f); 99 | GUILayout.EndHorizontal(); 100 | GUILayout.Space(6f); 101 | GUILayout.BeginHorizontal(); 102 | GUILayout.Space(9f); 103 | for (int l = GC_SmallIcons.Length / 2; l < GC_SmallIcons.Length; l++) DoButton(GC_SmallIcons[l], false); 104 | GUILayout.Space(3f); 105 | GUILayout.EndHorizontal(); 106 | 107 | // --- 108 | GUILayout.Space(3f); 109 | GUILayout.Label(GUIContent.none, Styles.Seperator); 110 | GUILayout.Space(3f); 111 | 112 | // --- 113 | EditorGUIUtility.labelWidth = 80f; 114 | EditorGUI.BeginChangeCheck(); 115 | GUILayout.Label(GC_Hierarchy); 116 | EditorNotes.Settings.labelExpandWidth[0] = EditorGUILayout.Toggle(GC_LabelExpand, EditorNotes.Settings.labelExpandWidth[0]); 117 | EditorNotes.Settings.iconPos[0] = (NotesAsset.IconPos)EditorGUILayout.EnumPopup(GC_IconPos, EditorNotes.Settings.iconPos[0]); 118 | EditorNotes.Settings.iconOffs[0] = EditorGUILayout.FloatField(GC_IconOffs, EditorNotes.Settings.iconOffs[0]); 119 | if (EditorGUI.EndChangeCheck()) 120 | { 121 | EditorUtility.SetDirty(EditorNotes.Settings); 122 | EditorApplication.RepaintHierarchyWindow(); 123 | } 124 | 125 | // --- 126 | GUILayout.Space(3f); 127 | GUILayout.Label(GUIContent.none, Styles.Seperator); 128 | GUILayout.Space(3f); 129 | 130 | // --- 131 | EditorGUIUtility.labelWidth = 80f; 132 | EditorGUI.BeginChangeCheck(); 133 | GUILayout.Label(GC_Project); 134 | EditorNotes.Settings.labelExpandWidth[1] = EditorGUILayout.Toggle(GC_LabelExpand, EditorNotes.Settings.labelExpandWidth[1]); 135 | EditorNotes.Settings.iconPos[1] = (NotesAsset.IconPos)EditorGUILayout.EnumPopup(GC_IconPos, EditorNotes.Settings.iconPos[1]); 136 | EditorNotes.Settings.iconOffs[1] = EditorGUILayout.FloatField(GC_IconOffs, EditorNotes.Settings.iconOffs[1]); 137 | if (EditorGUI.EndChangeCheck()) 138 | { 139 | EditorUtility.SetDirty(EditorNotes.Settings); 140 | EditorApplication.RepaintProjectWindow(); 141 | } 142 | 143 | // --- 144 | GUI.EndGroup(); 145 | } 146 | 147 | private void CloseWindow() 148 | { 149 | editorWindow.Close(); 150 | GUI.changed = true; 151 | GUIUtility.ExitGUI(); 152 | } 153 | 154 | // ------------------------------------------------------------------------------------------------------------ 155 | 156 | private void Init() 157 | { 158 | if (GC_LabelIcons == null) 159 | { 160 | GC_NoneButton = EditorGUIUtility.IconContent("sv_icon_none"); 161 | GC_NoneButton.text = "None"; 162 | 163 | GC_LabelIcons = GetTextures("sv_icon_name", "", 0, 8); 164 | GC_LabelIconsL = GetTextures("sv_label_", "", 0, 8); 165 | GC_SmallIcons = GetTextures("sv_icon_dot", "_sml", 0, 16); 166 | GC_LargeIcons = GetTextures("sv_icon_dot", "_pix16_gizmo", 0, 16); 167 | } 168 | 169 | SetSelectedTexture(EditorNotes.Settings.IconName); 170 | } 171 | 172 | private GUIContent[] GetTextures(string baseName, string postFix, int startIndex, int count) 173 | { 174 | GUIContent[] array = new GUIContent[count]; 175 | for (int i = 0; i < count; i++) 176 | { 177 | array[i] = EditorGUIUtility.IconContent(baseName + (startIndex + i) + postFix); 178 | } 179 | return array; 180 | } 181 | 182 | private void DoButton(GUIContent content, bool labelIcon) 183 | { 184 | Rect rect = GUILayoutUtility.GetRect(content, GUIStyle.none); 185 | 186 | if (content.image == selectedTexture) 187 | { 188 | Rect r = rect; 189 | r.x -= 2f; 190 | r.y -= 2f; 191 | r.width = selectedTexture.width + 4f; 192 | r.height = selectedTexture.height + 4f; 193 | GUI.Label(r, GUIContent.none, (!labelIcon) ? Styles.Selection : Styles.SelectionLabel); 194 | } 195 | 196 | if (GUI.Button(rect, content, GUIStyle.none)) 197 | { 198 | selectedTexture = (Texture2D)content.image; 199 | EditorNotes.Settings.IconName = GetSelectedTextureName(); 200 | EditorUtility.SetDirty(EditorNotes.Settings); 201 | EditorApplication.RepaintHierarchyWindow(); 202 | EditorApplication.RepaintProjectWindow(); 203 | } 204 | } 205 | 206 | private Texture2D ConvertLargeIconToSmallIcon(Texture2D largeIcon) 207 | { 208 | Texture2D result; 209 | if (largeIcon == null) 210 | { 211 | result = null; 212 | } 213 | else 214 | { 215 | for (int i = 0; i < GC_LabelIconsL.Length; i++) 216 | { 217 | if (GC_LabelIconsL[i].image == largeIcon) 218 | { 219 | result = (Texture2D)GC_LabelIcons[i].image; 220 | return result; 221 | } 222 | } 223 | for (int j = 0; j < GC_LargeIcons.Length; j++) 224 | { 225 | if (GC_LargeIcons[j].image == largeIcon) 226 | { 227 | result = (Texture2D)GC_SmallIcons[j].image; 228 | return result; 229 | } 230 | } 231 | result = largeIcon; 232 | } 233 | return result; 234 | } 235 | 236 | private Texture2D ConvertSmallIconToLargeIcon(Texture2D smallIcon) 237 | { 238 | bool labelIcon = smallIcon.name.Contains("icon_name"); 239 | 240 | Texture2D result; 241 | if (labelIcon) 242 | { 243 | for (int i = 0; i < GC_LabelIcons.Length; i++) 244 | { 245 | if (GC_LabelIcons[i].image == smallIcon) 246 | { 247 | result = (Texture2D)GC_LabelIconsL[i].image; 248 | return result; 249 | } 250 | } 251 | } 252 | else 253 | { 254 | for (int j = 0; j < GC_SmallIcons.Length; j++) 255 | { 256 | if (GC_SmallIcons[j].image == smallIcon) 257 | { 258 | result = (Texture2D)GC_LargeIcons[j].image; 259 | return result; 260 | } 261 | } 262 | } 263 | result = smallIcon; 264 | return result; 265 | } 266 | 267 | private void SetSelectedTexture(string name) 268 | { 269 | selectedTexture = null; 270 | foreach (GUIContent g in GC_LabelIconsL) 271 | { 272 | if (g.image.name == name) 273 | { 274 | selectedTexture = ConvertLargeIconToSmallIcon((Texture2D)g.image); 275 | return; 276 | } 277 | } 278 | 279 | foreach (GUIContent g in GC_LargeIcons) 280 | { 281 | if (g.image.name == name) 282 | { 283 | selectedTexture = ConvertLargeIconToSmallIcon((Texture2D)g.image); 284 | return; 285 | } 286 | } 287 | 288 | } 289 | 290 | private string GetSelectedTextureName() 291 | { 292 | if (selectedTexture != null) 293 | { 294 | Texture2D t = ConvertSmallIconToLargeIcon(selectedTexture); 295 | return (t == null ? "" : t.name); 296 | } 297 | 298 | return ""; 299 | } 300 | 301 | // ------------------------------------------------------------------------------------------------------------ 302 | } 303 | } 304 | --------------------------------------------------------------------------------