Files
2026-02-21 16:45:37 +08:00

256 lines
5.8 KiB
C#

using UnityEngine;
[ExecuteInEditMode]
[AddComponentMenu("MegaShapes/Track")]
public class MegaTracks : MonoBehaviour
{
public MegaShape shape;
public int curve;
public float start;
public Vector3 rotate = Vector3.zero;
public bool displayspline = true;
public Vector3 linkOff = Vector3.zero;
public Vector3 linkScale = Vector3.one;
public Vector3 linkOff1 = new Vector3(0f, 1f, 0f);
public Vector3 linkPivot = Vector3.zero;
public Vector3 linkRot = Vector3.zero;
public GameObject LinkObj;
public bool RandomOrder;
public float LinkSize = 1f;
public bool dolateupdate;
public bool animate;
public float speed;
public Vector3 trackup = Vector3.up;
public bool InvisibleUpdate;
public int seed;
public bool rebuild = true;
private bool visible = true;
public bool randRot;
private float lastpos = -1f;
private Matrix4x4 tm;
private Matrix4x4 wtm;
private int linkcount;
private int remain;
private Transform[] linkobjs;
[ContextMenu("Help")]
public void Help()
{
Application.OpenURL("http://www.west-racing.com/mf/?page_id=3538");
}
private void Awake()
{
lastpos = -1f;
rebuild = true;
Rebuild();
}
private void Reset()
{
Rebuild();
}
public void Rebuild()
{
BuildTrack();
}
private void Update()
{
if (animate)
{
start += speed * Time.deltaTime;
}
if ((visible || InvisibleUpdate) && !dolateupdate)
{
BuildTrack();
}
}
private void LateUpdate()
{
if ((visible || InvisibleUpdate) && dolateupdate)
{
BuildTrack();
}
}
private void BuildTrack()
{
if (shape != null && LinkObj != null && (rebuild || lastpos != start))
{
rebuild = false;
lastpos = start;
BuildObjectLinks(shape);
}
}
private void OnBecameVisible()
{
visible = true;
}
private void OnBecameInvisible()
{
visible = false;
}
private void InitLinkObjects(MegaShape path)
{
if (LinkObj == null)
{
return;
}
float length = path.splines[curve].length;
float num = (linkOff1.y - linkOff.y) * linkScale.x * LinkSize;
linkcount = (int)(length / num);
for (int i = linkcount; i < base.gameObject.transform.childCount; i++)
{
GameObject obj = base.gameObject.transform.GetChild(i).gameObject;
if (Application.isEditor)
{
Object.DestroyImmediate(obj);
}
else
{
Object.Destroy(obj);
}
}
linkobjs = new Transform[linkcount];
if (linkcount > base.gameObject.transform.childCount)
{
for (int j = 0; j < base.gameObject.transform.childCount; j++)
{
GameObject gameObject = base.gameObject.transform.GetChild(j).gameObject;
gameObject.SetActive(true);
linkobjs[j] = gameObject.transform;
}
int childCount = base.gameObject.transform.childCount;
for (int k = childCount; k < linkcount; k++)
{
GameObject gameObject2 = new GameObject();
gameObject2.name = "Link";
GameObject linkObj = LinkObj;
if ((bool)linkObj)
{
MeshRenderer component = linkObj.GetComponent<MeshRenderer>();
Mesh sharedMesh = MegaUtils.GetSharedMesh(linkObj);
MeshRenderer meshRenderer = gameObject2.AddComponent<MeshRenderer>();
MeshFilter meshFilter = gameObject2.AddComponent<MeshFilter>();
meshFilter.sharedMesh = sharedMesh;
meshRenderer.sharedMaterial = component.sharedMaterial;
gameObject2.transform.parent = base.gameObject.transform;
linkobjs[k] = gameObject2.transform;
}
}
}
else
{
for (int l = 0; l < linkcount; l++)
{
GameObject gameObject3 = base.gameObject.transform.GetChild(l).gameObject;
gameObject3.SetActive(true);
linkobjs[l] = gameObject3.transform;
}
}
Random.seed = 0;
for (int m = 0; m < linkcount; m++)
{
GameObject linkObj2 = LinkObj;
GameObject gameObject4 = base.gameObject.transform.GetChild(m).gameObject;
MeshRenderer component2 = linkObj2.GetComponent<MeshRenderer>();
Mesh sharedMesh2 = MegaUtils.GetSharedMesh(linkObj2);
MeshRenderer component3 = gameObject4.GetComponent<MeshRenderer>();
MeshFilter component4 = gameObject4.GetComponent<MeshFilter>();
component4.sharedMesh = sharedMesh2;
component3.sharedMaterials = component2.sharedMaterials;
}
}
private void BuildObjectLinks(MegaShape path)
{
float length = path.splines[curve].length;
if (LinkSize < 0.1f)
{
LinkSize = 0.1f;
}
float num = (linkOff1.y - linkOff.y) * linkScale.x * LinkSize;
int num2 = (int)(length / num);
if (num2 != linkcount)
{
InitLinkObjects(path);
}
Quaternion identity = Quaternion.identity;
identity = Quaternion.Euler(rotate);
float num3 = start * 0.01f;
Vector3 pos = linkPivot * linkScale.x * LinkSize;
float last = num3;
Vector3 ps = Vector3.zero;
Matrix4x4 matrix4x = Matrix4x4.TRS(pos, identity, Vector3.one);
Vector3 euler = Vector3.zero;
Quaternion identity2 = Quaternion.identity;
Random.seed = seed;
for (int i = 0; i < linkcount; i++)
{
float num4 = (float)(i + 1) / (float)linkcount + num3;
Quaternion linkQuat = GetLinkQuat(num4, last, out ps, path);
last = num4;
Quaternion quaternion = Quaternion.Euler(euler);
identity2 = linkQuat * identity * quaternion;
if ((bool)linkobjs[i])
{
Matrix4x4 matrix4x2 = Matrix4x4.TRS(ps, linkQuat, Vector3.one) * matrix4x;
linkobjs[i].localPosition = matrix4x2.GetColumn(3);
linkobjs[i].localRotation = identity2;
linkobjs[i].localScale = linkScale * LinkSize;
}
if (randRot)
{
float num5 = Random.Range(0f, 1f);
euler = (int)(num5 * (float)(int)(360f / MegaUtils.LargestValue1(linkRot))) * linkRot;
}
else
{
euler += linkRot;
}
}
}
private Quaternion GetLinkQuat(float alpha, float last, out Vector3 ps, MegaShape path)
{
int k = 0;
ps = path.splines[curve].InterpCurve3D(last, shape.normalizedInterp, ref k);
Vector3 vector = path.splines[curve].InterpCurve3D(alpha, shape.normalizedInterp, ref k);
Vector3 forward = vector - ps;
return Quaternion.LookRotation(forward, trackup);
}
}