using System; using System.Collections.Generic; using System.Linq; using System.Text; using UnityEngine.UI; namespace UnityEngine.Perception.GroundTruth { /// /// Interface that should be defined by a class that wants to be able to provide a image to the overlay /// panel. /// public interface IOverlayPanelProvider { /// /// The image to the overlay panel. /// Texture overlayImage { get; } /// /// The label of the overlay panel. /// string label { get; } } /// /// Some labeler's result in a full screen image per frame. The overlay panel controls which of these labeler's image /// is currently shown. /// public class OverlayPanel : MonoBehaviour { internal PerceptionCamera perceptionCamera { get; set; } bool m_Enabled; GUIStyle m_LabelStyle; GUIStyle m_SliderStyle; GUIStyle m_SelectorToggleStyle; GUIStyle m_WindowStyle; float m_SegmentTransparency = 0.8f; float m_BackgroundTransparency; GameObject m_SegCanvas; GameObject m_SegVisual; RawImage m_OverlayImage; int m_CachedHeight; int m_CachedWidth; bool m_ShowPopup = false; Texture2D m_NormalDropDownTexture; Texture2D m_HoverDropDownTexture; void SetEnabled(bool isEnabled) { if (isEnabled == m_Enabled) return; m_Enabled = isEnabled; m_SegCanvas.SetActive(isEnabled); foreach (var p in perceptionCamera.labelers) { if (p is IOverlayPanelProvider) { p.visualizationEnabled = isEnabled; } } m_OverlayImage.enabled = isEnabled; // Clear out the handle to the cached overlay texture if we are not isEnabled if (!isEnabled) m_OverlayImage.texture = null; } void SetupVisualizationElements() { m_Enabled = true; m_SegmentTransparency = 0.8f; m_BackgroundTransparency = 0.0f; m_SegVisual = GameObject.Instantiate(Resources.Load("SegmentTexture")); m_OverlayImage = m_SegVisual.GetComponent(); m_OverlayImage.material.SetFloat("_SegmentTransparency", m_SegmentTransparency); m_OverlayImage.material.SetFloat("_BackTransparency", m_BackgroundTransparency); if (m_SegVisual.transform is RectTransform rt) { rt.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, Screen.width); rt.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, Screen.height); } if (m_SegCanvas == null) { m_SegCanvas = new GameObject("overlay_canvas"); m_SegCanvas.AddComponent(); var canvas = m_SegCanvas.AddComponent(); canvas.renderMode = RenderMode.ScreenSpaceOverlay; m_SegCanvas.AddComponent(); m_SegVisual.transform.SetParent(m_SegCanvas.transform, false); } m_LabelStyle = new GUIStyle(GUI.skin.label) {padding = {left = 10}}; m_SliderStyle = new GUIStyle(GUI.skin.horizontalSlider) {margin = {left = 12}}; m_SelectorToggleStyle = new GUIStyle(GUI.skin.button); if (m_NormalDropDownTexture == null) { m_NormalDropDownTexture = Resources.Load("drop_down2"); m_HoverDropDownTexture = Resources.Load("drop_down"); } m_SelectorToggleStyle.normal.background = m_NormalDropDownTexture; m_SelectorToggleStyle.border = new RectOffset(7, 70, 6, 6); m_SelectorToggleStyle.alignment = TextAnchor.MiddleLeft; m_SelectorToggleStyle.clipping = TextClipping.Clip; m_SelectorToggleStyle.active.background = m_NormalDropDownTexture; m_SelectorToggleStyle.hover.background = m_HoverDropDownTexture; m_SelectorToggleStyle.focused.background = m_HoverDropDownTexture; m_WindowStyle = new GUIStyle(GUI.skin.window); var backTexture = Resources.Load("instance_back"); m_WindowStyle.normal.background = backTexture; } IOverlayPanelProvider m_ActiveProvider = null; // Make the contents of the window void OnSelectorPopup(int windowID) { foreach (var labeler in perceptionCamera.labelers.Where(l => l is IOverlayPanelProvider && l.enabled)) { var panel = labeler as IOverlayPanelProvider; if (GUILayout.Button(panel.label)) { m_ActiveProvider = panel; m_ShowPopup = false; } } } internal void OnDrawGUI(float x, float y, float width, float height) { var any = perceptionCamera.labelers.Any(l => l is IOverlayPanelProvider && l.enabled); // If there used to be active providers, but they have been turned off, remove // the active provider and return null. If one has come online, then set it to the active // provider if (!any) { m_ActiveProvider = null; } else { var findNewProvider = m_ActiveProvider == null; if (!findNewProvider) { if (m_ActiveProvider is CameraLabeler l) { findNewProvider = !l.enabled; } } if (findNewProvider) m_ActiveProvider= perceptionCamera.labelers.First(l => l is IOverlayPanelProvider && l.enabled) as IOverlayPanelProvider; } if (m_ActiveProvider == null) { if (m_SegCanvas != null) m_SegCanvas.SetActive(false); return; } if (m_OverlayImage == null) { SetupVisualizationElements(); } // If all overlays were offline, but now one has come on line // we need to set the canvas back to active if (!m_SegCanvas.activeSelf) m_SegCanvas.SetActive(true); GUILayout.Label("Overlay"); GUILayout.BeginHorizontal(); GUILayout.Space(10); GUILayout.Label("Enabled"); GUILayout.FlexibleSpace(); var isEnabled = GUILayout.Toggle(m_Enabled, ""); GUILayout.EndHorizontal(); SetEnabled(isEnabled); if (!isEnabled) { return; } // Create the overlay button GUILayout.Space(5); GUILayout.BeginHorizontal(); GUILayout.Space(10); // Truncate the label if it overflows the button size var label = m_ActiveProvider?.label ?? "Not Selected"; var trunc = new StringBuilder(label.Substring(0, Math.Min(label.Length, 10))); if (trunc.Length != label.Length) trunc.Append("..."); GUILayout.Label("Overlay: "); if (GUILayout.Button(trunc.ToString(), m_SelectorToggleStyle)) { // If bottom is clicked we need to show the popup window m_ShowPopup = true; } GUILayout.EndHorizontal(); if (m_ShowPopup) { var windowRect = new Rect(x, y, width, height); GUILayout.Window(0, windowRect, OnSelectorPopup, "Choose Overlay", m_WindowStyle); } // Create the transparency sliders GUILayout.Space(4); GUILayout.Label("Object Alpha:", m_LabelStyle); m_SegmentTransparency = GUILayout.HorizontalSlider(m_SegmentTransparency, 0.0f, 1.0f, m_SliderStyle, GUI.skin.horizontalSliderThumb); GUILayout.Space(4); GUILayout.Label("Background Alpha:", m_LabelStyle); m_BackgroundTransparency = GUILayout.HorizontalSlider(m_BackgroundTransparency, 0.0f, 1.0f, m_SliderStyle, GUI.skin.horizontalSliderThumb); GUI.skin.label.padding.left = 0; // Grab the overlay image from the active provider m_OverlayImage.texture = m_ActiveProvider?.overlayImage; var rt = m_SegVisual.transform as RectTransform; if (rt != null && m_CachedHeight != Screen.height) { m_CachedHeight = Screen.height; rt.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, m_CachedHeight); } if (rt != null && m_CachedWidth != Screen.width) { m_CachedWidth = Screen.width; rt.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, Screen.width); } if (!GUI.changed) return; m_OverlayImage.material.SetFloat("_SegmentTransparency", m_SegmentTransparency); m_OverlayImage.material.SetFloat("_BackTransparency", m_BackgroundTransparency); } } }