-
Notifications
You must be signed in to change notification settings - Fork 0
/
LayoutGroupRefresher.cs
74 lines (62 loc) · 2.08 KB
/
LayoutGroupRefresher.cs
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
using UnityEngine;
using UnityEngine.UI;
using System.Collections.Generic;
/// <summary>
/// Executes the LayoutGroups in reverse order to ensure proper rendering.
/// When multiple nested LayoutGroups need updating, the default system doesn't always
/// refresh them in the correct hierarchical order. It is important to rebuild the layout from the
/// bottom up, since the parent objects will need the size of its children.
/// This should be used in scenarios where you have nested LayoutGroups and should solve the issue
/// where when you enable/disable a LayoutGroup it fails to work on the first time you toggle the state.
/// Refer to:
/// https://discussions.unity.com/t/layoutgroup-does-not-refresh-in-its-current-frame/656699/7
/// https://discussions.unity.com/t/content-size-fitter-refresh-problem/678806/18
/// </summary>
public class LayoutGroupRefresher
{
private readonly List<LayoutGroup> _layoutGroups = new();
private RectTransform _cachedRoot;
private bool _isStructureCached;
public void CacheStructure(RectTransform root)
{
if (root == null) return;
_cachedRoot = root;
_layoutGroups.Clear();
// Cache layout groups and depths in a single pass
Queue<RectTransform> queue = new();
queue.Enqueue(root);
while (queue.Count > 0)
{
var current = queue.Dequeue();
var layoutGroup = current.GetComponent<LayoutGroup>();
if (layoutGroup != null)
{
_layoutGroups.Add(layoutGroup);
}
// Enqueue children for further processing
foreach (RectTransform child in current)
{
queue.Enqueue(child);
}
}
_isStructureCached = true;
}
public void RefreshLayoutGroups(RectTransform root = null)
{
if (root != null && root != _cachedRoot)
{
CacheStructure(root);
}
if (!_isStructureCached) return;
for (int i = _layoutGroups.Count - 1; i >= 0; i--)
{
var group = _layoutGroups[i];
if (group.transform is RectTransform rectTransform)
{
LayoutRebuilder.ForceRebuildLayoutImmediate(rectTransform);
}
}
// Force rebuild the root to ensure changes propagate.
LayoutRebuilder.ForceRebuildLayoutImmediate(root);
}
}