FairyGUI projection images, text, components

Disclaimer: This article is a blogger original article, follow the CC 4.0 BY-SA copyright agreement, reproduced, please attach the original source link and this statement.
This link: https://blog.csdn.net/wangjiangrong/article/details/95341797

In FairyGUI, text control that comes with the projector function, we can set the projected offset and color settings. But we want to give the students of UI pictures also add effects projection, it is impossible to be achieved. Then we threw program to help solve =. =

demand

You can add components to the projection, pictures, text projection may need to set the transparency (not present).

 

Thinking

Mo was first of all they go and change FairyGUI Editor level editor, it would have to start from the unity that. How to make unity know which components we want to set up the projector, and obtain the relevant parameters of projection. Observed that each control setting in, there is a custom set of data, we can enter some keywords in your custom data, and then when Unity parsing, processing, and thus need to know whether the control and projection Related parameters.

Then, knowing the parameters, how to achieve the projected results, start adding a Component to a UnityEngine.UI.Shadow GameObject needs of each projection GObject, and did not find anything with a soft. It comes through the original text Projection, went to see the realization of his method, find the relevant code is as follows:

//TextField.cs
public void OnPopulateMesh(VertexBuffer vb)
{
	....

	bool hasShadow = _shadowOffset.x != 0 || _shadowOffset.y != 0;
	......

	if (allocCount != count)
	{
		VertexBuffer vb2 = VertexBuffer.Begin();
		List<Vector3> vertList2 = vb2.vertices;
Y_5_2 || UNITY_5_3_OR_NEWER
		List<Vector4> uvList2 = vb2.uv0;

		List<Vector2> uvList2 = vb2.uv0;

		List<Color32> colList2 = vb2.colors;

		Color32 strokeColor = _strokeColor;
		......

		if (hasShadow)
		{
			for (int i = 0; i < count; i++)
			{
				Vector3 vert = vertList[i];
				Vector4 u = uvList[i];

				uvList2.Add(u);
				vertList2.Add(new Vector3(vert.x + _shadowOffset.x, vert.y - _shadowOffset.y, 0));
				colList2.Add(strokeColor);
			}
		}

		vb.Insert(vb2);
		vb2.End();
	}

	vb.AddTriangles();
    ......
}

Is substantially follow suit, the original vertex original text are offset (offset projection), and draw out the text color projection, and then draw the original text is superimposed thereon, in order to achieve Projection. Among them, we just modify a Boolean value strokeColor, you can reach overhead transparency effect.

 

achieve

The idea is TextField projected implementation for TextField, we only need to modify the value of strokeColor.a for GImage of Image, we need to add your own code to achieve a similar drawing projection.

File to edit five, GComponent, GImage, GObject, GTextField , NGraphics. Since then these are FairyGUI files directly change the words if the updated easily lead covering, so we can put these classes are changed to partial class then spent most of the logic code is written on the outside.

First of all, I would like to resolve our custom data set, I set the rules are as follows ShadowOffset: 5,5 | shadowAlpha: 0.5 | ShadowColor: 00FF00 , | split pairs. GObject.cs create a new file, customize the data parsing

using UnityEngine;
using System;

namespace FairyGUI
{
    public partial class GObject : EventDispatcher
	{
        bool mIsCustomShadowOffset = false;
        Vector2 mCustomShadowOffset = Vector2.zero;
        public bool IsCustomShadowOffset
        {
            get { return mIsCustomShadowOffset; }
        }
        public Vector2 CustomShadowOffset
        {
            get { return mCustomShadowOffset; }
        }

        bool mIsCustomShadowColor = false;
        Color mCustomShadowColor = Color.black;
        public bool IsCustomShadowColor
        {
            get { return mIsCustomShadowColor; }
        }
        public Color CustomShadowColor
        {
            get { return mCustomShadowColor; }
        }

        bool mIsCustomShadowAlpha = false;
        float mCustomShadowAlpha = 1f;
        public bool IsCustomShadowAlpha
        {
            get { return mIsCustomShadowAlpha; }
        }
        public float CustomShadowAlpha
        {
            get { return mCustomShadowAlpha; }
        }

        //call in AnalyUserDefineData
        public virtual void CustomAction()
        {

        }

