using System; using System.Collections.Generic; using System.Linq; using UnityEditor; using UnityEngine; namespace Unity.Tutorials.Core.Editor { /// /// Criterion for checking that a specific object is framed in the Scene view. /// public class FrameSelectedCriterion : Criterion { [Serializable] class ObjectReferenceCollection : CollectionWrapper { } [SerializeField] ObjectReferenceCollection m_ObjectReferences = new ObjectReferenceCollection(); /// /// Sets object references. /// /// public void SetObjectReferences(IEnumerable objectReferences) { m_ObjectReferences.SetItems(objectReferences); UpdateCompletion(); } /// /// Starts testing of the criterion. /// public override void StartTesting() { #if UNITY_2019_1_OR_NEWER SceneView.duringSceneGui += OnSceneGUI; #else SceneView.onSceneGUIDelegate += OnSceneGUI; #endif } /// /// Stops testing of the criterion. /// public override void StopTesting() { #if UNITY_2019_1_OR_NEWER SceneView.duringSceneGui -= OnSceneGUI; #else SceneView.onSceneGUIDelegate -= OnSceneGUI; #endif } /// /// Runs update logic for the criterion. /// /// /// Overriding the update completion state, as this criterion is not state based /// public override void UpdateCompletion() { } void OnSceneGUI(SceneView sceneView) { var evt = Event.current; if (evt.type == EventType.ExecuteCommand && evt.commandName == "FrameSelected") { if (!m_ObjectReferences.Any()) return; if (m_ObjectReferences.Count() != Selection.objects.Length) return; foreach (var objectReference in m_ObjectReferences) { var referencedObject = objectReference.SceneObjectReference.ReferencedObject; if (referencedObject == null) return; if (!Selection.objects.Contains(referencedObject)) return; } IsCompleted = true; } } /// /// Auto-completes the criterion. /// /// True if the auto-completion succeeded. public override bool AutoComplete() { if (!m_ObjectReferences.Any()) { Debug.LogWarning("Cannot auto-complete FrameSelectedCriterion with no object references"); return false; } var referencedObjects = m_ObjectReferences.Select(or => or.SceneObjectReference.ReferencedObject); if (referencedObjects.Any(obj => obj == null)) { Debug.LogWarning("Cannot auto-complete FrameSelectedCriterion with unresolved object references"); return false; } if (SceneView.lastActiveSceneView == null) { Debug.LogWarning("Cannot auto-complete FrameSelectedCriterion when there is no last active Scene View"); return false; } var previousActiveObject = Selection.activeObject; var previousSelection = Selection.objects.ToArray(); Selection.objects = referencedObjects.ToArray(); if (!SceneView.FrameLastActiveSceneView()) { Debug.LogWarning("Cannot auto-complete FrameSelectedCriterion since framing last active Scene View failed"); // Restore selection Selection.activeObject = previousActiveObject; Selection.objects = previousSelection; return false; } return true; } } }