using System.Collections.Generic; using JetBrains.Annotations; using UnityEditor; using UnityEditor.Experimental.SceneManagement; using UnityEditorInternal; using UnityEngine; using UTools = UnityEditor.Tools; namespace Module.NavigationTool.Editor.Tools { [UsedImplicitly] internal sealed class ToolUICanvasPicker : AbstractToolbarDrawer { public override bool Enabled => (UTools.visibleLayers & (1 << LayerMask.NameToLayer("UI"))) != 0; public override EToolbarPlacement Placement => EToolbarPlacement.Left; private static bool IS_DIRTY = true; private static string[] OPTIONS = new string[0]; private static int[] INSTANCE_IDS = new int[0]; private static void Initialize() { if (!IS_DIRTY) return; PrefabStage prefabStage = PrefabStageUtility.GetCurrentPrefabStage(); Canvas[] canvases = prefabStage != null ? prefabStage.prefabContentsRoot.GetComponentsInParent() : Object.FindObjectsOfType(); var list = new List(canvases.Length); var listNames = new List(canvases.Length); var listIds = new List(canvases.Length); listNames.Add("Select"); listIds.Add(-1); for (var i = 0; i < canvases.Length; i++) { Canvas root = canvases[i].rootCanvas; if (list.Contains(root)) continue; list.Add(root); listNames.Add(root.name); listIds.Add(root.GetInstanceID()); } OPTIONS = listNames.ToArray(); INSTANCE_IDS = listIds.ToArray(); IS_DIRTY = false; } public override void Update() { Initialize(); } protected override void Draw(Rect rect) { // Note: To fix an issue, where instantiated canvases wouldn't be detected, due to no events for canvas additions/removals exist in Unity API (at the moment) if (Event.current.type == EventType.MouseDown) { IS_DIRTY = true; Initialize(); } int temp = EditorGUI.Popup(rect, 0, OPTIONS, styles.popup); if (temp != 0 && OPTIONS.Length != 1) Focus(INSTANCE_IDS[temp]); } public override float CalculateWidth() { return 100.0f; } private static void Focus(int instanceId) { Object obj = EditorUtility.InstanceIDToObject(instanceId); var canvas = obj as Canvas; if (canvas == null) { if (obj != null) Debug.LogWarning("Failed to find Canvas component on object", obj); return; } Selection.activeObject = canvas; Bounds bounds = InternalEditorUtility.CalculateSelectionBounds(false, true, true); Vector3 point = bounds.center; Quaternion direction = canvas.transform.rotation; float size = Mathf.Max(bounds.extents.x, bounds.extents.y); bool ortho = canvas.renderMode == RenderMode.ScreenSpaceOverlay; for (var i = 0; i < SceneView.sceneViews.Count; i++) { var view = (SceneView)SceneView.sceneViews[i]; view.in2DMode = false; view.LookAt(point, direction, size, ortho, false); } } public static void SetAsDirty() { IS_DIRTY = true; } } }