//------------------------------------------------------------ // Game Framework // Copyright © 2013-2021 Jiang Yin. All rights reserved. // Homepage: https://gameframework.cn/ // Feedback: mailto:ellan@gameframework.cn //------------------------------------------------------------ using UnityEngine; using UnityEngine.UI; using UnityGameFramework.Runtime; using GeometryTD.CustomComponent; namespace UI { /// /// uGUI 界面组辅助器。 /// [DefaultExecutionOrder(200)] public class UGuiGroupHelper : UIGroupHelperBase { public const int DepthFactor = 10000; private int m_Depth = 0; private Canvas m_CachedCanvas = null; private RectTransform m_RectTransform = null; private int m_LastScreenWidth = -1; private int m_LastScreenHeight = -1; private Rect m_LastViewport = new Rect(float.MinValue, float.MinValue, float.MinValue, float.MinValue); /// /// 设置界面组深度。 /// /// 界面组深度。 public override void SetDepth(int depth) { m_Depth = depth; m_CachedCanvas.overrideSorting = true; m_CachedCanvas.sortingOrder = DepthFactor * depth; } private void Awake() { m_CachedCanvas = gameObject.GetOrAddComponent(); gameObject.GetOrAddComponent(); m_RectTransform = GetComponent(); } private void Start() { m_CachedCanvas.overrideSorting = true; m_CachedCanvas.sortingOrder = DepthFactor * m_Depth; if (m_RectTransform == null) { return; } m_RectTransform.anchorMin = Vector2.zero; m_RectTransform.anchorMax = Vector2.one; m_RectTransform.pivot = new Vector2(0.5f, 0.5f); m_RectTransform.anchoredPosition = Vector2.zero; m_RectTransform.sizeDelta = Vector2.zero; ApplyViewportClip(true); } private void LateUpdate() { ApplyViewportClip(false); } private void ApplyViewportClip(bool force) { if (m_RectTransform == null) { return; } int screenWidth = Screen.width; int screenHeight = Screen.height; Rect viewport = ResolveViewportRect(); if (!force && screenWidth == m_LastScreenWidth && screenHeight == m_LastScreenHeight && Mathf.Approximately(viewport.x, m_LastViewport.x) && Mathf.Approximately(viewport.y, m_LastViewport.y) && Mathf.Approximately(viewport.width, m_LastViewport.width) && Mathf.Approximately(viewport.height, m_LastViewport.height)) { return; } m_LastScreenWidth = screenWidth; m_LastScreenHeight = screenHeight; m_LastViewport = viewport; if (screenWidth <= 0 || screenHeight <= 0) { return; } float horizontalPadding = Mathf.Max(0f, (1f - viewport.width) * 0.5f * screenWidth); float verticalPadding = Mathf.Max(0f, (1f - viewport.height) * 0.5f * screenHeight); float canvasScale = ResolveCanvasScaleFactor(); float horizontalPaddingInCanvasUnit = horizontalPadding / canvasScale; float verticalPaddingInCanvasUnit = verticalPadding / canvasScale; m_RectTransform.offsetMin = new Vector2(horizontalPaddingInCanvasUnit, verticalPaddingInCanvasUnit); m_RectTransform.offsetMax = new Vector2(-horizontalPaddingInCanvasUnit, -verticalPaddingInCanvasUnit); } private Rect ResolveViewportRect() { if (ResolutionAdapterComponent.TryGetTargetViewport(out Rect adapterViewport)) { return adapterViewport; } Camera camera = m_CachedCanvas != null ? m_CachedCanvas.worldCamera : null; if (camera == null && m_CachedCanvas != null && m_CachedCanvas.rootCanvas != null) { camera = m_CachedCanvas.rootCanvas.worldCamera; } if (camera == null && GameEntry.Scene != null) { camera = GameEntry.Scene.MainCamera; } if (camera == null) { camera = Camera.main; } return camera != null ? camera.rect : new Rect(0f, 0f, 1f, 1f); } private float ResolveCanvasScaleFactor() { Canvas rootCanvas = m_CachedCanvas != null ? m_CachedCanvas.rootCanvas : null; float scale = rootCanvas != null ? rootCanvas.scaleFactor : (m_CachedCanvas != null ? m_CachedCanvas.scaleFactor : 1f); return scale > 0.0001f ? scale : 1f; } } }