using System.Collections.Generic; using UnityEngine; namespace Flexalon { public class FlexItem { public float MinSize; public float MaxSize; public float StartSize; public float ShrinkFactor; public float GrowFactor; public float FinalSize; } public static class Flex { public static void GrowOrShrink(List items, float usedSpace, float totalSpace, float gap) { if (totalSpace > usedSpace) { Grow(items, totalSpace, gap); } else { Shrink(items, totalSpace, gap); } } public static void Grow(List items, float space, float gap) { space -= gap * (items.Count - 1); var totalFactor = 0f; foreach (var item in items) { if (item.GrowFactor == 0) { item.FinalSize = Mathf.Clamp(item.StartSize, item.MinSize, item.MaxSize); } else if (item.StartSize >= item.MaxSize) { item.FinalSize = item.MaxSize; } else { item.FinalSize = item.StartSize; totalFactor += item.GrowFactor; } space = Mathf.Max(0, space - item.FinalSize); } var canGrow = totalFactor > 0; var remaining = space; while (canGrow) { canGrow = false; foreach (var item in items) { if (item.FinalSize < item.MaxSize && item.GrowFactor > 0) { if (totalFactor >= 1) { item.FinalSize = item.StartSize + remaining * item.GrowFactor * (1 / totalFactor); } else { item.FinalSize = item.StartSize + space * item.GrowFactor; } if (item.FinalSize > item.MaxSize) { item.FinalSize = item.MaxSize; totalFactor -= item.GrowFactor; remaining -= item.MaxSize; canGrow = totalFactor > 0; } else if (item.FinalSize < item.MinSize) { item.FinalSize = item.MinSize; totalFactor -= item.GrowFactor; remaining -= item.MinSize; canGrow = totalFactor > 0; item.GrowFactor = 0; } } } } } public static void Shrink(List items, float space, float gap) { var totalFactor = 0f; space -= gap * (items.Count - 1); foreach (var item in items) { item.FinalSize = Mathf.Clamp(item.StartSize, item.MinSize, item.MaxSize); if (item.FinalSize > item.MinSize && item.ShrinkFactor > 0) { totalFactor += item.ShrinkFactor; } else { space = Mathf.Max(0, space - item.FinalSize); } } bool canShrink = totalFactor > 0; while (canShrink) { canShrink = false; foreach (var item in items) { if (item.FinalSize > item.MinSize && item.ShrinkFactor > 0) { item.FinalSize = space * item.ShrinkFactor * (1 / totalFactor); if (item.FinalSize < item.MinSize) { item.FinalSize = item.MinSize; space = Mathf.Max(0, space - item.MinSize); totalFactor -= item.ShrinkFactor; canShrink = totalFactor > 0; } } } } } public static FlexItem CreateFlexItem(FlexalonNode node, int axis, float childSize, float usedSize, float layoutSize) { var growFactor = node.GetSizeType(axis) == SizeType.Fill ? node.SizeOfParent[axis] : 0; return new FlexItem() { MinSize = node.GetMinSize(axis, layoutSize), MaxSize = node.GetMaxSize(axis, layoutSize), StartSize = growFactor == 0 ? childSize : 0, // Don't support flex-basis + grow ShrinkFactor = node.CanShrink(axis) ? childSize / usedSize : 0, GrowFactor = growFactor }; } } }