using UnityEngine.Pool; namespace UnityEngine.UI { /// /// Utility functions for querying layout elements for their minimum, preferred, and flexible sizes. /// public static class LayoutUtility { /// /// Returns the minimum size of the layout element. /// /// The RectTransform of the layout element to query. /// The axis to query. This can be 0 or 1. /// All components on the GameObject that implement the ILayoutElement are queried. The one with the highest priority which has a value for this setting is used. If multiple componets have this setting and have the same priority, the maximum value out of those is used. public static float GetMinSize(RectTransform rect, int axis) { return axis == 0 ? GetMinWidth(rect) : GetMinHeight(rect); } /// /// Returns the preferred size of the layout element. /// /// The RectTransform of the layout element to query. /// The axis to query. This can be 0 or 1. /// /// All components on the GameObject that implement the ILayoutElement are queried. The one with the highest priority which has a value for this setting is used. If multiple componets have this setting and have the same priority, the maximum value out of those is used. /// public static float GetPreferredSize(RectTransform rect, int axis) { return axis == 0 ? GetPreferredWidth(rect) : GetPreferredHeight(rect); } /// /// Returns the flexible size of the layout element. /// /// /// All components on the GameObject that implement the ILayoutElement are queried. The one with the highest priority which has a value for this setting is used. If multiple componets have this setting and have the same priority, the maximum value out of those is used. /// /// The RectTransform of the layout element to query. /// The axis to query. This can be 0 or 1. public static float GetFlexibleSize(RectTransform rect, int axis) { return axis == 0 ? GetFlexibleWidth(rect) : GetFlexibleHeight(rect); } /// /// Returns the minimum width of the layout element. /// /// The RectTransform of the layout element to query. /// /// All components on the GameObject that implement the ILayoutElement are queried. The one with the highest priority which has a value for this setting is used. If multiple componets have this setting and have the same priority, the maximum value out of those is used. /// public static float GetMinWidth(RectTransform rect) { return GetLayoutProperty(rect, e => e.minWidth, 0); } /// /// Returns the preferred width of the layout element. /// /// The RectTransform of the layout element to query. /// /// All components on the GameObject that implement the ILayoutElement are queried. The one with the highest priority which has a value for this setting is used. If multiple componets have this setting and have the same priority, the maximum value out of those is used. /// public static float GetPreferredWidth(RectTransform rect) { return Mathf.Max(GetLayoutProperty(rect, e => e.minWidth, 0), GetLayoutProperty(rect, e => e.preferredWidth, 0)); } /// /// Returns the flexible width of the layout element. /// /// /// All components on the GameObject that implement the ILayoutElement are queried. The one with the highest priority which has a value for this setting is used. If multiple componets have this setting and have the same priority, the maximum value out of those is used /// /// The RectTransform of the layout element to query. public static float GetFlexibleWidth(RectTransform rect) { return GetLayoutProperty(rect, e => e.flexibleWidth, 0); } /// /// Returns the minimum height of the layout element. /// /// The RectTransform of the layout element to query. /// /// All components on the GameObject that implement the ILayoutElement are queried. The one with the highest priority which has a value for this setting is used. If multiple componets have this setting and have the same priority, the maximum value out of those is used. /// public static float GetMinHeight(RectTransform rect) { return GetLayoutProperty(rect, e => e.minHeight, 0); } /// /// Returns the preferred height of the layout element. /// /// The RectTransform of the layout element to query. /// /// All components on the GameObject that implement the ILayoutElement are queried. The one with the highest priority which has a value for this setting is used. If multiple componets have this setting and have the same priority, the maximum value out of those is used. /// public static float GetPreferredHeight(RectTransform rect) { return Mathf.Max(GetLayoutProperty(rect, e => e.minHeight, 0), GetLayoutProperty(rect, e => e.preferredHeight, 0)); } /// /// Returns the flexible height of the layout element. /// /// /// All components on the GameObject that implement the ILayoutElement are queried. The one with the highest priority which has a value for this setting is used. If multiple componets have this setting and have the same priority, the maximum value out of those is used. /// /// The RectTransform of the layout element to query. public static float GetFlexibleHeight(RectTransform rect) { return GetLayoutProperty(rect, e => e.flexibleHeight, 0); } /// /// Gets a calculated layout property for the layout element with the given RectTransform. /// /// The RectTransform of the layout element to get a property for. /// The property to calculate. /// The default value to use if no component on the layout element supplies the given property /// The calculated value of the layout property. public static float GetLayoutProperty(RectTransform rect, System.Func property, float defaultValue) { ILayoutElement dummy; return GetLayoutProperty(rect, property, defaultValue, out dummy); } /// /// Gets a calculated layout property for the layout element with the given RectTransform. /// /// The RectTransform of the layout element to get a property for. /// The property to calculate. /// The default value to use if no component on the layout element supplies the given property /// Optional out parameter to get the component that supplied the calculated value. /// The calculated value of the layout property. public static float GetLayoutProperty(RectTransform rect, System.Func property, float defaultValue, out ILayoutElement source) { source = null; if (rect == null) return 0; float min = defaultValue; int maxPriority = System.Int32.MinValue; var components = ListPool.Get(); rect.GetComponents(typeof(ILayoutElement), components); var componentsCount = components.Count; for (int i = 0; i < componentsCount; i++) { var layoutComp = components[i] as ILayoutElement; if (layoutComp is Behaviour && !((Behaviour)layoutComp).isActiveAndEnabled) continue; int priority = layoutComp.layoutPriority; // If this layout components has lower priority than a previously used, ignore it. if (priority < maxPriority) continue; float prop = property(layoutComp); // If this layout property is set to a negative value, it means it should be ignored. if (prop < 0) continue; // If this layout component has higher priority than all previous ones, // overwrite with this one's value. if (priority > maxPriority) { min = prop; maxPriority = priority; source = layoutComp; } // If the layout component has the same priority as a previously used, // use the largest of the values with the same priority. else if (prop > min) { min = prop; source = layoutComp; } } ListPool.Release(components); return min; } } }