using CommonUI.Gemo; using CommonUI_Unity3D.Impl; using System; using System.Collections.Generic; using System.Linq; using System.Text; using UnityEngine; using UnityEngine.UI; namespace CommonUnity3D.UGUI { public class BatchQuadsGraphics : UnityEngine.UI.MaskableGraphic { private DisplayNode mBinding; private Texture2D mTexture; private CommonUI.Cell.CPJAtlas mAtlas; CommonUI_Unity3D.Impl.UnityImage mSrc; private List<BatchImageQuad> mQuads = new List<BatchImageQuad>(); public override Texture mainTexture { get { return mTexture; } } public DisplayNode Binding { get { return mBinding; } } public CommonUI.Cell.CPJAtlas Atlas { get { return mAtlas; } set { mSrc = value.GetTile(0) as CommonUI_Unity3D.Impl.UnityImage; this.mAtlas = value; this.mTexture = mSrc.Texture2D; this.material = mSrc.TextureMaterial; base.SetAllDirty(); } } public BatchImageQuad[] Quads { get { return mQuads.ToArray(); } } public int QuadsCount { get { return mQuads.Count; } } public BatchImageQuad GetQuad(int i) { return mQuads[i]; } public void SetQuadVisible(int i, bool visible) { if (i >= 0 && i < mQuads.Count) { var b = mQuads[i]; if (b.visible != visible) { b.visible = visible; mQuads[i] = b; base.SetVerticesDirty(); } } } public void SetQuad(int i, BatchImageQuad quad) { if (i >= 0 && i < mQuads.Count) { mQuads[i] = quad; base.SetVerticesDirty(); } } public int AddQuad(BatchImageQuad qd) { int ret = mQuads.Count; mQuads.Add(qd); base.SetVerticesDirty(); return ret; } public int AddQuad(int index) { int ret = mQuads.Count; mQuads.Add(new BatchImageQuad(index)); base.SetVerticesDirty(); return ret; } public int AddQuad(int index, CommonUI.Data.ImageAnchor anchor, Vector2 pivot, Vector2 offset, Vector2 scale, float rotate) { int ret = mQuads.Count; var qd = new BatchImageQuad(index); qd.anchor = anchor; qd.pivot = pivot; qd.offset = offset; qd.scale = scale; qd.rotate = rotate; mQuads.Add(qd); base.SetVerticesDirty(); return ret; } public int AddQuadByKey(string key, CommonUI.Data.ImageAnchor anchor, Vector2 pivot, Vector2 offset, Vector2 scale, float rotate) { int index = mAtlas.GetIndexByKey(key); if (index >= 0) { return AddQuad(index, anchor, pivot, offset, scale, rotate); } return index; } public int AddQuadImageFont(string text) { int ret = mQuads.Count; var qd = new BatchImageQuad(text); mQuads.Add(qd); base.SetVerticesDirty(); return ret; } public int AddQuadImageFont(string text, CommonUI.Data.ImageAnchor anchor, Vector2 pivot, Vector2 offset, Vector2 scale, float rotate) { int ret = mQuads.Count; var qd = new BatchImageQuad(text); qd.anchor = anchor; qd.pivot = pivot; qd.offset = offset; qd.scale = scale; qd.rotate = rotate; mQuads.Add(qd); base.SetVerticesDirty(); return ret; } public void ClearQuads() { if (mQuads.Count > 0) { mQuads.Clear(); base.SetVerticesDirty(); } } public BatchQuadsGraphics() { this.material = ImageGraphics.DefaultImageMaterial; } protected override void Start() { this.mBinding = DisplayNode.AsDisplayNode(gameObject); base.Start(); } protected override void OnPopulateMesh(VertexHelper vh) { vh.Clear(); if (mAtlas != null) { uint rgba = UIUtils.Color_To_UInt32_RGBA(base.color); using (VertexHelperBuffer vertex = VertexHelperBuffer.AllocAutoRelease(vh)) { for (int i = 0; i < mQuads.Count; ++i) { var batch = mQuads[i]; if (batch.visible) { vertex.pushTransform(); if (!string.IsNullOrEmpty(batch.text)) { OnPopulateText(vertex, ref batch, rgba); } else if (batch.index >= 0) { OnPopulateTile(vertex, ref batch, rgba); } vertex.popTransform(); } } } } } protected virtual void OnPopulateTile(VertexHelperBuffer vertex, ref BatchImageQuad batch, uint rgba) { var rect = new Rect(0, 0, mAtlas.getWidth(batch.index), mAtlas.getHeight(batch.index)); var pivot = new Vector2(rect.width * batch.pivot.x, rect.height * batch.pivot.y); UIUtils.AdjustAnchor(batch.anchor, rectTransform.sizeDelta, ref rect); vertex.translate(rect.x + pivot.x + batch.offset.x, rect.y + pivot.y + batch.offset.y); vertex.scale(batch.scale.x, batch.scale.y); vertex.rotate(batch.rotate); mAtlas.addVertex(vertex, batch.index, -pivot.x, -pivot.y, 0, rgba); } protected virtual void OnPopulateText(VertexHelperBuffer vertex, ref BatchImageQuad batch, uint rgba) { var size = ImageFontGraphics.GetImageFontPreferredSize(mAtlas, batch.text); var rect = new Rect(0, 0, size.x, size.y); var pivot = new Vector2(rect.width * batch.pivot.x, rect.height * batch.pivot.y); UIUtils.AdjustAnchor(batch.anchor, rectTransform.sizeDelta, ref rect); vertex.translate(rect.x + pivot.x + batch.offset.x, rect.y + pivot.y + batch.offset.y); vertex.scale(batch.scale.x, batch.scale.y); vertex.rotate(batch.rotate); float sw = 0; for (int i = 0; i < batch.text.Length; i++) { char ch = batch.text[i]; int index = mAtlas.GetIndexByKey(ch.ToString()); if (index >= 0) { Vector2 char_size = new Vector2(mAtlas.getWidth(index), mAtlas.getHeight(index)); if (char_size.x > 0) { mAtlas.addVertex(vertex, index, sw - pivot.x, 0 - pivot.y, 0, rgba); sw += char_size.x; } } } } public override bool Raycast(Vector2 sp, Camera eventCamera) { if (mBinding.Enable && mBinding.EnableTouchInParents) { return base.Raycast(sp, eventCamera); } return false; } public struct BatchImageQuad { /// <summary> /// 图片索引 /// </summary> public int index; /// <summary> /// 图片字,不为空起效 /// </summary> public string text; /// <summary> /// 是否显示 /// </summary> public bool visible; /// <summary> /// 对其方式 /// </summary> public CommonUI.Data.ImageAnchor anchor; /// <summary> /// 旋转缩放参考点 /// </summary> public Vector2 pivot; /// <summary> /// 坐标 /// </summary> public Vector2 offset; /// <summary> /// 缩放 /// </summary> public Vector2 scale; /// <summary> /// 旋转 /// </summary> public float rotate; public BatchImageQuad(int index) { this.index = index; this.text = null; this.visible = true; this.anchor = CommonUI.Data.ImageAnchor.C_C; this.pivot = new Vector2(.5f, .5f); this.offset = Vector2.zero; this.scale = Vector2.one; this.rotate = 0; } public BatchImageQuad(string text) { this.index = -1; this.text = text; this.visible = true; this.anchor = CommonUI.Data.ImageAnchor.C_C; this.pivot = new Vector2(.5f, .5f); this.offset = Vector2.zero; this.scale = Vector2.one; this.rotate = 0; } } private void ResetTexture() { if (mSrc != null && mSrc.Texture2D != mTexture) { this.mTexture = mSrc.Texture2D; this.material = mSrc.TextureMaterial; base.SetAllDirty(); } } protected override void OnEnable() { base.OnEnable(); ResetTexture(); } void Update() { ResetTexture(); } } }