[Script] Flippable for UI Graphics

Hey,
I’ve been needing to flip sprites for some time now and using the scale solution proved to be a bad idea when using Layout grids and such so i decided to try and write a little script to flip the vertices instead. It’s currently doing the job for me and i would like to share it so here it is…

PS: Any improvement suggestions are most welcome.

using UnityEngine;
using System.Collections;
using System.Collections.Generic;

namespace UnityEngine.UI
{
    [RequireComponent(typeof(RectTransform)), RequireComponent(typeof(Graphic)), DisallowMultipleComponent, AddComponentMenu("UI/Flippable")]
    public class UIFlippable : MonoBehaviour, IVertexModifier {
     
        [SerializeField] private bool m_Horizontal = false;
        [SerializeField] private bool m_Veritical = false;
     
        /// <summary>
        /// Gets or sets a value indicating whether this <see cref="UnityEngine.UI.UIFlippable"/> should be flipped horizontally.
        /// </summary>
        /// <value><c>true</c> if horizontal; otherwise, <c>false</c>.</value>
        public bool horizontal
        {
            get { return this.m_Horizontal; }
            set { this.m_Horizontal = value; }
        }
     
        /// <summary>
        /// Gets or sets a value indicating whether this <see cref="UnityEngine.UI.UIFlippable"/> should be flipped vertically.
        /// </summary>
        /// <value><c>true</c> if vertical; otherwise, <c>false</c>.</value>
        public bool vertical
        {
            get { return this.m_Veritical; }
            set { this.m_Veritical = value; }
        }
     
        protected void OnValidate()
        {
            this.GetComponent<Graphic>().SetVerticesDirty();
        }
     
        public void ModifyVertices(List<UIVertex> verts)
        {
            RectTransform rt = this.transform as RectTransform;
         
            for (int i = 0; i < verts.Count; ++i)
            {
                UIVertex v = verts[i];
             
                // Modify positions
                v.position = new Vector3(
                    (this.m_Horizontal ? (v.position.x + (rt.rect.center.x - v.position.x) * 2) : v.position.x),
                    (this.m_Veritical ?  (v.position.y + (rt.rect.center.y - v.position.y) * 2) : v.position.y),
                    v.position.z
                );
             
                // Apply
                verts[i] = v;
            }
        }
    }
}

Usage: Just add the script as a component to any gameobject that has a graphic on it and it should be working…

3 Likes

Thanks for share , img screen shot will help users on what exactly this script does.

Thanks a ton for this script! I knew this is what I needed and I’m a bit stunned that this isn’t built into the “new” UI system.

I had to make some changes to get it working, because IVertexModifier is now deprecated. Posting my mod script below, but maybe someone can take a look and see if you can get it working with Text? I don’t know if the original handled Text graphics ok previously, but my script doesn’t seem to. However for Images it works great, and that’s what I needed!

using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using System;

namespace UnityEngine.UI
{
    [RequireComponent(typeof(RectTransform)), RequireComponent(typeof(Graphic)), DisallowMultipleComponent, AddComponentMenu("UI/Flippable")]
    public class UIFlippable : MonoBehaviour, IMeshModifier
    {

        [SerializeField]
        private bool m_Horizontal = false;
        [SerializeField]
        private bool m_Veritical = false;

        /// <summary>
        /// Gets or sets a value indicating whether this <see cref="UnityEngine.UI.UIFlippable"/> should be flipped horizontally.
        /// </summary>
        /// <value><c>true</c> if horizontal; otherwise, <c>false</c>.</value>
        public bool horizontal
        {
            get { return this.m_Horizontal; }
            set { this.m_Horizontal = value; this.GetComponent<Graphic>().SetVerticesDirty(); }
        }

        /// <summary>
        /// Gets or sets a value indicating whether this <see cref="UnityEngine.UI.UIFlippable"/> should be flipped vertically.
        /// </summary>
        /// <value><c>true</c> if vertical; otherwise, <c>false</c>.</value>
        public bool vertical
        {
            get { return this.m_Veritical; }
            set { this.m_Veritical = value; this.GetComponent<Graphic>().SetVerticesDirty(); }
        }

