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/FlexalonLayoutBase.cs | 157 ++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 157 insertions(+), 0 deletions(-)
diff --git a/Assets/Flexalon/Runtime/Core/FlexalonLayoutBase.cs b/Assets/Flexalon/Runtime/Core/FlexalonLayoutBase.cs
new file mode 100644
index 0000000..ef0a63f
--- /dev/null
+++ b/Assets/Flexalon/Runtime/Core/FlexalonLayoutBase.cs
@@ -0,0 +1,157 @@
+using UnityEngine;
+
+namespace Flexalon
+{
+ /// <summary>
+ /// Base class for all layout componets. See [custom layout](/docs/customLayout) for details
+ /// on how to extend this class. Assigns the Layout method to FlexalonNode and keeps the
+ /// node's children up to date.
+ /// </summary>
+ [DisallowMultipleComponent, RequireComponent(typeof(FlexalonObject))]
+ public abstract class LayoutBase : FlexalonComponent, Layout
+ {
+ /// <inheritdoc />
+ protected override void DoOnEnable()
+ {
+ _node.DetachAllChildren();
+ for (int i = 0; i < transform.childCount; i++)
+ {
+ _node.AddChild(Flexalon.GetOrCreateNode(transform.GetChild(i).gameObject));
+ }
+
+ Flexalon.GetOrCreate().PreUpdate += DetectChanges;
+ _node.SetMethod(this);
+ }
+
+ /// <inheritdoc />
+ protected override void DoOnDisable()
+ {
+ _node.SetMethod(null);
+ var flexalon = Flexalon.Get();
+ if (flexalon)
+ {
+ flexalon.PreUpdate -= DetectChanges;
+ }
+ }
+
+ /// <inheritdoc />
+ protected override void ResetProperties()
+ {
+ _node.DetachAllChildren();
+ }
+
+ // This function is complicated because it's working around two issues.
+ // First, OnTransformChildrenChanged doesn't always run on 2019.4 due to a bug.
+ // See https://issuetracker.unity3d.com/issues/ontransformchildrenchanged-doesnt-get-called-in-the-edit-mode-when-dragging-a-prefab-from-the-project-window-to-the-hierarchy
+ // Second, we need to deal with undo/redo. The strategy here is to do nothing on undo/redo except fix
+ // the node.Children list, since it isn't serialzed. To detect undo/redo, we check if the Parent or SiblingIndex
+ // values change in the serialized FlexalonResult matches the transform children.
+ private void DetectChanges()
+ {
+ // Check if any old children changed parents. They need to be marked dirty
+ // since their size may change after leaving the layout.
+ for (int i = 0; i < _node.Children.Count; i++)
+ {
+ var childNode = _node.Children[i];
+ if (!childNode.GameObject)
+ {
+ Flexalon.RecordFrameChanges = true;
+ childNode.Detach();
+ MarkDirty();
+ }
+ else if (childNode.GameObject.transform.parent != transform || childNode.IsDragging || childNode.SkipLayout || childNode.Constraint != null)
+ {
+ i--;
+ childNode.Detach();
+ if (childNode.Result.Parent == transform)
+ {
+#if UNITY_EDITOR
+ UnityEditor.Undo.RecordObject(childNode.Result, "Parent change");
+ UnityEditor.PrefabUtility.RecordPrefabInstancePropertyModifications(childNode.Result);
+ Flexalon.RecordFrameChanges = true;
+#endif
+ childNode.Result.Parent = null;
+ childNode.Result.SiblingIndex = 0;
+ childNode.MarkDirty();
+ MarkDirty();
+ }
+ }
+ }
+
+ // Check if we have any new or out of order children.
+ int index = 0;
+ for (int i = 0; i < transform.childCount; i++)
+ {
+ var child = transform.GetChild(i);
+ var childNode = Flexalon.GetOrCreateNode(child.gameObject);
+ if (childNode.IsDragging || childNode.SkipLayout || childNode.Constraint != null)
+ {
+ continue;
+ }
+
+ _node.InsertChild(childNode, index);
+ if (childNode.Result.Parent != transform || childNode.Result.SiblingIndex != index)
+ {
+#if UNITY_EDITOR
+ UnityEditor.Undo.RecordObject(childNode.Result, "Parent change");
+ UnityEditor.PrefabUtility.RecordPrefabInstancePropertyModifications(childNode.Result);
+ Flexalon.RecordFrameChanges = true;
+#endif
+ childNode.Result.Parent = transform;
+ childNode.Result.SiblingIndex = index;
+
+ childNode.MarkDirty();
+ MarkDirty();
+ }
+
+ index++;
+ }
+ }
+
+ protected override void Initialize()
+ {
+ base.Initialize();
+
+ if (!gameObject.TryGetComponent<FlexalonObject>(out var obj))
+ {
+ obj = Flexalon.AddComponent<FlexalonObject>(gameObject);
+ }
+
+ if (!Flexalon.IsRootCanvas(gameObject))
+ {
+ if (obj.WidthType == SizeType.Component)
+ {
+ obj.WidthType = SizeType.Layout;
+ }
+
+ if (obj.HeightType == SizeType.Component)
+ {
+ obj.HeightType = SizeType.Layout;
+ }
+
+ if (obj.DepthType == SizeType.Component)
+ {
+ obj.DepthType = SizeType.Layout;
+ }
+ }
+ }
+
+ /// <inheritdoc />
+ public virtual Bounds Measure(FlexalonNode node, Vector3 size, Vector3 min, Vector3 max)
+ {
+ throw new System.NotImplementedException();
+ }
+
+ /// <summary> Helper to assign the fill and shrink size for all children. </summary>
+ protected void SetChildrenFillShrinkSize(FlexalonNode node, Vector3 childSize, Vector3 layoutSize)
+ {
+ foreach (var child in node.Children)
+ {
+ child.SetShrinkFillSize(childSize, layoutSize);
+ }
+ }
+
+ /// <inheritdoc />
+ public virtual void Arrange(FlexalonNode node, Vector3 layoutSize) {}
+ }
+}
\ No newline at end of file
--
Gitblit v1.10.0