        //call in Setup_AfterAdd
        public void AnalyUserDefineData(object data)
        {
            if (data != null && !"".Equals(data.ToString()))
            {
                string[] args = data.ToString().Split('|');
                foreach(string arg in args)
                {
                    string[] keyvalue = arg.Split(':');
                    if (keyvalue.Length != 2)
                    {
                        continue;
                    }
                    if (keyvalue[0].Equals("ShadowOffset"))
                    {
                        mIsCustomShadowOffset = true;
                        string[] array = keyvalue[1].Split(',');
                        mCustomShadowOffset = new Vector2(float.Parse(array[0]), float.Parse(array[1]));
                    }
                    if (keyvalue[0].Equals("ShadowColor"))
                    {
                        mIsCustomShadowColor = true;
                        mCustomShadowColor = GetColorByHex(keyvalue[1]);
                    }
                    if (keyvalue[0].Equals("ShadowAlpha"))
                    {
                        mIsCustomShadowAlpha = true;
                        mCustomShadowAlpha = float.Parse(keyvalue[1]);
                    }
                }

                if (mIsCustomShadowAlpha && mIsCustomShadowColor)
                {
                    mCustomShadowColor.a = mCustomShadowAlpha;
                }

                CustomAction();
            }
        }

        //format:FF000
        Color GetColorByHex(string v)
        {
            if(v.Length == 6)
            {
                try
                {
                    float r = Convert.ToInt32($"{v[0]}{v[1]}", 16) / 255.0f;
                    float g = Convert.ToInt32($"{v[2]}{v[3]}", 16) / 255.0f;
                    float b = Convert.ToInt32($"{v[4]}{v[5]}", 16) / 255.0f;
                    return new Color(r, g, b);
                }
                catch
                {
                    return Color.black;
                }
            }
            return Color.black;
        }
    }
}

Wherein CustomAction After parsing data operation, will be implemented in a particular implementation and GTextField GImage later, the main information is parsed, re-assigned to other data subclass.

Then finally Setup_AfterAdd method of calling a GObject FairyGUI

AnalyUserDefineData(this.data);

So that you can get to the projection information for each of the GObject. Get the projection information, we're going to change the draw process components, first add a drop shadow transparency from the most simple text messages began.

GTextField.cs create a new file, you can then modify GTextField.strokeColor. as follows:

using UnityEngine;

namespace FairyGUI
{
    public partial class GTextField : GObject, ITextColorGear
    {
        //call in CustomAction
        void InitCustomSetting()
        {
            if (IsCustomShadowOffset)
            {
                
                this.shadowOffset = CustomShadowOffset;
            }
            if (IsCustomShadowColor)
            {
                this.strokeColor = CustomShadowColor;
            }
            else
            {
                if (IsCustomShadowAlpha)
                {
                    Color c = this.strokeColor;
                    c.a = CustomShadowAlpha;
                    this.strokeColor = c;
                }
            }
        }

        public override void CustomAction()
        {
            InitCustomSetting();
        }
    }
}

Results are as follows

We provided with two projections in FairyGUI text, a first projection green, red second projection, wherein the second customized data ShadowAlpha: 0.5 | ShadowColor: 00FF00

Unity after the release of results is as follows (color and alpha are in force)

Followed by a more complex picture projection process, now only deal with squared maps and pictures of the ordinary projection, we all look the specific code, posted here under the code changes.

First create NGraphics.cs file for record projection information (text of these fields such as GTextField.shadowOffset and GTextField.strokeColor), we need to create your own picture

using System.Collections.Generic;
using UnityEngine;

namespace FairyGUI
{
    public partial class NGraphics : IMeshFactory
    {
        bool mIsCustomShadowOffset = false;
        Vector2 mCustomShadowOffset = Vector2.zero;
        Color mCustomShadowColor = Color.black;

        //call in GImage CustomAction
        public void InitCustomShadow(Vector2 offset, Color c)
        {
            mIsCustomShadowOffset = true;
            mCustomShadowOffset = offset;
            mCustomShadowColor = c;
        }

