using System.Collections.Generic; using System.Linq; using UnityEngine; namespace SplineMesh { [ExecuteInEditMode] [SelectionBase] [DisallowMultipleComponent] public class SplineBending : MonoBehaviour { private GameObject generated; private Spline spline; private bool toUpdate; [Tooltip("Mesh to bend along the spline.")] public Mesh mesh; [Tooltip("Material to apply on the bent mesh.")] public Material material; [Tooltip("Physic material to apply on the bent mesh.")] public PhysicMaterial physicMaterial; [Tooltip("Translation to apply on the mesh before bending it.")] public Vector3 translation; [Tooltip("Rotation to apply on the mesh before bending it.")] public Vector3 rotation; [Tooltip("Scale to apply on the mesh before bending it.")] public Vector3 scale = Vector3.one; [Tooltip("If true, a mesh collider will be generated.")] public bool generateCollider = true; [Tooltip("If true, the mesh will be bent on play mode. If false, the bent mesh will be kept from the editor mode, allowing lighting baking.")] public bool updateInPlayMode; [Tooltip("If true, a mesh will be placed on each curve of the spline. If false, a single mesh will be placed for the whole spline.")] public bool curveSpace; [Tooltip("The mode to use to fill the choosen interval with the bent mesh.")] public MeshBender.FillingMode mode = MeshBender.FillingMode.StretchToInterval; private void OnEnable() { string n = "generated by " + GetType().Name; Transform transform = base.transform.Find(n); generated = ((transform != null) ? transform.gameObject : UOUtility.Create(n, base.gameObject)); spline = GetComponentInParent(); spline.NodeListChanged += delegate { toUpdate = true; }; toUpdate = true; } private void OnValidate() { if (!(spline == null)) { toUpdate = true; } } private void Update() { if ((updateInPlayMode || !Application.isPlaying) && toUpdate) { toUpdate = false; CreateMeshes(); } } public void CreateMeshes() { List list = new List(); if (curveSpace) { int num = 0; foreach (CubicBezierCurve curf in spline.curves) { GameObject gameObject = FindOrCreate("segment " + num++ + " mesh"); gameObject.GetComponent().SetInterval(curf); gameObject.GetComponent().enabled = generateCollider; list.Add(gameObject); } } else { GameObject gameObject2 = FindOrCreate("segment 1 mesh"); gameObject2.GetComponent().SetInterval(spline, 0f); gameObject2.GetComponent().enabled = generateCollider; list.Add(gameObject2); } foreach (GameObject item in (from Transform child in generated.transform select child.gameObject).Except(list)) { UOUtility.Destroy(item); } } private GameObject FindOrCreate(string name) { Transform transform = generated.transform.Find(name); GameObject gameObject; if (transform == null) { gameObject = UOUtility.Create(name, generated, typeof(MeshFilter), typeof(MeshRenderer), typeof(MeshBender), typeof(MeshCollider)); gameObject.isStatic = !updateInPlayMode; } else { gameObject = transform.gameObject; } gameObject.GetComponent().material = material; gameObject.GetComponent().material = physicMaterial; MeshBender component = gameObject.GetComponent(); component.Source = SourceMesh.Build(mesh).Translate(translation).Rotate(Quaternion.Euler(rotation)) .Scale(scale); component.Mode = mode; return gameObject; } } }