[Script] Curved Layout

Here is another quicky, to create curved menus.
Add it like you would any other layout group.

Then set the item size, curve offset and center point.

/// <summary>
/// Curved Layout Group Created by Freezy - http://www.ElicitIce.com
/// Posted on Unity Forums http://forum.unity3d.com/threads/script-curved-layout.403985/
///
/// Free for any use and alteration, source code may not be sold without my permission.
/// If you make improvements on this script please share them with the community.
///
/// </summary>

namespace UnityEngine.UI.Extensions {
    /// <summary>
    /// TODO:
    /// - add automatic child sizing, like in the HorizontalOrVerticalLayoutGroup.cs
    /// - nicer anchor handling for initial child positions
    /// </summary>
    [AddComponentMenu("Layout/Extensions/Curved Layout")]
    public class CurvedLayout : LayoutGroup {
        public Vector3 CurveOffset;

        // Yes these two could be combined into a single vector
        // but this makes it easier to use?
        [Tooltip("axis along which to place the items, Normalized before use")]
        public Vector3 itemAxis;
        [Tooltip("size of each item along the Normalized axis")]
        public float itemSize;

        // the slope can be moved by altering this setting, it could be constrained to the 0-1 range, but other values are usefull for animations
        public float centerpoint = 0.5f;

        protected override void OnEnable() { base.OnEnable(); CalculateRadial(); }
        public override void SetLayoutHorizontal() {
        }
        public override void SetLayoutVertical() {
        }
        public override void CalculateLayoutInputVertical() {
            CalculateRadial();
        }
        public override void CalculateLayoutInputHorizontal() {
            CalculateRadial();
        }
#if UNITY_EDITOR
        protected override void OnValidate() {
            base.OnValidate();
            CalculateRadial();
        }
#endif

        void CalculateRadial() {
            m_Tracker.Clear();
            if (transform.childCount == 0)
                return;

            //one liner for figuring out the pivot (why not a utility function switch statement?)
            Vector2 pivot = new Vector2(((int)childAlignment % 3) * 0.5f, ((int)childAlignment / 3) * 0.5f);

            //this seems to work ok-ish
            Vector3 lastPos = new Vector3(
                GetStartOffset(0, GetTotalPreferredSize(0)),
                GetStartOffset(1, GetTotalPreferredSize(1)),
                0f
            );

            // 0 = first, 1 = last child
            float lerp = 0;
            //no need to catch divide by 0 as childCount > 0
            float step = 1f / transform.childCount;

            //normalize and create a distance between items
            var dist = itemAxis.normalized * itemSize;

            for (int i = 0; i < transform.childCount; i++) {
                RectTransform child = (RectTransform)transform.GetChild(i);
                if (child != null) {
                    //stop the user from altering certain values in the editor
                    m_Tracker.Add(this, child,
                    DrivenTransformProperties.Anchors |
                    DrivenTransformProperties.AnchoredPosition |
                    DrivenTransformProperties.Pivot);
                    Vector3 vPos = lastPos + dist;

                    child.localPosition = lastPos = vPos + (lerp - centerpoint) * CurveOffset;

                    child.pivot = pivot;
                    //child anchors are not yet calculated, each child should set it's own size for now
                    child.anchorMin = child.anchorMax = new Vector2(0.5f, 0.5f);
                    lerp += step;
                }
            }

        }
    }
}

Thanks for the great addition, will get that merged with the next update

A bit of help @Freezy
Trying out the component and hitting a snag. If I use regular UI components they seem to draw fine. However if I use any primitive or custom controls, the control doesn’t get drawn.

Not a big issue for now, but it limits what child components can be used with it.

It works fine with composite buttons, which was my intended use case.
There is still a large issue with figuring out the proper sizing information, but I didn’t need it so I skipped that part for now.

I bet that the sizing information is what is causing other elements to be rendered incorrectly.
It is open source, so maybe somewhere along the timeline I or somebody else will fix it :stuck_out_tongue:

Yup, it’s hosted here:
https://bitbucket.org/ddreaper/unity-ui-extensions/src/c9354eadf4b9287790eb636c21e4107760cd7b87/Scripts/Layout/CurvedLayout.cs?at=develop_5.3

Just fork and fix/update if you get a chance.

A bit of help @Freezy

I have a question about these two files…

https://bitbucket.org/UnityUIExtensions/unity-ui-extensions/src/release/Runtime/Scripts/Layout/CurvedLayout.cs
https://bitbucket.org/UnityUIExtensions/unity-ui-extensions/src/release/Runtime/Scripts/Primitives/UICornerCut.cs

These two files have comments like:
/// Free for any use and alteration, source code may not be sold without my permission.
/// If you make improvements on this script please share them with the community.

“unity-ui-extensions” is under BSD License, and “unity-ui-extensions” uses these two source code.
So, is it possible to use “unity-ui-extensions” in commercial SW?
you said, “source code may not be sold without my permission.”
In this case, when commercial SW wants to use “unity-ui-extensions”, is any issue to use “unity-ui-extensions” which contains “CurvedLayout.cs”, “UICornerCut.cs”