        //call in NGraphics OnPopulateMesh
        //call in Image SliceFill
        public bool AddCustomShadow(VertexBuffer vb)
        {
            if (mIsCustomShadowOffset)
            {
                VertexBuffer vb2 = VertexBuffer.Begin();
                List<Vector3> vertList2 = vb2.vertices;
#if UNITY_5_2 || UNITY_5_3_OR_NEWER
                List<Vector4> uvList2 = vb2.uv0;
#else
                List<Vector2> uvList2 = vb2.uv0;
#endif
                List<Color32> colList2 = vb2.colors;

                for (int i = 0; i < vb.vertices.Count; i++)
                {
                    Vector3 vert = vb.vertices[i];
                    Vector4 u = vb.uv0[i];

                    uvList2.Add(u);
                    vertList2.Add(new Vector3(vert.x + mCustomShadowOffset.x, vert.y - mCustomShadowOffset.y, 0));
                    colList2.Add(mCustomShadowColor);
                }
                vb.Insert(vb2);
                vb2.End();
                return true;
            }
            return false;
        }
    }
}

Then create GImage.cs, to pass information to NGraphics GObject, that InitCustomShadow call the above method.

namespace FairyGUI
{
    public partial class GImage : GObject, IColorGear
    {
        public override void CustomAction()
        {
            if (IsCustomShadowOffset)
            {
                _content.graphics.InitCustomShadow(CustomShadowOffset, CustomShadowColor);
            }
        }
    }
}

Then we need to add logic projected in two places, namely call AddCustomShadow method of NGraphics. Ordinary picture called OnPopulateMesh method of NGraphics

public partial class NGraphics : IMeshFactory
{
    ...

    public void OnPopulateMesh(VertexBuffer vb)
    {
        Rect rect = texture.GetDrawRect(vb.contentRect);

        vb.AddQuad(rect, vb.vertexColor, vb.uvRect);

        AddCustomShadow(vb);

        vb.AddTriangles();
        vb._isArbitraryQuad = vertexMatrix != null;
    }
}

Pictures squared method called SliceFill Image of

public class Image : DisplayObject, IMeshFactory
{
		public void SliceFill(VertexBuffer vb)
		{
				for (int pi = 0; pi < 9; pi++)
				{
					...
				}

                if (graphics.AddCustomShadow(vb))
                {
                    vb.AddTriangles(TRIANGLES_9_GRID);
                    vb.AddTriangles(TRIANGLES_9_GRID, 16);
                }
                else
                {
                    vb.AddTriangles(TRIANGLES_9_GRID);
                }

                vb.AddTriangles();
		}
}

FIG effect as follows (purple ShadowAlpha projection disposed added: 0.5 | ShadowColor: 00FF00 | ShadowOffset: 5,5)

Finally, in addition to pictures and text, may be some custom components we need projection, but the internal components have a lot of elements, add one by one might be too much trouble, so we can GComponent, if the parent component has set up the projector information, subassemblies not, then automatically inherit it.

GComponent.cs a new document, which added a method for recursive inheritance Custom Data (GComponent subcomponents may be GComponent)

using System;
#if FAIRYGUI_TOLUA
using LuaInterface;
#endif

namespace FairyGUI
{
    /// <summary>
    /// Component
    /// </summary>
    public partial class GComponent : GObject
    {
        //call in ConstructFromResource, after child.Setup_BeforeAdd(buffer, curPos);
        void AnalyUserDefineDataToChild(GObject obj)
        {
            if (obj.data != null)
            {
                GComponent com = obj as GComponent;
                if (com != null)
                {
                    GObject[] array = com.GetChildren();
                    for (int j = 0; j < array.Length; j++)
                    {
                        if (array[j].data == null)
                        {
                            GComponent childCom = array[j] as GComponent;
                            if (childCom != null)
                            {
                                array[j].data = obj.data;
                                //if child is GComponent,for example GList, recursion 
                                AnalyUserDefineDataToChild(array[j]);
                            }
                            else
                            {
                                array[j].AnalyUserDefineData(obj.data);
                            }
                        }
                    }
                }
            }
        }
    }
}

Finally, we can call in ConstructFromResource method GComponent in.

public partial class GComponent : GObject
{
	.....

	internal void ConstructFromResource(List<GObject> objectPool, int poolIndex)
	{
		......

		child.underConstruct = true;
		child.Setup_BeforeAdd(buffer, curPos);

        AnalyUserDefineDataToChild(child);

        child.InternalSetParent(this);
		_children.Add(child);

		buffer.position = curPos + dataLen;

		......
    }

	......
}

 

Guess you like

Origin blog.csdn.net/wangjiangrong/article/details/95341797