using System; using UnityEditor; using UnityEngine; using UnityObject = UnityEngine.Object; namespace Unity.Tutorials.Core.Editor { /// /// Criterion for checking a Material's property modification. /// public class MaterialPropertyModifiedCriterion : Criterion { internal SceneObjectReference Target { get => m_Target.SceneObjectReference; set => m_Target.SceneObjectReference = value; } [SerializeField] ObjectReference m_Target = new ObjectReference(); internal string MaterialPropertyPath { get => m_MaterialPropertyPath; set => m_MaterialPropertyPath = value; } [SerializeField] string m_MaterialPropertyPath = ""; string m_InitialValue = null; static MaterialProperty FindProperty(string path, Material material) { UnityObject[] mats = new[] { material }; return MaterialEditor.GetMaterialProperty(mats, path); } static string GetPropertyValueToString(MaterialProperty property) { switch (property.type) { case MaterialProperty.PropType.Color: return property.colorValue.ToString(); case MaterialProperty.PropType.Vector: return property.vectorValue.ToString(); case MaterialProperty.PropType.Float: return property.floatValue.ToString(); case MaterialProperty.PropType.Range: return property.rangeLimits.ToString(); case MaterialProperty.PropType.Texture: return property.textureValue.GetInstanceID().ToString(); default: throw new ArgumentOutOfRangeException(); } } /// /// Starts testing of the criterion. /// public override void StartTesting() { InitializeRequiredStateIfNeeded(); EditorApplication.update += UpdateCompletion; } void InitializeRequiredStateIfNeeded() { if (m_InitialValue != null) return; if (string.IsNullOrEmpty(m_MaterialPropertyPath) || Target.ReferencedObject == null) return; var property = FindProperty(m_MaterialPropertyPath, (Material)Target.ReferencedObject); m_InitialValue = GetPropertyValueToString(property); } /// /// Stops testing of the criterion. /// public override void StopTesting() { m_InitialValue = null; EditorApplication.update -= UpdateCompletion; } /// /// Evaluates if the criterion is completed. /// /// protected override bool EvaluateCompletion() { InitializeRequiredStateIfNeeded(); if (m_InitialValue == null) return false; if (m_MaterialPropertyPath == null || Target.ReferencedObject == null) return false; var property = FindProperty(m_MaterialPropertyPath, (Material)Target.ReferencedObject); if (property == null) return false; var currentValue = GetPropertyValueToString(property); if (currentValue != m_InitialValue) return true; return false; } /// /// Auto-completes the criterion. /// /// True if the auto-completion succeeded. public override bool AutoComplete() { throw new NotImplementedException(); } } }