Advertisement
Peticov

ExposeAttributePropertyDrawer

Oct 18th, 2023 (edited)
110
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 5.78 KB | Source Code | 0 0
  1. using System.Collections.Generic;
  2. using UnityEditor;
  3. using UnityEditor.UIElements;
  4. using UnityEngine;
  5. using UnityEngine.UIElements;
  6.  
  7. [CustomPropertyDrawer(typeof(ExposeAttribute))]
  8. public class ExposeAttributePropertyDrawer : PropertyDrawer
  9. {
  10.     // UXML
  11.     private VisualTreeAsset _exposedFieldUxml;
  12.     private VisualTreeAsset ExposedFieldUxml
  13.     {
  14.         get
  15.         {
  16.             if (_exposedFieldUxml == null)
  17.             {
  18.                 var assetPath = AssetDatabase.GUIDToAssetPath(k_exposedFieldUxmlGuid);
  19.                 _exposedFieldUxml = AssetDatabase.LoadAssetAtPath<VisualTreeAsset>(assetPath);
  20.             }
  21.  
  22.             return _exposedFieldUxml;
  23.         }
  24.     }
  25.  
  26.     // VisualElements
  27.     private VisualElement _root;
  28.     private TemplateContainer _mainPanel;
  29.     private PropertyField _propertyField;
  30.     private VisualElement _propertyFieldsPanel;
  31.     private Foldout _foldout;
  32.  
  33.     // Constant values
  34.     private const string k_exposedFieldUxmlGuid = "1da7b35196ba6a24a940668dc4b2d818";
  35.  
  36.     public override VisualElement CreatePropertyGUI(SerializedProperty property)
  37.     {
  38.         CreateRoot();
  39.         InstantiateUXML();
  40.         QueryElements();
  41.         SetupElements(property);
  42.         AddVisualElementsToRoot();
  43.  
  44.         return _root;
  45.     }
  46.  
  47.     private void CreateRoot()
  48.     {
  49.         _root = new VisualElement();
  50.     }
  51.  
  52.     private void InstantiateUXML()
  53.     {
  54.         _mainPanel = ExposedFieldUxml.Instantiate();
  55.     }
  56.  
  57.     private void QueryElements()
  58.     {
  59.         QueryPropertyField();
  60.         QueryPropertyFieldsPanel();
  61.         QueryFoldout();
  62.     }
  63.  
  64.     private void SetupElements(SerializedProperty property)
  65.     {
  66.         SetupPropertyField(property);
  67.         // SetupFoldout(property);
  68.     }
  69.  
  70.     private void AddVisualElementsToRoot()
  71.     {
  72.         _root.Add(_mainPanel);
  73.     }
  74.  
  75.     private void QueryPropertyField()
  76.     {
  77.         _propertyField = _mainPanel.Q<PropertyField>("PropertyField");
  78.  
  79.         if (_propertyField == null)
  80.         {
  81.             Debug.LogError("_mainPanel.Q<PropertyField>(\"PropertyField\") returned null!");
  82.             return;
  83.         }
  84.     }
  85.  
  86.     private void QueryPropertyFieldsPanel()
  87.     {
  88.         _propertyFieldsPanel = _mainPanel.Q<VisualElement>("PropertyFieldsPanel");
  89.  
  90.         if (_propertyFieldsPanel == null)
  91.         {
  92.             Debug.LogError("_mainPanel.Q<VisualElement>(\"PropertyFieldsPanel\") returned null!");
  93.             return;
  94.         }
  95.     }
  96.  
  97.     private void QueryFoldout()
  98.     {
  99.         _foldout = _propertyFieldsPanel.Q<Foldout>();
  100.  
  101.         if (_foldout == null)
  102.         {
  103.             Debug.LogError("foldoutRoot.Q<Foldout>() returned null!");
  104.             return;
  105.         }
  106.     }
  107.  
  108.     private void SetupPropertyField(SerializedProperty property)
  109.     {
  110.         _propertyField.BindProperty(property);
  111.         _propertyField.RegisterValueChangeCallback(OnMainPropertyFieldChange);
  112.  
  113.         void OnMainPropertyFieldChange(SerializedPropertyChangeEvent changeEvent)
  114.         {
  115.             if (changeEvent.changedProperty.objectReferenceValue == null)
  116.             {
  117.                 _propertyFieldsPanel.style.display = DisplayStyle.None;
  118.                 return;
  119.             }
  120.  
  121.             _propertyFieldsPanel.style.display = DisplayStyle.Flex;
  122.             SetupFoldout(property);
  123.         }
  124.     }
  125.  
  126.     /// <summary>
  127.     /// Set text, create SerializedObject, create and add PropertyFields and register callback.
  128.     /// </summary>
  129.     /// <param name="property"></param>
  130.     /// <param name="propertyFields"></param>
  131.     private void SetupFoldout(SerializedProperty property)
  132.     {
  133.         if (property.objectReferenceValue == null)
  134.         {
  135.             _foldout.style.display = DisplayStyle.None;
  136.             return;
  137.         }
  138.  
  139.         _foldout.style.display = DisplayStyle.Flex;
  140.         _foldout.text = $"Edit \"{property.objectReferenceValue.name}\"";
  141.  
  142.         var serializedObject = CreateSerializedObject();
  143.         var propertyFields = CreateFoldoutPropertyFields();
  144.  
  145.         _foldout.Clear();
  146.  
  147.         foreach (var propField in propertyFields)
  148.             _foldout.Add(propField);
  149.  
  150.         _foldout.viewDataKey = GetFoldoutDataKey(property);
  151.         _foldout.RegisterValueChangedCallback(OnFoldoutValueChange);
  152.  
  153.         SerializedObject CreateSerializedObject()
  154.         {
  155.             return new SerializedObject(property.objectReferenceValue);
  156.         }
  157.  
  158.         PropertyField[] CreateFoldoutPropertyFields()
  159.         {
  160.             var prop = serializedObject.GetIterator();
  161.  
  162.             if (!prop.Next(true))
  163.                 return new PropertyField[0];
  164.  
  165.             int currentPropIndex = 0;
  166.  
  167.             List<PropertyField> propertyFieldsList = new(16);
  168.  
  169.             do
  170.             {
  171.                 if (currentPropIndex > 9)
  172.                 {
  173.                     var propCopy = prop.Copy();
  174.  
  175.                     var propPropField = new PropertyField(propCopy);
  176.                     propPropField.BindProperty(serializedObject);
  177.  
  178.                     propertyFieldsList.Add(propPropField);
  179.                 }
  180.  
  181.                 currentPropIndex++;
  182.             }
  183.             while (prop.Next(false));
  184.  
  185.             return propertyFieldsList.ToArray();
  186.         }
  187.  
  188.         void OnFoldoutValueChange(ChangeEvent<bool> changeEvent)
  189.         {
  190.             if (changeEvent.newValue)
  191.                 foreach (var propField in propertyFields)
  192.                     propField.style.display = DisplayStyle.Flex;
  193.             else
  194.                 foreach (var propField in propertyFields)
  195.                     propField.style.display = DisplayStyle.None;
  196.         }
  197.     }
  198.  
  199.     private string GetFoldoutDataKey(SerializedProperty property)
  200.     {
  201.         return $"{property.serializedObject.targetObject.GetInstanceID()}.{property.name}";
  202.     }
  203. }
  204.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement