使用
- 挂载LineChart.cs
- 点击autoCreate按钮,会创建子节点,可以在子节点上挂载自定义控件
实现
LineChart.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace ViVi.UIExtensions
{
[ExecuteInEditMode]
[RequireComponent(typeof(PTLineChartRender))]
public class LineChart : MonoBehaviour
{
public GameObject[] childNode;
void Awake()
{
}
// Update is called once per frame
void Update()
{
GameObject go;
Vector2 size = GetComponent<RectTransform>().rect.size;
LineChartRender render = GetComponent<LineChartRender>();
for (int i = 0; i < childNode.Length; i++)
{
go = childNode[i];
if(go!=null)
{
go.GetComponent<RectTransform>().anchoredPosition = new Vector2((size.x / (render.values.Length-1)) * i - size.x*0.5f ,size.y * render.values[i]- size.y*0.5f);
}
}
}
}
}
LineChartRender.cs
using UnityEngine;
using UnityEngine.UI;
namespace ViVi.UIExtensions{
public class LineChartRender : MaskableGraphic {
[Range (0f, 1f)]
public float[] values = new float[2]{1,1};
public Color BottomColor = Color.white;
public Color TopColor = Color.white;
public bool useEdge = false;
public bool useLine = false;
[Range (0f, 2.5f)]
public float lineWidth = 1.0f;
[Range (0f, 2.5f)]
public float edgeWidth = 1.0f;
public Color lineColor = Color.black;
public Color edgeColor = Color.black;
protected override void OnPopulateMesh(VertexHelper vh)
{
Vector2 size = GetComponent<RectTransform>().rect.size;
vh.Clear();
int partCount = values.Length;
float spx = size.x / (float) (partCount - 1);
float nx = 0;
float nx1 = 0;
float height = size.y;
float sph = size.y * 0.5f;
float spw = size.x * 0.5f;
for (int i = 0; i < partCount - 1; i++)
{
nx = spx * i - spw;
nx1 = nx + spx;
float x1= (float)i/(float)partCount;
float x2= (float)(i+1)/(float)partCount;
//UIVertex[] vertexs = new UIVertex[4];
UIVertex v1 = UIVertex.simpleVert;
UIVertex v2 = UIVertex.simpleVert;
UIVertex v3 = UIVertex.simpleVert;
UIVertex v4 = UIVertex.simpleVert;
v1.position = new Vector2(nx, height * values[i] - sph);
v2.position = new Vector2(nx, -sph);
v3.position = new Vector2(nx1, -sph);
v4.position = new Vector2(nx1, height * values[i + 1] - sph);
v1.color = Color.Lerp(BottomColor, TopColor, values[i]);
v2.color = Color.Lerp(BottomColor, TopColor, 0);
v3.color = Color.Lerp(BottomColor, TopColor, 0);
v4.color = Color.Lerp(BottomColor, TopColor, values[i+ 1]);
v1.uv0 = new Vector2(x1,values[i]);
v2.uv0 = new Vector2(x1,0);
v3.uv0 = new Vector2(x2,0);
v4.uv0 = new Vector2(x2,values[i+ 1]);
if (useLine)
{
if(i==0)
vh.AddUIVertexQuad (GetLine (v1.position, v2.position,lineColor,lineWidth));
vh.AddUIVertexQuad (GetLine (v3.position, v4.position,lineColor,lineWidth));
}
vh.AddUIVertexQuad(new UIVertex[4]{v4,v3,v2,v1});
if (useEdge)
{
vh.AddUIVertexQuad (GetLine (v1.position, v4.position,edgeColor,edgeWidth));
}
}
}
private UIVertex[] GetLine (Vector2 start, Vector2 end ,Color lcolor ,float lwidth) {
UIVertex[] vs = new UIVertex[4];
Vector2[] uv = new Vector2[4];
uv[0] = new Vector2(0, 0);
uv[1] = new Vector2(0, 1);
uv[2] = new Vector2(1, 0);
uv[3] = new Vector2(1, 1);
Vector2 v1 = end - start;
Vector2 v2 = (v1.y == 0f) ? new Vector2 (0f, 1f) : new Vector2 (1f, -v1.x / v1.y);
v2.Normalize ();
v2 *= lwidth / 2f;
Vector2[] pos = new Vector2[4];
pos[0] = start + v2;
pos[1] = end + v2;
pos[2] = end - v2;
pos[3] = start - v2;
for (int i = 0; i < 4; i++) {
UIVertex v = UIVertex.simpleVert;
v.color = lcolor;
v.position = pos[i];
v.uv0 = uv[i];
vs[i] = v;
}
return vs;
}
}
}
Editor 编辑器扩展
LineChartEditor.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
namespace ViVi.UIExtensions
{
[CustomEditor(typeof(LineChart))]
[CanEditMultipleObjects]
public class LineChartEditor: Editor
{
SerializedProperty childNode;
private LineChart lineChart;
void OnEnable()
{
lineChart = (LineChart) target;
childNode = serializedObject.FindProperty("childNode");
}
public override void OnInspectorGUI()
{
serializedObject.Update();
DrawDefaultInspector();
if (GUILayout.Button("Auto Create"))
{
LineChartRender render = null;
render = lineChart.gameObject.GetComponent<LineChartRender>();
childNode.ClearArray();
childNode.arraySize = 0;
GameObject go;
Vector2 size = lineChart.GetComponent<RectTransform>().rect.size;
for (int i = 0; i < render.values.Length; i++)
{
Transform tf = lineChart.transform.FindChild("v" + i);
RectTransform rect;
if (tf == null)
{
go = new GameObject();
rect = go.AddComponent<RectTransform>();
go.name = "v" + i;
//go.transform.parent = lineChart.transform;
rect.SetParent(lineChart.transform,false);
}
else
{
go = tf.gameObject;
rect = tf.GetComponent<RectTransform>();
}
rect.localScale = Vector3.one;
rect.localRotation = Quaternion.identity;
rect.pivot = new Vector2(0.5f,0.5f);
rect.sizeDelta = new Vector2(10,10);
rect.anchoredPosition = new Vector2((size.x / (render.values.Length-1)) * i - size.x*0.5f ,size.y * render.values[i]- size.y*0.5f);
childNode.arraySize += 1;
SerializedProperty npc =childNode.GetArrayElementAtIndex(childNode.arraySize-1);
npc.objectReferenceValue = go;
serializedObject.ApplyModifiedProperties();
}
}
if (GUILayout.Button("Clean Child"))
{
childNode.ClearArray();
childNode.arraySize = 0;
List<GameObject> child = new List<GameObject>();
for (int i = 0; i < lineChart.transform.childCount; i++)
{
child.Add(lineChart.transform.GetChild(i).gameObject);
}
for (int i = 0; i < child.Count; i++)
{
GameObject.DestroyImmediate(child[i]);
}
child.Clear();
serializedObject.ApplyModifiedProperties();
}
}
}
}