Example #1
0
        /// <summary>
        /// Runs a layout pass in the X direction, resolving edges that can be resolved.
        /// </summary>
        /// <param name="children">The children to resolve.</param>
        /// <returns>true if all children have all X edges constrained, or false otherwise.</returns>
        internal static bool RunPassX(this IEnumerable <RelativeLayoutResults> children)
        {
            bool done = true;

            foreach (var child in children)
            {
                float      width = child.EffectiveWidth;
                EdgeStatus l = child.LeftEdge, r = child.RightEdge;
                if (LockEdgeAnchor(l, r))
                {
                    child.UseSizeDeltaX = true;
                }
                LockEdgeAnchor(l);
                LockEdgeAnchor(r);
                LockEdgeRelative(l, -width, r);
                LockEdgeRelative(r, width, l);
                // Lock to other components
                if (child.LeftParams != null)
                {
                    LockEdgeComponent(l, child.LeftParams.RightEdge);
                }
                if (child.RightParams != null)
                {
                    LockEdgeComponent(r, child.RightParams.LeftEdge);
                }
                if (!l.Locked || !r.Locked)
                {
                    done = false;
                }
            }
            return(done);
        }
Example #2
0
        /// <summary>
        /// Runs a layout pass in the Y direction, resolving edges that can be resolved.
        /// </summary>
        /// <param name="children">The children to resolve.</param>
        /// <returns>true if all children have all Y edges constrained, or false otherwise.</returns>
        internal static bool RunPassY(this IEnumerable <RelativeLayoutResults> children)
        {
            bool done = true;

            foreach (var child in children)
            {
                float      height = child.EffectiveHeight;
                EdgeStatus t = child.TopEdge, b = child.BottomEdge;
                if (LockEdgeAnchor(t, b))
                {
                    child.UseSizeDeltaY = true;
                }
                LockEdgeAnchor(b);
                LockEdgeAnchor(t);
                LockEdgeRelative(b, -height, t);
                LockEdgeRelative(t, height, b);
                // Lock to other components
                if (child.BottomParams != null)
                {
                    LockEdgeComponent(b, child.BottomParams.TopEdge);
                }
                if (child.TopParams != null)
                {
                    LockEdgeComponent(t, child.TopParams.BottomEdge);
                }
                if (!t.Locked || !b.Locked)
                {
                    done = false;
                }
            }
            return(done);
        }
Example #3
0
 /// <summary>
 /// Executes the vertical layout.
 /// </summary>
 /// <param name="children">The components to lay out.</param>
 /// <param name="scratch">The location where components will be temporarily stored.</param>
 /// <param name="mBottom">The bottom margin.</param>
 /// <param name="mTop">The top margin.</param>
 internal static void ExecuteY(this IEnumerable <RelativeLayoutResults> children,
                               List <ILayoutController> scratch, float mBottom = 0.0f, float mTop = 0.0f)
 {
     foreach (var child in children)
     {
         var        rt = child.Transform;
         var        insets = child.Insets;
         EdgeStatus t = child.TopEdge, b = child.BottomEdge;
         // Set corner positions
         rt.anchorMin = new Vector2(rt.anchorMin.x, b.FromAnchor);
         rt.anchorMax = new Vector2(rt.anchorMax.x, t.FromAnchor);
         // If anchored by pivot, resize with current anchors
         if (child.UseSizeDeltaY)
         {
             rt.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, child.
                                          PreferredHeight);
         }
         else
         {
             // Bottom
             rt.offsetMin = new Vector2(rt.offsetMin.x, b.Offset + insets.bottom +
                                        (b.FromAnchor <= 0.0f ? mBottom : 0.0f));
             // Top
             rt.offsetMax = new Vector2(rt.offsetMax.x, t.Offset - insets.top -
                                        (t.FromAnchor >= 1.0f ? mTop : 0.0f));
         }
         // Execute layout controllers if present
         scratch.Clear();
         rt.gameObject.GetComponents(scratch);
         foreach (var component in scratch)
         {
             component.SetLayoutVertical();
         }
     }
 }
Example #4
0
 /// <summary>
 /// Executes the horizontal layout.
 /// </summary>
 /// <param name="children">The components to lay out.</param>
 /// <param name="scratch">The location where components will be temporarily stored.</param>
 /// <param name="mLeft">The left margin.</param>
 /// <param name="mRight">The right margin.</param>
 internal static void ExecuteX(this IEnumerable <RelativeLayoutResults> children,
                               List <ILayoutController> scratch, float mLeft = 0.0f, float mRight = 0.0f)
 {
     foreach (var child in children)
     {
         var        rt = child.Transform;
         var        insets = child.Insets;
         EdgeStatus l = child.LeftEdge, r = child.RightEdge;
         // Set corner positions
         rt.anchorMin = new Vector2(l.FromAnchor, 0.0f);
         rt.anchorMax = new Vector2(r.FromAnchor, 1.0f);
         // If anchored by pivot, resize with current anchors
         if (child.UseSizeDeltaX)
         {
             rt.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, child.
                                          PreferredWidth);
         }
         else
         {
             // Left
             rt.offsetMin = new Vector2(l.Offset + insets.left + (l.FromAnchor <= 0.0f ?
                                                                  mLeft : 0.0f), rt.offsetMin.y);
             // Right
             rt.offsetMax = new Vector2(r.Offset - insets.right - (r.FromAnchor >=
                                                                   1.0f ? mRight : 0.0f), rt.offsetMax.y);
         }
         // Execute layout controllers if present
         scratch.Clear();
         rt.gameObject.GetComponents(scratch);
         foreach (var component in scratch)
         {
             component.SetLayoutHorizontal();
         }
     }
 }
