using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Linq; using UnityEditor; using UnityEditor.Rendering; using UnityEngine; namespace Misaki.ShaderGUI { public abstract class MaterialUIScope : IMaterialUIScope where TExpandableBit : Enum, IConvertible { protected MaterialEditor editor; protected IEnumerable materialProperties; protected IMaterialUIScopeContainer owner; protected ReadOnlyCollection materials; protected virtual bool ShowSection => true; protected virtual bool IsSubHeader => false; protected virtual bool SpaceAtEnd => true; protected virtual string DocumentationURL => string.Empty; protected abstract TExpandableBit ExpandableBit { get; } protected abstract GUIContent Header { get; } public MaterialEditor Editor => editor; protected abstract void LoadMaterialProperties(); protected abstract void DrawContent(); public void Initialize(MaterialEditor materialEditor, IEnumerable properties, IMaterialUIScopeContainer container) { editor = materialEditor; materialProperties = properties; owner = container; materials = editor.GetMaterials().ToList().AsReadOnly(); UpdateMaterialProperties(properties); } public MaterialProperty FindProperty(string propertyName) { if (materialProperties == null) { throw new Exception("Material properties are not initialized."); } if (string.IsNullOrEmpty(propertyName)) { throw new ArgumentException("Property name cannot be null or empty.", nameof(propertyName)); } return materialProperties.First(p => p.name == propertyName); } public void UpdateMaterialProperties(IEnumerable properties) { materialProperties = properties; LoadMaterialProperties(); } public void Draw() { if (!ShowSection) { return; } using var scope = new MaterialHeaderScope(Header, Convert.ToUInt32(ExpandableBit), editor, spaceAtEnd: SpaceAtEnd, subHeader: IsSubHeader, documentationURL: DocumentationURL); if (scope.expanded) { DrawContent(); } } } }