将Spline移出Plugin,以调整SplineRenderer的OnWillCameraRender
This commit is contained in:
812
Assets/Dreamteck/Splines/Components/ObjectBender.cs
Normal file
812
Assets/Dreamteck/Splines/Components/ObjectBender.cs
Normal file
@@ -0,0 +1,812 @@
|
||||
using UnityEngine;
|
||||
#if UNITY_EDITOR
|
||||
using UnityEditor;
|
||||
#endif
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
|
||||
namespace Dreamteck.Splines
|
||||
{
|
||||
[AddComponentMenu("Dreamteck/Splines/Users/Object Bender")]
|
||||
public class ObjectBender : SplineUser
|
||||
{
|
||||
public enum Axis { X, Y, Z }
|
||||
public enum NormalMode { Spline, Auto, Custom }
|
||||
public enum ForwardMode { Spline, Custom }
|
||||
public bool bend
|
||||
{
|
||||
get { return _bend; }
|
||||
set
|
||||
{
|
||||
if(_bend != value)
|
||||
{
|
||||
_bend = value;
|
||||
if (value)
|
||||
{
|
||||
UpdateReferences();
|
||||
Rebuild();
|
||||
} else Revert();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[SerializeField]
|
||||
[HideInInspector]
|
||||
private bool _bend = false;
|
||||
public Axis axis
|
||||
{
|
||||
get { return _axis; }
|
||||
set
|
||||
{
|
||||
if (spline != null && value != _axis)
|
||||
{
|
||||
_axis = value;
|
||||
UpdateReferences();
|
||||
Rebuild();
|
||||
}
|
||||
else _axis = value;
|
||||
}
|
||||
}
|
||||
|
||||
public NormalMode upMode
|
||||
{
|
||||
get { return _normalMode; }
|
||||
set
|
||||
{
|
||||
if (spline != null && value != _normalMode)
|
||||
{
|
||||
_normalMode = value;
|
||||
Rebuild();
|
||||
} else _normalMode = value;
|
||||
}
|
||||
}
|
||||
|
||||
public Vector3 customNormal
|
||||
{
|
||||
get { return _customNormal; }
|
||||
set
|
||||
{
|
||||
if (spline != null && value != _customNormal)
|
||||
{
|
||||
_customNormal = value;
|
||||
Rebuild();
|
||||
}
|
||||
else _customNormal = value;
|
||||
}
|
||||
}
|
||||
|
||||
public ForwardMode forwardMode
|
||||
{
|
||||
get { return _forwardMode; }
|
||||
set
|
||||
{
|
||||
if (spline != null && value != _forwardMode)
|
||||
{
|
||||
_forwardMode = value;
|
||||
Rebuild();
|
||||
} else _forwardMode = value;
|
||||
}
|
||||
}
|
||||
|
||||
public Vector3 customForward
|
||||
{
|
||||
get { return _customForward; }
|
||||
set
|
||||
{
|
||||
if (spline != null && value != _customForward)
|
||||
{
|
||||
_customForward = value;
|
||||
Rebuild();
|
||||
}
|
||||
else _customForward = value;
|
||||
}
|
||||
}
|
||||
[HideInInspector]
|
||||
public BendProperty[] bendProperties = new BendProperty[0];
|
||||
[SerializeField]
|
||||
[HideInInspector]
|
||||
private bool _parentIsTheSpline = false;
|
||||
[SerializeField]
|
||||
[HideInInspector]
|
||||
private TS_Bounds bounds = null;
|
||||
|
||||
[SerializeField]
|
||||
[HideInInspector]
|
||||
private Axis _axis = Axis.Z;
|
||||
[SerializeField]
|
||||
[HideInInspector]
|
||||
private NormalMode _normalMode = NormalMode.Auto;
|
||||
[SerializeField]
|
||||
[HideInInspector]
|
||||
private ForwardMode _forwardMode = ForwardMode.Spline;
|
||||
[SerializeField]
|
||||
[HideInInspector]
|
||||
[UnityEngine.Serialization.FormerlySerializedAs("_upVector")]
|
||||
private Vector3 _customNormal = Vector3.up;
|
||||
[SerializeField]
|
||||
[HideInInspector]
|
||||
private Vector3 _customForward = Vector3.forward;
|
||||
Matrix4x4 normalMatrix = new Matrix4x4();
|
||||
Quaternion bendRotation = Quaternion.identity;
|
||||
|
||||
private void GetTransformsRecursively(Transform current, ref List<Transform> transformList)
|
||||
{
|
||||
transformList.Add(current);
|
||||
foreach (Transform child in current)
|
||||
{
|
||||
GetTransformsRecursively(child, ref transformList);
|
||||
}
|
||||
}
|
||||
|
||||
private void GetObjects()
|
||||
{
|
||||
List<Transform> found = new List<Transform>();
|
||||
GetTransformsRecursively(transform, ref found);
|
||||
BendProperty[] newProperties = new BendProperty[found.Count];
|
||||
for (int i = 0; i < found.Count; i++)
|
||||
{
|
||||
CreateProperty(ref newProperties[i], found[i]);
|
||||
}
|
||||
bendProperties = newProperties;
|
||||
SplineComputer splineComponent = GetComponent<SplineComputer>();
|
||||
_parentIsTheSpline = splineComponent == spline;
|
||||
}
|
||||
|
||||
public TS_Bounds GetBounds()
|
||||
{
|
||||
return new TS_Bounds(bounds.min, bounds.max, bounds.center);
|
||||
}
|
||||
|
||||
#if UNITY_EDITOR
|
||||
public void EditorGenerateLightmapUVs()
|
||||
{
|
||||
for (int i = 0; i < bendProperties.Length; i++)
|
||||
{
|
||||
if (bendProperties[i].bendMesh)
|
||||
{
|
||||
if (bendProperties[i].filter == null) continue;
|
||||
if (bendProperties[i].filter.sharedMesh == null) continue;
|
||||
EditorUtility.DisplayProgressBar("Generating Lightmap UVS", bendProperties[i].filter.sharedMesh.name, (float)i / (bendProperties.Length - 1));
|
||||
Unwrapping.GenerateSecondaryUVSet(bendProperties[i].filter.sharedMesh);
|
||||
}
|
||||
}
|
||||
EditorUtility.ClearProgressBar();
|
||||
}
|
||||
#endif
|
||||
|
||||
private void CreateProperty(ref BendProperty property, Transform t)
|
||||
{
|
||||
property = new BendProperty(t, t == transform); //Create a new bend property for each child
|
||||
for (int i = 0; i < bendProperties.Length; i++)
|
||||
{
|
||||
//Search for properties that have the same trasform and copy their settings
|
||||
if (bendProperties[i].transform.transform == t)
|
||||
{
|
||||
property.enabled = bendProperties[i].enabled;
|
||||
property.applyRotation = bendProperties[i].applyRotation;
|
||||
property.applyScale = bendProperties[i].applyScale;
|
||||
property.bendMesh = bendProperties[i].bendMesh;
|
||||
property.bendCollider = bendProperties[i].bendCollider;
|
||||
property.generateLightmapUVs = bendProperties[i].generateLightmapUVs;
|
||||
property.colliderUpdateRate = bendProperties[i].colliderUpdateRate;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (t.transform != trs)
|
||||
{
|
||||
property.originalPosition = trs.InverseTransformPoint(t.position);
|
||||
property.originalRotation = Quaternion.Inverse(trs.rotation) * t.rotation;
|
||||
}
|
||||
}
|
||||
|
||||
private void CalculateBounds()
|
||||
{
|
||||
if (bounds == null) bounds = new TS_Bounds(Vector3.zero, Vector3.zero);
|
||||
bounds.min = bounds.max = Vector3.zero;
|
||||
for (int i = 0; i < bendProperties.Length; i++)
|
||||
{
|
||||
CalculatePropertyBounds(ref bendProperties[i]);
|
||||
}
|
||||
for (int i = 0; i < bendProperties.Length; i++)
|
||||
{
|
||||
CalculatePercents(bendProperties[i]);
|
||||
}
|
||||
}
|
||||
|
||||
private void CalculatePropertyBounds(ref BendProperty property)
|
||||
{
|
||||
if (!property.enabled) return;
|
||||
if (property.isParent && _parentIsTheSpline) return;
|
||||
if (property.transform.transform == trs)
|
||||
{
|
||||
if (0f < bounds.min.x) bounds.min.x = 0f;
|
||||
if (0f < bounds.min.y) bounds.min.y = 0f;
|
||||
if (0f < bounds.min.z) bounds.min.z = 0f;
|
||||
if (0f > bounds.max.x) bounds.max.x = 0f;
|
||||
if (0f > bounds.max.y) bounds.max.y = 0f;
|
||||
if (0f > bounds.max.z) bounds.max.z = 0f;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (property.originalPosition.x < bounds.min.x) bounds.min.x = property.originalPosition.x;
|
||||
if (property.originalPosition.y < bounds.min.y) bounds.min.y = property.originalPosition.y;
|
||||
if (property.originalPosition.z < bounds.min.z) bounds.min.z = property.originalPosition.z;
|
||||
if (property.originalPosition.x > bounds.max.x) bounds.max.x = property.originalPosition.x;
|
||||
if (property.originalPosition.y > bounds.max.y) bounds.max.y = property.originalPosition.y;
|
||||
if (property.originalPosition.z > bounds.max.z) bounds.max.z = property.originalPosition.z;
|
||||
}
|
||||
if (property.editMesh != null)
|
||||
{
|
||||
for (int n = 0; n < property.editMesh.vertices.Length; n++)
|
||||
{
|
||||
Vector3 localPos = property.transform.TransformPoint(property.editMesh.vertices[n]);
|
||||
localPos = trs.InverseTransformPoint(localPos);
|
||||
if (localPos.x < bounds.min.x) bounds.min.x = localPos.x;
|
||||
if (localPos.y < bounds.min.y) bounds.min.y = localPos.y;
|
||||
if (localPos.z < bounds.min.z) bounds.min.z = localPos.z;
|
||||
if (localPos.x > bounds.max.x) bounds.max.x = localPos.x;
|
||||
if (localPos.y > bounds.max.y) bounds.max.y = localPos.y;
|
||||
if (localPos.z > bounds.max.z) bounds.max.z = localPos.z;
|
||||
}
|
||||
}
|
||||
|
||||
if (property.editColliderMesh != null)
|
||||
{
|
||||
for (int n = 0; n < property.editColliderMesh.vertices.Length; n++)
|
||||
{
|
||||
Vector3 localPos = property.transform.TransformPoint(property.editColliderMesh.vertices[n]);
|
||||
localPos = trs.InverseTransformPoint(localPos);
|
||||
if (localPos.x < bounds.min.x) bounds.min.x = localPos.x;
|
||||
if (localPos.y < bounds.min.y) bounds.min.y = localPos.y;
|
||||
if (localPos.z < bounds.min.z) bounds.min.z = localPos.z;
|
||||
if (localPos.x > bounds.max.x) bounds.max.x = localPos.x;
|
||||
if (localPos.y > bounds.max.y) bounds.max.y = localPos.y;
|
||||
if (localPos.z > bounds.max.z) bounds.max.z = localPos.z;
|
||||
}
|
||||
}
|
||||
|
||||
if (property.originalSpline != null)
|
||||
{
|
||||
for (int n = 0; n < property.originalSpline.points.Length; n++)
|
||||
{
|
||||
Vector3 localPos = trs.InverseTransformPoint(property.originalSpline.points[n].position);
|
||||
if (localPos.x < bounds.min.x) bounds.min.x = localPos.x;
|
||||
if (localPos.y < bounds.min.y) bounds.min.y = localPos.y;
|
||||
if (localPos.z < bounds.min.z) bounds.min.z = localPos.z;
|
||||
if (localPos.x > bounds.max.x) bounds.max.x = localPos.x;
|
||||
if (localPos.y > bounds.max.y) bounds.max.y = localPos.y;
|
||||
if (localPos.z > bounds.max.z) bounds.max.z = localPos.z;
|
||||
}
|
||||
}
|
||||
bounds.CreateFromMinMax(bounds.min, bounds.max);
|
||||
}
|
||||
|
||||
public void CalculatePercents(BendProperty property)
|
||||
{
|
||||
if (property.transform.transform != trs) property.positionPercent = GetPercentage(trs.InverseTransformPoint(property.transform.position));
|
||||
else property.positionPercent = GetPercentage(Vector3.zero);
|
||||
if (property.editMesh != null)
|
||||
{
|
||||
if (property.vertexPercents.Length != property.editMesh.vertexCount) property.vertexPercents = new Vector3[property.editMesh.vertexCount];
|
||||
if (property.editColliderMesh != null)
|
||||
{
|
||||
if (property.colliderVertexPercents.Length != property.editMesh.vertexCount) property.colliderVertexPercents = new Vector3[property.editColliderMesh.vertexCount];
|
||||
}
|
||||
for (int i = 0; i < property.editMesh.vertexCount; i++)
|
||||
{
|
||||
Vector3 localVertex = property.transform.TransformPoint(property.editMesh.vertices[i]);
|
||||
localVertex = trs.InverseTransformPoint(localVertex);
|
||||
property.vertexPercents[i] = GetPercentage(localVertex);
|
||||
}
|
||||
if (property.editColliderMesh != null)
|
||||
{
|
||||
for (int i = 0; i < property.editColliderMesh.vertexCount; i++)
|
||||
{
|
||||
Vector3 localVertex = property.transform.TransformPoint(property.editColliderMesh.vertices[i]);
|
||||
localVertex = trs.InverseTransformPoint(localVertex);
|
||||
property.colliderVertexPercents[i] = GetPercentage(localVertex);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (property.splineComputer != null)
|
||||
{
|
||||
SplinePoint[] points = property.splineComputer.GetPoints();
|
||||
property.splinePointPercents = new Vector3[points.Length];
|
||||
property.primaryTangentPercents = new Vector3[points.Length];
|
||||
property.secondaryTangentPercents = new Vector3[points.Length];
|
||||
for (int i = 0; i < points.Length; i++)
|
||||
{
|
||||
property.splinePointPercents[i] = GetPercentage(trs.InverseTransformPoint(points[i].position));
|
||||
property.primaryTangentPercents[i] = GetPercentage(trs.InverseTransformPoint(points[i].tangent));
|
||||
property.secondaryTangentPercents[i] = GetPercentage(trs.InverseTransformPoint(points[i].tangent2));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void Revert()
|
||||
{
|
||||
for (int i = 0; i < bendProperties.Length; i++)
|
||||
{
|
||||
bendProperties[i].Revert();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void UpdateReferences()
|
||||
{
|
||||
if (!hasTransform)
|
||||
{
|
||||
CacheTransform();
|
||||
}
|
||||
if (_bend)
|
||||
{
|
||||
for (int i = 0; i < bendProperties.Length; i++) bendProperties[i].Revert();
|
||||
}
|
||||
GetObjects();
|
||||
CalculateBounds();
|
||||
if (_bend)
|
||||
{
|
||||
Bend();
|
||||
for (int i = 0; i < bendProperties.Length; i++)
|
||||
{
|
||||
bendProperties[i].Apply(i > 0 || trs != spline.transform);
|
||||
bendProperties[i].Update();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void GetevalResult(Vector3 percentage)
|
||||
{
|
||||
switch (axis)
|
||||
{
|
||||
case Axis.X: Evaluate(percentage.x, ref evalResult); break;
|
||||
case Axis.Y: Evaluate(percentage.y, ref evalResult); break;
|
||||
case Axis.Z: Evaluate(percentage.z, ref evalResult); break;
|
||||
}
|
||||
switch (_normalMode)
|
||||
{
|
||||
case NormalMode.Auto: evalResult.up = Vector3.Cross(evalResult.forward, evalResult.right); break;
|
||||
case NormalMode.Custom: evalResult.up = _customNormal; break;
|
||||
}
|
||||
if (_forwardMode == ForwardMode.Custom) evalResult.forward = customForward;
|
||||
Vector3 right = evalResult.right;
|
||||
|
||||
Quaternion axisRotation = Quaternion.identity;
|
||||
|
||||
switch (axis)
|
||||
{
|
||||
case Axis.Z:
|
||||
evalResult.position += right * Mathf.Lerp(bounds.min.x, bounds.max.x, percentage.x) * evalResult.size;
|
||||
evalResult.position += evalResult.up * Mathf.Lerp(bounds.min.y, bounds.max.y, percentage.y) * evalResult.size;
|
||||
break;
|
||||
case Axis.X:
|
||||
axisRotation = Quaternion.Euler(0f, -90f, 0f);
|
||||
evalResult.position += right * Mathf.Lerp(bounds.max.z, bounds.min.z, percentage.z) * evalResult.size;
|
||||
evalResult.position += evalResult.up * Mathf.Lerp(bounds.min.y, bounds.max.y, percentage.y) * evalResult.size;
|
||||
break;
|
||||
case Axis.Y:
|
||||
axisRotation = Quaternion.Euler(90f, 0f, 0f);
|
||||
evalResult.position += right * Mathf.Lerp(bounds.min.x, bounds.max.x, percentage.x) * evalResult.size;
|
||||
evalResult.position += evalResult.up * Mathf.Lerp(bounds.min.z, bounds.max.z, percentage.z) * evalResult.size;
|
||||
break;
|
||||
}
|
||||
|
||||
bendRotation = evalResult.rotation * axisRotation;
|
||||
normalMatrix = Matrix4x4.TRS(evalResult.position, bendRotation, Vector3.one * evalResult.size).inverse.transpose;
|
||||
}
|
||||
|
||||
private Vector3 GetPercentage(Vector3 point)
|
||||
{
|
||||
point.x = Mathf.InverseLerp(bounds.min.x, bounds.max.x, point.x);
|
||||
point.y = Mathf.InverseLerp(bounds.min.y, bounds.max.y, point.y);
|
||||
point.z = Mathf.InverseLerp(bounds.min.z, bounds.max.z, point.z);
|
||||
return point;
|
||||
}
|
||||
|
||||
protected override void Build()
|
||||
{
|
||||
base.Build();
|
||||
if (_bend) Bend();
|
||||
}
|
||||
|
||||
private void Bend()
|
||||
{
|
||||
if (sampleCount <= 1) return;
|
||||
if (bendProperties.Length == 0) return;
|
||||
for (int i = 0; i < bendProperties.Length; i++)
|
||||
{
|
||||
BendObject(bendProperties[i]);
|
||||
}
|
||||
}
|
||||
|
||||
public void BendObject(BendProperty p)
|
||||
{
|
||||
if (!p.enabled) return;
|
||||
if (p.isParent && _parentIsTheSpline) return;
|
||||
GetevalResult(p.positionPercent);
|
||||
p.transform.position = evalResult.position;
|
||||
if (p.applyRotation)
|
||||
{
|
||||
//p.transform.rotation = evalResult.rotation * axisRotation * p.originalRotation;
|
||||
p.transform.rotation = bendRotation * (Quaternion.Inverse(p.parentRotation) * p.originalRotation);
|
||||
} else p.transform.rotation = p.originalRotation;
|
||||
if (p.applyScale) p.transform.scale = p.originalScale * evalResult.size;
|
||||
|
||||
Matrix4x4 toLocalMatrix = Matrix4x4.TRS(p.transform.position, p.transform.rotation, p.transform.scale).inverse;
|
||||
if (p.editMesh != null)
|
||||
{
|
||||
BendMesh(p.vertexPercents, p.normals, p.editMesh, toLocalMatrix);
|
||||
p.editMesh.hasUpdate = true;
|
||||
}
|
||||
|
||||
if (p._editColliderMesh != null)
|
||||
{
|
||||
BendMesh(p.colliderVertexPercents, p.colliderNormals, p.editColliderMesh, toLocalMatrix);
|
||||
p.editColliderMesh.hasUpdate = true;
|
||||
}
|
||||
|
||||
if (p.originalSpline != null && !p.isParent)
|
||||
{
|
||||
for (int n = 0; n < p.splinePointPercents.Length; n++)
|
||||
{
|
||||
SplinePoint point = p.originalSpline.points[n];
|
||||
GetevalResult(p.splinePointPercents[n]);
|
||||
point.position = evalResult.position;
|
||||
GetevalResult(p.primaryTangentPercents[n]);
|
||||
point.tangent = evalResult.position;
|
||||
GetevalResult(p.secondaryTangentPercents[n]);
|
||||
point.tangent2 = evalResult.position;
|
||||
switch (axis)
|
||||
{
|
||||
case Axis.X: point.normal = Quaternion.LookRotation(evalResult.forward, evalResult.up) * Quaternion.FromToRotation(Vector3.up, evalResult.up) * point.normal; break;
|
||||
case Axis.Y: point.normal = Quaternion.LookRotation(evalResult.forward, evalResult.up) * Quaternion.FromToRotation(Vector3.up, evalResult.up) * point.normal; break;
|
||||
case Axis.Z: point.normal = Quaternion.LookRotation(evalResult.forward, evalResult.up) * point.normal; break;
|
||||
}
|
||||
p.destinationSpline.points[n] = point;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void BendMesh(Vector3[] vertexPercents, Vector3[] originalNormals, TS_Mesh mesh, Matrix4x4 worldToLocalMatrix)
|
||||
{
|
||||
if(mesh.vertexCount != vertexPercents.Length)
|
||||
{
|
||||
Debug.LogError("Vertex count mismatch");
|
||||
return;
|
||||
}
|
||||
for (int i = 0; i < mesh.vertexCount; i++)
|
||||
{
|
||||
Vector3 percent = vertexPercents[i];
|
||||
if (axis == Axis.Y) percent.z = 1f - percent.z;
|
||||
GetevalResult(percent);
|
||||
mesh.vertices[i] = worldToLocalMatrix.MultiplyPoint3x4(evalResult.position);
|
||||
mesh.normals[i] = worldToLocalMatrix.MultiplyVector(normalMatrix.MultiplyVector(originalNormals[i]));
|
||||
}
|
||||
}
|
||||
|
||||
protected override void PostBuild()
|
||||
{
|
||||
base.PostBuild();
|
||||
if (!_bend) return;
|
||||
for (int i = 0; i < bendProperties.Length; i++)
|
||||
{
|
||||
bendProperties[i].Apply(i > 0 || trs != spline.transform);
|
||||
bendProperties[i].Update();
|
||||
}
|
||||
}
|
||||
|
||||
protected override void LateRun()
|
||||
{
|
||||
base.LateRun();
|
||||
for (int i = 0; i < bendProperties.Length; i++)
|
||||
{
|
||||
bendProperties[i].Update();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
[System.Serializable]
|
||||
public class BendProperty
|
||||
{
|
||||
public bool enabled = true;
|
||||
public bool isValid
|
||||
{
|
||||
get
|
||||
{
|
||||
return transform != null && transform.transform != null;
|
||||
}
|
||||
}
|
||||
public TS_Transform transform;
|
||||
public bool applyRotation = true;
|
||||
public bool applyScale = true;
|
||||
public bool bendMesh
|
||||
{
|
||||
get { return _bendMesh; }
|
||||
set
|
||||
{
|
||||
if (value != _bendMesh)
|
||||
{
|
||||
_bendMesh = value;
|
||||
if (value)
|
||||
{
|
||||
if (filter != null && filter.sharedMesh != null)
|
||||
{
|
||||
normals = originalMesh.normals;
|
||||
for (int i = 0; i < normals.Length; i++) normals[i] = transform.transform.TransformDirection(normals[i]);
|
||||
}
|
||||
} else RevertMesh();
|
||||
}
|
||||
}
|
||||
}
|
||||
public bool generateLightmapUVs = false;
|
||||
public bool bendCollider
|
||||
{
|
||||
get { return _bendCollider; }
|
||||
set
|
||||
{
|
||||
if (value != _bendCollider)
|
||||
{
|
||||
_bendCollider = value;
|
||||
if (value)
|
||||
{
|
||||
if (collider != null && collider.sharedMesh != null && collider.sharedMesh != originalMesh) colliderNormals = originalColliderMesh.normals;
|
||||
}
|
||||
else RevertCollider();
|
||||
}
|
||||
}
|
||||
}
|
||||
public bool bendSpline
|
||||
{
|
||||
get { return _bendSpline; }
|
||||
set
|
||||
{
|
||||
_bendSpline = value;
|
||||
if (value)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
[SerializeField]
|
||||
[HideInInspector]
|
||||
private bool _bendMesh = true;
|
||||
[SerializeField]
|
||||
[HideInInspector]
|
||||
private bool _bendSpline = true;
|
||||
[SerializeField]
|
||||
[HideInInspector]
|
||||
private bool _bendCollider = true;
|
||||
|
||||
private float colliderUpdateDue = 0f;
|
||||
public float colliderUpdateRate = 0.2f;
|
||||
private bool updateCollider = false;
|
||||
|
||||
public Vector3 originalPosition = Vector3.zero;
|
||||
public Vector3 originalScale = Vector3.one;
|
||||
public Quaternion originalRotation = Quaternion.identity;
|
||||
public Quaternion parentRotation = Quaternion.identity;
|
||||
public Vector3 positionPercent;
|
||||
|
||||
public Vector3[] vertexPercents = new Vector3[0];
|
||||
public Vector3[] normals = new Vector3[0];
|
||||
public Vector3[] colliderVertexPercents = new Vector3[0];
|
||||
public Vector3[] colliderNormals = new Vector3[0];
|
||||
|
||||
[SerializeField]
|
||||
[HideInInspector]
|
||||
private Mesh originalMesh = null;
|
||||
[SerializeField]
|
||||
[HideInInspector]
|
||||
private Mesh originalColliderMesh = null;
|
||||
private Spline _originalSpline;
|
||||
|
||||
[SerializeField]
|
||||
[HideInInspector]
|
||||
private Mesh destinationMesh = null;
|
||||
[SerializeField]
|
||||
[HideInInspector]
|
||||
private Mesh destinationColliderMesh = null;
|
||||
public Spline destinationSpline;
|
||||
|
||||
public TS_Mesh editMesh
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!bendMesh || originalMesh == null) _editMesh = null;
|
||||
else if (_editMesh == null && originalMesh != null) _editMesh = new TS_Mesh(originalMesh);
|
||||
return _editMesh;
|
||||
}
|
||||
}
|
||||
public TS_Mesh editColliderMesh
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!bendCollider || originalColliderMesh == null) _editColliderMesh = null;
|
||||
else if (_editColliderMesh == null && originalColliderMesh != null && originalColliderMesh != originalMesh) _editColliderMesh = new TS_Mesh(originalColliderMesh);
|
||||
return _editColliderMesh;
|
||||
}
|
||||
}
|
||||
public Spline originalSpline
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!bendSpline || splineComputer == null) _originalSpline = null;
|
||||
else if (_originalSpline == null && splineComputer != null) {
|
||||
_originalSpline = new Spline(splineComputer.type);
|
||||
_originalSpline.points = splineComputer.GetPoints();
|
||||
}
|
||||
return _originalSpline;
|
||||
}
|
||||
}
|
||||
|
||||
public TS_Mesh _editMesh = null;
|
||||
public TS_Mesh _editColliderMesh = null;
|
||||
|
||||
public MeshFilter filter = null;
|
||||
public MeshCollider collider = null;
|
||||
public SplineComputer splineComputer = null;
|
||||
|
||||
public Vector3[] splinePointPercents = new Vector3[0];
|
||||
public Vector3[] primaryTangentPercents = new Vector3[0];
|
||||
public Vector3[] secondaryTangentPercents = new Vector3[0];
|
||||
|
||||
[SerializeField]
|
||||
[HideInInspector]
|
||||
private bool parent = false;
|
||||
|
||||
public bool isParent {
|
||||
get { return parent; }
|
||||
}
|
||||
|
||||
|
||||
public BendProperty(Transform t, bool parent = false)
|
||||
{
|
||||
this.parent = parent;
|
||||
transform = new TS_Transform(t);
|
||||
originalPosition = t.localPosition;
|
||||
originalScale = t.localScale;
|
||||
originalRotation = t.localRotation;
|
||||
parentRotation = t.transform.rotation;
|
||||
if (t.transform.parent != null) parentRotation = t.transform.parent.rotation;
|
||||
filter = t.GetComponent<MeshFilter>();
|
||||
collider = t.GetComponent<MeshCollider>();
|
||||
if (filter != null && filter.sharedMesh != null)
|
||||
{
|
||||
originalMesh = filter.sharedMesh;
|
||||
normals = originalMesh.normals;
|
||||
for (int i = 0; i < normals.Length; i++) normals[i] = transform.transform.TransformDirection(normals[i]).normalized;
|
||||
}
|
||||
|
||||
if (collider != null && collider.sharedMesh != null)
|
||||
{
|
||||
originalColliderMesh = collider.sharedMesh;
|
||||
colliderNormals = originalColliderMesh.normals;
|
||||
for (int i = 0; i < colliderNormals.Length; i++) colliderNormals[i] = transform.transform.TransformDirection(colliderNormals[i]);
|
||||
}
|
||||
if (!parent) splineComputer = t.GetComponent<SplineComputer>();
|
||||
if (splineComputer != null)
|
||||
{
|
||||
if (splineComputer.isClosed) originalSpline.Close();
|
||||
destinationSpline = new Spline(originalSpline.type);
|
||||
destinationSpline.points = new SplinePoint[originalSpline.points.Length];
|
||||
destinationSpline.points = splineComputer.GetPoints();
|
||||
if (splineComputer.isClosed) destinationSpline.Close();
|
||||
}
|
||||
}
|
||||
|
||||
public void Revert()
|
||||
{
|
||||
if (!isValid) return;
|
||||
RevertTransform();
|
||||
RevertCollider();
|
||||
RevertMesh();
|
||||
if (splineComputer != null) splineComputer.SetPoints(_originalSpline.points);
|
||||
}
|
||||
|
||||
private void RevertMesh()
|
||||
{
|
||||
if (filter != null) filter.sharedMesh = originalMesh;
|
||||
destinationMesh = null;
|
||||
}
|
||||
|
||||
private void RevertTransform()
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
if (!Application.isPlaying)
|
||||
{
|
||||
transform.transform.localPosition = originalPosition;
|
||||
transform.transform.localRotation = originalRotation;
|
||||
}
|
||||
else
|
||||
{
|
||||
transform.localPosition = originalPosition;
|
||||
transform.localRotation = originalRotation;
|
||||
transform.Update();
|
||||
}
|
||||
#else
|
||||
transform.localPosition = originalPosition;
|
||||
transform.localRotation = originalRotation;
|
||||
transform.Update();
|
||||
#endif
|
||||
transform.scale = originalScale;
|
||||
transform.Update();
|
||||
}
|
||||
|
||||
private void RevertCollider()
|
||||
{
|
||||
if (collider != null) collider.sharedMesh = originalColliderMesh;
|
||||
destinationColliderMesh = null;
|
||||
}
|
||||
|
||||
public void Apply(bool applyTransform)
|
||||
{
|
||||
if (!enabled) return;
|
||||
if (!isValid) return;
|
||||
if(applyTransform) transform.Update();
|
||||
if (editMesh != null && editMesh.hasUpdate) ApplyMesh();
|
||||
if (bendCollider && collider != null)
|
||||
{
|
||||
if (!updateCollider)
|
||||
{
|
||||
if((editColliderMesh == null && editMesh != null) || editColliderMesh != null)
|
||||
{
|
||||
updateCollider = true;
|
||||
if(Application.isPlaying) colliderUpdateDue = Time.time + colliderUpdateRate;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (splineComputer != null) ApplySpline();
|
||||
}
|
||||
|
||||
public void Update()
|
||||
{
|
||||
if (Time.time >= colliderUpdateDue && updateCollider)
|
||||
{
|
||||
updateCollider = false;
|
||||
ApplyCollider();
|
||||
}
|
||||
}
|
||||
|
||||
private void ApplyMesh()
|
||||
{
|
||||
if (filter == null) return;
|
||||
MeshUtility.CalculateTangents(editMesh);
|
||||
if (destinationMesh == null)
|
||||
{
|
||||
destinationMesh = new Mesh();
|
||||
destinationMesh.name = originalMesh.name;
|
||||
}
|
||||
|
||||
editMesh.WriteMesh(ref destinationMesh);
|
||||
destinationMesh.RecalculateBounds();
|
||||
filter.sharedMesh = destinationMesh;
|
||||
}
|
||||
|
||||
private void ApplyCollider()
|
||||
{
|
||||
if (collider == null) return;
|
||||
if (originalColliderMesh == originalMesh) collider.sharedMesh = filter.sharedMesh; //if the collider has the same mesh as the filter - just copy it
|
||||
else
|
||||
{
|
||||
MeshUtility.CalculateTangents(editColliderMesh);
|
||||
if (destinationColliderMesh == null)
|
||||
{
|
||||
destinationColliderMesh = new Mesh();
|
||||
destinationColliderMesh.name = originalColliderMesh.name;
|
||||
}
|
||||
editColliderMesh.WriteMesh(ref destinationColliderMesh);
|
||||
destinationColliderMesh.RecalculateBounds();
|
||||
collider.sharedMesh = destinationColliderMesh;
|
||||
}
|
||||
}
|
||||
|
||||
private void ApplySpline()
|
||||
{
|
||||
if (destinationSpline == null) return;
|
||||
splineComputer.SetPoints(destinationSpline.points);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user