Star.cs
using System;
using UnityEngine;
[ExecuteInEditMode,RequireComponent(typeof(MeshFilter), typeof(MeshRenderer))]
public class Star : MonoBehaviour {
[Serializable]
public class Point {
public Color color;
public Vector3 offset;
}
public Point[] points;
public int frequency = 1;
public Color centerColor;
private Mesh mesh;
private Vector3[] vertices;
private Color[] colors;
private int[] triangles;
public void UpdateStar()
{
GetComponent<MeshFilter>().mesh = mesh = new Mesh();
mesh.name = "Star Mesh";
if (frequency < 1)
{
frequency = 1;
}
if (points == null || points.Length == 0)
{
points = new Point[] { new Point() };
}
int numberOfPoints = frequency * points.Length;
vertices = new Vector3[numberOfPoints + 1];
colors = new Color[numberOfPoints + 1];
triangles = new int[numberOfPoints * 3];
float angle = -360f / numberOfPoints;
colors[0] = new Color(centerColor.r, centerColor.g, centerColor.b, centerColor.a); ;
for (int iF = 0, v = 1, t = 1; iF < frequency; iF++)
{
for (int iP = 0; iP < points.Length; iP += 1, v += 1, t += 3)
{
vertices[v] = Quaternion.Euler(0f, 0f, angle * (v - 1)) * points[iP].offset;
colors[v] = new Color(points[iP].color.r, points[iP].color.g, points[iP].color.b, points[iP].color.a);
triangles[t] = v;
triangles[t + 1] = v + 1;
}
}
triangles[triangles.Length - 1] = 1;
mesh.vertices = vertices;
mesh.colors = colors;
mesh.triangles = triangles;
}
void OnEnable () {
UpdateStar();
}
//void Update()
//{
// if (Application.isEditor)
// {
// UpdateStar();
// }
//}
void Reset()
{
UpdateStar();
}
void OnDisable()
{
if (Application.isEditor)
{
GetComponent<MeshFilter>().mesh = null;
DestroyImmediate(mesh);
}
}
}
Star.shader
Shader "Star"{
SubShader{
Tags{ "Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent"}
Blend SrcAlpha OneMinusSrcAlpha
Cull Off
Lighting Off
ZWrite Off
Pass{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
struct data {
float4 vertex : POSITION;
fixed4 color: COLOR;
};
data vert (data v) {
v.vertex = mul(UNITY_MATRIX_MVP, v.vertex);
return v;
}
fixed4 frag(data f) : COLOR {
return f.color;
}
ENDCG
}
}
}
StarInspector.cs
using UnityEditor;
using UnityEngine;
[CanEditMultipleObjects, CustomEditor(typeof(Star))]
public class StarInspector : Editor {
private static Vector3 pointSnap = Vector3.one * 0.1f;
private static GUIContent
insertContent = new GUIContent("+", "duplicate this point"),
deleteContent = new GUIContent("-", "delete this point"),
pointContent = GUIContent.none,
teleportContent = new GUIContent("T");
private static GUILayoutOption
buttonWidth = GUILayout.MaxWidth(20f),
colorWidth = GUILayout.MaxWidth(50f);
private SerializedObject star;
private SerializedProperty
points,
frequency,
centerColor;
private int teleportingElement;
void OnEnable () {
star = new SerializedObject(targets);
points = star.FindProperty("points");
frequency = star.FindProperty("frequency");
centerColor = star.FindProperty("centerColor");
teleportingElement = -1;
teleportContent.tooltip = "start teleporting this point";
}
public override void OnInspectorGUI () {
star.Update();
GUILayout.Label("Points");
for(int i = 0; i < points.arraySize; i++){
SerializedProperty
point = points.GetArrayElementAtIndex(i),
offset = point.FindPropertyRelative("offset");
if(offset == null){
break;
}
EditorGUILayout.BeginHorizontal();
EditorGUILayout.PropertyField(offset, pointContent);
EditorGUILayout.PropertyField(point.FindPropertyRelative("color"), pointContent, colorWidth);
if(GUILayout.Button(teleportContent, EditorStyles.miniButtonLeft, buttonWidth)){
if(teleportingElement >= 0){
points.MoveArrayElement(teleportingElement, i);
teleportingElement = -1;
teleportContent.tooltip = "start teleporting this point";
}
else{
teleportingElement = i;
teleportContent.tooltip = "teleport here";
}
}
if(GUILayout.Button(insertContent, EditorStyles.miniButtonMid, buttonWidth)){
points.InsertArrayElementAtIndex(i);
}
if(GUILayout.Button(deleteContent, EditorStyles.miniButtonRight, buttonWidth)){
points.DeleteArrayElementAtIndex(i);
}
EditorGUILayout.EndHorizontal();
}
if(teleportingElement >= 0){
GUILayout.Label("teleporting point " + teleportingElement);
}
EditorGUILayout.PropertyField(frequency);
EditorGUILayout.PropertyField(centerColor);
if(
star.ApplyModifiedProperties() ||
(Event.current.type == EventType.ValidateCommand &&
Event.current.commandName == "UndoRedoPerformed")
){
foreach(Star s in targets){
if(PrefabUtility.GetPrefabType(s) != PrefabType.Prefab){
s.UpdateStar();
}
}
}
}
void OnSceneGUI()
{
Star star = (Star)target;
Transform starTrans = star.transform;
Undo.RecordObject(star, "Move star transform");
float angle = -360 / (star.frequency * star.points.Length);
for (int i =0;i<star.points.Length;++i)
{
Quaternion rotation = Quaternion.Euler(0,0,angle *i);
Vector3 oldPoint = starTrans.TransformPoint(rotation * star.points[i].offset),
newPoint = Handles.FreeMoveHandle(oldPoint, Quaternion.identity, 0.05f, pointSnap, Handles.DotCap);
if (oldPoint != newPoint)
{
star.points[i].offset = Quaternion.Inverse(rotation) * starTrans.InverseTransformPoint(newPoint);
star.UpdateStar();
}
}
}
}