using System; using System.Collections.Generic; using System.Reflection; using UnityEditor; using UnityEditor.ShaderGraph.Drawing; using UnityEditor.UIElements; using UnityEngine; using UnityEngine.UIElements; namespace UnityEditor.ShaderGraph.Drawing.Inspector.PropertyDrawers { [SGPropertyDrawer(typeof(Vector3))] class Vector3PropertyDrawer : IPropertyDrawer { internal delegate void ValueChangedCallback(Vector3 newValue); public Action preValueChangeCallback { get; set; } public Action postValueChangeCallback { get; set; } EventCallback m_KeyDownCallback; EventCallback m_FocusOutCallback; public int mUndoGroup { get; set; } = -1; void CreateCallbacks() { m_KeyDownCallback = new EventCallback(evt => { // Record Undo for input field edit if (mUndoGroup == -1) { mUndoGroup = Undo.GetCurrentGroup(); preValueChangeCallback?.Invoke(); } // Handle escaping input field edit if (evt.keyCode == KeyCode.Escape && mUndoGroup > -1) { Undo.RevertAllDownToGroup(mUndoGroup); mUndoGroup = -1; evt.StopPropagation(); } // Dont record Undo again until input field is unfocused mUndoGroup++; postValueChangeCallback?.Invoke(); }); m_FocusOutCallback = new EventCallback(evt => { // Reset UndoGroup when done editing input field mUndoGroup = -1; }); } public Vector3PropertyDrawer() { CreateCallbacks(); } internal VisualElement CreateGUI( ValueChangedCallback valueChangedCallback, Vector3 fieldToDraw, string labelName, out VisualElement propertyVec3Field, int indentLevel = 0) { var vector3Field = new Vector3Field { value = fieldToDraw }; var inputFields = vector3Field.Query("unity-text-input").ToList(); foreach (var inputField in inputFields) { inputField.RegisterCallback(m_KeyDownCallback); inputField.RegisterCallback(m_FocusOutCallback); } vector3Field.RegisterValueChangedCallback(evt => { // Only true when setting value via FieldMouseDragger // Undo recorded once per dragger release if (mUndoGroup == -1) preValueChangeCallback?.Invoke(); valueChangedCallback(evt.newValue); postValueChangeCallback?.Invoke(); }); propertyVec3Field = vector3Field; var defaultRow = new PropertyRow(PropertyDrawerUtils.CreateLabel(labelName, indentLevel)); defaultRow.Add(propertyVec3Field); defaultRow.styleSheets.Add(Resources.Load("Styles/PropertyRow")); return defaultRow; } public Action inspectorUpdateDelegate { get; set; } public VisualElement DrawProperty(PropertyInfo propertyInfo, object actualObject, InspectableAttribute attribute) { return this.CreateGUI( // Use the setter from the provided property as the callback newValue => propertyInfo.GetSetMethod(true).Invoke(actualObject, new object[] { newValue }), (Vector3)propertyInfo.GetValue(actualObject), attribute.labelName, out var propertyVisualElement); } } }