        protected void OnValidate()
        {
            this.GetComponent<Graphic>().SetVerticesDirty();
        }

        public void ModifyVertices(List<UIVertex> verts)
        {
            RectTransform rt = this.transform as RectTransform;

            for (int i = 0; i < verts.Count; ++i)
            {
                UIVertex v = verts[i];

                // Modify positions
                v.position = new Vector3(
                    (this.m_Horizontal ? (v.position.x + (rt.rect.center.x - v.position.x) * 2) : v.position.x),
                    (this.m_Veritical ? (v.position.y + (rt.rect.center.y - v.position.y) * 2) : v.position.y),
                    v.position.z
                );

                // Apply
                verts[i] = v;
            }
        }


        readonly List<UIVertex> buffer = new List<UIVertex>();
        readonly List<int> indexList = new List<int>();

        public void ModifyMesh(Mesh mesh)
        {
            throw new NotImplementedException();
        }

        public void ModifyMesh(VertexHelper verts)
        {
            buffer.Clear();
            indexList.Clear();
            verts.GetUIVertexStream(buffer);
            ModifyVertices(buffer);
            for (int i = 0; i < buffer.Count; i++)
                indexList.Add(i);
            verts.AddUIVertexStream(buffer, indexList);

        }
    }
}
1 Like

Some fix for last script in method ModifyMesh(VertexHelper verts), because I had some issues with alpha and extra lines on my UI.
Text from documentation about VertexHelper.GetUIVertexStream - “Create a stream of UI vertex (in triangles) from the stream.”

According to this fixed method looks:

public void ModifyMesh(VertexHelper verts) {
    List<UIVertex> buffer = new List<UIVertex>();
    verts.GetUIVertexStream(buffer);
    ModifyVertices(buffer);
    verts.AddUIVertexTriangleStream(buffer);
}

All class code:

using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using System;

namespace UnityEngine.UI {
    [RequireComponent(typeof(RectTransform)), RequireComponent(typeof(Graphic)), DisallowMultipleComponent, AddComponentMenu("UI/Flippable")]
    public class UIFlippable : MonoBehaviour, IMeshModifier {

        [SerializeField]
        private bool m_Horizontal = false;
        [SerializeField]
        private bool m_Veritical = false;

        /// <summary>
        /// Gets or sets a value indicating whether this <see cref="UnityEngine.UI.UIFlippable"/> should be flipped horizontally.
        /// </summary>
        /// <value><c>true</c> if horizontal; otherwise, <c>false</c>.</value>
        public bool horizontal {
            get { return this.m_Horizontal; }
            set { this.m_Horizontal = value; this.GetComponent<Graphic>().SetVerticesDirty(); }
        }

        /// <summary>
        /// Gets or sets a value indicating whether this <see cref="UnityEngine.UI.UIFlippable"/> should be flipped vertically.
        /// </summary>
        /// <value><c>true</c> if vertical; otherwise, <c>false</c>.</value>
        public bool vertical {
            get { return this.m_Veritical; }
            set { this.m_Veritical = value; this.GetComponent<Graphic>().SetVerticesDirty(); }
        }

        protected void OnValidate() {
            this.GetComponent<Graphic>().SetVerticesDirty();
        }

        public void ModifyVertices(List<UIVertex> verts) {
            RectTransform rt = this.transform as RectTransform;

            for (int i = 0; i < verts.Count; ++i) {
                UIVertex v = verts[i];

                // Modify positions
                v.position = new Vector3(
                    (this.m_Horizontal ? (v.position.x + (rt.rect.center.x - v.position.x) * 2) : v.position.x),
                    (this.m_Veritical ? (v.position.y + (rt.rect.center.y - v.position.y) * 2) : v.position.y),
                    v.position.z
                );

                // Apply
                verts[i] = v;
            }
        }

        public void ModifyMesh(Mesh mesh) {
        }

        public void ModifyMesh(VertexHelper verts) {
            List<UIVertex> buffer = new List<UIVertex>();
            verts.GetUIVertexStream(buffer);
            ModifyVertices(buffer);
            verts.AddUIVertexTriangleStream(buffer);
        }
    }
}