Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using Unity.Mathematics;
- using UnityEngine;
- using UnityEngine.Splines;
- #if UNITY_EDITOR
- using UnityEditor;
- #endif
- namespace sc.modeling.splines.runtime.auxiliary
- {
- //This component can exposed connections, to which the start/end of a spline can be attached.
- //Useful to link two splines together, or to create intersections
- public class SplineJunction : MonoBehaviour
- {
- public Vector3 offset;
- [Serializable]
- public class Connection
- {
- public SplineContainer splineContainer;
- public enum Target
- {
- Start,
- End
- }
- public Target connect;
- [Space]
- public Vector3 position;
- public Vector3 rotation;
- [Space]
- [Min(0.01f)]
- [Tooltip("Control how strongly the spline gets aligned to the connection. This is essentially the knot tangent.")]
- public float stiffness = 5f;
- }
- public List<Connection> connections = new List<Connection>();
- private void Reset()
- {
- Connection a = new Connection();
- a.position.z = -1f;
- a.rotation.y = 180f;
- a.stiffness = 5f;
- a.connect = Connection.Target.Start;
- Connection b = new Connection();
- b.position.z = 1f;
- b.rotation.y = 0f;
- b.stiffness = 5f;
- b.connect = Connection.Target.End;
- connections.Add(a);
- connections.Add(b);
- }
- public void Reconnect()
- {
- foreach (Connection connection in connections)
- {
- if(connection.splineContainer == null) continue;
- Vector3 worldPos = this.transform.TransformPoint(connection.position + offset);
- Vector3 localPos = connection.splineContainer.transform.InverseTransformPoint(worldPos);
- int knotIndex = connection.connect == Connection.Target.Start ? 0 : connection.splineContainer.Splines[0].Knots.Count()-1;
- BezierKnot knot = connection.splineContainer.Splines[0].Knots.ElementAt(knotIndex);
- knot.Position = localPos;
- knot.Rotation = (this.transform.rotation) * Quaternion.Euler(connection.rotation);
- BezierTangent tangentType;
- if (connection.connect == Connection.Target.Start)
- {
- tangentType = BezierTangent.Out;
- knot.TangentOut = new float3(0f, 0f, connection.stiffness);
- }
- else
- {
- tangentType = BezierTangent.In;
- knot.TangentIn = new float3(0f, 0f, connection.stiffness);
- }
- connection.splineContainer.Splines[0].SetKnot(knotIndex, knot, tangentType);
- connection.splineContainer.Splines[0].SetTangentMode(knotIndex, TangentMode.Continuous);
- }
- }
- private void OnDrawGizmos()
- {
- DrawGizmos(false);
- }
- private void OnDrawGizmosSelected()
- {
- DrawGizmos(true);
- }
- private void DrawGizmos(bool selected)
- {
- #if UNITY_EDITOR
- Gizmos.matrix = this.transform.localToWorldMatrix;
- float handleSize = 0.2f;
- handleSize *= HandleUtility.GetHandleSize(this.transform.position);
- Handles.matrix = Gizmos.matrix;
- if (selected)
- {
- if (transform.hasChanged)
- {
- transform.hasChanged = false;
- Reconnect();
- }
- }
- foreach (Connection connection in connections)
- {
- if (!selected)
- {
- //Make the junction selectable
- Gizmos.color = Color.cyan;
- //Gizmos.color = Color.clear;
- Gizmos.DrawCube(connection.position, Vector3.one * handleSize);
- }
- else
- {
- Gizmos.color = connection.splineContainer == null ? Color.red : Color.green;
- Gizmos.DrawWireCube(connection.position + offset, Vector3.one * handleSize);
- Vector3 normal = (Quaternion.Euler(connection.rotation) * Vector3.forward).normalized;
- Handles.color = Gizmos.color;
- Handles.DrawAAPolyLine(Texture2D.whiteTexture, 3f, new []{ connection.position, connection.position + normal});
- }
- }
- #endif
- }
- }
- #if UNITY_EDITOR
- [CustomEditor(typeof(SplineJunction))]
- [CanEditMultipleObjects]
- public class SplineJunctionInspector : Editor
- {
- [MenuItem("GameObject/Spline/Junction", false, 1000)]
- private static void AddObjectMenu()
- {
- GameObject gameObject = new GameObject("Spline Junction", new []{typeof(SplineJunction)});
- if (Selection.activeGameObject) gameObject.transform.parent = Selection.activeGameObject.transform;
- Selection.activeGameObject = gameObject;
- EditorApplication.ExecuteMenuItem("GameObject/Move To View");
- if(Application.isPlaying == false) UnityEditor.SceneManagement.EditorSceneManager.MarkSceneDirty(UnityEngine.SceneManagement.SceneManager.GetActiveScene());
- }
- public override void OnInspectorGUI()
- {
- EditorGUI.BeginChangeCheck();
- base.OnInspectorGUI();
- if (EditorGUI.EndChangeCheck())
- {
- foreach (var m_target in targets)
- ((SplineJunction)m_target).Reconnect();
- }
- }
- }
- #endif
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement