From d2ab30e7a69bfe7efda63ae75812207377917bd3 Mon Sep 17 00:00:00 2001
From: miepzerino <o.skotnik@gmail.com>
Date: Sun, 30 Mar 2025 18:50:27 +0000
Subject: [PATCH] Merge branch 'Flexalon-UI-Layouts' into develop

---
 Assets/Flexalon/Runtime/Core/FlexalonMath.cs |  540 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 540 insertions(+), 0 deletions(-)

diff --git a/Assets/Flexalon/Runtime/Core/FlexalonMath.cs b/Assets/Flexalon/Runtime/Core/FlexalonMath.cs
new file mode 100644
index 0000000..bf03681
--- /dev/null
+++ b/Assets/Flexalon/Runtime/Core/FlexalonMath.cs
@@ -0,0 +1,540 @@
+using UnityEngine;
+
+namespace Flexalon
+{
+    /// <summary> Common math help functions. </summary>
+    public static class Math
+    {
+        public static readonly float MaxValue = 999999f;
+        public static readonly Vector3 MaxVector = new Vector3(MaxValue, MaxValue, MaxValue);
+
+        /// <summary> Returns the opposite direction. </summary>
+        /// <param name="direction"> The direction to get the opposite of. </param>
+        /// <returns> The opposite direction. </returns>
+        public static Direction GetOppositeDirection(Direction direction)
+        {
+            switch (direction)
+            {
+                case Direction.PositiveX: return Direction.NegativeX;
+                case Direction.NegativeX: return Direction.PositiveX;
+                case Direction.PositiveY: return Direction.NegativeY;
+                case Direction.NegativeY: return Direction.PositiveY;
+                case Direction.PositiveZ: return Direction.NegativeZ;
+                case Direction.NegativeZ: return Direction.PositiveZ;
+                default: return Direction.PositiveX;
+            }
+        }
+
+        /// <summary> Returns the opposite direction. </summary>
+        /// <param name="direction"> The direction to get the opposite of. </param>
+        /// <returns> The opposite direction. </returns>
+        public static Direction GetOppositeDirection(int direction)
+        {
+            return GetOppositeDirection((Direction)direction);
+        }
+
+        /// <summary> Returns the axis of a direction. </summary>
+        /// <param name="direction"> The direction to get the axis of. </param>
+        /// <returns> The axis of the direction. </returns>
+        public static Axis GetAxisFromDirection(Direction direction)
+        {
+            switch (direction)
+            {
+                case Direction.PositiveX: return Axis.X;
+                case Direction.NegativeX: return Axis.X;
+                case Direction.PositiveY: return Axis.Y;
+                case Direction.NegativeY: return Axis.Y;
+                case Direction.PositiveZ: return Axis.Z;
+                case Direction.NegativeZ: return Axis.Z;
+                default: return Axis.X;
+            }
+        }
+
+        /// <summary> Returns the axis of a direction. </summary>
+        /// <param name="direction"> The direction to get the axis of. </param>
+        /// <returns> The axis of the direction. </returns>
+        public static Axis GetAxisFromDirection(int direction)
+        {
+            return GetAxisFromDirection((Direction)direction);
+        }
+
+        /// <summary> Returns the positive and negative directions of an axis. </summary>
+        /// <param name="axis"> The axis to get the directions of. </param>
+        /// <returns> The positive and negative directions of the axis. </returns>
+        public static (Direction, Direction) GetDirectionsFromAxis(Axis axis)
+        {
+            switch (axis)
+            {
+                case Axis.X: return (Direction.PositiveX, Direction.NegativeX);
+                case Axis.Y: return (Direction.PositiveY, Direction.NegativeY);
+                case Axis.Z: return (Direction.PositiveZ, Direction.NegativeZ);
+                default: return (Direction.PositiveX, Direction.NegativeX);
+            }
+        }
+
+        /// <summary> Returns the positive and negative directions of an axis. </summary>
+        /// <param name="axis"> The axis to get the directions of. </param>
+        /// <returns> The positive and negative directions of the axis. </returns>
+        public static (Direction, Direction) GetDirectionsFromAxis(int axis)
+        {
+            return GetDirectionsFromAxis((Axis)axis);
+        }
+
+        /// <summary> Returns the positive direction of an axis. </summary>
+        /// <param name="axis"> The axis to get the direction of. </param>
+        /// <returns> The positive direction of the axis. </returns>
+        public static float GetPositiveFromDirection(Direction direction)
+        {
+            switch (direction)
+            {
+                case Direction.PositiveX:
+                case Direction.PositiveY:
+                case Direction.PositiveZ:
+                    return 1;
+                default:
+                    return -1;
+            }
+        }
+
+        /// <summary> Returns the positive direction of an axis. </summary>
+        /// <param name="axis"> The axis to get the direction of. </param>
+        /// <returns> The positive direction of the axis. </returns>
+        public static float GetPositiveFromDirection(int direction)
+        {
+            return GetPositiveFromDirection((Direction)direction);
+        }
+
+        /// <summary> Returns a unit vector in the direction. </summary>
+        /// <param name="direction"> The direction to get the vector of. </param>
+        /// <returns> A unit vector in the direction. </returns>
+        public static Vector3 GetVectorFromDirection(Direction direction)
+        {
+            switch (direction)
+            {
+                case Direction.PositiveX:
+                    return Vector3.right;
+                case Direction.PositiveY:
+                    return Vector3.up;
+                case Direction.PositiveZ:
+                    return Vector3.forward;
+                case Direction.NegativeX:
+                    return Vector3.left;
+                case Direction.NegativeY:
+                    return Vector3.down;
+                case Direction.NegativeZ:
+                    return Vector3.back;
+            }
+
+            return Vector3.zero;
+        }
+
+        /// <summary> Returns a unit vector in the direction. </summary>
+        /// <param name="direction"> The direction to get the vector of. </param>
+        /// <returns> A unit vector in the direction. </returns>
+        public static Vector3 GetVectorFromDirection(int direction)
+        {
+            return GetVectorFromDirection((Direction)direction);
+        }
+
+        /// <summary> Returns a unit vector in the positive direction of axis. </summary>
+        /// <param name="axis"> The axis to get the vector of. </param>
+        /// <returns> A unit vector in the axis. </returns>
+        public static Vector3 GetVectorFromAxis(Axis axis)
+        {
+            switch (axis)
+            {
+                case Axis.X:
+                    return Vector3.right;
+                case Axis.Y:
+                    return Vector3.up;
+                case Axis.Z:
+                    return Vector3.forward;
+            }
+
+            return Vector3.zero;
+        }
+
+        /// <summary> Returns a unit vector in the positive direction of axis. </summary>
+        /// <param name="axis"> The axis to get the vector of. </param>
+        /// <returns> A unit vector in the axis. </returns>
+        public static Vector3 GetVectorFromAxis(int axis)
+        {
+            return GetVectorFromAxis((Axis)axis);
+        }
+
+        /// <summary> Returns the other two axes. </summary>
+        /// <param name="axis"> The axis to get the other two axes of. </param>
+        /// <returns> The other two axes. </returns>
+        public static (Axis, Axis) GetOtherAxes(Axis axis)
+        {
+            switch (axis)
+            {
+                case Axis.X: return (Axis.Y, Axis.Z);
+                case Axis.Y: return (Axis.X, Axis.Z);
+                default: return (Axis.X, Axis.Y);
+            }
+        }
+
+        /// <summary> Returns the other two axes. </summary>
+        /// <param name="axis"> The axis to get the other two axes of. </param>
+        /// <returns> The other two axes. </returns>
+        public static (int, int) GetOtherAxes(int axis)
+        {
+            var other = GetOtherAxes((Axis)axis);
+            return ((int)other.Item1, (int)other.Item2);
+        }
+
+        /// <summary> Given two axes, returns the third axis. </summary>
+        /// <param name="axis1"> The first axis. </param>
+        /// <param name="axis2"> The second axis. </param>
+        /// <returns> The third axis. </returns>
+        public static Axis GetThirdAxis(Axis axis1, Axis axis2)
+        {
+            var otherAxes = GetOtherAxes(axis1);
+            return (otherAxes.Item1 == axis2) ? otherAxes.Item2 : otherAxes.Item1;
+        }
+
+        /// <summary> Given two axes, returns the third axis. </summary>
+        /// <param name="axis1"> The first axis. </param>
+        /// <param name="axis2"> The second axis. </param>
+        /// <returns> The third axis. </returns>
+        public static int GetThirdAxis(int axis1, int axis2)
+        {
+            return (int) GetThirdAxis((Axis)axis1, (Axis)axis2);
+        }
+
+        /// <summary> Returns the axes of a plane. </summary>
+        /// <param name="plane"> The plane to get the axes of. </param>
+        /// <returns> The axes of the plane. </returns>
+        public static (Axis, Axis) GetPlaneAxes(Plane plane)
+        {
+            switch (plane)
+            {
+                case Plane.XY: return (Axis.X, Axis.Y);
+                case Plane.XZ: return (Axis.X, Axis.Z);
+                default: return (Axis.Z, Axis.Y);
+            }
+        }
+
+        /// <summary> Returns the axes of a plane. </summary>
+        /// <param name="plane"> The plane to get the axes of. </param>
+        /// <returns> The axes of the plane. </returns>
+        public static (int, int) GetPlaneAxesInt(Plane plane)
+        {
+            var axes = GetPlaneAxes(plane);
+            return ((int)axes.Item1, (int)axes.Item2);
+        }
+
+        /// <summary> Multiplies each component of two vectors. </summary>
+        /// <param name="a"> The first vector. </param>
+        /// <param name="b"> The second vector. </param>
+        /// <returns> The multiplied vector. </returns>
+        public static Vector3 Mul(Vector3 a, Vector3 b)
+        {
+            a.x *= b.x;
+            a.y *= b.y;
+            a.z *= b.z;
+            return a;
+        }
+
+        /// <summary> Divides each component of two vectors. </summary>
+        /// <param name="a"> The divided vector. </param>
+        /// <param name="b"> The divisor vector. </param>
+        /// <returns> The divided vector. </returns>
+        public static Vector3 Div(Vector3 a, Vector3 b)
+        {
+            a.x /= b.x;
+            a.y /= b.y;
+            a.z /= b.z;
+            return a;
+        }
+
+        /// <summary> Rotates a bounds around the origin and returns a new bounds
+        /// that encapsulates all of the rotated corners. </summary>
+        /// <param name="bounds"> The bounds to rotate. </param>
+        /// <param name="rotation"> The rotation to rotate the bounds by. </param>
+        /// <returns> The new bounds. </returns>
+        public static Bounds RotateBounds(Bounds bounds, Quaternion rotation)
+        {
+            if (rotation == Quaternion.identity) return bounds;
+
+            var rotatedCenter = rotation * bounds.center;
+            var p1 = rotation * bounds.max;
+            var p2 = rotation * new Vector3(bounds.max.x, bounds.max.y, bounds.min.z);
+            var p3 = rotation * new Vector3(bounds.max.x, bounds.min.y, bounds.max.z);
+            var p4 = rotation * new Vector3(bounds.max.x, bounds.min.y, bounds.min.z);
+            var p5 = rotation * new Vector3(bounds.min.x, bounds.max.y, bounds.max.z);
+            var p6 = rotation * new Vector3(bounds.min.x, bounds.max.y, bounds.min.z);
+            var p7 = rotation * new Vector3(bounds.min.x, bounds.min.y, bounds.max.z);
+            var p8 = rotation * bounds.min;
+
+            var rotatedBounds = new Bounds(rotatedCenter, Vector3.zero);
+            rotatedBounds.Encapsulate(p1);
+            rotatedBounds.Encapsulate(p2);
+            rotatedBounds.Encapsulate(p3);
+            rotatedBounds.Encapsulate(p4);
+            rotatedBounds.Encapsulate(p5);
+            rotatedBounds.Encapsulate(p6);
+            rotatedBounds.Encapsulate(p7);
+            rotatedBounds.Encapsulate(p8);
+            return rotatedBounds;
+        }
+
+        /// <summary> Creates rotated and scaled bounds at center. </summary>
+        /// <param name="center"> The center of the bounds. </param>
+        /// <param name="size"> The size of the bound before rotation. </param>
+        /// <param name="rotation"> The rotation to apply to the size.  </param>
+        public static Bounds CreateRotatedBounds(Vector3 center, Vector3 size, Quaternion rotation)
+        {
+            if (rotation == Quaternion.identity) return new Bounds(center, size);
+            var bounds = RotateBounds(new Bounds(Vector3.zero, size), rotation);
+            bounds.center = center;
+            return bounds;
+        }
+
+        /// <summary> Scales a bounds by multiplying the center and size by 'scale'. </summary>
+        /// <param name="bounds"> The bounds to scale. </param>
+        /// <param name="scale"> The scale to scale the bounds by. </param>
+        /// <returns> The scaled bounds. </returns>
+        public static Bounds ScaleBounds(Bounds bounds, Vector3 scale)
+        {
+            bounds.center = Math.Mul(bounds.center, scale);
+            bounds.size = Math.Mul(bounds.size, scale);
+            return bounds;
+        }
+
+        /// <summary> Determines the aligned position in a size. </summary>
+        /// <param name="size"> The size to align to. </param>
+        /// <param name="align"> The alignment. </param>
+        /// <returns> The aligned position. </returns>
+        public static float Align(float size, Align align)
+        {
+            if (align == global::Flexalon.Align.Start)
+            {
+                return -size * 0.5f;
+            }
+            else if (align == global::Flexalon.Align.End)
+            {
+                return size * 0.5f;
+            }
+
+            return 0;
+        }
+
+        /// <summary> Determines the aligned position in a size for an axis. </summary>
+        /// <param name="size"> The size to align to. </param>
+        /// <param name="axis"> The axis to align to. </param>
+        /// <param name="align"> The alignment. </param>
+        /// <returns> The aligned position. </returns>
+        public static float Align(Vector3 size, int axis, Align align)
+        {
+            return Align(size[axis], align);
+        }
+
+        /// <summary> Determines the aligned position in a size. </summary>
+        /// <param name="size"> The size to align to. </param>
+        /// <param name="horizontal"> The horizontal alignment. </param>
+        /// <param name="vertical"> The vertical alignment. </param>
+        /// <param name="depth"> The depth alignment. </param>
+        /// <returns> The aligned position. </returns>
+        public static Vector3 Align(Vector3 size, Align horizontal, Align vertical, Align depth)
+        {
+            return new Vector3(
+                Align(size, 0, horizontal),
+                Align(size, 1, vertical),
+                Align(size, 2, depth));
+        }
+
+        /// <summary> Aligns a child size to a parent size. </summary>
+        /// <param name="childSize"> The size of the child. </param>
+        /// <param name="parentSize"> The size of the parent. </param>
+        /// <param name="parentAlign"> The alignment of the parent. </param>
+        /// <param name="childAlign"> The pivot of the child. </param>
+        /// <returns> The aligned position of the child. </returns>
+        public static float Align(float childSize, float parentSize, Align parentAlign, Align childAlign)
+        {
+            return Align(parentSize, parentAlign) - Align(childSize, childAlign);
+        }
+
+        /// <summary> Aligns a child size to a parent size. </summary>
+        /// <param name="childSize"> The size of the child. </param>
+        /// <param name="parentSize"> The size of the parent. </param>
+        /// <param name="align"> The alignment of the parent and child. </param>
+        /// <returns> The aligned position of the child. </returns>
+        public static float Align(float childSize, float parentSize, Align align)
+        {
+            return Align(childSize, parentSize, align, align);
+        }
+
+        /// <summary> Aligns a child size to a parent size on an axis. </summary>
+        /// <param name="childSize"> The size of the child. </param>
+        /// <param name="parentSize"> The size of the parent. </param>
+        /// <param name="axis"> The axis to align on. </param>
+        /// <param name="align"> The alignment of the parent and child. </param>
+        /// <returns> The aligned position of the child. </returns>
+        public static float Align(Vector3 childSize, Vector3 parentSize, int axis, Align align)
+        {
+            return Align(childSize[axis], parentSize[axis], align);
+        }
+
+        /// <summary> Aligns a child size to a parent size on an axis. </summary>
+        /// <param name="childSize"> The size of the child. </param>
+        /// <param name="parentSize"> The size of the parent. </param>
+        /// <param name="axis"> The axis to align on. </param>
+        /// <param name="align"> The alignment of the parent and child. </param>
+        /// <returns> The aligned position of the child. </returns>
+        public static float Align(Vector3 childSize, Vector3 parentSize, Axis axis, Align align)
+        {
+            return Align(childSize, parentSize, (int)axis, align);
+        }
+
+        /// <summary> Aligns a child size to a parent size on an axis. </summary>
+        /// <param name="childSize"> The size of the child. </param>
+        /// <param name="parentSize"> The size of the parent. </param>
+        /// <param name="axis"> The axis to align on. </param>
+        /// <param name="parentAlign"> The alignment of the parent. </param>
+        /// <param name="childAlign"> The pivot of the child. </param>
+        /// <returns> The aligned position of the child. </returns>
+        public static float Align(Vector3 childSize, Vector3 parentSize, int axis, Align parentAlign, Align childAlign)
+        {
+            return Align(childSize[axis], parentSize[axis], parentAlign, childAlign);
+        }
+
+        /// <summary> Aligns a child size to a parent size on an axis. </summary>
+        /// <param name="childSize"> The size of the child. </param>
+        /// <param name="parentSize"> The size of the parent. </param>
+        /// <param name="axis"> The axis to align on. </param>
+        /// <param name="parentAlign"> The alignment of the parent. </param>
+        /// <param name="childAlign"> The pivot of the child. </param>
+        /// <returns> The aligned position of the child. </returns>
+        public static float Align(Vector3 childSize, Vector3 parentSize, Axis axis, Align parentAlign, Align childAlign)
+        {
+            return Align(childSize, parentSize, (int)axis, parentAlign, childAlign);
+        }
+
+        /// <summary> Aligns a child size to a parent size on all axes. </summary>
+        /// <param name="childSize"> The size of the child. </param>
+        /// <param name="parentSize"> The size of the parent. </param>
+        /// <param name="parentHorizontal"> The horizontal alignment of the parent. </param>
+        /// <param name="parentVertical"> The vertical alignment of the parent. </param>
+        /// <param name="parentDepth"> The depth alignment of the parent. </param>
+        /// <param name="childHorizontal"> The horizontal pivot of the child. </param>
+        /// <param name="childVertical"> The vertical pivot of the child. </param>
+        /// <param name="childDepth"> The depth pivot of the child. </param>
+        /// <returns> The aligned position of the child. </returns>
+        public static Vector3 Align(Vector3 childSize, Vector3 parentSize, Align parentHorizontal, Align parentVertical, Align parentDepth, Align childHorizontal, Align childVertical, Align childDepth)
+        {
+            return Align(parentSize, parentHorizontal, parentVertical, parentDepth) -
+                Align(childSize, childHorizontal, childVertical, childDepth);
+        }
+
+        /// <summary> Aligns a child size to a parent size on all axes. </summary>
+        /// <param name="childSize"> The size of the child. </param>
+        /// <param name="parentSize"> The size of the parent. </param>
+        /// <param name="horizontal"> The horizontal alignment of the parent and child. </param>
+        /// <param name="vertical"> The vertical alignment of the parent and child. </param>
+        /// <param name="depth"> The depth alignment of the parent and child. </param>
+        /// <returns> The aligned position of the child. </returns>
+        public static Vector3 Align(Vector3 childSize, Vector3 parentSize, Align horizontal, Align vertical, Align depth)
+        {
+            return Align(parentSize, horizontal, vertical, depth) -
+                Align(childSize, horizontal, vertical, depth);
+        }
+
+        /// <summary> Given the bounds of a component, creates a bounds for the node respecting the
+        /// size types. Aspect ratio is preserved when possible. </summary>
+        /// <param name="componentBounds"> The bounds of the component. </param>
+        /// <param name="node"> The node to measure the bounds for. </param>
+        /// <param name="size"> The size of the node. </param>
+        /// <param name="min"> The minimum size of the node. </param>
+        /// <param name="max"> The maximum size of the node. </param>
+        /// <returns> The bounds of the node. </returns>
+        public static Bounds MeasureComponentBounds(Bounds componentBounds, FlexalonNode node, Vector3 size, Vector3 min, Vector3 max)
+        {
+            componentBounds.size = Vector3.Max(componentBounds.size, Vector3.one * 0.0001f);
+            var bounds = componentBounds;
+
+            bool componentX = node.GetSizeType(Axis.X) == SizeType.Component;
+            bool componentY = node.GetSizeType(Axis.Y) == SizeType.Component;
+            bool componentZ = node.GetSizeType(Axis.Z) == SizeType.Component;
+
+            var scale = (componentX && componentY && componentZ) ? 1 :
+                Mathf.Min(
+                    componentX ? float.MaxValue : size.x / bounds.size.x,
+                    componentY ? float.MaxValue : size.y / bounds.size.y,
+                    componentZ ? float.MaxValue : size.z / bounds.size.z);
+
+            var maxScale = Mathf.Min(max.x / bounds.size.x, max.y / bounds.size.y, max.z / bounds.size.z);
+            var minScale = Mathf.Max(min.x / bounds.size.x, min.y / bounds.size.y, min.z / bounds.size.z);
+            var clampedScale = Mathf.Clamp(scale, minScale, maxScale);
+            var clampedSize = Math.Clamp(size, min, max);
+
+            bounds.size = new Vector3(
+                componentX ? bounds.size.x * clampedScale : clampedSize.x,
+                componentY ? bounds.size.y * clampedScale : clampedSize.y,
+                componentZ ? bounds.size.z * clampedScale : clampedSize.z);
+
+            bounds.center = Math.Mul(bounds.center, Math.Div(bounds.size, componentBounds.size));
+            return bounds;
+        }
+
+        /// <summary> Given the bounds of a component, creates a bounds for the node respecting the
+        /// size types. Aspect ratio is preserved for X and Y when possible. </summary>
+        /// <param name="componentBounds"> The bounds of the component. </param>
+        /// <param name="node"> The node to measure the bounds for. </param>
+        /// <param name="size"> The size of the node. </param>
+        /// <param name="min"> The minimum size of the node. </param>
+        /// <param name="max"> The maximum size of the node. </param>
+        /// <returns> The bounds of the node. </returns>
+        public static Bounds MeasureComponentBounds2D(Bounds componentBounds, FlexalonNode node, Vector3 size, Vector3 min, Vector3 max)
+        {
+            componentBounds.size = Vector3.Max(componentBounds.size, Vector3.one * 0.0001f);
+            var bounds = componentBounds;
+
+            bool componentX = node.GetSizeType(Axis.X) == SizeType.Component;
+            bool componentY = node.GetSizeType(Axis.Y) == SizeType.Component;
+
+            var scale = (componentX && componentY) ? 1 :
+                Mathf.Min(
+                    componentX ? float.MaxValue : size.x / bounds.size.x,
+                    componentY ? float.MaxValue : size.y / bounds.size.y);
+
+            var maxScale = Mathf.Min(max.x / bounds.size.x, max.y / bounds.size.y);
+            var minScale = Mathf.Max(min.x / bounds.size.x, min.y / bounds.size.y);
+            var clampedScale = Mathf.Clamp(scale, minScale, maxScale);
+            var clampedSize = Math.Clamp(size, min, max);
+
+            bounds.size = new Vector3(
+                componentX ? bounds.size.x * clampedScale : clampedSize.x,
+                componentY ? bounds.size.y * clampedScale : clampedSize.y,
+                clampedSize.z);
+
+            bounds.center = Math.Mul(bounds.center, Math.Div(bounds.size, componentBounds.size));
+            return bounds;
+        }
+
+        /// <summary> Applies absolute value of to each vector component. </summary>
+        /// <param name="v"> The vector to apply absolute value to. </param>
+        /// <returns> The vector with absolute value applied. </returns>
+        public static Vector3 Abs(Vector3 v)
+        {
+            v.x = Mathf.Abs(v.x);
+            v.y = Mathf.Abs(v.y);
+            v.z = Mathf.Abs(v.z);
+            return v;
+        }
+
+        /// <summary> Clamps value of to each vector component between min and max. </summary>
+        /// <param name="v"> The vector to clamp. </param>
+        /// <param name="min"> The minimum value. </param>
+        /// <param name="max"> The maximum value. </param>
+        /// <returns> The clamped vector. </returns>
+        public static Vector3 Clamp(Vector3 v, Vector3 min, Vector3 max)
+        {
+            v.x = Mathf.Clamp(v.x, min.x, max.x);
+            v.y = Mathf.Clamp(v.y, min.y, max.y);
+            v.z = Mathf.Clamp(v.z, min.z, max.z);
+            return v;
+        }
+    }
+}
\ No newline at end of file

--
Gitblit v1.9.3