Example #5
0
 /// <summary>
 /// Locks an edge if it is constrained to an anchor.
 /// </summary>
 /// <param name="edge">The edge to check.</param>
 private static void LockEdgeAnchor(EdgeStatus edge)
 {
     if (edge.Constraint == RelativeConstraintType.ToAnchor)
     {
         edge.Constraint = RelativeConstraintType.Locked;
         edge.Offset     = 0.0f;
     }
 }
Example #6
0
 /// <summary>
 /// Locks an edge if it can be determined from another component.
 /// </summary>
 /// <param name="edge">The edge to check.</param>
 /// <param name="offset">The component's offset in that direction.</param>
 /// <param name="otherEdge">The opposing edge of the referenced component.</param>
 private static void LockEdgeComponent(EdgeStatus edge, EdgeStatus otherEdge)
 {
     if (edge.Constraint == RelativeConstraintType.ToComponent && otherEdge.Locked)
     {
         edge.Constraint = RelativeConstraintType.Locked;
         edge.FromAnchor = otherEdge.FromAnchor;
         edge.Offset     = otherEdge.Offset;
     }
 }
Example #7
0
        /// <summary>
        /// Resolves a component reference if needed.
        /// </summary>
        /// <param name="edge">The edge to resolve.</param>
        /// <param name="lookup">The location where the component can be looked up.</param>
        /// <returns>The linked parameters for that edge if needed.</returns>
        private static RelativeLayoutResults InitResolve(EdgeStatus edge,
                                                         IDictionary <GameObject, RelativeLayoutResults> lookup)
        {
            RelativeLayoutResults result = null;

            if (edge.Constraint == RelativeConstraintType.ToComponent)
            {
                if (!lookup.TryGetValue(edge.FromComponent, out result))
                {
                    edge.Constraint = RelativeConstraintType.Unconstrained;
                }
            }
            return(result);
        }
Example #8
0
        /// <summary>
        /// Locks both edges if they are constrained to the same anchor.
        /// </summary>
        /// <param name="edge">The edge to check.</param>
        /// <param name="otherEdge">The other edge to check.</param>
        /// <returns>true if it was able to lock, or false otherwise.</returns>
        private static bool LockEdgeAnchor(EdgeStatus edge, EdgeStatus otherEdge)
        {
            bool useDelta = edge.Constraint == RelativeConstraintType.ToAnchor && otherEdge.
                            Constraint == RelativeConstraintType.ToAnchor && edge.FromAnchor == otherEdge.
                            FromAnchor;

            if (useDelta)
            {
                edge.Constraint      = RelativeConstraintType.Locked;
                otherEdge.Constraint = RelativeConstraintType.Locked;
                edge.Offset          = 0.0f;
                otherEdge.Offset     = 0.0f;
            }
            return(useDelta);
        }
Example #9
0
        /// <summary>
        /// Calculates the minimum size in the Y direction.
        /// </summary>
        /// <param name="children">The components to lay out.</param>
        /// <returns>The minimum vertical size.</returns>
        internal static float GetMinSizeY(this IEnumerable <RelativeLayoutResults> children)
        {
            float maxHeight = 0.0f, height;

            foreach (var child in children)
            {
                var        insets = child.Insets;
                EdgeStatus bottom = child.BottomEdge, top = child.TopEdge;
                float      aMin = bottom.FromAnchor, aMax = top.FromAnchor;
                if (aMax > aMin)
                {
                    // "Elbow room" method
                    height = (child.EffectiveHeight + bottom.Offset - top.Offset) /
                             (aMax - aMin);
                }
                else
                {
                    // Anchors are together
                    float oMin = bottom.Offset, oMax = top.Offset;
                    if (oMin == oMax)
                    {
                        oMin = oMax = child.EffectiveHeight * 0.5f;
                    }
                    if (oMin < 0.0f)
                    {
                        oMin /= -Math.Max(MIN_SIZE_RATIO, aMax);
                    }
                    else
                    {
                        oMin /= Math.Max(MIN_SIZE_RATIO, 1.0f - aMax);
                    }
                    if (oMax < 0.0f)
                    {
                        oMax /= -Math.Max(MIN_SIZE_RATIO, aMax);
                    }
                    else
                    {
                        oMax /= Math.Max(MIN_SIZE_RATIO, 1.0f - aMax);
                    }
                    height = Math.Max(oMin, oMax);
                }
                if (height > maxHeight)
                {
                    maxHeight = height;
                }
            }
            return(maxHeight);
        }
