Created
May 15, 2025 10:09
-
-
Save shane-harper/0bc85511193600bceb6e618212bb04cc to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using UnityEngine; | |
#if UNITY_EDITOR | |
using UnityEditor; | |
#endif | |
/// <summary> | |
/// A component for adding annotations to GameObjects in a scene | |
/// </summary> | |
[AddComponentMenu("Annotation")] | |
internal sealed class Annotation : MonoBehaviour | |
{ | |
[SerializeField, TextArea] private string _text; | |
#if UNITY_EDITOR | |
[CustomEditor(typeof(Annotation), true), CanEditMultipleObjects] | |
internal sealed class AnnotationEditor : Editor | |
{ | |
private SerializedProperty _text; | |
private bool _isEditable; | |
private string _lastFocusedControl; | |
private void OnEnable() | |
{ | |
// Get text property and begin editing if annotation has not been set | |
_text = serializedObject.FindProperty(nameof(_text)); | |
if (string.IsNullOrWhiteSpace(_text.stringValue)) | |
{ | |
Edit(); | |
} | |
} | |
public override void OnInspectorGUI() | |
{ | |
serializedObject.Update(); | |
// Draw the non-editable annotation | |
if (!_isEditable) | |
{ | |
var style = new GUIStyle(EditorStyles.label) { wordWrap = true, richText = true }; | |
EditorGUILayout.LabelField(GUIContent.none, new GUIContent(_text.stringValue), style); | |
// Add context menu to allow editing | |
var e = Event.current; | |
if (e.type == EventType.ContextClick && GUILayoutUtility.GetLastRect().Contains(e.mousePosition)) | |
{ | |
ShowContextMenu(); | |
e.Use(); | |
} | |
return; | |
} | |
// Draw editable annotation | |
using (var check = new EditorGUI.ChangeCheckScope()) | |
{ | |
var style = new GUIStyle(EditorStyles.textArea) { wordWrap = true, richText = false }; | |
GUI.SetNextControlName(nameof(_text)); | |
_text.stringValue = EditorGUILayout.TextArea(_text.stringValue, style); | |
serializedObject.ApplyModifiedProperties(); | |
if (check.changed) | |
{ | |
EditorUtility.SetDirty(target); | |
} | |
// Disable editing when losing focus | |
var currentFocusedControl = GUI.GetNameOfFocusedControl(); | |
if (_lastFocusedControl == nameof(_text) && currentFocusedControl != nameof(_text)) | |
{ | |
_isEditable = false; | |
} | |
_lastFocusedControl = currentFocusedControl; | |
} | |
} | |
private void ShowContextMenu() | |
{ | |
var menu = new GenericMenu(); | |
menu.AddItem(new GUIContent("Edit"), false, Edit); | |
menu.ShowAsContext(); | |
} | |
private void Edit() | |
{ | |
_isEditable = true; | |
} | |
} | |
#endif | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment