using System; using System.Collections.Generic; using System.Linq; using System.Text; using CommonUI.Data; using UnityEngine; using UnityEngine.UI; using CommonUI_Unity3D.Impl; using BaseVertexEffect = UnityEngine.UI.BaseMeshEffect; namespace CommonUnity3D.UGUI { //--------------------------------------------------------------------------------------------------- public class TextGraphics : Text, ITextComponent { public enum UnderlineStyle { Sequence = 0, Fill = 1, Sliced = 2, } public static string DefaultUnderlineChar = "_"; public static UnderlineStyle DefaultUnderlineType = UnderlineStyle.Fill; private DisplayNode mBinding; private BaseVertexEffect mTextEffect; private CommonUI.Data.TextAnchor mTextAnchor = CommonUI.Data.TextAnchor.L_T; private static readonly UIVertex[] m_TempVerts = new UIVertex[4]; [SerializeField] private Vector2 m_TextOffset = new Vector2(); [SerializeField] private Color m_FontColor = Color.white; [SerializeField] private bool m_IsUnderline = false; [SerializeField] private string m_UnderlineChar = DefaultUnderlineChar; [SerializeField] private UnderlineStyle m_UnderlineType = DefaultUnderlineType; public DisplayNode Binding { get { return mBinding; } } public BaseVertexEffect TextEffect { get { return mTextEffect; } } public string Text { get { return this.text; } set { if (value == null) value = ""; if (value != this.text) { this.text = value; } } } public int FontSize { get { return this.fontSize; } set { this.fontSize = value; } } public UnityEngine.Color FontColor { get { return m_FontColor; } set { if (m_FontColor != value) { m_FontColor = value; value.a = base.color.a * value.a; base.color = value; } } } public Vector2 TextOffset { get { return m_TextOffset; } set { if (value != m_TextOffset) { m_TextOffset = value; base.SetVerticesDirty(); } } } public CommonUI.Data.TextAnchor Anchor { get { return mTextAnchor; } set { this.mTextAnchor = value; this.alignment = UIUtils.ToUnityAnchor(value); } } public CommonUI.Data.FontStyle Style { get { return (CommonUI.Data.FontStyle)base.fontStyle; } set { base.fontStyle = (UnityEngine.FontStyle)value; } } public bool IsUnderline { get { return m_IsUnderline; } set { if (value != m_IsUnderline) { m_IsUnderline = value; base.SetVerticesDirty(); } } } public string UnderlineChar { get { return m_UnderlineChar; } set { if (value != m_UnderlineChar) { m_UnderlineChar = value; base.SetVerticesDirty(); } } } public UnderlineStyle UnderlineType { get { return m_UnderlineType; } set { if (value != m_UnderlineType) { m_UnderlineType = value; base.SetVerticesDirty(); } } } public Vector2 PreferredSize { get { return new Vector2(base.preferredWidth, base.preferredHeight); } } public Rect LastCaretPosition { get { return new Rect(mBinding.Width, 0, UIFactory.Instance.DefaultCaretSize.x, mBinding.Height); } } public TextGraphics() { this.font = UIFactory.Instance.DefaultFont; this.fontSize = 24; this.fontStyle = UnityEngine.FontStyle.Normal; this.color = Color.white; this.resizeTextForBestFit = true; this.resizeTextMinSize = UIFactory.Instance.DefaultFontBestFitMin; this.resizeTextMaxSize = UIFactory.Instance.DefaultFontBestFitMax; this.horizontalOverflow = HorizontalWrapMode.Overflow; this.verticalOverflow = VerticalWrapMode.Overflow; //this.RegisterDirtyVerticesCallback(()=> { OnRefreshUnderline(); }); } protected override void Start() { this.mBinding = DisplayNode.AsDisplayNode(gameObject); base.Start(); } public UnityEngine.UI.Outline AddBorder(UnityEngine.Color bc, Vector2 distance) { if (mTextEffect != null) { Component.Destroy(mTextEffect); } if (distance != Vector2.zero) { UnityEngine.UI.Outline border = base.gameObject.AddComponent(); border.effectColor = bc; border.effectDistance = new Vector2(distance.x, -distance.y); this.mTextEffect = border; return border; } return null; } public UnityEngine.UI.Shadow AddShadow(UnityEngine.Color bc, Vector2 distance) { if (mTextEffect != null) { Component.Destroy(mTextEffect); } if (distance != Vector2.zero) { UnityEngine.UI.Shadow shadow = base.gameObject.AddComponent(); shadow.effectColor = bc; shadow.effectDistance = new Vector2(distance.x, -distance.y); this.mTextEffect = shadow; return shadow; } return null; } public void SetBorder(Color bc, Vector2 distance) { AddBorder(bc, distance); } public void SetShadow(Color bc, Vector2 distance) { AddShadow(bc, distance); } public void SetFont(UnityEngine.Font font) { this.font = font; } public void SetTextFont(UnityEngine.Font font, int size, UnityEngine.FontStyle style) { this.font = font; this.fontSize = size; this.fontStyle = style; } protected override void OnPopulateMesh(VertexHelper vh) { base.OnPopulateMesh(vh); if (m_IsUnderline) { this.OnPopulateUnderlineMesh(vh); } if (m_TextOffset != Vector2.zero) { this.OnPopulateOffset(vh); } } protected virtual void OnPopulateOffset(VertexHelper vh) { if (font == null) { return; } Vector3 offset = new Vector3(m_TextOffset.x, -m_TextOffset.y); var vertex = UIVertex.simpleVert; for (int i = vh.currentVertCount - 1; i >= 0; --i) { vh.PopulateUIVertex(ref vertex, i); vertex.position += offset; vh.SetUIVertex(vertex, i); } } protected virtual void OnPopulateUnderlineMesh(VertexHelper vh) { if (font == null) { return; } if (vh.currentVertCount >= 4) { this.m_DisableFontTextureRebuiltCallback = true; Vector2 size = base.rectTransform.rect.size; TextGenerationSettings generationSettings = this.GetGenerationSettings(size); this.cachedTextGenerator.Populate(m_UnderlineChar, generationSettings); IList verts = this.cachedTextGenerator.verts; int num = verts.Count - 4; if (num >= 4) { UICharInfo dchar = this.cachedTextGenerator.characters[0]; if (dchar.charWidth > 0) { UIVertex begin_vertex = UIVertex.simpleVert; UIVertex end_vertex = UIVertex.simpleVert; vh.PopulateUIVertex(ref begin_vertex, 0); vh.PopulateUIVertex(ref end_vertex, vh.currentVertCount - 2); float d = 1f / this.pixelsPerUnit; switch (m_UnderlineType) { case UnderlineStyle.Fill: { for (int j = 0; j < 4; j++) { m_TempVerts[j] = verts[j]; m_TempVerts[j].position = m_TempVerts[j].position * d; } m_TempVerts[0].position.x = m_TempVerts[3].position.x = begin_vertex.position.x; m_TempVerts[1].position.x = m_TempVerts[2].position.x = end_vertex.position.x; vh.AddUIVertexQuad(m_TempVerts); } break; case UnderlineStyle.Sequence: for (float x = begin_vertex.position.x; x < end_vertex.position.x; x += dchar.charWidth) { for (int j = 0; j < 4; j++) { m_TempVerts[j] = verts[j]; m_TempVerts[j].position = m_TempVerts[j].position * d; m_TempVerts[j].position.x += x; } vh.AddUIVertexQuad(m_TempVerts); } break; case UnderlineStyle.Sliced: { float u_clip = Math.Abs(verts[1].uv0.x - verts[0].uv0.x) / 3;//将u切成3份// float x_clip = (dchar.charWidth) / 3;//将x切成3份// float u_0 = verts[0].uv0.x; float u_1 = u_0 + u_clip; float u_3 = verts[1].uv0.x; float u_2 = u_3 - u_clip; float x_0 = begin_vertex.position.x; float x_1 = x_0 + x_clip; float x_3 = end_vertex.position.x; float x_2 = x_3 - x_clip; for (int i = m_TempVerts.Length - 1; i >= 0; --i) { m_TempVerts[i] = verts[i]; m_TempVerts[i].position = m_TempVerts[i].position * d; } // left { m_TempVerts[3].position.x = m_TempVerts[0].position.x = x_0; m_TempVerts[2].position.x = m_TempVerts[1].position.x = x_1; m_TempVerts[3].uv0.x = m_TempVerts[0].uv0.x = u_0; m_TempVerts[2].uv0.x = m_TempVerts[1].uv0.x = u_1; vh.AddUIVertexQuad(m_TempVerts); } // center { m_TempVerts[3].position.x = m_TempVerts[0].position.x = x_1; m_TempVerts[2].position.x = m_TempVerts[1].position.x = x_2; m_TempVerts[3].uv0.x = m_TempVerts[0].uv0.x = u_1; m_TempVerts[2].uv0.x = m_TempVerts[1].uv0.x = u_2; vh.AddUIVertexQuad(m_TempVerts); } // right { m_TempVerts[3].position.x = m_TempVerts[0].position.x = x_2; m_TempVerts[2].position.x = m_TempVerts[1].position.x = x_3; m_TempVerts[3].uv0.x = m_TempVerts[0].uv0.x = u_2; m_TempVerts[2].uv0.x = m_TempVerts[1].uv0.x = u_3; vh.AddUIVertexQuad(m_TempVerts); } } break; } } } this.m_DisableFontTextureRebuiltCallback = false; } } public override bool Raycast(Vector2 sp, Camera eventCamera) { if (mBinding.Enable && mBinding.EnableTouchInParents) { return base.Raycast(sp, eventCamera); } return false; } readonly Vector3[] m_Corners = new Vector3[4]; private Rect rootCanvasRect { get { rectTransform.GetWorldCorners(m_Corners); if (canvas) { Canvas rootCanvas = canvas.rootCanvas; for (int i = 0; i < 4; ++i) m_Corners[i] = rootCanvas.transform.InverseTransformPoint(m_Corners[i]); } return new Rect(m_Corners[0].x, m_Corners[0].y, m_Corners[2].x - m_Corners[0].x, m_Corners[2].y - m_Corners[0].y); } } public override void Cull(Rect clipRect, bool validRect) { var cull = !validRect || !clipRect.Overlaps(rootCanvasRect, true); UpdateCull(cull); } private void UpdateCull(bool cull) { var cullingChanged = canvasRenderer.cull != cull; canvasRenderer.cull = cull; if (cullingChanged) { onCullStateChanged.Invoke(cull); SetVerticesDirty(); } } } }