miepzerino
2025-03-30 d2ab30e7a69bfe7efda63ae75812207377917bd3
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
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<FlexItem> items, float usedSpace, float totalSpace, float gap)
        {
            if (totalSpace > usedSpace)
            {
                Grow(items, totalSpace, gap);
            }
            else
            {
                Shrink(items, totalSpace, gap);
            }
        }
 
        public static void Grow(List<FlexItem> 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<FlexItem> 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
            };
        }
    }
}