Example #10
0
        /// <summary>
        /// Calculates the minimum size in the X direction.
        /// </summary>
        /// <param name="children">The components to lay out.</param>
        /// <returns>The minimum horizontal size.</returns>
        internal static float GetMinSizeX(this IEnumerable <RelativeLayoutResults> children)
        {
            float maxWidth = 0.0f, width;

            foreach (var child in children)
            {
                var        insets = child.Insets;
                EdgeStatus left = child.LeftEdge, right = child.RightEdge;
                float      aMin = left.FromAnchor, aMax = right.FromAnchor;
                if (aMax > aMin)
                {
                    // "Elbow room" method
                    width = (child.EffectiveWidth + left.Offset - right.Offset) /
                            (aMax - aMin);
                }
                else
                {
                    // Anchors are together
                    float oMin = left.Offset, oMax = right.Offset;
                    if (oMin == oMax)
                    {
                        oMin = oMax = child.EffectiveWidth * 0.5f;
                    }
                    if (oMin < 0.0f)
                    {
                        oMin /= -Math.Max(MIN_SIZE_RATIO, aMax);
                    }
                    else
                    {
                        oMin /= Math.Max(MIN_SIZE_RATIO, 1.0f - aMax);
                    }
                    if (oMax < 0.0f)
                    {
                        oMax /= -Math.Max(MIN_SIZE_RATIO, aMax);
                    }
                    else
                    {
                        oMax /= Math.Max(MIN_SIZE_RATIO, 1.0f - aMax);
                    }
                    width = Math.Max(oMin, oMax);
                }
                if (width > maxWidth)
                {
                    maxWidth = width;
                }
            }
            return(maxWidth);
        }
Example #11
0
        /// <summary>
        /// Calculates the minimum size the component must be to support a specific child
        /// component.
        /// </summary>
        /// <param name="min">The lower edge constraint.</param>
        /// <param name="max">The upper edge constraint.</param>
        /// <param name="effective">The component size in that dimension plus margins.</param>
        /// <returns>The minimum parent component size to fit the child.</returns>
        internal static float ElbowRoom(EdgeStatus min, EdgeStatus max, float effective)
        {
            float aMin = min.FromAnchor, aMax = max.FromAnchor, result, offMin = min.Offset,
                  offMax = max.Offset;

            if (aMax > aMin)
            {
                // "Elbow room" method
                result = (effective + offMin - offMax) / (aMax - aMin);
            }
            else
            {
                // Anchors are together
                result = Math.Max(effective, Math.Max(Math.Abs(offMin), Math.Abs(offMax)));
            }
            return(result);
        }
Example #12
0
 /// <summary>
 /// Locks an edge if it can be determined from the other edge.
 /// </summary>
 /// <param name="edge">The edge to check.</param>
 /// <param name="size">The component's effective size in that direction.</param>
 /// <param name="opposing">The component's other edge.</param>
 private static void LockEdgeRelative(EdgeStatus edge, float size, EdgeStatus opposing)
 {
     if (edge.Constraint == RelativeConstraintType.Unconstrained)
     {
         if (opposing.Locked)
         {
             edge.Constraint = RelativeConstraintType.Locked;
             edge.FromAnchor = opposing.FromAnchor;
             edge.Offset     = opposing.Offset + size;
         }
         else if (opposing.Constraint == RelativeConstraintType.Unconstrained)
         {
             // Both unconstrained, full size
             edge.Constraint     = RelativeConstraintType.Locked;
             edge.FromAnchor     = 0.0f;
             edge.Offset         = 0.0f;
             opposing.Constraint = RelativeConstraintType.Locked;
             opposing.FromAnchor = 1.0f;
             opposing.Offset     = 0.0f;
         }
     }
 }
Example #13
0
        /// <summary>
        /// Calculates the minimum size the component must be to support a specific child
        /// component.
        /// </summary>
        /// <param name="min">The lower edge constraint.</param>
        /// <param name="max">The upper edge constraint.</param>
        /// <param name="effective">The component size in that dimension plus margins.</param>
        /// <returns>The minimum parent component size to fit the child.</returns>
        internal static float ElbowRoom(EdgeStatus min, EdgeStatus max, float effective)
        {
            float aMin = min.FromAnchor, aMax = max.FromAnchor, result;

            if (aMax > aMin)
            {
                // "Elbow room" method
                result = (effective + min.Offset - max.Offset) / (aMax - aMin);
            }
            else
            {
                // Anchors are together
                float oMin = min.Offset, oMax = max.Offset;
                if (oMin == oMax)
                {
                    oMin = oMax = effective * 0.5f;
                }
                if (oMin < 0.0f)
                {
                    oMin /= -Math.Max(MIN_SIZE_RATIO, aMax);
                }
                else
                {
                    oMin /= Math.Max(MIN_SIZE_RATIO, 1.0f - aMax);
                }
                if (oMax < 0.0f)
                {
                    oMax /= -Math.Max(MIN_SIZE_RATIO, aMax);
                }
                else
                {
                    oMax /= Math.Max(MIN_SIZE_RATIO, 1.0f - aMax);
                }
                result = Math.Max(oMin, oMax);
            }
            return(result);
        }