diff --git a/Assets/Plugins/BezierSolution.meta b/Assets/Plugins/BezierSolution.meta new file mode 100644 index 00000000..d4602db1 --- /dev/null +++ b/Assets/Plugins/BezierSolution.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 75bf1bb8530d74e468ff02c71de6a222 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/BezierSolution/Attributes.meta b/Assets/Plugins/BezierSolution/Attributes.meta new file mode 100644 index 00000000..5ae72786 --- /dev/null +++ b/Assets/Plugins/BezierSolution/Attributes.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 1e3f966a8e1c81a429b6881944ddb88a +folderAsset: yes +timeCreated: 1620639369 +licenseType: Store +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/BezierSolution/Attributes/MinMaxRangeAttribute.cs b/Assets/Plugins/BezierSolution/Attributes/MinMaxRangeAttribute.cs new file mode 100644 index 00000000..62787eed --- /dev/null +++ b/Assets/Plugins/BezierSolution/Attributes/MinMaxRangeAttribute.cs @@ -0,0 +1,71 @@ +using UnityEngine; +#if UNITY_EDITOR +using UnityEditor; +#endif + +namespace BezierSolution +{ + public class MinMaxRangeAttribute : PropertyAttribute + { + public float min; + public float max; + + public MinMaxRangeAttribute( float min, float max ) + { + this.min = min; + this.max = max; + } + } +} + +#if UNITY_EDITOR +namespace BezierSolution.Extras +{ + [CustomPropertyDrawer( typeof( MinMaxRangeAttribute ) )] + public class MixMaxRangeAttributeDrawer : PropertyDrawer + { + private const float MIN_MAX_SLIDER_TEXT_FIELD_WIDTH = 45f; + + // Min-max slider credit: https://github.com/Unity-Technologies/UnityCsReference/blob/61f92bd79ae862c4465d35270f9d1d57befd1761/Editor/Mono/Inspector/LightEditor.cs#L328-L363 + public override void OnGUI( Rect position, SerializedProperty property, GUIContent label ) + { + MinMaxRangeAttribute minMaxRange = attribute as MinMaxRangeAttribute; + + SerializedProperty minProp = property.FindPropertyRelative( "x" ); + SerializedProperty maxProp = property.FindPropertyRelative( "y" ); + + position = EditorGUI.PrefixLabel( position, label ); + EditorGUI.BeginProperty( position, GUIContent.none, property ); + + Rect minRect = new Rect( position ) { width = MIN_MAX_SLIDER_TEXT_FIELD_WIDTH }; + Rect maxRect = new Rect( position ) { xMin = position.xMax - MIN_MAX_SLIDER_TEXT_FIELD_WIDTH }; + Rect sliderRect = new Rect( position ) { xMin = minRect.xMax + 5f, xMax = maxRect.xMin - 5f }; + + EditorGUI.BeginChangeCheck(); + + EditorGUI.PropertyField( minRect, minProp, GUIContent.none ); + + Vector2 value = property.vector2Value; + EditorGUI.BeginChangeCheck(); + EditorGUI.MinMaxSlider( sliderRect, ref value.x, ref value.y, minMaxRange.min, minMaxRange.max ); + if( EditorGUI.EndChangeCheck() ) + property.vector2Value = value; + + EditorGUI.PropertyField( maxRect, maxProp, GUIContent.none ); + + if( EditorGUI.EndChangeCheck() ) + { + float x = minProp.floatValue; + float y = maxProp.floatValue; + + if( x < minMaxRange.min || x > minMaxRange.max ) + minProp.floatValue = Mathf.Clamp( x, minMaxRange.min, minMaxRange.max ); + if( y < minMaxRange.min || y > minMaxRange.max ) + maxProp.floatValue = Mathf.Clamp( y, minMaxRange.min, minMaxRange.max ); + } + + EditorGUI.EndProperty(); + } + } +} +#endif \ No newline at end of file diff --git a/Assets/Plugins/BezierSolution/Attributes/MinMaxRangeAttribute.cs.meta b/Assets/Plugins/BezierSolution/Attributes/MinMaxRangeAttribute.cs.meta new file mode 100644 index 00000000..2c394140 --- /dev/null +++ b/Assets/Plugins/BezierSolution/Attributes/MinMaxRangeAttribute.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 277efd8192415fd4fb70032186bd5ed0 +timeCreated: 1620638811 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/BezierSolution/BezierPoint.cs b/Assets/Plugins/BezierSolution/BezierPoint.cs new file mode 100644 index 00000000..fa9743ad --- /dev/null +++ b/Assets/Plugins/BezierSolution/BezierPoint.cs @@ -0,0 +1,459 @@ +using UnityEngine; + +namespace BezierSolution +{ + [AddComponentMenu( "Bezier Solution/Bezier Point" )] + [HelpURL( "https://github.com/yasirkula/UnityBezierSolution" )] + public partial class BezierPoint : MonoBehaviour + { + public Vector3 localPosition + { + get { return transform.localPosition; } + set + { + if( transform.localPosition == value ) + return; + + transform.localPosition = value; + spline.dirtyFlags |= InternalDirtyFlags.EndPointTransformChange | InternalDirtyFlags.ControlPointPositionChange; + } + } + +#pragma warning disable 0649 + [SerializeField, HideInInspector] + private Vector3 m_position; + public Vector3 position + { + get { return m_position; } + set + { + if( transform.position == value ) + return; + + transform.position = value; + spline.dirtyFlags |= InternalDirtyFlags.EndPointTransformChange | InternalDirtyFlags.ControlPointPositionChange; + } + } + + public Quaternion localRotation + { + get { return transform.localRotation; } + set + { + if( transform.localRotation == value ) + return; + + transform.localRotation = value; + spline.dirtyFlags |= InternalDirtyFlags.EndPointTransformChange | InternalDirtyFlags.ControlPointPositionChange; + } + } + + public Quaternion rotation + { + get { return transform.rotation; } + set + { + if( transform.rotation == value ) + return; + + transform.rotation = value; + spline.dirtyFlags |= InternalDirtyFlags.EndPointTransformChange | InternalDirtyFlags.ControlPointPositionChange; + } + } + + public Vector3 localEulerAngles + { + get { return transform.localEulerAngles; } + set + { + if( transform.localEulerAngles == value ) + return; + + transform.localEulerAngles = value; + spline.dirtyFlags |= InternalDirtyFlags.EndPointTransformChange | InternalDirtyFlags.ControlPointPositionChange; + } + } + + public Vector3 eulerAngles + { + get { return transform.eulerAngles; } + set + { + if( transform.eulerAngles == value ) + return; + + transform.eulerAngles = value; + spline.dirtyFlags |= InternalDirtyFlags.EndPointTransformChange | InternalDirtyFlags.ControlPointPositionChange; + } + } + + public Vector3 localScale + { + get { return transform.localScale; } + set + { + if( transform.localScale == value ) + return; + + transform.localScale = value; + spline.dirtyFlags |= InternalDirtyFlags.EndPointTransformChange | InternalDirtyFlags.ControlPointPositionChange; + } + } + + [SerializeField, HideInInspector] + private Vector3 m_precedingControlPointLocalPosition = Vector3.left; + public Vector3 precedingControlPointLocalPosition + { + get { return m_precedingControlPointLocalPosition; } + set + { + if( m_precedingControlPointLocalPosition == value ) + return; + + m_precedingControlPointLocalPosition = value; + m_precedingControlPointPosition = transform.TransformPoint( value ); + + if( m_handleMode == HandleMode.Aligned ) + { + m_followingControlPointLocalPosition = -m_precedingControlPointLocalPosition.normalized * m_followingControlPointLocalPosition.magnitude; + m_followingControlPointPosition = transform.TransformPoint( m_followingControlPointLocalPosition ); + } + else if( m_handleMode == HandleMode.Mirrored ) + { + m_followingControlPointLocalPosition = -m_precedingControlPointLocalPosition; + m_followingControlPointPosition = transform.TransformPoint( m_followingControlPointLocalPosition ); + } + + spline.dirtyFlags |= InternalDirtyFlags.ControlPointPositionChange; + } + } + + [SerializeField, HideInInspector] + private Vector3 m_precedingControlPointPosition; + public Vector3 precedingControlPointPosition + { + get { return m_precedingControlPointPosition; } + set + { + if( m_precedingControlPointPosition == value ) + return; + + m_precedingControlPointPosition = value; + m_precedingControlPointLocalPosition = transform.InverseTransformPoint( value ); + + if( transform.hasChanged ) + { + m_position = transform.position; + m_followingControlPointPosition = transform.TransformPoint( m_followingControlPointLocalPosition ); + + spline.dirtyFlags |= InternalDirtyFlags.EndPointTransformChange; + transform.hasChanged = false; + } + + if( m_handleMode == HandleMode.Aligned ) + { + m_followingControlPointPosition = m_position - ( m_precedingControlPointPosition - m_position ).normalized * + ( m_followingControlPointPosition - m_position ).magnitude; + m_followingControlPointLocalPosition = transform.InverseTransformPoint( m_followingControlPointPosition ); + } + else if( m_handleMode == HandleMode.Mirrored ) + { + m_followingControlPointPosition = 2f * m_position - m_precedingControlPointPosition; + m_followingControlPointLocalPosition = transform.InverseTransformPoint( m_followingControlPointPosition ); + } + + spline.dirtyFlags |= InternalDirtyFlags.ControlPointPositionChange; + } + } + + [SerializeField, HideInInspector] + private Vector3 m_followingControlPointLocalPosition = Vector3.right; + public Vector3 followingControlPointLocalPosition + { + get { return m_followingControlPointLocalPosition; } + set + { + if( m_followingControlPointLocalPosition == value ) + return; + + m_followingControlPointLocalPosition = value; + m_followingControlPointPosition = transform.TransformPoint( value ); + + if( m_handleMode == HandleMode.Aligned ) + { + m_precedingControlPointLocalPosition = -m_followingControlPointLocalPosition.normalized * m_precedingControlPointLocalPosition.magnitude; + m_precedingControlPointPosition = transform.TransformPoint( m_precedingControlPointLocalPosition ); + } + else if( m_handleMode == HandleMode.Mirrored ) + { + m_precedingControlPointLocalPosition = -m_followingControlPointLocalPosition; + m_precedingControlPointPosition = transform.TransformPoint( m_precedingControlPointLocalPosition ); + } + + spline.dirtyFlags |= InternalDirtyFlags.ControlPointPositionChange; + } + } + + [SerializeField, HideInInspector] + private Vector3 m_followingControlPointPosition; + public Vector3 followingControlPointPosition + { + get { return m_followingControlPointPosition; } + set + { + if( m_followingControlPointPosition == value ) + return; + + m_followingControlPointPosition = value; + m_followingControlPointLocalPosition = transform.InverseTransformPoint( value ); + + if( transform.hasChanged ) + { + m_position = transform.position; + m_precedingControlPointPosition = transform.TransformPoint( m_precedingControlPointLocalPosition ); + + spline.dirtyFlags |= InternalDirtyFlags.EndPointTransformChange; + transform.hasChanged = false; + } + + if( m_handleMode == HandleMode.Aligned ) + { + m_precedingControlPointPosition = m_position - ( m_followingControlPointPosition - m_position ).normalized * + ( m_precedingControlPointPosition - m_position ).magnitude; + m_precedingControlPointLocalPosition = transform.InverseTransformPoint( m_precedingControlPointPosition ); + } + else if( m_handleMode == HandleMode.Mirrored ) + { + m_precedingControlPointPosition = 2f * m_position - m_followingControlPointPosition; + m_precedingControlPointLocalPosition = transform.InverseTransformPoint( m_precedingControlPointPosition ); + } + + spline.dirtyFlags |= InternalDirtyFlags.ControlPointPositionChange; + } + } + + [SerializeField, HideInInspector] + private HandleMode m_handleMode = HandleMode.Mirrored; + public HandleMode handleMode + { + get { return m_handleMode; } + set + { + if( m_handleMode == value ) + return; + + m_handleMode = value; + + if( value == HandleMode.Aligned || value == HandleMode.Mirrored ) + { + // Temporarily change the value of m_precedingControlPointLocalPosition so that it will be different from precedingControlPointLocalPosition + // and precedingControlPointLocalPosition's setter will run + Vector3 _precedingControlPointLocalPosition = m_precedingControlPointLocalPosition; + m_precedingControlPointLocalPosition -= Vector3.one; + + precedingControlPointLocalPosition = _precedingControlPointLocalPosition; + } + + spline.dirtyFlags |= InternalDirtyFlags.ControlPointPositionChange; + } + } + + [SerializeField, HideInInspector] + [UnityEngine.Serialization.FormerlySerializedAs( "normal" )] + private Vector3 m_normal = Vector3.up; + public Vector3 normal + { + get { return m_normal; } + set + { + if( m_normal == value ) + return; + + m_normal = value; + spline.dirtyFlags |= InternalDirtyFlags.NormalChange; + } + } + + [SerializeField, HideInInspector] + [UnityEngine.Serialization.FormerlySerializedAs( "autoCalculatedNormalAngleOffset" )] + private float m_autoCalculatedNormalAngleOffset = 0f; + public float autoCalculatedNormalAngleOffset + { + get { return m_autoCalculatedNormalAngleOffset; } + set + { + if( m_autoCalculatedNormalAngleOffset == value ) + return; + + m_autoCalculatedNormalAngleOffset = value; + spline.dirtyFlags |= InternalDirtyFlags.NormalOffsetChange; + } + } + + [SerializeField, HideInInspector] + private Vector3[] m_intermediateNormals; + public Vector3[] intermediateNormals + { + get { return m_intermediateNormals; } + set + { + // In this special case, don't early exit if the assigned array is the same because one of its elements might have changed. + // We can safely early exit if the assigned value was null or empty, though + if( ( m_intermediateNormals == null || m_intermediateNormals.Length == 0 ) && ( value == null || value.Length == 0 ) ) + return; + + m_intermediateNormals = value; + spline.dirtyFlags |= InternalDirtyFlags.NormalChange; + } + } + + [SerializeField, HideInInspector] + [UnityEngine.Serialization.FormerlySerializedAs( "extraData" )] + private ExtraData m_extraData; + public ExtraData extraData + { + get { return m_extraData; } + set + { + if( m_extraData == value ) + return; + + m_extraData = value; + spline.dirtyFlags |= InternalDirtyFlags.ExtraDataChange; + } + } +#pragma warning restore 0649 + + public BezierSpline spline { get; internal set; } + public int index { get; internal set; } + + public BezierPoint previousPoint + { + get + { + if( spline ) + { + if( index > 0 ) + return spline.endPoints[index - 1]; + else if( spline.loop ) + return spline.endPoints[spline.endPoints.Count - 1]; + } + + return null; + } + } + + public BezierPoint nextPoint + { + get + { + if( spline ) + { + if( index < spline.endPoints.Count - 1 ) + return spline.endPoints[index + 1]; + else if( spline.loop ) + return spline.endPoints[0]; + } + + return null; + } + } + + private void Awake() + { + transform.hasChanged = true; + } + + private void OnDestroy() + { + if( spline ) + spline.dirtyFlags |= InternalDirtyFlags.All; + } + + public void CopyTo( BezierPoint other ) + { + other.transform.localPosition = transform.localPosition; + other.transform.localRotation = transform.localRotation; + other.transform.localScale = transform.localScale; + + other.m_handleMode = m_handleMode; + + other.m_precedingControlPointLocalPosition = m_precedingControlPointLocalPosition; + other.m_followingControlPointLocalPosition = m_followingControlPointLocalPosition; + + other.m_normal = m_normal; + other.m_autoCalculatedNormalAngleOffset = m_autoCalculatedNormalAngleOffset; + + other.m_extraData = m_extraData; + } + + public void Refresh() + { + m_position = transform.position; + m_precedingControlPointPosition = transform.TransformPoint( m_precedingControlPointLocalPosition ); + m_followingControlPointPosition = transform.TransformPoint( m_followingControlPointLocalPosition ); + + transform.hasChanged = false; + } + + internal void RefreshIfChanged() + { + if( transform.hasChanged ) + { + Refresh(); + spline.dirtyFlags |= InternalDirtyFlags.EndPointTransformChange | InternalDirtyFlags.ControlPointPositionChange; + } + } + + internal void SetNormalAndResetIntermediateNormals( Vector3 normal, string undo ) + { + if( spline && spline.autoCalculateNormals ) + return; + +#if UNITY_EDITOR + if( !string.IsNullOrEmpty( undo ) ) + UnityEditor.Undo.RecordObject( this, undo ); +#endif + + this.normal = normal; + intermediateNormals = null; + + BezierPoint previousPoint = this.previousPoint; + if( previousPoint && previousPoint.m_intermediateNormals != null && previousPoint.m_intermediateNormals.Length > 0 ) + { +#if UNITY_EDITOR + if( !string.IsNullOrEmpty( undo ) ) + UnityEditor.Undo.RecordObject( previousPoint, undo ); +#endif + + previousPoint.intermediateNormals = null; + } + } + + public void Reset() + { + localPosition = Vector3.zero; + localRotation = Quaternion.identity; + localScale = Vector3.one; + + precedingControlPointLocalPosition = Vector3.left; + followingControlPointLocalPosition = Vector3.right; + + m_normal = Vector3.up; + m_autoCalculatedNormalAngleOffset = 0f; + + m_extraData = new ExtraData(); + + transform.hasChanged = true; + } + +#if UNITY_EDITOR + [ContextMenu( "Invert Spline" )] + private void InvertSplineContextMenu() + { + if( spline ) + spline.InvertSpline( "Invert spline" ); + } +#endif + } +} \ No newline at end of file diff --git a/Assets/Plugins/BezierSolution/BezierPoint.cs.meta b/Assets/Plugins/BezierSolution/BezierPoint.cs.meta new file mode 100644 index 00000000..d5d45d95 --- /dev/null +++ b/Assets/Plugins/BezierSolution/BezierPoint.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: b9cf9c5931a3b3c4ba456c8213d7ebfc +timeCreated: 1472737829 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/BezierSolution/BezierSolution.Runtime.asmdef b/Assets/Plugins/BezierSolution/BezierSolution.Runtime.asmdef new file mode 100644 index 00000000..c00f7ac0 --- /dev/null +++ b/Assets/Plugins/BezierSolution/BezierSolution.Runtime.asmdef @@ -0,0 +1,3 @@ +{ + "name": "BezierSolution.Runtime" +} diff --git a/Assets/Plugins/BezierSolution/BezierSolution.Runtime.asmdef.meta b/Assets/Plugins/BezierSolution/BezierSolution.Runtime.asmdef.meta new file mode 100644 index 00000000..81eba57e --- /dev/null +++ b/Assets/Plugins/BezierSolution/BezierSolution.Runtime.asmdef.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 624c061ee4dfdaf4787b9c0bb51b4c1f +AssemblyDefinitionImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/BezierSolution/BezierSpline.cs b/Assets/Plugins/BezierSolution/BezierSpline.cs new file mode 100644 index 00000000..92c0602e --- /dev/null +++ b/Assets/Plugins/BezierSolution/BezierSpline.cs @@ -0,0 +1,1506 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEngine; + +#if UNITY_2017_3_OR_NEWER +[assembly: System.Runtime.CompilerServices.InternalsVisibleTo( "BezierSolution.Editor" )] +#else +[assembly: System.Runtime.CompilerServices.InternalsVisibleTo( "Assembly-CSharp-Editor" )] +[assembly: System.Runtime.CompilerServices.InternalsVisibleTo( "Assembly-CSharp-Editor-firstpass" )] +#endif +namespace BezierSolution +{ + [AddComponentMenu( "Bezier Solution/Bezier Spline" )] + [HelpURL( "https://github.com/yasirkula/UnityBezierSolution" )] + [ExecuteInEditMode] + public partial class BezierSpline : MonoBehaviour, IEnumerable + { + internal List endPoints = new List(); // This is not readonly because otherwise BezierWalkers' "Simulate In Editor" functionality may break after recompilation + + public int Count { get { return endPoints.Count; } } + public BezierPoint this[int index] { get { return endPoints[index]; } } + + private float? m_length = null; + public float length + { + get + { + if( m_length == null ) + m_length = GetLengthApproximately( 0f, 1f ); + + return m_length.Value; + } + } + + [System.Obsolete( "Length is renamed to length" )] + public float Length { get { return length; } } + + [SerializeField, HideInInspector] + [UnityEngine.Serialization.FormerlySerializedAs( "loop" )] + private bool m_loop = false; + public bool loop + { + get { return m_loop; } + set + { + if( m_loop != value ) + { + m_loop = value; + dirtyFlags |= InternalDirtyFlags.All; + } + } + } + + public bool drawGizmos = false; + public Color gizmoColor = Color.white; + [UnityEngine.Serialization.FormerlySerializedAs( "m_gizmoSmoothness" )] + public int gizmoSmoothness = 4; + + private static Material gizmoMaterial; + + [SerializeField, HideInInspector] + [UnityEngine.Serialization.FormerlySerializedAs( "Internal_AutoConstructMode" )] + private SplineAutoConstructMode m_autoConstructMode = SplineAutoConstructMode.None; + public SplineAutoConstructMode autoConstructMode + { + get { return m_autoConstructMode; } + set + { + if( m_autoConstructMode != value ) + { + m_autoConstructMode = value; + + if( value != SplineAutoConstructMode.None ) + dirtyFlags |= InternalDirtyFlags.EndPointTransformChange | InternalDirtyFlags.ControlPointPositionChange; + } + } + } + + [SerializeField, HideInInspector] + [UnityEngine.Serialization.FormerlySerializedAs( "Internal_AutoCalculateNormals" )] + private bool m_autoCalculateNormals = false; + public bool autoCalculateNormals + { + get { return m_autoCalculateNormals; } + set + { + if( m_autoCalculateNormals != value ) + { + m_autoCalculateNormals = value; + dirtyFlags |= InternalDirtyFlags.NormalOffsetChange; + } + } + } + + [SerializeField, HideInInspector] + [UnityEngine.Serialization.FormerlySerializedAs( "Internal_AutoCalculatedNormalsAngle" )] + private float m_autoCalculatedNormalsAngle = 0f; + public float autoCalculatedNormalsAngle + { + get { return m_autoCalculatedNormalsAngle; } + set + { + if( m_autoCalculatedNormalsAngle != value ) + { + m_autoCalculatedNormalsAngle = value; + dirtyFlags |= InternalDirtyFlags.NormalOffsetChange; + } + } + } + + [SerializeField, HideInInspector] + private int m_autoCalculatedIntermediateNormalsCount = 10; + public int autoCalculatedIntermediateNormalsCount + { + get { return m_autoCalculatedIntermediateNormalsCount; } + set + { + value = Mathf.Clamp( value, 0, 999 ); + + if( m_autoCalculatedIntermediateNormalsCount != value ) + { + m_autoCalculatedIntermediateNormalsCount = value; + dirtyFlags |= InternalDirtyFlags.NormalOffsetChange; + } + } + } + + private EvenlySpacedPointsHolder m_evenlySpacedPoints = null; + public EvenlySpacedPointsHolder evenlySpacedPoints + { + get + { + if( m_evenlySpacedPoints == null ) + m_evenlySpacedPoints = CalculateEvenlySpacedPoints( m_evenlySpacedPointsResolution, m_evenlySpacedPointsAccuracy ); + + return m_evenlySpacedPoints; + } + } + + private PointCache m_pointCache = null; + public PointCache pointCache + { + get + { + if( m_pointCache == null ) + m_pointCache = GeneratePointCache( resolution: m_pointCacheResolution ); + + return m_pointCache; + } + } + + [SerializeField, HideInInspector] + private float m_evenlySpacedPointsResolution = 10f; + public float evenlySpacedPointsResolution + { + get { return m_evenlySpacedPointsResolution; } + set + { + value = Mathf.Clamp( value, 1f, 999f ); + + if( m_evenlySpacedPointsResolution != value ) + { + m_evenlySpacedPointsResolution = value; + m_evenlySpacedPoints = null; + + dirtyFlags = InternalDirtyFlags.All; + } + } + } + + [SerializeField, HideInInspector] + private float m_evenlySpacedPointsAccuracy = 3f; + public float evenlySpacedPointsAccuracy + { + get { return m_evenlySpacedPointsAccuracy; } + set + { + value = Mathf.Clamp( value, 1f, 999f ); + + if( m_evenlySpacedPointsAccuracy != value ) + { + m_evenlySpacedPointsAccuracy = value; + m_evenlySpacedPoints = null; + + dirtyFlags = InternalDirtyFlags.All; + } + } + } + + [SerializeField, HideInInspector] + private int m_pointCacheResolution = 100; + public int pointCacheResolution + { + get { return m_pointCacheResolution; } + set + { + value = Mathf.Clamp( value, 10, 10000 ); + + if( m_pointCacheResolution != value ) + { + m_pointCacheResolution = value; + m_pointCache = null; + + dirtyFlags = InternalDirtyFlags.All; + } + } + } + + public event SplineChangeDelegate onSplineChanged; + + public int version { get; private set; } + + internal InternalDirtyFlags dirtyFlags; + + private void Awake() + { + Refresh(); + } + +#if UNITY_EDITOR + private void OnTransformChildrenChanged() + { + dirtyFlags |= InternalDirtyFlags.All; + Refresh(); + } +#endif + + private void LateUpdate() + { + CheckDirty(); + } + + internal void CheckDirty() + { + for( int i = 0; i < endPoints.Count; i++ ) + endPoints[i].RefreshIfChanged(); + + if( dirtyFlags != InternalDirtyFlags.None && endPoints.Count >= 2 ) + { + DirtyFlags publishedDirtyFlags = DirtyFlags.None; + + if( ( dirtyFlags & InternalDirtyFlags.ExtraDataChange ) == InternalDirtyFlags.ExtraDataChange ) + publishedDirtyFlags |= DirtyFlags.ExtraDataChanged; + + if( ( dirtyFlags & ( InternalDirtyFlags.EndPointTransformChange | InternalDirtyFlags.ControlPointPositionChange ) ) != InternalDirtyFlags.None ) + { + if( m_autoConstructMode == SplineAutoConstructMode.None ) + publishedDirtyFlags |= DirtyFlags.SplineShapeChanged; + else + { + switch( m_autoConstructMode ) + { + case SplineAutoConstructMode.Linear: ConstructLinearPath(); break; + case SplineAutoConstructMode.Smooth1: AutoConstructSpline(); break; + case SplineAutoConstructMode.Smooth2: AutoConstructSpline2(); break; + } + + // If a control point position was changed only, we've reverted that change by auto constructing the spline again + dirtyFlags &= ~InternalDirtyFlags.ControlPointPositionChange; + + // If an end point's position was changed, then the spline's shape has indeed changed + if( ( dirtyFlags & InternalDirtyFlags.EndPointTransformChange ) == InternalDirtyFlags.EndPointTransformChange ) + publishedDirtyFlags |= DirtyFlags.SplineShapeChanged; + } + } + + if( ( dirtyFlags & ( InternalDirtyFlags.NormalChange | InternalDirtyFlags.NormalOffsetChange | InternalDirtyFlags.EndPointTransformChange | InternalDirtyFlags.ControlPointPositionChange ) ) != InternalDirtyFlags.None ) + { + if( !m_autoCalculateNormals ) + { + // Normals are actually changed only when NormalChange flag is on + if( ( dirtyFlags & InternalDirtyFlags.NormalChange ) == InternalDirtyFlags.NormalChange ) + publishedDirtyFlags |= DirtyFlags.NormalsChanged; + } + else + { + if( m_autoCalculatedIntermediateNormalsCount <= 0 ) + AutoCalculateNormals( m_autoCalculatedNormalsAngle, calculateIntermediateNormals: false ); + else + AutoCalculateNormals( m_autoCalculatedNormalsAngle, m_autoCalculatedIntermediateNormalsCount + 1, true ); + + // If an end point's only normal vector was changed, we've reverted that change by auto calculating the normals again + dirtyFlags &= ~InternalDirtyFlags.NormalChange; + + // If an end point's position or normal calculation offset was changed, then the spline's normals have indeed changed + if( ( dirtyFlags & ( InternalDirtyFlags.NormalOffsetChange | InternalDirtyFlags.EndPointTransformChange | InternalDirtyFlags.ControlPointPositionChange ) ) != InternalDirtyFlags.None ) + publishedDirtyFlags |= DirtyFlags.NormalsChanged; + } + } + + if( ( publishedDirtyFlags & DirtyFlags.SplineShapeChanged ) == DirtyFlags.SplineShapeChanged ) + { + m_length = null; + m_evenlySpacedPoints = null; + } + + m_pointCache = null; + version++; + + if( onSplineChanged != null ) + { + try + { + onSplineChanged( this, publishedDirtyFlags ); + } + catch( System.Exception e ) + { + Debug.LogException( e ); + } + } + } + + dirtyFlags = InternalDirtyFlags.None; + } + + public void Initialize( int endPointsCount ) + { + if( endPointsCount < 2 ) + { + Debug.LogError( "Can't initialize spline with " + endPointsCount + " point(s). At least 2 points are needed" ); + return; + } + + // Destroy current end points + endPoints.Clear(); + GetComponentsInChildren( endPoints ); + + for( int i = endPoints.Count - 1; i >= 0; i-- ) + DestroyImmediate( endPoints[i].gameObject ); + + // Create new end points + endPoints.Clear(); + + for( int i = 0; i < endPointsCount; i++ ) + InsertNewPointAt( i ); + + Refresh(); + } + + public void Refresh() + { + endPoints.Clear(); + GetComponentsInChildren( endPoints ); + + for( int i = 0; i < endPoints.Count; i++ ) + { + endPoints[i].spline = this; + endPoints[i].index = i; + } + + CheckDirty(); + } + + public BezierPoint InsertNewPointAt( int index ) + { + if( index < 0 || index > endPoints.Count ) + { + Debug.LogError( "Index " + index + " is out of range: [0," + endPoints.Count + "]" ); + return null; + } + + int prevCount = endPoints.Count; + BezierPoint point = new GameObject( "Point" ).AddComponent(); + point.spline = this; + + Transform parent = endPoints.Count == 0 ? transform : ( index == 0 ? endPoints[0].transform.parent : endPoints[index - 1].transform.parent ); + int siblingIndex = index == 0 ? 0 : endPoints[index - 1].transform.GetSiblingIndex() + 1; + point.transform.SetParent( parent, false ); + point.transform.SetSiblingIndex( siblingIndex ); + + if( endPoints.Count == prevCount ) // If spline isn't automatically Refresh()'ed + endPoints.Insert( index, point ); + + for( int i = index; i < endPoints.Count; i++ ) + endPoints[i].index = i; + + dirtyFlags |= InternalDirtyFlags.All; + + return point; + } + + public BezierPoint DuplicatePointAt( int index ) + { + if( index < 0 || index >= endPoints.Count ) + { + Debug.LogError( "Index " + index + " is out of range: [0," + ( endPoints.Count - 1 ) + "]" ); + return null; + } + + BezierPoint newPoint = InsertNewPointAt( index + 1 ); + endPoints[index].CopyTo( newPoint ); + + return newPoint; + } + + public void RemovePointAt( int index ) + { + if( endPoints.Count <= 2 ) + { + Debug.LogError( "Can't remove point: spline must consist of at least two points!" ); + return; + } + + if( index < 0 || index >= endPoints.Count ) + { + Debug.LogError( "Index " + index + " is out of range: [0," + endPoints.Count + ")" ); + return; + } + + BezierPoint point = endPoints[index]; + endPoints.RemoveAt( index ); + + for( int i = index; i < endPoints.Count; i++ ) + endPoints[i].index = i; + + DestroyImmediate( point.gameObject ); + + dirtyFlags |= InternalDirtyFlags.All; + } + + public void SwapPointsAt( int index1, int index2 ) + { + if( index1 == index2 ) + return; + + if( index1 < 0 || index1 >= endPoints.Count || index2 < 0 || index2 >= endPoints.Count ) + { + Debug.LogError( "Indices must be in range [0," + ( endPoints.Count - 1 ) + "]" ); + return; + } + + BezierPoint point1 = endPoints[index1]; + BezierPoint point2 = endPoints[index2]; + + int point1SiblingIndex = point1.transform.GetSiblingIndex(); + int point2SiblingIndex = point2.transform.GetSiblingIndex(); + + Transform point1Parent = point1.transform.parent; + Transform point2Parent = point2.transform.parent; + + endPoints[index1] = point2; + endPoints[index2] = point1; + + point1.index = index2; + point2.index = index1; + + if( point1Parent != point2Parent ) + { + point1.transform.SetParent( point2Parent, true ); + point2.transform.SetParent( point1Parent, true ); + } + + point1.transform.SetSiblingIndex( point2SiblingIndex ); + point2.transform.SetSiblingIndex( point1SiblingIndex ); + + dirtyFlags |= InternalDirtyFlags.All; + } + + public void ChangePointIndex( int previousIndex, int newIndex ) + { + ChangePointIndex( previousIndex, newIndex, null ); + } + + internal void ChangePointIndex( int previousIndex, int newIndex, string undo ) + { + if( previousIndex == newIndex ) + return; + + if( previousIndex < 0 || previousIndex >= endPoints.Count || newIndex < 0 || newIndex >= endPoints.Count ) + { + Debug.LogError( "Indices must be in range [0," + ( endPoints.Count - 1 ) + "]" ); + return; + } + + BezierPoint point1 = endPoints[previousIndex]; + BezierPoint point2 = endPoints[newIndex]; + +#if UNITY_EDITOR + if( undo != null ) + UnityEditor.Undo.RegisterCompleteObjectUndo( point1.transform.parent, undo ); +#endif + + if( previousIndex < newIndex ) + { + for( int i = previousIndex; i < newIndex; i++ ) + endPoints[i] = endPoints[i + 1]; + } + else + { + for( int i = previousIndex; i > newIndex; i-- ) + endPoints[i] = endPoints[i - 1]; + } + + endPoints[newIndex] = point1; + + Transform point2Parent = point2.transform.parent; + if( point1.transform.parent != point2Parent ) + { +#if UNITY_EDITOR + if( undo != null ) + { + UnityEditor.Undo.SetTransformParent( point1.transform, point2Parent, undo ); + UnityEditor.Undo.RegisterCompleteObjectUndo( point2Parent, undo ); + } + else +#endif + point1.transform.SetParent( point2Parent, true ); + + int point2SiblingIndex = point2.transform.GetSiblingIndex(); + if( previousIndex < newIndex ) + { + if( point1.transform.GetSiblingIndex() < point2SiblingIndex ) + point1.transform.SetSiblingIndex( point2SiblingIndex ); + else + point1.transform.SetSiblingIndex( point2SiblingIndex + 1 ); + } + else + { + if( point1.transform.GetSiblingIndex() < point2SiblingIndex ) + point1.transform.SetSiblingIndex( point2SiblingIndex - 1 ); + else + point1.transform.SetSiblingIndex( point2SiblingIndex ); + } + } + else + point1.transform.SetSiblingIndex( point2.transform.GetSiblingIndex() ); + + for( int i = 0; i < endPoints.Count; i++ ) + endPoints[i].index = i; + + dirtyFlags |= InternalDirtyFlags.All; + } + + public void InvertSpline() + { + InvertSpline( null ); + } + + internal void InvertSpline( string undo ) + { +#if UNITY_EDITOR + // In Editor, this.endPoints will change at each for-iteration due to OnTransformChildrenChanged + // but we need the list to be immutable while this function is being executed + List endPoints = new List( this.endPoints ); +#endif + + endPoints.Reverse(); + + for( int i = endPoints.Count / 2 - 1; i >= 0; i-- ) + { + BezierPoint point1 = endPoints[i]; + BezierPoint point2 = endPoints[endPoints.Count - 1 - i]; + + int point1SiblingIndex = point1.transform.GetSiblingIndex(); + int point2SiblingIndex = point2.transform.GetSiblingIndex(); + + Transform point1Parent = point1.transform.parent; + Transform point2Parent = point2.transform.parent; + +#if UNITY_EDITOR + if( undo != null ) + { + UnityEditor.Undo.RegisterCompleteObjectUndo( point1Parent, undo ); + UnityEditor.Undo.RegisterCompleteObjectUndo( point2Parent, undo ); + } +#endif + + if( point1Parent != point2Parent ) + { +#if UNITY_EDITOR + if( undo != null ) + { + UnityEditor.Undo.SetTransformParent( point1.transform, point2Parent, undo ); + UnityEditor.Undo.SetTransformParent( point2.transform, point1Parent, undo ); + } + else +#endif + { + point1.transform.SetParent( point2Parent, true ); + point2.transform.SetParent( point1Parent, true ); + } + } + + point1.transform.SetSiblingIndex( point2SiblingIndex ); + point2.transform.SetSiblingIndex( point1SiblingIndex ); + } + + for( int i = 0; i < endPoints.Count; i++ ) + { +#if UNITY_EDITOR + if( undo != null ) + UnityEditor.Undo.RecordObject( endPoints[i], undo ); +#endif + + // Swap control points + Vector3 precedingControlPointLocalPosition = endPoints[i].precedingControlPointLocalPosition; + endPoints[i].precedingControlPointLocalPosition = endPoints[i].followingControlPointLocalPosition; + endPoints[i].followingControlPointLocalPosition = precedingControlPointLocalPosition; + + endPoints[i].index = i; + } + +#if UNITY_EDITOR + this.endPoints = endPoints; +#endif + + dirtyFlags |= InternalDirtyFlags.All; + } + + public Vector3 GetPoint( float normalizedT ) + { + if( !m_loop ) + { + if( normalizedT <= 0f ) + return endPoints[0].position; + else if( normalizedT >= 1f ) + return endPoints[endPoints.Count - 1].position; + } + else + { + // 2nd conditions isn't 'else if' because in rare occasions, floating point precision issues may arise; e.g. for normalizedT = -0.0000000149, + // incrementing the value by 1 results in perfect 1.0000000000 with no mantissa + if( normalizedT < 0f ) + normalizedT += 1f; + if( normalizedT >= 1f ) + normalizedT -= 1f; + } + + float t = normalizedT * ( m_loop ? endPoints.Count : ( endPoints.Count - 1 ) ); + + BezierPoint startPoint, endPoint; + + int startIndex = (int) t; + int endIndex = startIndex + 1; + + if( endIndex == endPoints.Count ) + endIndex = 0; + + startPoint = endPoints[startIndex]; + endPoint = endPoints[endIndex]; + + float localT = t - startIndex; + float oneMinusLocalT = 1f - localT; + + return oneMinusLocalT * oneMinusLocalT * oneMinusLocalT * startPoint.position + + 3f * oneMinusLocalT * oneMinusLocalT * localT * startPoint.followingControlPointPosition + + 3f * oneMinusLocalT * localT * localT * endPoint.precedingControlPointPosition + + localT * localT * localT * endPoint.position; + } + + public Vector3 GetTangent( float normalizedT ) + { + if( !m_loop ) + { + if( normalizedT <= 0f ) + return 3f * ( endPoints[0].followingControlPointPosition - endPoints[0].position ); + else if( normalizedT >= 1f ) + { + int index = endPoints.Count - 1; + return 3f * ( endPoints[index].position - endPoints[index].precedingControlPointPosition ); + } + } + else + { + if( normalizedT < 0f ) + normalizedT += 1f; + if( normalizedT >= 1f ) + normalizedT -= 1f; + } + + float t = normalizedT * ( m_loop ? endPoints.Count : ( endPoints.Count - 1 ) ); + + BezierPoint startPoint, endPoint; + + int startIndex = (int) t; + int endIndex = startIndex + 1; + + if( endIndex == endPoints.Count ) + endIndex = 0; + + startPoint = endPoints[startIndex]; + endPoint = endPoints[endIndex]; + + float localT = t - startIndex; + float oneMinusLocalT = 1f - localT; + + return 3f * oneMinusLocalT * oneMinusLocalT * ( startPoint.followingControlPointPosition - startPoint.position ) + + 6f * oneMinusLocalT * localT * ( endPoint.precedingControlPointPosition - startPoint.followingControlPointPosition ) + + 3f * localT * localT * ( endPoint.position - endPoint.precedingControlPointPosition ); + } + + public Vector3 GetNormal( float normalizedT ) + { + if( !m_loop ) + { + if( normalizedT <= 0f ) + return endPoints[0].normal; + else if( normalizedT >= 1f ) + return endPoints[endPoints.Count - 1].normal; + } + else + { + if( normalizedT < 0f ) + normalizedT += 1f; + if( normalizedT >= 1f ) + normalizedT -= 1f; + } + + float t = normalizedT * ( m_loop ? endPoints.Count : ( endPoints.Count - 1 ) ); + + int startIndex = (int) t; + int endIndex = startIndex + 1; + + if( endIndex == endPoints.Count ) + endIndex = 0; + + float localT = t - startIndex; + + Vector3[] intermediateNormals = endPoints[startIndex].intermediateNormals; + if( intermediateNormals != null && intermediateNormals.Length > 0 ) + { + localT *= intermediateNormals.Length - 1; + int localStartIndex = (int) localT; + + return ( localStartIndex < intermediateNormals.Length - 1 ) ? Vector3.LerpUnclamped( intermediateNormals[localStartIndex], intermediateNormals[localStartIndex + 1], localT - localStartIndex ) : intermediateNormals[localStartIndex]; + } + + Vector3 startNormal = endPoints[startIndex].normal; + Vector3 endNormal = endPoints[endIndex].normal; + + Vector3 normal = Vector3.LerpUnclamped( startNormal, endNormal, localT ); + if( normal.y == 0f && normal.x == 0f && normal.z == 0f ) + { + // Don't return Vector3.zero as normal + normal = Vector3.LerpUnclamped( startNormal, endNormal, localT > 0.01f ? ( localT - 0.01f ) : ( localT + 0.01f ) ); + if( normal.y == 0f && normal.x == 0f && normal.z == 0f ) + normal = Vector3.up; + } + + return normal; + } + + public BezierPoint.ExtraData GetExtraData( float normalizedT ) + { + return GetExtraData( normalizedT, defaultExtraDataLerpFunction ); + } + + public BezierPoint.ExtraData GetExtraData( float normalizedT, ExtraDataLerpFunction lerpFunction ) + { + if( !m_loop ) + { + if( normalizedT <= 0f ) + return endPoints[0].extraData; + else if( normalizedT >= 1f ) + return endPoints[endPoints.Count - 1].extraData; + } + else + { + if( normalizedT < 0f ) + normalizedT += 1f; + if( normalizedT >= 1f ) + normalizedT -= 1f; + } + + float t = normalizedT * ( m_loop ? endPoints.Count : ( endPoints.Count - 1 ) ); + + int startIndex = (int) t; + int endIndex = startIndex + 1; + + if( endIndex == endPoints.Count ) + endIndex = 0; + + return lerpFunction( endPoints[startIndex].extraData, endPoints[endIndex].extraData, t - startIndex ); + } + + public float GetLengthApproximately( float startNormalizedT, float endNormalizedT, float accuracy = 50f ) + { + if( endNormalizedT < startNormalizedT ) + { + float temp = startNormalizedT; + startNormalizedT = endNormalizedT; + endNormalizedT = temp; + } + + if( startNormalizedT < 0f ) + startNormalizedT = 0f; + + if( endNormalizedT > 1f ) + endNormalizedT = 1f; + + float step = AccuracyToStepSize( accuracy ) * ( endNormalizedT - startNormalizedT ); + + float length = 0f; + Vector3 prevPoint = GetPoint( startNormalizedT ); + for( float i = startNormalizedT + step; i < endNormalizedT; i += step ) + { + Vector3 thisPoint = GetPoint( i ); + length += Vector3.Distance( thisPoint, prevPoint ); + prevPoint = thisPoint; + } + + length += Vector3.Distance( prevPoint, GetPoint( endNormalizedT ) ); + + return length; + } + + public Segment GetSegmentAt( float normalizedT ) + { + if( !m_loop ) + { + if( normalizedT <= 0f ) + return new Segment( endPoints[0], endPoints[1], 0f ); + else if( normalizedT >= 1f ) + return new Segment( endPoints[endPoints.Count - 2], endPoints[endPoints.Count - 1], 1f ); + } + else + { + if( normalizedT < 0f ) + normalizedT += 1f; + if( normalizedT >= 1f ) + normalizedT -= 1f; + } + + float t = normalizedT * ( m_loop ? endPoints.Count : ( endPoints.Count - 1 ) ); + + int startIndex = (int) t; + int endIndex = startIndex + 1; + + if( endIndex == endPoints.Count ) + endIndex = 0; + + return new Segment( endPoints[startIndex], endPoints[endIndex], t - startIndex ); + } + + [System.Obsolete( "GetNearestPointIndicesTo is renamed to GetSegmentAt" )] + public Segment GetNearestPointIndicesTo( float normalizedT ) + { + return GetSegmentAt( normalizedT ); + } + + public Vector3 FindNearestPointTo( Vector3 worldPos, float accuracy = 100f, int secondPassIterations = 7, float secondPassExtents = 0.025f ) + { + float normalizedT; + return FindNearestPointTo( worldPos, out normalizedT, accuracy, secondPassIterations, secondPassExtents ); + } + + public Vector3 FindNearestPointTo( Vector3 worldPos, out float normalizedT, float accuracy = 100f, int secondPassIterations = 7, float secondPassExtents = 0.025f ) + { + Vector3 result = Vector3.zero; + normalizedT = -1f; + + float step = AccuracyToStepSize( accuracy ); + + float minDistance = Mathf.Infinity; + for( float i = 0f; i < 1f; i += step ) + { + Vector3 thisPoint = GetPoint( i ); + float thisDistance = ( worldPos - thisPoint ).sqrMagnitude; + if( thisDistance < minDistance ) + { + minDistance = thisDistance; + result = thisPoint; + normalizedT = i; + } + } + + // Do a second pass near the current normalizedT using binary search + // Credit: https://pomax.github.io/bezierinfo/#projections + if( secondPassIterations > 0 ) + { + float minT = normalizedT - secondPassExtents; + float maxT = normalizedT + secondPassExtents; + + for( int i = 0; i < secondPassIterations; i++ ) + { + float leftT = ( minT + normalizedT ) * 0.5f; + float rightT = ( maxT + normalizedT ) * 0.5f; + + Vector3 leftPoint = GetPoint( leftT ); + Vector3 rightPoint = GetPoint( rightT ); + + float leftDistance = ( worldPos - leftPoint ).sqrMagnitude; + float rightDistance = ( worldPos - rightPoint ).sqrMagnitude; + + if( leftDistance < minDistance && leftDistance < rightDistance ) + { + minDistance = leftDistance; + result = leftPoint; + maxT = normalizedT; + normalizedT = leftT; + } + else if( rightDistance < minDistance && rightDistance < leftDistance ) + { + minDistance = rightDistance; + result = rightPoint; + minT = normalizedT; + normalizedT = rightT; + } + else + { + minT = leftT; + maxT = rightT; + } + } + } + + return result; + } + + public Vector3 FindNearestPointToLine( Vector3 lineStart, Vector3 lineEnd, float accuracy = 100f, int secondPassIterations = 7, float secondPassExtents = 0.025f ) + { + Vector3 pointOnLine; + float normalizedT; + return FindNearestPointToLine( lineStart, lineEnd, out pointOnLine, out normalizedT, accuracy, secondPassIterations, secondPassExtents ); + } + + public Vector3 FindNearestPointToLine( Vector3 lineStart, Vector3 lineEnd, out Vector3 pointOnLine, out float normalizedT, float accuracy = 100f, int secondPassIterations = 7, float secondPassExtents = 0.025f ) + { + Vector3 result = Vector3.zero; + pointOnLine = Vector3.zero; + normalizedT = -1f; + + float step = AccuracyToStepSize( accuracy ); + + // Find closest point on line + // Credit: https://github.com/Unity-Technologies/UnityCsReference/blob/61f92bd79ae862c4465d35270f9d1d57befd1761/Editor/Mono/HandleUtility.cs#L115-L128 + Vector3 lineDirection = lineEnd - lineStart; + float length = lineDirection.magnitude; + Vector3 normalizedLineDirection = lineDirection; + if( length > .000001f ) + normalizedLineDirection /= length; + + float minDistance = Mathf.Infinity; + for( float i = 0f; i < 1f; i += step ) + { + Vector3 thisPoint = GetPoint( i ); + + // Find closest point on line + // Credit: https://github.com/Unity-Technologies/UnityCsReference/blob/61f92bd79ae862c4465d35270f9d1d57befd1761/Editor/Mono/HandleUtility.cs#L115-L128 + Vector3 closestPointOnLine = lineStart + normalizedLineDirection * Mathf.Clamp( Vector3.Dot( normalizedLineDirection, thisPoint - lineStart ), 0f, length ); + + float thisDistance = ( closestPointOnLine - thisPoint ).sqrMagnitude; + if( thisDistance < minDistance ) + { + minDistance = thisDistance; + result = thisPoint; + pointOnLine = closestPointOnLine; + normalizedT = i; + } + } + + // Do a second pass near the current normalizedT using binary search + // Credit: https://pomax.github.io/bezierinfo/#projections + if( secondPassIterations > 0 ) + { + float minT = normalizedT - secondPassExtents; + float maxT = normalizedT + secondPassExtents; + + for( int i = 0; i < secondPassIterations; i++ ) + { + float leftT = ( minT + normalizedT ) * 0.5f; + float rightT = ( maxT + normalizedT ) * 0.5f; + + Vector3 leftPoint = GetPoint( leftT ); + Vector3 rightPoint = GetPoint( rightT ); + + Vector3 leftClosestPointOnLine = lineStart + normalizedLineDirection * Mathf.Clamp( Vector3.Dot( normalizedLineDirection, leftPoint - lineStart ), 0f, length ); + Vector3 rightClosestPointOnLine = lineStart + normalizedLineDirection * Mathf.Clamp( Vector3.Dot( normalizedLineDirection, rightPoint - lineStart ), 0f, length ); + + float leftDistance = ( leftClosestPointOnLine - leftPoint ).sqrMagnitude; + float rightDistance = ( rightClosestPointOnLine - rightPoint ).sqrMagnitude; + + if( leftDistance < minDistance && leftDistance < rightDistance ) + { + minDistance = leftDistance; + result = leftPoint; + pointOnLine = leftClosestPointOnLine; + maxT = normalizedT; + normalizedT = leftT; + } + else if( rightDistance < minDistance && rightDistance < leftDistance ) + { + minDistance = rightDistance; + result = rightPoint; + pointOnLine = rightClosestPointOnLine; + minT = normalizedT; + normalizedT = rightT; + } + else + { + minT = leftT; + maxT = rightT; + } + } + } + + return result; + } + + // Credit: https://gamedev.stackexchange.com/a/27138 + public Vector3 MoveAlongSpline( ref float normalizedT, float deltaMovement, int accuracy = 3 ) + { + float constant = deltaMovement / ( ( m_loop ? endPoints.Count : ( endPoints.Count - 1 ) ) * accuracy ); + for( int i = 0; i < accuracy; i++ ) + normalizedT += constant / GetTangent( normalizedT ).magnitude; + + return GetPoint( normalizedT ); + } + + public void ConstructLinearPath() + { + for( int i = 0; i < endPoints.Count; i++ ) + { + endPoints[i].handleMode = BezierPoint.HandleMode.Free; + endPoints[i].RefreshIfChanged(); + } + + for( int i = 0; i < endPoints.Count; i++ ) + { + if( i < endPoints.Count - 1 ) + { + Vector3 midPoint = ( endPoints[i].position + endPoints[i + 1].position ) * 0.5f; + endPoints[i].followingControlPointPosition = midPoint; + endPoints[i + 1].precedingControlPointPosition = midPoint; + } + else + { + Vector3 midPoint = ( endPoints[i].position + endPoints[0].position ) * 0.5f; + endPoints[i].followingControlPointPosition = midPoint; + endPoints[0].precedingControlPointPosition = midPoint; + } + } + } + + // Credit: http://www.codeproject.com/Articles/31859/Draw-a-Smooth-Curve-through-a-Set-of-2D-Points-wit + public void AutoConstructSpline() + { + for( int i = 0; i < endPoints.Count; i++ ) + { + endPoints[i].handleMode = BezierPoint.HandleMode.Mirrored; + endPoints[i].RefreshIfChanged(); + } + + int n = endPoints.Count - 1; + if( n == 1 ) + { + endPoints[0].followingControlPointPosition = ( 2 * endPoints[0].position + endPoints[1].position ) / 3f; + endPoints[1].precedingControlPointPosition = 2 * endPoints[0].followingControlPointPosition - endPoints[0].position; + + return; + } + + Vector3[] rhs; + if( m_loop ) + rhs = new Vector3[n + 1]; + else + rhs = new Vector3[n]; + + for( int i = 1; i < n - 1; i++ ) + rhs[i] = 4 * endPoints[i].position + 2 * endPoints[i + 1].position; + + rhs[0] = endPoints[0].position + 2 * endPoints[1].position; + + if( !m_loop ) + rhs[n - 1] = ( 8 * endPoints[n - 1].position + endPoints[n].position ) * 0.5f; + else + { + rhs[n - 1] = 4 * endPoints[n - 1].position + 2 * endPoints[n].position; + rhs[n] = ( 8 * endPoints[n].position + endPoints[0].position ) * 0.5f; + } + + // Get first control points + int rhsLength = rhs.Length; + Vector3[] controlPoints = new Vector3[rhsLength]; // Solution vector + float[] tmp = new float[rhsLength]; // Temp workspace + + float b = 2f; + controlPoints[0] = rhs[0] / b; + for( int i = 1; i < rhsLength; i++ ) // Decomposition and forward substitution + { + float val = 1f / b; + tmp[i] = val; + b = ( i < rhsLength - 1 ? 4f : 3.5f ) - val; + controlPoints[i] = ( rhs[i] - controlPoints[i - 1] ) / b; + } + + for( int i = 1; i < rhsLength; i++ ) + controlPoints[rhsLength - i - 1] -= tmp[rhsLength - i] * controlPoints[rhsLength - i]; // Backsubstitution + + for( int i = 0; i < n; i++ ) + { + // First control point + endPoints[i].followingControlPointPosition = controlPoints[i]; + + if( m_loop ) + endPoints[i + 1].precedingControlPointPosition = 2 * endPoints[i + 1].position - controlPoints[i + 1]; + else + { + // Second control point + if( i < n - 1 ) + endPoints[i + 1].precedingControlPointPosition = 2 * endPoints[i + 1].position - controlPoints[i + 1]; + else + endPoints[i + 1].precedingControlPointPosition = ( endPoints[n].position + controlPoints[n - 1] ) * 0.5f; + } + } + + if( m_loop ) + { + float controlPointDistance = Vector3.Distance( endPoints[0].followingControlPointPosition, endPoints[0].position ); + Vector3 direction = Vector3.Normalize( endPoints[n].position - endPoints[1].position ); + endPoints[0].precedingControlPointPosition = endPoints[0].position + direction * controlPointDistance; + endPoints[0].followingControlPointLocalPosition = -endPoints[0].precedingControlPointLocalPosition; + } + } + + // Credit: http://stackoverflow.com/questions/3526940/how-to-create-a-cubic-bezier-curve-when-given-n-points-in-3d + public void AutoConstructSpline2() + { + // This method doesn't work well with 2 end poins + if( endPoints.Count == 2 ) + { + AutoConstructSpline(); + return; + } + + for( int i = 0; i < endPoints.Count; i++ ) + { + endPoints[i].handleMode = BezierPoint.HandleMode.Mirrored; + endPoints[i].RefreshIfChanged(); + } + + for( int i = 0; i < endPoints.Count; i++ ) + { + Vector3 pMinus1, p1, p2; + + if( i == 0 ) + { + if( m_loop ) + pMinus1 = endPoints[endPoints.Count - 1].position; + else + pMinus1 = endPoints[0].position; + } + else + pMinus1 = endPoints[i - 1].position; + + if( m_loop ) + { + p1 = endPoints[( i + 1 ) % endPoints.Count].position; + p2 = endPoints[( i + 2 ) % endPoints.Count].position; + } + else + { + if( i < endPoints.Count - 2 ) + { + p1 = endPoints[i + 1].position; + p2 = endPoints[i + 2].position; + } + else if( i == endPoints.Count - 2 ) + { + p1 = endPoints[i + 1].position; + p2 = endPoints[i + 1].position; + } + else + { + p1 = endPoints[i].position; + p2 = endPoints[i].position; + } + } + + endPoints[i].followingControlPointPosition = endPoints[i].position + ( p1 - pMinus1 ) / 6f; + + if( i < endPoints.Count - 1 ) + endPoints[i + 1].precedingControlPointPosition = p1 - ( p2 - endPoints[i].position ) / 6f; + else if( m_loop ) + endPoints[0].precedingControlPointPosition = p1 - ( p2 - endPoints[i].position ) / 6f; + } + } + + // Credit: https://stackoverflow.com/a/14241741/2373034 + // Alternative approach: https://stackoverflow.com/a/25458216/2373034 + public void AutoCalculateNormals( float normalAngle = 0f, int smoothness = 10, bool calculateIntermediateNormals = false ) + { + for( int i = 0; i < endPoints.Count; i++ ) + endPoints[i].RefreshIfChanged(); + + Vector3 tangent = new Vector3(), rotatedNormal = new Vector3(); + smoothness = Mathf.Max( 1, smoothness ); + float _1OverSmoothness = 1f / smoothness; + + if( smoothness <= 1 ) + calculateIntermediateNormals = false; + + // Calculate initial point's normal using Frenet formula + Segment segment = new Segment( endPoints[0], endPoints[1], 0f ); + Vector3 tangent1 = segment.GetTangent( 0f ).normalized; + Vector3 tangent2 = segment.GetTangent( 0.025f ).normalized; + Vector3 cross = Vector3.Cross( tangent2, tangent1 ).normalized; + if( Mathf.Approximately( cross.sqrMagnitude, 0f ) ) // This is not a curved spline but rather a straight line + cross = Vector3.Cross( tangent2, ( tangent2.x != 0f || tangent2.z != 0f ) ? Vector3.up : Vector3.forward ); + + // prevNormal stores the unrotated normal whereas endpoints[index].normal stores the rotated normal + Vector3 prevNormal = Vector3.Cross( cross, tangent1 ).normalized; + endPoints[0].normal = Quaternion.AngleAxis( normalAngle + endPoints[0].autoCalculatedNormalAngleOffset, tangent1 ) * prevNormal; + + // Calculate other points' normals by iteratively (smoothness) calculating normals between the previous point and the next point + for( int i = 0; i < endPoints.Count; i++ ) + { + if( i < endPoints.Count - 1 ) + segment = new Segment( endPoints[i], endPoints[i + 1], 0f ); + else if( m_loop ) + segment = new Segment( endPoints[i], endPoints[0], 0f ); + else + break; + + Vector3[] intermediateNormals = null; + if( !calculateIntermediateNormals ) + segment.point1.intermediateNormals = null; + else + { + intermediateNormals = segment.point1.intermediateNormals; + if( intermediateNormals == null || intermediateNormals.Length != smoothness + 1 ) + segment.point1.intermediateNormals = intermediateNormals = new Vector3[smoothness + 1]; + + intermediateNormals[0] = segment.point1.normal; + } + + float normalAngle1 = normalAngle + segment.point1.autoCalculatedNormalAngleOffset; + float normalAngle2 = normalAngle + segment.point2.autoCalculatedNormalAngleOffset; + + for( int j = 1; j <= smoothness; j++ ) + { + float localT = j * _1OverSmoothness; + tangent = segment.GetTangent( localT ).normalized; + prevNormal = Vector3.Cross( tangent, Vector3.Cross( prevNormal, tangent ).normalized ).normalized; + + if( calculateIntermediateNormals ) + { + float _normalAngle = Mathf.LerpUnclamped( normalAngle1, normalAngle2, localT ); + intermediateNormals[j] = rotatedNormal = ( _normalAngle == 0f ) ? prevNormal : ( Quaternion.AngleAxis( _normalAngle, tangent ) * prevNormal ); + } + } + + if( !calculateIntermediateNormals ) + rotatedNormal = ( normalAngle2 == 0f ) ? prevNormal : ( Quaternion.AngleAxis( normalAngle2, tangent ) * prevNormal ); + + if( i < endPoints.Count - 1 ) + endPoints[i + 1].normal = rotatedNormal; + else + { + if( !calculateIntermediateNormals ) + { + if( rotatedNormal != -endPoints[0].normal ) + endPoints[0].normal = ( endPoints[0].normal + rotatedNormal ).normalized; + } + else + { + // In a looping spline, the first end point's normal value is a special case because the initial value that we've assigned to it + // might end up vastly different from the final rotatedNormal that we've found. To accommodate to this change, we'll find the + // angle difference between these two values and gradually apply that difference to the first end point's intermediate normals + Vector3 initialNormal0 = endPoints[0].normal; + float normal0DeltaAngle = Vector3.Angle( initialNormal0, rotatedNormal ); + if( Mathf.Abs( normal0DeltaAngle ) > 5f ) + { + // Vector3.SignedAngle: https://github.com/Unity-Technologies/UnityCsReference/blob/61f92bd79ae862c4465d35270f9d1d57befd1761/Runtime/Export/Math/Vector3.cs#L316-L328 + // The function itself isn't available on Unity 5.6 so its source code is copy&pasted here + float cross_x = initialNormal0.y * rotatedNormal.z - initialNormal0.z * rotatedNormal.y; + float cross_y = initialNormal0.z * rotatedNormal.x - initialNormal0.x * rotatedNormal.z; + float cross_z = initialNormal0.x * rotatedNormal.y - initialNormal0.y * rotatedNormal.x; + normal0DeltaAngle *= Mathf.Sign( tangent.x * cross_x + tangent.y * cross_y + tangent.z * cross_z ); + + segment = new Segment( endPoints[0], endPoints[1], 0f ); + intermediateNormals = endPoints[0].intermediateNormals; + endPoints[0].normal = intermediateNormals[0] = rotatedNormal; + + for( int j = 1; j < smoothness; j++ ) + { + float localT = j * _1OverSmoothness; + intermediateNormals[j] = Quaternion.AngleAxis( Mathf.LerpUnclamped( normal0DeltaAngle, 0f, localT ), segment.GetTangent( localT ).normalized ) * intermediateNormals[j]; + } + } + } + } + } + } + + // Credit: https://www.youtube.com/watch?v=d9k97JemYbM + public EvenlySpacedPointsHolder CalculateEvenlySpacedPoints( float resolution = 10f, float accuracy = 3f ) + { + int segmentCount = m_loop ? endPoints.Count : ( endPoints.Count - 1 ); + List evenlySpacedPoints = new List( segmentCount + Mathf.CeilToInt( segmentCount * resolution * 1.25f ) ); + + // Calculate each spline segment's approximate length and store it temporarily in the list so that + // we won't have to calculate the same value twice in the 2nd loop. We'll remove these length values + // from the list at the end of the operation + float estimatedSplineLength = 0f; + for( int i = 0; i < segmentCount; i++ ) + { + BezierPoint point1 = endPoints[i]; + BezierPoint point2 = ( i < endPoints.Count - 1 ) ? endPoints[i + 1] : endPoints[0]; + + float controlNetLength = Vector3.Distance( point1.position, point1.followingControlPointPosition ) + Vector3.Distance( point1.followingControlPointPosition, point2.precedingControlPointPosition ) + Vector3.Distance( point2.precedingControlPointPosition, point2.position ); + float estimatedCurveLength = Vector3.Distance( point1.position, point2.position ) + controlNetLength * 0.5f; + + estimatedSplineLength += estimatedCurveLength; + evenlySpacedPoints.Add( estimatedCurveLength ); + } + + float averageSegmentLength = estimatedSplineLength / segmentCount; + float distanceBetweenEvenlySpacedPoints = averageSegmentLength / resolution; + float remainingDistanceToEvenlySpacedPoint = distanceBetweenEvenlySpacedPoints; + float totalLength = 0f; + + Vector3 previousPoint = endPoints[0].position; + evenlySpacedPoints.Add( 0f ); + + for( int i = 0; i < segmentCount; i++ ) + { + Segment segment = new Segment( endPoints[i], ( i < endPoints.Count - 1 ) ? endPoints[i + 1] : endPoints[0], 0f ); + + float estimatedCurveLength = evenlySpacedPoints[i]; + float tMultiplier = 1f / ( resolution * accuracy * ( estimatedCurveLength / averageSegmentLength ) ); + float t = 0, previousT = 0f; + while( t < 1f ) + { + t += tMultiplier; + if( t > 1f ) + t = 1f; + + Vector3 point = segment.GetPoint( t ); + float distanceToPreviousPoint = Vector3.Distance( previousPoint, point ); + while( distanceToPreviousPoint >= remainingDistanceToEvenlySpacedPoint ) + { + float newEvenlySpacedPointLocalT = previousT + ( t - previousT ) * ( remainingDistanceToEvenlySpacedPoint / distanceToPreviousPoint ); + evenlySpacedPoints.Add( segment.GetNormalizedT( newEvenlySpacedPointLocalT ) ); + + //distanceToPreviousPoint -= remainingDistanceToEvenlySpacedPoint; + distanceToPreviousPoint = Vector3.Distance( segment.GetPoint( newEvenlySpacedPointLocalT ), point ); + remainingDistanceToEvenlySpacedPoint = distanceBetweenEvenlySpacedPoints; + totalLength += distanceBetweenEvenlySpacedPoints; + previousT = newEvenlySpacedPointLocalT; + } + + remainingDistanceToEvenlySpacedPoint -= distanceToPreviousPoint; + previousT = t; + previousPoint = point; + } + } + + totalLength += distanceBetweenEvenlySpacedPoints - remainingDistanceToEvenlySpacedPoint; + + // If the last calculated evenly spaced point is too close to the final point (t=1f), remove it. + // The space between last 3 evenly spaced points won't really be even but the difference will be + // negligible when resolution isn't too small + if( remainingDistanceToEvenlySpacedPoint >= distanceBetweenEvenlySpacedPoints * 0.5f ) + evenlySpacedPoints.RemoveAt( evenlySpacedPoints.Count - 1 ); + + evenlySpacedPoints.Add( 1f ); + + // Remove spline segment lengths from list (which were temporarily stored there) + evenlySpacedPoints.RemoveRange( 0, segmentCount ); + + return new EvenlySpacedPointsHolder( this, totalLength, evenlySpacedPoints.ToArray() ); + } + + public PointCache GeneratePointCache( PointCacheFlags cachedData = PointCacheFlags.All, int resolution = 100 ) + { + return GeneratePointCache( evenlySpacedPoints, defaultExtraDataLerpFunction, cachedData, resolution ); + } + + public PointCache GeneratePointCache( EvenlySpacedPointsHolder lookupTable, ExtraDataLerpFunction extraDataLerpFunction, PointCacheFlags cachedData = PointCacheFlags.All, int resolution = 100 ) + { + if( cachedData == PointCacheFlags.None ) + return new PointCache( null, null, null, null, null, false ); + + if( lookupTable == null ) + lookupTable = evenlySpacedPoints; + + if( resolution < 2 ) + resolution = 2; + + Vector3[] positions = null, normals = null, tangents = null, bitangents = null; + BezierPoint.ExtraData[] extraDatas = null; + if( ( cachedData & PointCacheFlags.Positions ) == PointCacheFlags.Positions ) + positions = new Vector3[resolution]; + if( ( cachedData & PointCacheFlags.Normals ) == PointCacheFlags.Normals ) + normals = new Vector3[resolution]; + if( ( cachedData & PointCacheFlags.Tangents ) == PointCacheFlags.Tangents ) + tangents = new Vector3[resolution]; + if( ( cachedData & PointCacheFlags.Bitangents ) == PointCacheFlags.Bitangents ) + bitangents = new Vector3[resolution]; + if( ( cachedData & PointCacheFlags.ExtraDatas ) == PointCacheFlags.ExtraDatas ) + extraDatas = new BezierPoint.ExtraData[resolution]; + + float indexMultiplier = 1f / ( resolution - 1 ); + + for( int i = 0; i < resolution; i++ ) + { + Segment segment = GetSegmentAt( lookupTable.GetNormalizedTAtPercentage( i * indexMultiplier ) ); + + if( positions != null ) + positions[i] = segment.GetPoint(); + if( normals != null ) + normals[i] = segment.GetNormal().normalized; + if( tangents != null ) + tangents[i] = segment.GetTangent().normalized; + if( bitangents != null ) + { + Vector3 normal = ( normals != null ) ? normals[i] : segment.GetNormal().normalized; + Vector3 tangent = ( tangents != null ) ? tangents[i] : segment.GetTangent().normalized; + bitangents[i] = Vector3.Cross( normal, tangent ); + } + if( extraDatas != null ) + extraDatas[i] = segment.GetExtraData( extraDataLerpFunction ); + } + + return new PointCache( positions, normals, tangents, bitangents, extraDatas, loop ); + } + + public void ClearIntermediateNormals() + { + for( int i = 0; i < endPoints.Count; i++ ) + endPoints[i].intermediateNormals = null; + } + + private float AccuracyToStepSize( float accuracy ) + { + if( accuracy <= 0f ) + return 0.2f; + + return Mathf.Clamp( 1f / accuracy, 0.001f, 0.2f ); + } + + // Renders the spline gizmo during gameplay + // Credit: https://docs.unity3d.com/ScriptReference/GL.html + private void OnRenderObject() + { + if( !drawGizmos || endPoints.Count < 2 ) + return; + + if( !gizmoMaterial ) + { + Shader shader = Shader.Find( "Hidden/Internal-Colored" ); + gizmoMaterial = new Material( shader ) { hideFlags = HideFlags.HideAndDontSave }; + gizmoMaterial.SetInt( "_SrcBlend", (int) UnityEngine.Rendering.BlendMode.SrcAlpha ); + gizmoMaterial.SetInt( "_DstBlend", (int) UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha ); + gizmoMaterial.SetInt( "_Cull", (int) UnityEngine.Rendering.CullMode.Off ); + gizmoMaterial.SetInt( "_ZWrite", 0 ); + } + + gizmoMaterial.SetPass( 0 ); + + GL.Begin( GL.LINES ); + GL.Color( gizmoColor ); + + Vector3 lastPos = endPoints[0].position; + + float gizmoStep = 1f / ( endPoints.Count * Mathf.Clamp( gizmoSmoothness, 1, 30 ) ); + for( float i = gizmoStep; i < 1f; i += gizmoStep ) + { + GL.Vertex3( lastPos.x, lastPos.y, lastPos.z ); + lastPos = GetPoint( i ); + GL.Vertex3( lastPos.x, lastPos.y, lastPos.z ); + } + + GL.Vertex3( lastPos.x, lastPos.y, lastPos.z ); + lastPos = GetPoint( 1f ); + GL.Vertex3( lastPos.x, lastPos.y, lastPos.z ); + + GL.End(); + } + + IEnumerator IEnumerable.GetEnumerator() + { + return endPoints.GetEnumerator(); + } + + IEnumerator IEnumerable.GetEnumerator() + { + return endPoints.GetEnumerator(); + } + +#if UNITY_EDITOR + [ContextMenu( "Invert Spline" )] + private void InvertSplineContextMenu() + { + InvertSpline( "Invert spline" ); + } + + internal void Reset() + { + for( int i = endPoints.Count - 1; i >= 0; i-- ) + UnityEditor.Undo.DestroyObjectImmediate( endPoints[i].gameObject ); + + Initialize( 2 ); + + endPoints[0].localPosition = Vector3.back; + endPoints[1].localPosition = Vector3.forward; + + UnityEditor.Undo.RegisterCreatedObjectUndo( endPoints[0].gameObject, "Initialize Spline" ); + UnityEditor.Undo.RegisterCreatedObjectUndo( endPoints[1].gameObject, "Initialize Spline" ); + + UnityEditor.Selection.activeTransform = endPoints[0].transform; + } +#endif + } +} \ No newline at end of file diff --git a/Assets/Plugins/BezierSolution/BezierSpline.cs.meta b/Assets/Plugins/BezierSolution/BezierSpline.cs.meta new file mode 100644 index 00000000..84f3eaff --- /dev/null +++ b/Assets/Plugins/BezierSolution/BezierSpline.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: a3dbf94c21a22d74d895b2051a04ba1e +timeCreated: 1620216034 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: -400 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/BezierSolution/Demo.meta b/Assets/Plugins/BezierSolution/Demo.meta new file mode 100644 index 00000000..b09e0107 --- /dev/null +++ b/Assets/Plugins/BezierSolution/Demo.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 4b55326d0aea81b42b7f407fffdad047 +folderAsset: yes +timeCreated: 1620724489 +licenseType: Store +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/BezierSolution/Demo/DemoScene.unity b/Assets/Plugins/BezierSolution/Demo/DemoScene.unity new file mode 100644 index 00000000..0f7a0246 --- /dev/null +++ b/Assets/Plugins/BezierSolution/Demo/DemoScene.unity @@ -0,0 +1,6403 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!29 &1 +OcclusionCullingSettings: + m_ObjectHideFlags: 0 + serializedVersion: 2 + m_OcclusionBakeSettings: + smallestOccluder: 5 + smallestHole: 0.25 + backfaceThreshold: 100 + m_SceneGUID: 00000000000000000000000000000000 + m_OcclusionCullingData: {fileID: 0} +--- !u!104 &2 +RenderSettings: + m_ObjectHideFlags: 0 + serializedVersion: 8 + m_Fog: 0 + m_FogColor: {r: 0.5, g: 0.5, b: 0.5, a: 1} + m_FogMode: 3 + m_FogDensity: 0.01 + m_LinearFogStart: 0 + m_LinearFogEnd: 300 + m_AmbientSkyColor: {r: 0.46323532, g: 0.46163794, b: 0.45642304, a: 1} + m_AmbientEquatorColor: {r: 0.114, g: 0.125, b: 0.133, a: 1} + m_AmbientGroundColor: {r: 0.047, g: 0.043, b: 0.035, a: 1} + m_AmbientIntensity: 2 + m_AmbientMode: 3 + m_SubtractiveShadowColor: {r: 0.42, g: 0.478, b: 0.627, a: 1} + m_SkyboxMaterial: {fileID: 10304, guid: 0000000000000000f000000000000000, type: 0} + m_HaloStrength: 0.5 + m_FlareStrength: 1 + m_FlareFadeSpeed: 3 + m_HaloTexture: {fileID: 0} + m_SpotCookie: {fileID: 10001, guid: 0000000000000000e000000000000000, type: 0} + m_DefaultReflectionMode: 0 + m_DefaultReflectionResolution: 128 + m_ReflectionBounces: 1 + m_ReflectionIntensity: 1 + m_CustomReflection: {fileID: 0} + m_Sun: {fileID: 0} + m_IndirectSpecularColor: {r: 0, g: 0, b: 0, a: 1} +--- !u!157 &3 +LightmapSettings: + m_ObjectHideFlags: 0 + serializedVersion: 9 + m_GIWorkflowMode: 1 + m_GISettings: + serializedVersion: 2 + m_BounceScale: 1 + m_IndirectOutputScale: 1 + m_AlbedoBoost: 1 + m_TemporalCoherenceThreshold: 1 + m_EnvironmentLightingMode: 0 + m_EnableBakedLightmaps: 0 + m_EnableRealtimeLightmaps: 0 + m_LightmapEditorSettings: + serializedVersion: 8 + m_Resolution: 2 + m_BakeResolution: 40 + m_TextureWidth: 1024 + m_TextureHeight: 1024 + m_AO: 0 + m_AOMaxDistance: 1 + m_CompAOExponent: 1 + m_CompAOExponentDirect: 0 + m_Padding: 2 + m_LightmapParameters: {fileID: 0} + m_LightmapsBakeMode: 1 + m_TextureCompression: 1 + m_FinalGather: 0 + m_FinalGatherFiltering: 1 + m_FinalGatherRayCount: 256 + m_ReflectionCompression: 2 + m_MixedBakeMode: 1 + m_BakeBackend: 0 + m_PVRSampling: 1 + m_PVRDirectSampleCount: 32 + m_PVRSampleCount: 500 + m_PVRBounces: 2 + m_PVRFiltering: 0 + m_PVRFilteringMode: 1 + m_PVRCulling: 1 + m_PVRFilteringGaussRadiusDirect: 1 + m_PVRFilteringGaussRadiusIndirect: 5 + m_PVRFilteringGaussRadiusAO: 2 + m_PVRFilteringAtrousColorSigma: 1 + m_PVRFilteringAtrousNormalSigma: 1 + m_PVRFilteringAtrousPositionSigma: 1 + m_LightingDataAsset: {fileID: 0} + m_ShadowMaskMode: 2 +--- !u!196 &4 +NavMeshSettings: + serializedVersion: 2 + m_ObjectHideFlags: 0 + m_BuildSettings: + serializedVersion: 2 + agentTypeID: 0 + agentRadius: 0.5 + agentHeight: 2 + agentSlope: 45 + agentClimb: 0.4 + ledgeDropHeight: 0 + maxJumpAcrossDistance: 0 + minRegionArea: 2 + manualCellSize: 0 + cellSize: 0.16666667 + manualTileSize: 0 + tileSize: 256 + accuratePlacement: 0 + m_NavMeshData: {fileID: 0} +--- !u!1 &40843851 +GameObject: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + serializedVersion: 5 + m_Component: + - component: {fileID: 40843852} + - component: {fileID: 40843853} + m_Layer: 0 + m_Name: Point + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &40843852 +Transform: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 40843851} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0.09533131, y: 0, z: -0.37467003} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 728216727} + m_RootOrder: 8 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &40843853 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 40843851} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: b9cf9c5931a3b3c4ba456c8213d7ebfc, type: 3} + m_Name: + m_EditorClassIdentifier: + m_position: {x: -0.0009370744, y: 0.23681915, z: -0.81338} + m_precedingControlPointLocalPosition: {x: 0.1676443, y: 0, z: -0.1521187} + m_precedingControlPointPosition: {x: 0.45358112, y: -0.25398397, z: -0.621827} + m_followingControlPointLocalPosition: {x: -0.1676443, y: 0, z: 0.15211868} + m_followingControlPointPosition: {x: -0.45545524, y: 0.72762233, z: -1.004933} + m_handleMode: 0 + m_normal: {x: 0.58069587, y: 0.7, z: 0.4156831} + m_autoCalculatedNormalAngleOffset: 0 + m_extraData: + c1: 0 + c2: 0 + c3: 0 + c4: 0 +--- !u!1 &54814373 +GameObject: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + serializedVersion: 5 + m_Component: + - component: {fileID: 54814377} + - component: {fileID: 54814376} + - component: {fileID: 54814375} + - component: {fileID: 54814374} + - component: {fileID: 54814378} + m_Layer: 0 + m_Name: CubeConstantTime + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!23 &54814374 +MeshRenderer: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 54814373} + m_Enabled: 1 + m_CastShadows: 0 + m_ReceiveShadows: 0 + m_MotionVectors: 0 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_Materials: + - {fileID: 10303, guid: 0000000000000000f000000000000000, type: 0} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_PreserveUVs: 1 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_SelectedEditorRenderState: 3 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: 0 +--- !u!65 &54814375 +BoxCollider: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 54814373} + m_Material: {fileID: 0} + m_IsTrigger: 0 + m_Enabled: 1 + serializedVersion: 2 + m_Size: {x: 1, y: 1, z: 1} + m_Center: {x: 0, y: 0, z: 0} +--- !u!33 &54814376 +MeshFilter: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 54814373} + m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0} +--- !u!4 &54814377 +Transform: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 54814373} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: -6.211, y: 0, z: -1.793} + m_LocalScale: {x: 0.3480177, y: 0.34801766, z: 0.34801766} + m_Children: + - {fileID: 939553622} + - {fileID: 337675390} + m_Father: {fileID: 0} + m_RootOrder: 2 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &54814378 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 54814373} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 46d12b9f97514694e962a3395a73e638, type: 3} + m_Name: + m_EditorClassIdentifier: + spline: {fileID: 2112567397} + travelMode: 2 + travelTime: 5 + m_normalizedT: 0 + highQuality: 0 + movementLerpModifier: 10 + rotationLerpModifier: 10 + lookAt: 1 + onPathCompleted: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.Events.UnityEvent, UnityEngine, Version=0.0.0.0, Culture=neutral, + PublicKeyToken=null +--- !u!1 &122881950 +GameObject: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + serializedVersion: 5 + m_Component: + - component: {fileID: 122881951} + - component: {fileID: 122881952} + m_Layer: 0 + m_Name: Point + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &122881951 +Transform: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 122881950} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 2.2035134, y: 0, z: -0.914206} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 2112567398} + m_RootOrder: 8 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &122881952 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 122881950} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: b9cf9c5931a3b3c4ba456c8213d7ebfc, type: 3} + m_Name: + m_EditorClassIdentifier: + m_position: {x: -3.8904982, y: -0.88245815, z: -1.3306568} + m_precedingControlPointLocalPosition: {x: -0.04451251, y: -0, z: 0.13437235} + m_precedingControlPointPosition: {x: -3.944724, y: -0.7170844, z: -1.2501781} + m_followingControlPointLocalPosition: {x: 0.04451251, y: 0, z: -0.13437235} + m_followingControlPointPosition: {x: -3.8362718, y: -1.0478318, z: -1.4111356} + m_handleMode: 2 + m_normal: {x: -0.9049172, y: -0.3849958, z: 0.18139249} + m_autoCalculatedNormalAngleOffset: 0 + m_extraData: + c1: 0 + c2: 0 + c3: 0 + c4: 0 +--- !u!1 &126177800 +GameObject: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + serializedVersion: 5 + m_Component: + - component: {fileID: 126177802} + - component: {fileID: 126177801} + m_Layer: 0 + m_Name: BezierSpline + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &126177801 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 126177800} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: a3dbf94c21a22d74d895b2051a04ba1e, type: 3} + m_Name: + m_EditorClassIdentifier: + m_loop: 1 + drawGizmos: 0 + gizmoColor: {r: 0.94482756, g: 1, b: 0, a: 1} + gizmoSmoothness: 10 + m_autoConstructMode: 0 + m_autoCalculateNormals: 0 + m_autoCalculatedNormalsAngle: 0 +--- !u!4 &126177802 +Transform: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 126177800} + m_LocalRotation: {x: -0.7071068, y: 0, z: -0, w: 0.7071068} + m_LocalPosition: {x: -1.92, y: -1.1799998, z: 3.5899997} + m_LocalScale: {x: 2.1852562, y: 2.1852572, z: 2.1852572} + m_Children: + - {fileID: 631746914} + - {fileID: 662000307} + - {fileID: 1534014694} + - {fileID: 1985424694} + - {fileID: 1105749771} + - {fileID: 544969634} + m_Father: {fileID: 0} + m_RootOrder: 6 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &131298668 +GameObject: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + serializedVersion: 5 + m_Component: + - component: {fileID: 131298669} + - component: {fileID: 131298670} + m_Layer: 0 + m_Name: Point + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &131298669 +Transform: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 131298668} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 2.2071965, y: 0, z: 0.71702635} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 2112567398} + m_RootOrder: 4 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &131298670 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 131298668} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: b9cf9c5931a3b3c4ba456c8213d7ebfc, type: 3} + m_Name: + m_EditorClassIdentifier: + m_position: {x: -3.8501935, y: 1.1945807, z: -0.5778339} + m_precedingControlPointLocalPosition: {x: 0.022587538, y: -0, z: 0.10904813} + m_precedingControlPointPosition: {x: -3.8188117, y: 1.3362834, z: -0.5367127} + m_followingControlPointLocalPosition: {x: -0.022587538, y: 0, z: -0.10904813} + m_followingControlPointPosition: {x: -3.8815756, y: 1.0528779, z: -0.61895514} + m_handleMode: 2 + m_normal: {x: -0.9249737, y: 0.09831916, z: 0.36709264} + m_autoCalculatedNormalAngleOffset: 0 + m_extraData: + c1: 0 + c2: 0 + c3: 0 + c4: 0 +--- !u!1 &143379203 +GameObject: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + serializedVersion: 5 + m_Component: + - component: {fileID: 143379204} + - component: {fileID: 143379205} + m_Layer: 0 + m_Name: Point + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &143379204 +Transform: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 143379203} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0.14654635, y: 0, z: -0.27365372} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 728216727} + m_RootOrder: 14 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &143379205 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 143379203} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: b9cf9c5931a3b3c4ba456c8213d7ebfc, type: 3} + m_Name: + m_EditorClassIdentifier: + m_position: {x: 0.13402754, y: 0.536808, z: -0.6994278} + m_precedingControlPointLocalPosition: {x: 0.061824072, y: -0, z: -0.21266727} + m_precedingControlPointPosition: {x: 0.30577466, y: -0.12182021, z: -0.6876327} + m_followingControlPointLocalPosition: {x: -0.061824072, y: 0, z: 0.21266727} + m_followingControlPointPosition: {x: -0.037719548, y: 1.1954362, z: -0.7112229} + m_handleMode: 2 + m_normal: {x: 0.83512044, y: 0.22674516, z: 0.5011592} + m_autoCalculatedNormalAngleOffset: 0 + m_extraData: + c1: 0 + c2: 0 + c3: 0 + c4: 0 +--- !u!1 &154533942 +GameObject: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + serializedVersion: 5 + m_Component: + - component: {fileID: 154533943} + - component: {fileID: 154533944} + m_Layer: 0 + m_Name: Point + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &154533943 +Transform: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 154533942} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: -0.16923457, y: 0, z: -0.67851686} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 728216727} + m_RootOrder: 10 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &154533944 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 154533942} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: b9cf9c5931a3b3c4ba456c8213d7ebfc, type: 3} + m_Name: + m_EditorClassIdentifier: + m_position: {x: -0.70388436, y: -0.64788294, z: -1.3201047} + m_precedingControlPointLocalPosition: {x: -0.09696913, y: -0, z: 0.06397148} + m_precedingControlPointPosition: {x: -0.9661542, y: -0.43725896, z: -1.4399302} + m_followingControlPointLocalPosition: {x: 0.09696913, y: 0, z: -0.06397148} + m_followingControlPointPosition: {x: -0.44161463, y: -0.8585069, z: -1.2002796} + m_handleMode: 2 + m_normal: {x: -0.47486883, y: -0.799978, z: -0.36678988} + m_autoCalculatedNormalAngleOffset: 0 + m_extraData: + c1: 0 + c2: 0 + c3: 0 + c4: 0 +--- !u!1 &223479489 +GameObject: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + serializedVersion: 5 + m_Component: + - component: {fileID: 223479492} + - component: {fileID: 223479491} + - component: {fileID: 223479490} + - component: {fileID: 223479493} + m_Layer: 0 + m_Name: Line Renderer + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &223479490 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 223479489} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 09bf7d81c21c8564abb7c13d3e848e94, type: 3} + m_Name: + m_EditorClassIdentifier: + m_spline: {fileID: 728216726} + m_splineSampleRange: {x: 0, y: 1} + m_smoothness: 10 + executeInEditMode: 1 + prevSpline: {fileID: 728216726} +--- !u!120 &223479491 +LineRenderer: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 223479489} + m_Enabled: 1 + m_CastShadows: 1 + m_ReceiveShadows: 1 + m_MotionVectors: 0 + m_LightProbeUsage: 0 + m_ReflectionProbeUsage: 0 + m_Materials: + - {fileID: 10754, guid: 0000000000000000f000000000000000, type: 0} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_PreserveUVs: 0 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_SelectedEditorRenderState: 3 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: 0 + m_Positions: + - {x: 0, y: 0, z: 0} + - {x: 0.18870926, y: -0.35196757, z: 0.06055498} + - {x: 0.40720844, y: -0.63751316, z: 0.14628792} + - {x: 0.6490313, y: -0.86403537, z: 0.25263333} + - {x: 0.9077112, y: -1.0389333, z: 0.37502384} + - {x: 1.1767821, y: -1.1696053, z: 0.50889313} + - {x: 1.4497769, y: -1.2634516, z: 0.6496738} + - {x: 1.7202293, y: -1.3278708, z: 0.7927995} + - {x: 1.9816729, y: -1.3702619, z: 0.9337034} + - {x: 2.227641, y: -1.3980246, z: 1.0678186} + - {x: 2.4516673, y: -1.4185572, z: 1.1905786} + - {x: 2.6569571, y: -1.4205208, z: 1.3052297} + - {x: 2.8491502, y: -1.3914468, z: 1.4165242} + - {x: 3.025429, y: -1.3370361, z: 1.5221555} + - {x: 3.1829758, y: -1.2629929, z: 1.6198164} + - {x: 3.318974, y: -1.1750193, z: 1.7072} + - {x: 3.4306064, y: -1.0788181, z: 1.7819993} + - {x: 3.5150557, y: -0.980093, z: 1.8419073} + - {x: 3.5695045, y: -0.8845463, z: 1.8846169} + - {x: 3.591136, y: -0.7978809, z: 1.907821} + - {x: 3.577133, y: -0.72579956, z: 1.909213} + - {x: 3.5262089, y: -0.6724801, z: 1.8875377} + - {x: 3.4432025, y: -0.6359997, z: 1.8457495} + - {x: 3.334482, y: -0.61290956, z: 1.7878543} + - {x: 3.2064166, y: -0.5997622, z: 1.7178586} + - {x: 3.065375, y: -0.59310865, z: 1.6397686} + - {x: 2.9177265, y: -0.5895021, z: 1.5575905} + - {x: 2.7698398, y: -0.58549356, z: 1.4753305} + - {x: 2.6280837, y: -0.57763505, z: 1.396995} + - {x: 2.4988275, y: -0.56247854, z: 1.3265901} + - {x: 2.3884401, y: -0.5365758, z: 1.2681221} + - {x: 2.3020258, y: -0.49759603, z: 1.2247466} + - {x: 2.2396312, y: -0.4476812, z: 1.1962149} + - {x: 2.2000384, y: -0.39008784, z: 1.1814291} + - {x: 2.18203, y: -0.3280759, z: 1.1792897} + - {x: 2.1843874, y: -0.26490235, z: 1.1886983} + - {x: 2.2058935, y: -0.20382643, z: 1.2085557} + - {x: 2.2453299, y: -0.14810658, z: 1.237763} + - {x: 2.301479, y: -0.10100031, z: 1.2752217} + - {x: 2.3731232, y: -0.06576657, z: 1.3198328} + - {x: 2.459044, y: -0.045663357, z: 1.3704973} + - {x: 2.557375, y: -0.042583942, z: 1.4259284} + - {x: 2.6636553, y: -0.05296445, z: 1.4840848} + - {x: 2.7727737, y: -0.071871996, z: 1.5427383} + - {x: 2.8796206, y: -0.094377756, z: 1.5996594} + - {x: 2.979085, y: -0.11555052, z: 1.6526196} + - {x: 3.0660572, y: -0.1304605, z: 1.6993895} + - {x: 3.1354265, y: -0.13417697, z: 1.7377402} + - {x: 3.1820831, y: -0.121769905, z: 1.7654428} + - {x: 3.2009163, y: -0.088308096, z: 1.7802684} + - {x: 3.1868157, y: -0.028861761, z: 1.7799879} + - {x: 3.1368368, y: 0.059543133, z: 1.763334} + - {x: 3.056697, y: 0.17205381, z: 1.7328854} + - {x: 2.954279, y: 0.30186105, z: 1.6921822} + - {x: 2.8374658, y: 0.4421556, z: 1.6447648} + - {x: 2.7141404, y: 0.5861285, z: 1.5941734} + - {x: 2.5921855, y: 0.7269701, z: 1.5439482} + - {x: 2.479484, y: 0.8578713, z: 1.4976295} + - {x: 2.3839192, y: 0.9720228, z: 1.4587575} + - {x: 2.3133736, y: 1.0626156, z: 1.4308724} + - {x: 2.2757304, y: 1.1228399, z: 1.4175147} + - {x: 2.276269, y: 1.1483389, z: 1.4210812} + - {x: 2.3098574, y: 1.1445632, z: 1.4393973} + - {x: 2.3687596, y: 1.1194166, z: 1.4691453} + - {x: 2.4452403, y: 1.0808017, z: 1.5070076} + - {x: 2.5315633, y: 1.0366223, z: 1.5496665} + - {x: 2.6199937, y: 0.9947808, z: 1.593804} + - {x: 2.7027955, y: 0.96318066, z: 1.6361026} + - {x: 2.772233, y: 0.9497249, z: 1.6732444} + - {x: 2.820571, y: 0.96231675, z: 1.7019117} + - {x: 2.840073, y: 1.0088594, z: 1.7187868} + - {x: 2.8250499, y: 1.094814, z: 1.7213842} + - {x: 2.7779927, y: 1.2158728, z: 1.7105467} + - {x: 2.7034385, y: 1.3652878, z: 1.6879497} + - {x: 2.6059241, y: 1.5363095, z: 1.6552684} + - {x: 2.4899867, y: 1.722189, z: 1.614178} + - {x: 2.360163, y: 1.9161775, z: 1.5663536} + - {x: 2.2209902, y: 2.1115258, z: 1.5134706} + - {x: 2.077005, y: 2.301485, z: 1.4572041} + - {x: 1.9327445, y: 2.4793062, z: 1.3992293} + - {x: 1.792746, y: 2.6382403, z: 1.3412216} + - {x: 1.6608235, y: 2.7727356, z: 1.2846048} + - {x: 1.5379009, y: 2.88203, z: 1.2297986} + - {x: 1.4241797, y: 2.9665587, z: 1.1769713} + - {x: 1.319861, y: 3.0267565, z: 1.1262913} + - {x: 1.2251465, y: 3.0630584, z: 1.0779271} + - {x: 1.1402371, y: 3.0758996, z: 1.032047} + - {x: 1.0653346, y: 3.0657153, z: 0.9888195} + - {x: 1.0006398, y: 3.0329404, z: 0.9484128} + - {x: 0.9463544, y: 2.97801, z: 0.91099536} + - {x: 0.90267956, y: 2.901359, z: 0.8767357} + - {x: 0.8698128, y: 2.8041403, z: 0.84589183} + - {x: 0.84793496, y: 2.690377, z: 0.8190799} + - {x: 0.8372237, y: 2.5648096, z: 0.7970066} + - {x: 0.83785623, y: 2.4321787, z: 0.7803781} + - {x: 0.8500099, y: 2.297225, z: 0.7699008} + - {x: 0.87386185, y: 2.164689, z: 0.7662804} + - {x: 0.9095894, y: 2.039312, z: 0.77022386} + - {x: 0.9573699, y: 1.925834, z: 0.7824367} + - {x: 1.0173806, y: 1.8289957, z: 0.8036258} + - {x: 1.0897987, y: 1.7535381, z: 0.83449686} + - {x: 1.1741503, y: 1.7030176, z: 0.8752402} + - {x: 1.2673559, y: 1.676254, z: 0.9239812} + - {x: 1.3656857, y: 1.6708841, z: 0.9783293} + - {x: 1.4654086, y: 1.6845436, z: 1.0358939} + - {x: 1.5627943, y: 1.7148689, z: 1.0942845} + - {x: 1.6541125, y: 1.7594959, z: 1.15111} + - {x: 1.7356324, y: 1.8160608, z: 1.20398} + - {x: 1.8036237, y: 1.8821998, z: 1.2505039} + - {x: 1.8543559, y: 1.955549, z: 1.288291} + - {x: 1.8840985, y: 2.0337443, z: 1.3149506} + - {x: 1.8903966, y: 2.1143548, z: 1.3287973} + - {x: 1.8758975, y: 2.1946785, z: 1.330967} + - {x: 1.844524, y: 2.2719462, z: 1.3233006} + - {x: 1.8001993, y: 2.3433888, z: 1.3076394} + - {x: 1.7468457, y: 2.406237, z: 1.2858244} + - {x: 1.6883867, y: 2.4577215, z: 1.2596967} + - {x: 1.6287447, y: 2.4950733, z: 1.2310973} + - {x: 1.5718429, y: 2.5155232, z: 1.2018673} + - {x: 1.5216041, y: 2.5163019, z: 1.173848} + - {x: 1.481951, y: 2.4946404, z: 1.1488804} + - {x: 1.4559613, y: 2.449158, z: 1.1285101} + - {x: 1.4433311, y: 2.3840306, z: 1.1131017} + - {x: 1.4429114, y: 2.3048227, z: 1.1027248} + - {x: 1.4535527, y: 2.2170985, z: 1.0974482} + - {x: 1.4741063, y: 2.126423, z: 1.0973418} + - {x: 1.5034225, y: 2.0383599, z: 1.1024745} + - {x: 1.5403526, y: 1.9584742, z: 1.1129156} + - {x: 1.5837471, y: 1.8923302, z: 1.1287346} + - {x: 1.632457, y: 1.8454926, z: 1.1500007} + - {x: 1.6853331, y: 1.8235257, z: 1.1767831} + - {x: 1.7409636, y: 1.8307364, z: 1.2088432} + - {x: 1.7968856, y: 1.8664002, z: 1.2447095} + - {x: 1.8503737, y: 1.9285362, z: 1.2826034} + - {x: 1.8987029, y: 2.015162, z: 1.3207452} + - {x: 1.9391472, y: 2.124296, z: 1.3573563} + - {x: 1.9689815, y: 2.2539566, z: 1.3906568} + - {x: 1.9854805, y: 2.4021618, z: 1.4188681} + - {x: 1.9859186, y: 2.5669303, z: 1.4402108} + - {x: 1.9675704, y: 2.74628, z: 1.4529058} + - {x: 1.9277105, y: 2.938229, z: 1.4551737} + - {x: 1.8643728, y: 3.1402998, z: 1.4455972} + - {x: 1.7786278, y: 3.3480282, z: 1.424203} + - {x: 1.6723047, y: 3.5564542, z: 1.3913808} + - {x: 1.5472336, y: 3.7606175, z: 1.3475194} + - {x: 1.4052441, y: 3.955558, z: 1.2930077} + - {x: 1.2481657, y: 4.136316, z: 1.2282345} + - {x: 1.0778282, y: 4.2979302, z: 1.153589} + - {x: 0.89606106, y: 4.435442, z: 1.0694602} + - {x: 0.70469415, y: 4.54389, z: 0.9762367} + - {x: 0.50555706, y: 4.6183147, z: 0.8743079} + - {x: 0.30094647, y: 4.6548185, z: 0.76445997} + - {x: 0.09502673, y: 4.653752, z: 0.6490685} + - {x: -0.107569695, y: 4.6165285, z: 0.53090763} + - {x: -0.30221152, y: 4.5445623, z: 0.41275048} + - {x: -0.48426628, y: 4.439266, z: 0.29737067} + - {x: -0.6491027, y: 4.3020535, z: 0.18754125} + - {x: -0.7920892, y: 4.1343384, z: 0.086036205} + - {x: -0.90859365, y: 3.9375343, z: -0.004371643} + - {x: -0.9939842, y: 3.7130544, z: -0.08090854} + - {x: -1.0436292, y: 3.4623125, z: -0.14080095} + - {x: -1.0543416, y: 3.1869001, z: -0.1820612} + - {x: -1.0287147, y: 2.8891242, z: -0.20584607} + - {x: -0.97078586, y: 2.5714688, z: -0.21409655} + - {x: -0.884593, y: 2.2364194, z: -0.20875502} + - {x: -0.77417326, y: 1.886461, z: -0.19176197} + - {x: -0.6435652, y: 1.5240779, z: -0.16506004} + - {x: -0.4968059, y: 1.1517556, z: -0.13059139} + - {x: -0.33793354, y: 0.7719785, z: -0.09029722} + - {x: -0.17098558, y: 0.38723135, z: -0.04611945} + m_Parameters: + serializedVersion: 2 + widthMultiplier: 0.125 + widthCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 2 + time: 0 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + colorGradient: + serializedVersion: 2 + key0: {r: 1, g: 0, b: 0, a: 1} + key1: {r: 1, g: 0.49803922, b: 0, a: 1} + key2: {r: 1, g: 1, b: 0, a: 0} + key3: {r: 0, g: 1, b: 0, a: 0} + key4: {r: 0, g: 0, b: 1, a: 0} + key5: {r: 0.18039216, g: 0.16862746, b: 0.37254903, a: 0} + key6: {r: 0.54509807, g: 0, b: 1, a: 0} + key7: {r: 1, g: 0, b: 0, a: 0} + ctime0: 0 + ctime1: 9362 + ctime2: 18724 + ctime3: 28086 + ctime4: 37449 + ctime5: 46811 + ctime6: 56173 + ctime7: 65535 + atime0: 0 + atime1: 65535 + atime2: 0 + atime3: 0 + atime4: 0 + atime5: 0 + atime6: 0 + atime7: 0 + m_Mode: 0 + m_NumColorKeys: 8 + m_NumAlphaKeys: 2 + numCornerVertices: 0 + numCapVertices: 0 + alignment: 0 + textureMode: 0 + m_UseWorldSpace: 0 + m_Loop: 1 +--- !u!4 &223479492 +Transform: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 223479489} + m_LocalRotation: {x: -0, y: -0, z: -0.0000000074505797, w: 1} + m_LocalPosition: {x: -1.793683, y: -2.401421, z: -2.1546016} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 8 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &223479493 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 223479489} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 9b6258aafd9a87344833937e5e546638, type: 3} + m_Name: + m_EditorClassIdentifier: + m_spline: {fileID: 728216726} + m_normalizedT: 0 + m_updatePosition: 1 + m_positionOffset: {x: 0, y: 0, z: 0} + m_updateRotation: 0 + m_rotationOffset: {x: 0, y: 0, z: 0} + executeInEditMode: 1 + prevSpline: {fileID: 728216726} +--- !u!1 &337675389 +GameObject: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + serializedVersion: 5 + m_Component: + - component: {fileID: 337675390} + - component: {fileID: 337675393} + - component: {fileID: 337675392} + - component: {fileID: 337675391} + m_Layer: 0 + m_Name: Cube (2) + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &337675390 +Transform: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 337675389} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0.25000012, y: 0.24000002, z: 0.5600003} + m_LocalScale: {x: 0.31189755, y: 0.31189737, z: 0.3118974} + m_Children: [] + m_Father: {fileID: 54814377} + m_RootOrder: 1 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!23 &337675391 +MeshRenderer: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 337675389} + m_Enabled: 1 + m_CastShadows: 1 + m_ReceiveShadows: 1 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_Materials: + - {fileID: 10303, guid: 0000000000000000f000000000000000, type: 0} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_PreserveUVs: 1 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_SelectedEditorRenderState: 3 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: 0 +--- !u!65 &337675392 +BoxCollider: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 337675389} + m_Material: {fileID: 0} + m_IsTrigger: 0 + m_Enabled: 1 + serializedVersion: 2 + m_Size: {x: 1, y: 1, z: 1} + m_Center: {x: 0, y: 0, z: 0} +--- !u!33 &337675393 +MeshFilter: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 337675389} + m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0} +--- !u!1 &413396497 +GameObject: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + serializedVersion: 5 + m_Component: + - component: {fileID: 413396498} + - component: {fileID: 413396499} + m_Layer: 0 + m_Name: Point + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &413396498 +Transform: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 413396497} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 1.1932082, y: 0, z: 0.5836157} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 2112567398} + m_RootOrder: 5 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &413396499 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 413396497} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: b9cf9c5931a3b3c4ba456c8213d7ebfc, type: 3} + m_Name: + m_EditorClassIdentifier: + m_position: {x: -5.1551228, y: 0.89528805, z: -0.22174269} + m_precedingControlPointLocalPosition: {x: 0.25231743, y: -0, z: 0.07634574} + m_precedingControlPointPosition: {x: -4.829468, y: 1.0246911, z: -0.29039794} + m_followingControlPointLocalPosition: {x: -0.25231743, y: 0, z: -0.07634574} + m_followingControlPointPosition: {x: -5.480778, y: 0.76588506, z: -0.15308747} + m_handleMode: 2 + m_normal: {x: -0.25912416, y: 0.8722114, z: 0.41485173} + m_autoCalculatedNormalAngleOffset: 0 + m_extraData: + c1: 0 + c2: 0 + c3: 0 + c4: 0 +--- !u!1 &453311153 +GameObject: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + serializedVersion: 5 + m_Component: + - component: {fileID: 453311154} + - component: {fileID: 453311155} + m_Layer: 0 + m_Name: Point + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &453311154 +Transform: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 453311153} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0.33476523, y: 0, z: -1.2419409} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 728216727} + m_RootOrder: 4 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &453311155 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 453311153} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: b9cf9c5931a3b3c4ba456c8213d7ebfc, type: 3} + m_Name: + m_EditorClassIdentifier: + m_position: {x: 0.6653608, y: -2.4470844, z: -0.7841042} + m_precedingControlPointLocalPosition: {x: -0.11511052, y: -0, z: -0.01853376} + m_precedingControlPointPosition: {x: 0.3565162, y: -2.4852567, z: -0.96185434} + m_followingControlPointLocalPosition: {x: 0.11511052, y: 0, z: 0.01853376} + m_followingControlPointPosition: {x: 0.9742056, y: -2.4089122, z: -0.6063541} + m_handleMode: 2 + m_normal: {x: 0.14744414, y: -0.9880916, z: -0.043992385} + m_autoCalculatedNormalAngleOffset: 0 + m_extraData: + c1: 0 + c2: 0 + c3: 0 + c4: 0 +--- !u!1 &460958476 +GameObject: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + serializedVersion: 5 + m_Component: + - component: {fileID: 460958477} + - component: {fileID: 460958480} + - component: {fileID: 460958479} + - component: {fileID: 460958478} + m_Layer: 0 + m_Name: Cube + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &460958477 +Transform: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 460958476} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: -0.25, y: 0.241, z: 0.56} + m_LocalScale: {x: 0.31189713, y: 0.31189713, z: 0.31189713} + m_Children: [] + m_Father: {fileID: 1232478182} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!23 &460958478 +MeshRenderer: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 460958476} + m_Enabled: 1 + m_CastShadows: 1 + m_ReceiveShadows: 1 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_Materials: + - {fileID: 10303, guid: 0000000000000000f000000000000000, type: 0} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_PreserveUVs: 1 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_SelectedEditorRenderState: 3 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: 0 +--- !u!65 &460958479 +BoxCollider: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 460958476} + m_Material: {fileID: 0} + m_IsTrigger: 0 + m_Enabled: 1 + serializedVersion: 2 + m_Size: {x: 1, y: 1, z: 1} + m_Center: {x: 0, y: 0, z: 0} +--- !u!33 &460958480 +MeshFilter: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 460958476} + m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0} +--- !u!1 &464286540 +GameObject: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + serializedVersion: 5 + m_Component: + - component: {fileID: 464286541} + - component: {fileID: 464286542} + m_Layer: 0 + m_Name: Point + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &464286541 +Transform: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 464286540} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: -0.58062786, y: 0, z: -1.2748513} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 728216727} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &464286542 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 464286540} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: b9cf9c5931a3b3c4ba456c8213d7ebfc, type: 3} + m_Name: + m_EditorClassIdentifier: + m_position: {x: -1.793683, y: -2.401421, z: -2.1546016} + m_precedingControlPointLocalPosition: {x: -0.20887783, y: -0, z: 0.41264752} + m_precedingControlPointPosition: {x: -2.3658783, y: -1.1092684, z: -2.309412} + m_followingControlPointLocalPosition: {x: 0.20887783, y: 0, z: -0.41264752} + m_followingControlPointPosition: {x: -1.2214879, y: -3.693573, z: -1.9997915} + m_handleMode: 2 + m_normal: {x: -0.7773821, y: -0.4021886, z: -0.48365435} + m_autoCalculatedNormalAngleOffset: 0 + m_extraData: + c1: 0 + c2: 0 + c3: 0 + c4: 0 +--- !u!1 &544969633 +GameObject: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + serializedVersion: 5 + m_Component: + - component: {fileID: 544969634} + - component: {fileID: 544969635} + m_Layer: 0 + m_Name: Point + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &544969634 +Transform: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 544969633} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: -1.204, y: -0, z: 0.5} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 126177802} + m_RootOrder: 5 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &544969635 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 544969633} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: b9cf9c5931a3b3c4ba456c8213d7ebfc, type: 3} + m_Name: + m_EditorClassIdentifier: + m_position: {x: -4.5510483, y: -0.08737111, z: 3.5899997} + m_precedingControlPointLocalPosition: {x: -0.11810255, y: 0, z: 0.4408207} + m_precedingControlPointPosition: {x: -4.8091326, y: 0.87593555, z: 3.5899994} + m_followingControlPointLocalPosition: {x: 0.11810255, y: -0.000000007450581, z: -0.44082057} + m_followingControlPointPosition: {x: -4.292964, y: -1.0506775, z: 3.5899997} + m_handleMode: 2 + m_normal: {x: 0, y: 1, z: 0} + m_autoCalculatedNormalAngleOffset: 0 + m_extraData: + c1: 0 + c2: 0 + c3: 0 + c4: 0 +--- !u!1 &600501173 +GameObject: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + serializedVersion: 5 + m_Component: + - component: {fileID: 600501174} + - component: {fileID: 600501175} + m_Layer: 0 + m_Name: Point + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &600501174 +Transform: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 600501173} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: -1} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 2112567398} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &600501175 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 600501173} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: b9cf9c5931a3b3c4ba456c8213d7ebfc, type: 3} + m_Name: + m_EditorClassIdentifier: + m_position: {x: -6.7218084, y: -1.273006, z: -0.46243596} + m_precedingControlPointLocalPosition: {x: 0.23100758, y: -0, z: -0.2599901} + m_precedingControlPointPosition: {x: -6.4308515, y: -1.5744811, z: -0.6778449} + m_followingControlPointLocalPosition: {x: -0.23100758, y: 0, z: 0.2599901} + m_followingControlPointPosition: {x: -7.012766, y: -0.97153074, z: -0.2470271} + m_handleMode: 2 + m_normal: {x: 0.7193235, y: 0.694675, z: -0.00062566035} + m_autoCalculatedNormalAngleOffset: 0 + m_extraData: + c1: 0 + c2: 0 + c3: 0 + c4: 0 +--- !u!1 &625103346 +GameObject: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + serializedVersion: 5 + m_Component: + - component: {fileID: 625103347} + - component: {fileID: 625103348} + m_Layer: 0 + m_Name: Point + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &625103347 +Transform: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 625103346} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: -0.020844705, y: 0, z: -0.42781916} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 728216727} + m_RootOrder: 12 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &625103348 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 625103346} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: b9cf9c5931a3b3c4ba456c8213d7ebfc, type: 3} + m_Name: + m_EditorClassIdentifier: + m_position: {x: -0.31173208, y: 0.09321916, z: -1.0057212} + m_precedingControlPointLocalPosition: {x: 0.04138258, y: -0, z: 0.039102413} + m_precedingControlPointPosition: {x: -0.20155706, y: 0.2059021, z: -0.9296272} + m_followingControlPointLocalPosition: {x: -0.04138258, y: 0, z: -0.039102413} + m_followingControlPointPosition: {x: -0.42190713, y: -0.019463778, z: -1.0818152} + m_handleMode: 2 + m_normal: {x: -0.607768, y: 0.75676596, z: -0.24067266} + m_autoCalculatedNormalAngleOffset: 0 + m_extraData: + c1: 0 + c2: 0 + c3: 0 + c4: 0 +--- !u!1 &631746913 +GameObject: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + serializedVersion: 5 + m_Component: + - component: {fileID: 631746914} + - component: {fileID: 631746915} + m_Layer: 0 + m_Name: Point + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &631746914 +Transform: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 631746913} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: -1} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 126177802} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &631746915 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 631746913} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: b9cf9c5931a3b3c4ba456c8213d7ebfc, type: 3} + m_Name: + m_EditorClassIdentifier: + m_position: {x: -1.92, y: -3.3652573, z: 3.59} + m_precedingControlPointLocalPosition: {x: -0.37536645, y: 0, z: -0.011424422} + m_precedingControlPointPosition: {x: -2.7402718, y: -3.3902225, z: 3.59} + m_followingControlPointLocalPosition: {x: 0.37536645, y: -0, z: 0.011424422} + m_followingControlPointPosition: {x: -1.0997281, y: -3.340292, z: 3.59} + m_handleMode: 2 + m_normal: {x: 0, y: 1, z: 0} + m_autoCalculatedNormalAngleOffset: 0 + m_extraData: + c1: 0 + c2: 0 + c3: 0 + c4: 0 +--- !u!1 &658625639 +GameObject: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + serializedVersion: 5 + m_Component: + - component: {fileID: 658625640} + - component: {fileID: 658625641} + m_Layer: 0 + m_Name: Point + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &658625640 +Transform: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 658625639} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0.32759959, y: 0, z: -1.6923558} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 728216727} + m_RootOrder: 1 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &658625641 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 658625639} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: b9cf9c5931a3b3c4ba456c8213d7ebfc, type: 3} + m_Name: + m_EditorClassIdentifier: + m_position: {x: 0.65798414, y: -3.8199782, z: -0.964023} + m_precedingControlPointLocalPosition: {x: -0.26152948, y: -0, z: 0.0075016036} + m_precedingControlPointPosition: {x: -0.045015067, y: -3.755364, z: -1.349223} + m_followingControlPointLocalPosition: {x: 0.26152948, y: 0, z: -0.0075016036} + m_followingControlPointPosition: {x: 1.3609834, y: -3.8845925, z: -0.5788225} + m_handleMode: 2 + m_normal: {x: -0.016490009, y: -0.99056274, z: -0.13606451} + m_autoCalculatedNormalAngleOffset: 0 + m_extraData: + c1: 0 + c2: 0 + c3: 0 + c4: 0 +--- !u!1 &662000306 +GameObject: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + serializedVersion: 5 + m_Component: + - component: {fileID: 662000307} + - component: {fileID: 662000308} + m_Layer: 0 + m_Name: Point + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &662000307 +Transform: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 662000306} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 1.096, y: 0, z: 0.57} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 126177802} + m_RootOrder: 1 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &662000308 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 662000306} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: b9cf9c5931a3b3c4ba456c8213d7ebfc, type: 3} + m_Name: + m_EditorClassIdentifier: + m_position: {x: 0.4750408, y: 0.06559682, z: 3.5899997} + m_precedingControlPointLocalPosition: {x: -0.10456419, y: -0.000000014901161, z: -0.44148737} + m_precedingControlPointPosition: {x: 0.24654114, y: -0.8991667, z: 3.5899997} + m_followingControlPointLocalPosition: {x: 0.10456419, y: 0, z: 0.4414876} + m_followingControlPointPosition: {x: 0.70354044, y: 1.0303609, z: 3.5899994} + m_handleMode: 2 + m_normal: {x: 0, y: 1, z: 0} + m_autoCalculatedNormalAngleOffset: 0 + m_extraData: + c1: 0 + c2: 0 + c3: 0 + c4: 0 +--- !u!1 &711877544 +GameObject: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + serializedVersion: 5 + m_Component: + - component: {fileID: 711877545} + - component: {fileID: 711877546} + m_Layer: 0 + m_Name: Point + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &711877545 +Transform: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 711877544} + m_LocalRotation: {x: 0, y: -0.46767247, z: 0, w: 0.8839019} + m_LocalPosition: {x: -0.95804244, y: 0, z: -0.159632} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 728216727} + m_RootOrder: 16 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &711877546 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 711877544} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: b9cf9c5931a3b3c4ba456c8213d7ebfc, type: 3} + m_Name: + m_EditorClassIdentifier: + m_position: {x: -2.8373122, y: 1.0608914, z: -2.2954025} + m_precedingControlPointLocalPosition: {x: 0.26239017, y: -0, z: 0.12974901} + m_precedingControlPointPosition: {x: -2.7365513, y: 1.9388982, z: -2.126583} + m_followingControlPointLocalPosition: {x: -0.26239017, y: 0, z: -0.12974901} + m_followingControlPointPosition: {x: -2.9380734, y: 0.1828847, z: -2.4642222} + m_handleMode: 2 + m_normal: {x: -0.8694943, y: 0.18763782, z: -0.45691547} + m_autoCalculatedNormalAngleOffset: 0 + m_extraData: + c1: 0 + c2: 0 + c3: 0 + c4: 0 +--- !u!1 &728216725 +GameObject: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + serializedVersion: 5 + m_Component: + - component: {fileID: 728216727} + - component: {fileID: 728216726} + m_Layer: 0 + m_Name: BezierSpline + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &728216726 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 728216725} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: a3dbf94c21a22d74d895b2051a04ba1e, type: 3} + m_Name: + m_EditorClassIdentifier: + m_loop: 1 + drawGizmos: 0 + gizmoColor: {r: 1, g: 1, b: 1, a: 1} + gizmoSmoothness: 4 + m_autoConstructMode: 0 + m_autoCalculateNormals: 0 + m_autoCalculatedNormalsAngle: 0 +--- !u!4 &728216727 +Transform: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 728216725} + m_LocalRotation: {x: -0.64049584, y: -0.16919641, z: -0.18505219, w: 0.72587425} + m_LocalPosition: {x: -0.267, y: 1.395, z: -0.814} + m_LocalScale: {x: 3.073782, y: 3.0737824, z: 3.0737824} + m_Children: + - {fileID: 464286541} + - {fileID: 658625640} + - {fileID: 1446967690} + - {fileID: 1145851119} + - {fileID: 453311154} + - {fileID: 1614952849} + - {fileID: 2093860276} + - {fileID: 1162037918} + - {fileID: 40843852} + - {fileID: 898965707} + - {fileID: 154533943} + - {fileID: 1605569297} + - {fileID: 625103347} + - {fileID: 2095587045} + - {fileID: 143379204} + - {fileID: 1139223968} + - {fileID: 711877545} + m_Father: {fileID: 0} + m_RootOrder: 4 + m_LocalEulerAnglesHint: {x: -97.062996, y: -183.898, z: 155.113} +--- !u!1 &731062953 +GameObject: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + serializedVersion: 5 + m_Component: + - component: {fileID: 731062954} + - component: {fileID: 731062955} + m_Layer: 0 + m_Name: Point + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &731062954 +Transform: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 731062953} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0.8655467, y: 0, z: -0.59801215} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 2112567398} + m_RootOrder: 7 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &731062955 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 731062953} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: b9cf9c5931a3b3c4ba456c8213d7ebfc, type: 3} + m_Name: + m_EditorClassIdentifier: + m_position: {x: -5.6016293, y: -0.6507651, z: -0.63316625} + m_precedingControlPointLocalPosition: {x: -0.2517035, y: -0, z: 0.1955263} + m_precedingControlPointPosition: {x: -5.920567, y: -0.433995, z: -0.43904063} + m_followingControlPointLocalPosition: {x: 0.2517035, y: 0, z: -0.1955263} + m_followingControlPointPosition: {x: -5.2826915, y: -0.86753523, z: -0.8272919} + m_handleMode: 2 + m_normal: {x: -0.5942438, y: -0.79999065, z: -0.083001696} + m_autoCalculatedNormalAngleOffset: 0 + m_extraData: + c1: 0 + c2: 0 + c3: 0 + c4: 0 +--- !u!1 &762584196 +GameObject: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + serializedVersion: 5 + m_Component: + - component: {fileID: 762584197} + - component: {fileID: 762584198} + m_Layer: 0 + m_Name: Point + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &762584197 +Transform: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 762584196} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0.69329214, y: 0, z: 0.25895193} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 2112567398} + m_RootOrder: 6 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &762584198 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 762584196} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: b9cf9c5931a3b3c4ba456c8213d7ebfc, type: 3} + m_Name: + m_EditorClassIdentifier: + m_position: {x: -5.804125, y: 0.4181628, z: -0.16590267} + m_precedingControlPointLocalPosition: {x: 0.054610252, y: -0, z: 0.19693798} + m_precedingControlPointPosition: {x: -5.7297072, y: 0.67583835, z: -0.09733203} + m_followingControlPointLocalPosition: {x: -0.054610252, y: 0, z: -0.19693798} + m_followingControlPointPosition: {x: -5.8785424, y: 0.16048726, z: -0.23447327} + m_handleMode: 2 + m_normal: {x: -0.9091707, y: 0.16029505, z: 0.38433605} + m_autoCalculatedNormalAngleOffset: 0 + m_extraData: + c1: 0 + c2: 0 + c3: 0 + c4: 0 +--- !u!1 &895981909 +GameObject: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + serializedVersion: 5 + m_Component: + - component: {fileID: 895981910} + - component: {fileID: 895981911} + m_Layer: 0 + m_Name: Point + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &895981910 +Transform: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 895981909} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 1.328733, y: 0, z: 1.2379045} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 2112567398} + m_RootOrder: 3 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &895981911 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 895981909} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: b9cf9c5931a3b3c4ba456c8213d7ebfc, type: 3} + m_Name: + m_EditorClassIdentifier: + m_position: {x: -4.966832, y: 1.7455047, z: 0.024984956} + m_precedingControlPointLocalPosition: {x: -0.29872727, y: -0, z: 0.07156277} + m_precedingControlPointPosition: {x: -5.3488545, y: 1.7984647, z: 0.18116021} + m_followingControlPointLocalPosition: {x: 0.29872727, y: 0, z: -0.07156277} + m_followingControlPointPosition: {x: -4.5848093, y: 1.6925446, z: -0.13119042} + m_handleMode: 2 + m_normal: {x: -0.23649618, y: -0.93588424, z: -0.2611328} + m_autoCalculatedNormalAngleOffset: 0 + m_extraData: + c1: 0 + c2: 0 + c3: 0 + c4: 0 +--- !u!1 &898965706 +GameObject: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + serializedVersion: 5 + m_Component: + - component: {fileID: 898965707} + - component: {fileID: 898965708} + m_Layer: 0 + m_Name: Point + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &898965707 +Transform: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 898965706} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: -0.23520721, y: 0, z: -0.30570728} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 728216727} + m_RootOrder: 9 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &898965708 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 898965706} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: b9cf9c5931a3b3c4ba456c8213d7ebfc, type: 3} + m_Name: + m_EditorClassIdentifier: + m_position: {x: -0.8910035, y: 0.49993795, z: -1.2778659} + m_precedingControlPointLocalPosition: {x: 0.048472665, y: -0, z: 0.097998515} + m_precedingControlPointPosition: {x: -0.76332873, y: 0.7911583, z: -1.1691167} + m_followingControlPointLocalPosition: {x: -0.048472665, y: 0, z: -0.097998515} + m_followingControlPointPosition: {x: -1.0186782, y: 0.2087177, z: -1.3866152} + m_handleMode: 2 + m_normal: {x: -0.78797454, y: 0.48641947, z: -0.37748158} + m_autoCalculatedNormalAngleOffset: 0 + m_extraData: + c1: 0 + c2: 0 + c3: 0 + c4: 0 +--- !u!1 &939553621 +GameObject: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + serializedVersion: 5 + m_Component: + - component: {fileID: 939553622} + - component: {fileID: 939553625} + - component: {fileID: 939553624} + - component: {fileID: 939553623} + m_Layer: 0 + m_Name: Cube + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &939553622 +Transform: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 939553621} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: -0.25, y: 0.241, z: 0.56} + m_LocalScale: {x: 0.31189713, y: 0.31189713, z: 0.31189713} + m_Children: [] + m_Father: {fileID: 54814377} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!23 &939553623 +MeshRenderer: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 939553621} + m_Enabled: 1 + m_CastShadows: 1 + m_ReceiveShadows: 1 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_Materials: + - {fileID: 10303, guid: 0000000000000000f000000000000000, type: 0} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_PreserveUVs: 1 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_SelectedEditorRenderState: 3 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: 0 +--- !u!65 &939553624 +BoxCollider: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 939553621} + m_Material: {fileID: 0} + m_IsTrigger: 0 + m_Enabled: 1 + serializedVersion: 2 + m_Size: {x: 1, y: 1, z: 1} + m_Center: {x: 0, y: 0, z: 0} +--- !u!33 &939553625 +MeshFilter: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 939553621} + m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0} +--- !u!1 &955921217 +GameObject: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + serializedVersion: 5 + m_Component: + - component: {fileID: 955921218} + - component: {fileID: 955921219} + m_Layer: 0 + m_Name: Point + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &955921218 +Transform: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 955921217} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0.4148326, y: 0, z: 1.1464027} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 2112567398} + m_RootOrder: 2 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &955921219 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 955921217} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: b9cf9c5931a3b3c4ba456c8213d7ebfc, type: 3} + m_Name: + m_EditorClassIdentifier: + m_position: {x: -6.1423287, y: 1.5123409, z: 0.35921788} + m_precedingControlPointLocalPosition: {x: -0.26369286, y: -0, z: -0.18036842} + m_precedingControlPointPosition: {x: -6.4848595, y: 1.249064, z: 0.38445622} + m_followingControlPointLocalPosition: {x: 0.26369286, y: 0, z: 0.18036842} + m_followingControlPointPosition: {x: -5.7997985, y: 1.7756177, z: 0.3339796} + m_handleMode: 2 + m_normal: {x: 0.52189255, y: -0.7224707, z: -0.4535023} + m_autoCalculatedNormalAngleOffset: 0 + m_extraData: + c1: 0 + c2: 0 + c3: 0 + c4: 0 +--- !u!1 &1060012329 +GameObject: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + serializedVersion: 5 + m_Component: + - component: {fileID: 1060012330} + - component: {fileID: 1060012331} + m_Layer: 0 + m_Name: Point + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &1060012330 +Transform: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 1060012329} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: -0.2534232, y: 0, z: 0.15569419} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 2112567398} + m_RootOrder: 1 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &1060012331 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 1060012329} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: b9cf9c5931a3b3c4ba456c8213d7ebfc, type: 3} + m_Name: + m_EditorClassIdentifier: + m_position: {x: -7.0220146, y: 0.16584405, z: 0.17641443} + m_precedingControlPointLocalPosition: {x: -0.069139004, y: -0, z: -0.3577338} + m_precedingControlPointPosition: {x: -7.1185946, y: -0.29838046, z: 0.039472237} + m_followingControlPointLocalPosition: {x: 0.069139004, y: 0, z: 0.3577338} + m_followingControlPointPosition: {x: -6.925434, y: 0.6300685, z: 0.3133566} + m_handleMode: 2 + m_normal: {x: 0.9276652, y: -0.08578991, z: -0.3634246} + m_autoCalculatedNormalAngleOffset: 0 + m_extraData: + c1: 0 + c2: 0 + c3: 0 + c4: 0 +--- !u!1 &1105749770 +GameObject: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + serializedVersion: 5 + m_Component: + - component: {fileID: 1105749771} + - component: {fileID: 1105749772} + m_Layer: 0 + m_Name: Point + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &1105749771 +Transform: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 1105749770} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: -0.764, y: -0, z: 1.19} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 126177802} + m_RootOrder: 4 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &1105749772 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 1105749770} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: b9cf9c5931a3b3c4ba456c8213d7ebfc, type: 3} + m_Name: + m_EditorClassIdentifier: + m_position: {x: -3.5895357, y: 1.4204566, z: 3.5899994} + m_precedingControlPointLocalPosition: {x: 0.2513588, y: 0, z: -0.102871776} + m_precedingControlPointPosition: {x: -3.0402522, y: 1.1956553, z: 3.5899994} + m_followingControlPointLocalPosition: {x: -0.2513587, y: 0, z: 0.102872014} + m_followingControlPointPosition: {x: -4.1388187, y: 1.6452584, z: 3.5899994} + m_handleMode: 2 + m_normal: {x: 0, y: 1, z: 0} + m_autoCalculatedNormalAngleOffset: 0 + m_extraData: + c1: 0 + c2: 0 + c3: 0 + c4: 0 +--- !u!1 &1108260712 +GameObject: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + serializedVersion: 5 + m_Component: + - component: {fileID: 1108260713} + - component: {fileID: 1108260716} + - component: {fileID: 1108260715} + - component: {fileID: 1108260714} + m_Layer: 0 + m_Name: Cube (2) + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &1108260713 +Transform: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 1108260712} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0.25, y: 0.24, z: 0.56} + m_LocalScale: {x: 0.31189734, y: 0.31189725, z: 0.31189728} + m_Children: [] + m_Father: {fileID: 1232478182} + m_RootOrder: 1 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!23 &1108260714 +MeshRenderer: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 1108260712} + m_Enabled: 1 + m_CastShadows: 1 + m_ReceiveShadows: 1 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_Materials: + - {fileID: 10303, guid: 0000000000000000f000000000000000, type: 0} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_PreserveUVs: 1 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_SelectedEditorRenderState: 3 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: 0 +--- !u!65 &1108260715 +BoxCollider: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 1108260712} + m_Material: {fileID: 0} + m_IsTrigger: 0 + m_Enabled: 1 + serializedVersion: 2 + m_Size: {x: 1, y: 1, z: 1} + m_Center: {x: 0, y: 0, z: 0} +--- !u!33 &1108260716 +MeshFilter: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 1108260712} + m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0} +--- !u!1 &1139223967 +GameObject: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + serializedVersion: 5 + m_Component: + - component: {fileID: 1139223968} + - component: {fileID: 1139223969} + m_Layer: 0 + m_Name: Point + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &1139223968 +Transform: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 1139223967} + m_LocalRotation: {x: 0, y: -0.43977654, z: 0, w: 0.8981073} + m_LocalPosition: {x: -0.37753546, y: 0, z: 0.24967329} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 728216727} + m_RootOrder: 15 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &1139223969 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 1139223967} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: b9cf9c5931a3b3c4ba456c8213d7ebfc, type: 3} + m_Name: + m_EditorClassIdentifier: + m_position: {x: -1.288126, y: 2.216894, z: -1.2802937} + m_precedingControlPointLocalPosition: {x: 0.11589549, y: -0, z: -0.22728457} + m_precedingControlPointPosition: {x: -0.61341816, y: 2.0310283, z: -0.9264536} + m_followingControlPointLocalPosition: {x: -0.11589549, y: 0, z: 0.22728457} + m_followingControlPointPosition: {x: -1.9628341, y: 2.4027593, z: -1.6341338} + m_handleMode: 2 + m_normal: {x: 0.15332708, y: 0.96464854, z: 0.21434553} + m_autoCalculatedNormalAngleOffset: 0 + m_extraData: + c1: 0 + c2: 0 + c3: 0 + c4: 0 +--- !u!1 &1145851118 +GameObject: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + serializedVersion: 5 + m_Component: + - component: {fileID: 1145851119} + - component: {fileID: 1145851120} + m_Layer: 0 + m_Name: Point + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &1145851119 +Transform: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 1145851118} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0.30689815, y: 0, z: -1.4043213} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 728216727} + m_RootOrder: 3 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &1145851120 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 1145851118} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: b9cf9c5931a3b3c4ba456c8213d7ebfc, type: 3} + m_Name: + m_EditorClassIdentifier: + m_position: {x: 0.5947571, y: -2.9379969, z: -0.8864795} + m_precedingControlPointLocalPosition: {x: 0.122305445, y: -0, z: -0.029033283} + m_precedingControlPointPosition: {x: 0.924191, y: -3.0460806, z: -0.7159325} + m_followingControlPointLocalPosition: {x: -0.122305445, y: 0, z: 0.029033283} + m_followingControlPointPosition: {x: 0.26532307, y: -2.8299122, z: -1.0570265} + m_handleMode: 2 + m_normal: {x: 0.1935738, y: 0.95363593, z: 0.23045112} + m_autoCalculatedNormalAngleOffset: 0 + m_extraData: + c1: 0 + c2: 0 + c3: 0 + c4: 0 +--- !u!1 &1162037917 +GameObject: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + serializedVersion: 5 + m_Component: + - component: {fileID: 1162037918} + - component: {fileID: 1162037919} + m_Layer: 0 + m_Name: Point + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &1162037918 +Transform: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 1162037917} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0.48002267, y: 0, z: -0.88866645} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 728216727} + m_RootOrder: 7 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &1162037919 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 1162037917} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: b9cf9c5931a3b3c4ba456c8213d7ebfc, type: 3} + m_Name: + m_EditorClassIdentifier: + m_position: {x: 1.0463902, y: -1.3925617, z: -0.43581474} + m_precedingControlPointLocalPosition: {x: -0.0038200452, y: -0, z: -0.07248306} + m_precedingControlPointPosition: {x: 1.0380363, y: -1.6130693, z: -0.4687251} + m_followingControlPointLocalPosition: {x: 0.0038200452, y: 0, z: 0.07248306} + m_followingControlPointPosition: {x: 1.054744, y: -1.172054, z: -0.4029044} + m_handleMode: 2 + m_normal: {x: 0.8731006, y: -0.10416141, z: 0.4762834} + m_autoCalculatedNormalAngleOffset: 0 + m_extraData: + c1: 0 + c2: 0 + c3: 0 + c4: 0 +--- !u!1 &1232478177 +GameObject: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + serializedVersion: 5 + m_Component: + - component: {fileID: 1232478182} + - component: {fileID: 1232478181} + - component: {fileID: 1232478180} + - component: {fileID: 1232478179} + - component: {fileID: 1232478178} + m_Layer: 0 + m_Name: CubeConstantSpeed + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &1232478178 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 1232478177} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 148310ac13c958d4c93f53cdfe985375, type: 3} + m_Name: + m_EditorClassIdentifier: + spline: {fileID: 728216726} + travelMode: 1 + speed: 3 + m_normalizedT: 0 + rotationLerpModifier: 10 + lookAt: 1 + onPathCompleted: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.Events.UnityEvent, UnityEngine, Version=0.0.0.0, Culture=neutral, + PublicKeyToken=null +--- !u!23 &1232478179 +MeshRenderer: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 1232478177} + m_Enabled: 1 + m_CastShadows: 0 + m_ReceiveShadows: 0 + m_MotionVectors: 0 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_Materials: + - {fileID: 10303, guid: 0000000000000000f000000000000000, type: 0} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_PreserveUVs: 1 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_SelectedEditorRenderState: 3 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: 0 +--- !u!65 &1232478180 +BoxCollider: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 1232478177} + m_Material: {fileID: 0} + m_IsTrigger: 0 + m_Enabled: 1 + serializedVersion: 2 + m_Size: {x: 1, y: 1, z: 1} + m_Center: {x: 0, y: 0, z: 0} +--- !u!33 &1232478181 +MeshFilter: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 1232478177} + m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0} +--- !u!4 &1232478182 +Transform: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 1232478177} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: -2.163, y: 0, z: -3.046} + m_LocalScale: {x: 0.3480177, y: 0.34801766, z: 0.34801766} + m_Children: + - {fileID: 460958477} + - {fileID: 1108260713} + m_Father: {fileID: 0} + m_RootOrder: 3 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1 &1322218942 +GameObject: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + serializedVersion: 5 + m_Component: + - component: {fileID: 1322218943} + - component: {fileID: 1322218944} + m_Layer: 0 + m_Name: Point + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &1322218943 +Transform: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 1322218942} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 1.1326222, y: 0, z: -1.4042461} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 2112567398} + m_RootOrder: 9 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &1322218944 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 1322218942} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: b9cf9c5931a3b3c4ba456c8213d7ebfc, type: 3} + m_Name: + m_EditorClassIdentifier: + m_position: {x: -5.276272, y: -1.643007, z: -1.1160387} + m_precedingControlPointLocalPosition: {x: 0.36725235, y: -0, z: 0.014299035} + m_precedingControlPointPosition: {x: -4.8043866, y: -1.5779157, z: -1.2607422} + m_followingControlPointLocalPosition: {x: -0.36725235, y: 0, z: -0.014299035} + m_followingControlPointPosition: {x: -5.748157, y: -1.7080985, z: -0.9713352} + m_handleMode: 2 + m_normal: {x: -0.020790216, y: 0.9354034, z: 0.3529707} + m_autoCalculatedNormalAngleOffset: 0 + m_extraData: + c1: 0 + c2: 0 + c3: 0 + c4: 0 +--- !u!1 &1446967689 +GameObject: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + serializedVersion: 5 + m_Component: + - component: {fileID: 1446967690} + - component: {fileID: 1446967691} + m_Layer: 0 + m_Name: Point + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &1446967690 +Transform: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 1446967689} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0.7488578, y: 0, z: -1.4432334} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 728216727} + m_RootOrder: 2 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &1446967691 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 1446967689} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: b9cf9c5931a3b3c4ba456c8213d7ebfc, type: 3} + m_Name: + m_EditorClassIdentifier: + m_position: {x: 1.7834499, y: -3.1272206, z: -0.24538863} + m_precedingControlPointLocalPosition: {x: 0.039981365, y: -0, z: -0.06662555} + m_precedingControlPointPosition: {x: 1.892648, y: -3.3368483, z: -0.21111095} + m_followingControlPointLocalPosition: {x: -0.039981365, y: 0, z: 0.06662555} + m_followingControlPointPosition: {x: 1.6742518, y: -2.9175935, z: -0.27966607} + m_handleMode: 2 + m_normal: {x: 0.7452239, y: 0.46616223, z: 0.47679573} + m_autoCalculatedNormalAngleOffset: 0 + m_extraData: + c1: 0 + c2: 0 + c3: 0 + c4: 0 +--- !u!1001 &1452082602 +Prefab: + m_ObjectHideFlags: 0 + serializedVersion: 2 + m_Modification: + m_TransformParent: {fileID: 0} + m_Modifications: + - target: {fileID: 400002, guid: 44b1882f3e87f214ba0c12a8e3b15d36, type: 3} + propertyPath: m_LocalPosition.x + value: -6.7218084 + objectReference: {fileID: 0} + - target: {fileID: 400002, guid: 44b1882f3e87f214ba0c12a8e3b15d36, type: 3} + propertyPath: m_LocalPosition.y + value: -1.273006 + objectReference: {fileID: 0} + - target: {fileID: 400002, guid: 44b1882f3e87f214ba0c12a8e3b15d36, type: 3} + propertyPath: m_LocalPosition.z + value: -0.46243596 + objectReference: {fileID: 0} + - target: {fileID: 400002, guid: 44b1882f3e87f214ba0c12a8e3b15d36, type: 3} + propertyPath: m_LocalRotation.x + value: -0 + objectReference: {fileID: 0} + - target: {fileID: 400002, guid: 44b1882f3e87f214ba0c12a8e3b15d36, type: 3} + propertyPath: m_LocalRotation.y + value: -0 + objectReference: {fileID: 0} + - target: {fileID: 400002, guid: 44b1882f3e87f214ba0c12a8e3b15d36, type: 3} + propertyPath: m_LocalRotation.z + value: -0 + objectReference: {fileID: 0} + - target: {fileID: 400002, guid: 44b1882f3e87f214ba0c12a8e3b15d36, type: 3} + propertyPath: m_LocalRotation.w + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 400002, guid: 44b1882f3e87f214ba0c12a8e3b15d36, type: 3} + propertyPath: m_RootOrder + value: 9 + objectReference: {fileID: 0} + - target: {fileID: 400002, guid: 44b1882f3e87f214ba0c12a8e3b15d36, type: 3} + propertyPath: m_LocalScale.x + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 400002, guid: 44b1882f3e87f214ba0c12a8e3b15d36, type: 3} + propertyPath: m_LocalScale.y + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 400002, guid: 44b1882f3e87f214ba0c12a8e3b15d36, type: 3} + propertyPath: m_LocalScale.z + value: 1 + objectReference: {fileID: 0} + - target: {fileID: 3300000, guid: 44b1882f3e87f214ba0c12a8e3b15d36, type: 3} + propertyPath: m_Mesh + value: + objectReference: {fileID: 4300000, guid: 44b1882f3e87f214ba0c12a8e3b15d36, type: 3} + - target: {fileID: 400000, guid: 44b1882f3e87f214ba0c12a8e3b15d36, type: 3} + propertyPath: m_LocalPosition.x + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 400000, guid: 44b1882f3e87f214ba0c12a8e3b15d36, type: 3} + propertyPath: m_LocalPosition.z + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 400000, guid: 44b1882f3e87f214ba0c12a8e3b15d36, type: 3} + propertyPath: m_LocalPosition.y + value: 0 + objectReference: {fileID: 0} + - target: {fileID: 2300000, guid: 44b1882f3e87f214ba0c12a8e3b15d36, type: 3} + propertyPath: m_Materials.Array.data[0] + value: + objectReference: {fileID: 2100000, guid: 6b88831b1ed3c38439c9be5ac64f87c1, type: 2} + m_RemovedComponents: [] + m_ParentPrefab: {fileID: 100100000, guid: 44b1882f3e87f214ba0c12a8e3b15d36, type: 3} + m_IsPrefabParent: 0 +--- !u!1 &1452082603 stripped +GameObject: + m_PrefabParentObject: {fileID: 100000, guid: 44b1882f3e87f214ba0c12a8e3b15d36, type: 3} + m_PrefabInternal: {fileID: 1452082602} +--- !u!114 &1452082604 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 1452082603} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 0e815427364673446939224ffdf5e5fd, type: 3} + m_Name: + m_EditorClassIdentifier: + m_spline: {fileID: 2112567397} + m_splineSampleRange: {x: 0, y: 1} + m_highQuality: 1 + m_bendAxis: 1 + m_extraRotation: 0 + m_invertDirection: 0 + m_thicknessMultiplier: {x: 0.1, y: 0.1} + m_normalsMode: 0 + m_tangentsMode: 0 + m_autoRefresh: 1 + executeInEditMode: 1 + prevSpline: {fileID: 2112567397} + prevNormalsMode: 0 + prevTangentsMode: 0 + prevHighQuality: 1 + originalMesh: {fileID: 4300000, guid: 44b1882f3e87f214ba0c12a8e3b15d36, type: 3} +--- !u!1 &1452082605 stripped +GameObject: + m_PrefabParentObject: {fileID: 100002, guid: 44b1882f3e87f214ba0c12a8e3b15d36, type: 3} + m_PrefabInternal: {fileID: 1452082602} +--- !u!114 &1452082606 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 1452082605} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 9b6258aafd9a87344833937e5e546638, type: 3} + m_Name: + m_EditorClassIdentifier: + m_spline: {fileID: 2112567397} + m_normalizedT: 0 + m_updatePosition: 1 + m_positionOffset: {x: 0, y: 0, z: 0} + m_updateRotation: 0 + m_rotationOffset: {x: 0, y: 0, z: 0} + executeInEditMode: 1 + prevSpline: {fileID: 2112567397} +--- !u!1 &1534014693 +GameObject: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + serializedVersion: 5 + m_Component: + - component: {fileID: 1534014694} + - component: {fileID: 1534014695} + m_Layer: 0 + m_Name: Point + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &1534014694 +Transform: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 1534014693} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0.646, y: -0, z: 1.21} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 126177802} + m_RootOrder: 2 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &1534014695 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 1534014693} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: b9cf9c5931a3b3c4ba456c8213d7ebfc, type: 3} + m_Name: + m_EditorClassIdentifier: + m_position: {x: -0.5083244, y: 1.4641616, z: 3.5899994} + m_precedingControlPointLocalPosition: {x: 0.2679745, y: 0.00000011920929, z: 0.12020564} + m_precedingControlPointPosition: {x: 0.0772686, y: 1.7268419, z: 3.5899992} + m_followingControlPointLocalPosition: {x: -0.26797426, y: 0, z: -0.120205164} + m_followingControlPointPosition: {x: -1.0939168, y: 1.2014825, z: 3.5899994} + m_handleMode: 2 + m_normal: {x: 0, y: 1, z: 0} + m_autoCalculatedNormalAngleOffset: 0 + m_extraData: + c1: 0 + c2: 0 + c3: 0 + c4: 0 +--- !u!1 &1605569296 +GameObject: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + serializedVersion: 5 + m_Component: + - component: {fileID: 1605569297} + - component: {fileID: 1605569298} + m_Layer: 0 + m_Name: Point + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &1605569297 +Transform: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 1605569296} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0.12739748, y: 0, z: -0.57114893} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 728216727} + m_RootOrder: 11 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &1605569298 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 1605569296} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: b9cf9c5931a3b3c4ba456c8213d7ebfc, type: 3} + m_Name: + m_EditorClassIdentifier: + m_position: {x: 0.09041545, y: -0.36767662, z: -0.839651} + m_precedingControlPointLocalPosition: {x: -0.023200836, y: -0, z: -0.0884429} + m_precedingControlPointPosition: {x: 0.030401051, y: -0.63377905, z: -0.9073142} + m_followingControlPointLocalPosition: {x: 0.023200836, y: 0, z: 0.0884429} + m_followingControlPointPosition: {x: 0.15042987, y: -0.10157418, z: -0.7719878} + m_handleMode: 2 + m_normal: {x: 0.84708905, y: -0.30220485, z: 0.43716398} + m_autoCalculatedNormalAngleOffset: 0 + m_extraData: + c1: 0 + c2: 0 + c3: 0 + c4: 0 +--- !u!1 &1614952848 +GameObject: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + serializedVersion: 5 + m_Component: + - component: {fileID: 1614952849} + - component: {fileID: 1614952850} + m_Layer: 0 + m_Name: Point + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &1614952849 +Transform: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 1614952848} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0.60577995, y: 0, z: -1.222258} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 728216727} + m_RootOrder: 5 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &1614952850 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 1614952848} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: b9cf9c5931a3b3c4ba456c8213d7ebfc, type: 3} + m_Name: + m_EditorClassIdentifier: + m_position: {x: 1.3931326, y: -2.4302828, z: -0.37461364} + m_precedingControlPointLocalPosition: {x: 0.039254766, y: -0, z: -0.07889486} + m_precedingControlPointPosition: {x: 1.5007018, y: -2.6772232, z: -0.34602535} + m_followingControlPointLocalPosition: {x: -0.039254766, y: 0, z: 0.07889486} + m_followingControlPointPosition: {x: 1.2855636, y: -2.1833425, z: -0.40320194} + m_handleMode: 2 + m_normal: {x: 0.7788984, y: 0.39562988, z: 0.4866151} + m_autoCalculatedNormalAngleOffset: 0 + m_extraData: + c1: 0 + c2: 0 + c3: 0 + c4: 0 +--- !u!1 &1733954120 +GameObject: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + serializedVersion: 5 + m_Component: + - component: {fileID: 1733954124} + - component: {fileID: 1733954123} + - component: {fileID: 1733954122} + - component: {fileID: 1733954121} + - component: {fileID: 1733954125} + m_Layer: 0 + m_Name: Particle System + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &1733954121 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 1733954120} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 954f54b0dafe0cf488e4e15934cae013, type: 3} + m_Name: + m_EditorClassIdentifier: + spline: {fileID: 126177801} + followMode: 0 +--- !u!199 &1733954122 +ParticleSystemRenderer: + serializedVersion: 3 + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 1733954120} + m_Enabled: 1 + m_CastShadows: 0 + m_ReceiveShadows: 0 + m_MotionVectors: 1 + m_LightProbeUsage: 0 + m_ReflectionProbeUsage: 0 + m_Materials: + - {fileID: 10301, guid: 0000000000000000f000000000000000, type: 0} + - {fileID: 10301, guid: 0000000000000000f000000000000000, type: 0} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_PreserveUVs: 0 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_SelectedEditorRenderState: 0 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: 0 + m_RenderMode: 5 + m_SortMode: 0 + m_MinParticleSize: 0 + m_MaxParticleSize: 0.5 + m_CameraVelocityScale: 0 + m_VelocityScale: 0 + m_LengthScale: 2 + m_SortingFudge: 0 + m_NormalDirection: 1 + m_RenderAlignment: 0 + m_Pivot: {x: 0, y: 0, z: 0} + m_UseCustomVertexStreams: 0 + m_VertexStreams: 00010304 + m_Mesh: {fileID: 0} + m_Mesh1: {fileID: 0} + m_Mesh2: {fileID: 0} + m_Mesh3: {fileID: 0} +--- !u!198 &1733954123 +ParticleSystem: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 1733954120} + serializedVersion: 5 + lengthInSec: 5 + simulationSpeed: 1 + looping: 1 + prewarm: 0 + playOnAwake: 1 + autoRandomSeed: 1 + startDelay: + serializedVersion: 2 + minMaxState: 0 + scalar: 0 + minScalar: 0 + maxCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 2 + time: 0 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + - serializedVersion: 2 + time: 1 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + minCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 2 + time: 0 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + - serializedVersion: 2 + time: 1 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + moveWithTransform: 0 + moveWithCustomTransform: {fileID: 0} + scalingMode: 1 + randomSeed: 500886790 + InitialModule: + serializedVersion: 3 + enabled: 1 + startLifetime: + serializedVersion: 2 + minMaxState: 3 + scalar: 5 + minScalar: 3 + maxCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 2 + time: 0 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + - serializedVersion: 2 + time: 1 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + minCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 2 + time: 0 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + - serializedVersion: 2 + time: 1 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + startSpeed: + serializedVersion: 2 + minMaxState: 0 + scalar: 0 + minScalar: 5 + maxCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 2 + time: 0 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + - serializedVersion: 2 + time: 1 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + minCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 2 + time: 0 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + - serializedVersion: 2 + time: 1 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + startColor: + serializedVersion: 2 + minMaxState: 0 + minColor: {r: 1, g: 1, b: 1, a: 1} + maxColor: {r: 1, g: 1, b: 1, a: 1} + maxGradient: + serializedVersion: 2 + key0: {r: 1, g: 1, b: 1, a: 1} + key1: {r: 1, g: 1, b: 1, a: 1} + key2: {r: 0, g: 0, b: 0, a: 0} + key3: {r: 0, g: 0, b: 0, a: 0} + key4: {r: 0, g: 0, b: 0, a: 0} + key5: {r: 0, g: 0, b: 0, a: 0} + key6: {r: 0, g: 0, b: 0, a: 0} + key7: {r: 0, g: 0, b: 0, a: 0} + ctime0: 0 + ctime1: 65535 + ctime2: 0 + ctime3: 0 + ctime4: 0 + ctime5: 0 + ctime6: 0 + ctime7: 0 + atime0: 0 + atime1: 65535 + atime2: 0 + atime3: 0 + atime4: 0 + atime5: 0 + atime6: 0 + atime7: 0 + m_Mode: 0 + m_NumColorKeys: 2 + m_NumAlphaKeys: 2 + minGradient: + serializedVersion: 2 + key0: {r: 1, g: 1, b: 1, a: 1} + key1: {r: 1, g: 1, b: 1, a: 1} + key2: {r: 0, g: 0, b: 0, a: 0} + key3: {r: 0, g: 0, b: 0, a: 0} + key4: {r: 0, g: 0, b: 0, a: 0} + key5: {r: 0, g: 0, b: 0, a: 0} + key6: {r: 0, g: 0, b: 0, a: 0} + key7: {r: 0, g: 0, b: 0, a: 0} + ctime0: 0 + ctime1: 65535 + ctime2: 0 + ctime3: 0 + ctime4: 0 + ctime5: 0 + ctime6: 0 + ctime7: 0 + atime0: 0 + atime1: 65535 + atime2: 0 + atime3: 0 + atime4: 0 + atime5: 0 + atime6: 0 + atime7: 0 + m_Mode: 0 + m_NumColorKeys: 2 + m_NumAlphaKeys: 2 + startSize: + serializedVersion: 2 + minMaxState: 3 + scalar: 0.5 + minScalar: 0.2 + maxCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 2 + time: 0 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + - serializedVersion: 2 + time: 1 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + minCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 2 + time: 0 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + - serializedVersion: 2 + time: 1 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + startSizeY: + serializedVersion: 2 + minMaxState: 3 + scalar: 1 + minScalar: 1 + maxCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 2 + time: 0 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + - serializedVersion: 2 + time: 1 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + minCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 2 + time: 0 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + - serializedVersion: 2 + time: 1 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + startSizeZ: + serializedVersion: 2 + minMaxState: 3 + scalar: 1 + minScalar: 1 + maxCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 2 + time: 0 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + - serializedVersion: 2 + time: 1 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + minCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 2 + time: 0 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + - serializedVersion: 2 + time: 1 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + startRotationX: + serializedVersion: 2 + minMaxState: 0 + scalar: 0 + minScalar: 0 + maxCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 2 + time: 0 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + - serializedVersion: 2 + time: 1 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + minCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 2 + time: 0 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + - serializedVersion: 2 + time: 1 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + startRotationY: + serializedVersion: 2 + minMaxState: 0 + scalar: 0 + minScalar: 0 + maxCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 2 + time: 0 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + - serializedVersion: 2 + time: 1 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + minCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 2 + time: 0 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + - serializedVersion: 2 + time: 1 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + startRotation: + serializedVersion: 2 + minMaxState: 0 + scalar: 0 + minScalar: 0 + maxCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 2 + time: 0 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + - serializedVersion: 2 + time: 1 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + minCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 2 + time: 0 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + - serializedVersion: 2 + time: 1 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + randomizeRotationDirection: 0 + maxNumParticles: 150 + size3D: 0 + rotation3D: 0 + gravityModifier: + serializedVersion: 2 + minMaxState: 0 + scalar: 0 + minScalar: 0 + maxCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 2 + time: 0 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + - serializedVersion: 2 + time: 1 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + minCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 2 + time: 0 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + - serializedVersion: 2 + time: 1 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + ShapeModule: + serializedVersion: 4 + enabled: 1 + type: 4 + angle: 25 + length: 5 + boxX: 1 + boxY: 1 + boxZ: 1 + radius: + value: 0.38 + mode: 0 + spread: 0 + speed: + serializedVersion: 2 + minMaxState: 0 + scalar: 1 + minScalar: 1 + maxCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 2 + time: 0 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + - serializedVersion: 2 + time: 1 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + minCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 2 + time: 0 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + - serializedVersion: 2 + time: 1 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + arc: + value: 360 + mode: 0 + spread: 0 + speed: + serializedVersion: 2 + minMaxState: 0 + scalar: 1 + minScalar: 1 + maxCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 2 + time: 0 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + - serializedVersion: 2 + time: 1 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + minCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 2 + time: 0 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + - serializedVersion: 2 + time: 1 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + placementMode: 0 + m_Mesh: {fileID: 0} + m_MeshRenderer: {fileID: 0} + m_SkinnedMeshRenderer: {fileID: 0} + m_MeshMaterialIndex: 0 + m_MeshNormalOffset: 0 + m_MeshScale: 1 + m_UseMeshMaterialIndex: 0 + m_UseMeshColors: 1 + alignToDirection: 0 + randomDirectionAmount: 0 + sphericalDirectionAmount: 0 + EmissionModule: + enabled: 1 + serializedVersion: 4 + rateOverTime: + serializedVersion: 2 + minMaxState: 0 + scalar: 30 + minScalar: 10 + maxCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 2 + time: 0 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + - serializedVersion: 2 + time: 1 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + minCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 2 + time: 0 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + - serializedVersion: 2 + time: 1 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + rateOverDistance: + serializedVersion: 2 + minMaxState: 0 + scalar: 0 + minScalar: 0 + maxCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 2 + time: 0 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + - serializedVersion: 2 + time: 1 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + minCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 2 + time: 0 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + - serializedVersion: 2 + time: 1 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + m_BurstCount: 0 + m_Bursts: [] + SizeModule: + enabled: 0 + curve: + serializedVersion: 2 + minMaxState: 1 + scalar: 1 + minScalar: 1 + maxCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 2 + time: 0 + value: 0 + inSlope: 0 + outSlope: 1 + tangentMode: 0 + - serializedVersion: 2 + time: 1 + value: 1 + inSlope: 1 + outSlope: 0 + tangentMode: 0 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + minCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 2 + time: 0 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + - serializedVersion: 2 + time: 1 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + y: + serializedVersion: 2 + minMaxState: 1 + scalar: 1 + minScalar: 1 + maxCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 2 + time: 0 + value: 0 + inSlope: 0 + outSlope: 1 + tangentMode: 0 + - serializedVersion: 2 + time: 1 + value: 1 + inSlope: 1 + outSlope: 0 + tangentMode: 0 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + minCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 2 + time: 0 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + - serializedVersion: 2 + time: 1 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + z: + serializedVersion: 2 + minMaxState: 1 + scalar: 1 + minScalar: 1 + maxCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 2 + time: 0 + value: 0 + inSlope: 0 + outSlope: 1 + tangentMode: 0 + - serializedVersion: 2 + time: 1 + value: 1 + inSlope: 1 + outSlope: 0 + tangentMode: 0 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + minCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 2 + time: 0 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + - serializedVersion: 2 + time: 1 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + separateAxes: 0 + RotationModule: + enabled: 0 + x: + serializedVersion: 2 + minMaxState: 0 + scalar: 0 + minScalar: 0 + maxCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 2 + time: 0 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + - serializedVersion: 2 + time: 1 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + minCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 2 + time: 0 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + - serializedVersion: 2 + time: 1 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + y: + serializedVersion: 2 + minMaxState: 0 + scalar: 0 + minScalar: 0 + maxCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 2 + time: 0 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + - serializedVersion: 2 + time: 1 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + minCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 2 + time: 0 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + - serializedVersion: 2 + time: 1 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + curve: + serializedVersion: 2 + minMaxState: 0 + scalar: 0.7853982 + minScalar: 0.7853982 + maxCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 2 + time: 0 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + - serializedVersion: 2 + time: 1 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + minCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 2 + time: 0 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + - serializedVersion: 2 + time: 1 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + separateAxes: 0 + ColorModule: + enabled: 0 + gradient: + serializedVersion: 2 + minMaxState: 1 + minColor: {r: 1, g: 1, b: 1, a: 1} + maxColor: {r: 1, g: 1, b: 1, a: 1} + maxGradient: + serializedVersion: 2 + key0: {r: 1, g: 1, b: 1, a: 1} + key1: {r: 1, g: 1, b: 1, a: 1} + key2: {r: 0, g: 0, b: 0, a: 0} + key3: {r: 0, g: 0, b: 0, a: 0} + key4: {r: 0, g: 0, b: 0, a: 0} + key5: {r: 0, g: 0, b: 0, a: 0} + key6: {r: 0, g: 0, b: 0, a: 0} + key7: {r: 0, g: 0, b: 0, a: 0} + ctime0: 0 + ctime1: 65535 + ctime2: 0 + ctime3: 0 + ctime4: 0 + ctime5: 0 + ctime6: 0 + ctime7: 0 + atime0: 0 + atime1: 65535 + atime2: 0 + atime3: 0 + atime4: 0 + atime5: 0 + atime6: 0 + atime7: 0 + m_Mode: 0 + m_NumColorKeys: 2 + m_NumAlphaKeys: 2 + minGradient: + serializedVersion: 2 + key0: {r: 1, g: 1, b: 1, a: 1} + key1: {r: 1, g: 1, b: 1, a: 1} + key2: {r: 0, g: 0, b: 0, a: 0} + key3: {r: 0, g: 0, b: 0, a: 0} + key4: {r: 0, g: 0, b: 0, a: 0} + key5: {r: 0, g: 0, b: 0, a: 0} + key6: {r: 0, g: 0, b: 0, a: 0} + key7: {r: 0, g: 0, b: 0, a: 0} + ctime0: 0 + ctime1: 65535 + ctime2: 0 + ctime3: 0 + ctime4: 0 + ctime5: 0 + ctime6: 0 + ctime7: 0 + atime0: 0 + atime1: 65535 + atime2: 0 + atime3: 0 + atime4: 0 + atime5: 0 + atime6: 0 + atime7: 0 + m_Mode: 0 + m_NumColorKeys: 2 + m_NumAlphaKeys: 2 + UVModule: + enabled: 0 + frameOverTime: + serializedVersion: 2 + minMaxState: 1 + scalar: 0.9999 + minScalar: 0.9999 + maxCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 2 + time: 0 + value: 0 + inSlope: 0 + outSlope: 1 + tangentMode: 0 + - serializedVersion: 2 + time: 1 + value: 1 + inSlope: 1 + outSlope: 0 + tangentMode: 0 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + minCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 2 + time: 0 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + - serializedVersion: 2 + time: 1 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + startFrame: + serializedVersion: 2 + minMaxState: 0 + scalar: 0 + minScalar: 0 + maxCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 2 + time: 0 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + - serializedVersion: 2 + time: 1 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + minCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 2 + time: 0 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + - serializedVersion: 2 + time: 1 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + tilesX: 1 + tilesY: 1 + animationType: 0 + rowIndex: 0 + cycles: 1 + uvChannelMask: -1 + flipU: 0 + flipV: 0 + randomRow: 1 + VelocityModule: + enabled: 0 + x: + serializedVersion: 2 + minMaxState: 0 + scalar: 0 + minScalar: 0 + maxCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 2 + time: 0 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + - serializedVersion: 2 + time: 1 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + minCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 2 + time: 0 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + - serializedVersion: 2 + time: 1 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + y: + serializedVersion: 2 + minMaxState: 0 + scalar: 0 + minScalar: 0 + maxCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 2 + time: 0 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + - serializedVersion: 2 + time: 1 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + minCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 2 + time: 0 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + - serializedVersion: 2 + time: 1 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + z: + serializedVersion: 2 + minMaxState: 0 + scalar: 0 + minScalar: 0 + maxCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 2 + time: 0 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + - serializedVersion: 2 + time: 1 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + minCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 2 + time: 0 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + - serializedVersion: 2 + time: 1 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + inWorldSpace: 0 + InheritVelocityModule: + enabled: 0 + m_Mode: 0 + m_Curve: + serializedVersion: 2 + minMaxState: 0 + scalar: 0 + minScalar: 0 + maxCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 2 + time: 0 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + - serializedVersion: 2 + time: 1 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + minCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 2 + time: 0 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + - serializedVersion: 2 + time: 1 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + ForceModule: + enabled: 0 + x: + serializedVersion: 2 + minMaxState: 0 + scalar: 0 + minScalar: 0 + maxCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 2 + time: 0 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + - serializedVersion: 2 + time: 1 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + minCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 2 + time: 0 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + - serializedVersion: 2 + time: 1 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + y: + serializedVersion: 2 + minMaxState: 0 + scalar: 0 + minScalar: 0 + maxCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 2 + time: 0 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + - serializedVersion: 2 + time: 1 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + minCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 2 + time: 0 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + - serializedVersion: 2 + time: 1 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + z: + serializedVersion: 2 + minMaxState: 0 + scalar: 0 + minScalar: 0 + maxCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 2 + time: 0 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + - serializedVersion: 2 + time: 1 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + minCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 2 + time: 0 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + - serializedVersion: 2 + time: 1 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + inWorldSpace: 0 + randomizePerFrame: 0 + ExternalForcesModule: + enabled: 0 + multiplier: 1 + ClampVelocityModule: + enabled: 0 + x: + serializedVersion: 2 + minMaxState: 0 + scalar: 1 + minScalar: 1 + maxCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 2 + time: 0 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + - serializedVersion: 2 + time: 1 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + minCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 2 + time: 0 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + - serializedVersion: 2 + time: 1 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + y: + serializedVersion: 2 + minMaxState: 0 + scalar: 1 + minScalar: 1 + maxCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 2 + time: 0 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + - serializedVersion: 2 + time: 1 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + minCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 2 + time: 0 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + - serializedVersion: 2 + time: 1 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + z: + serializedVersion: 2 + minMaxState: 0 + scalar: 1 + minScalar: 1 + maxCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 2 + time: 0 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + - serializedVersion: 2 + time: 1 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + minCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 2 + time: 0 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + - serializedVersion: 2 + time: 1 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + magnitude: + serializedVersion: 2 + minMaxState: 0 + scalar: 1 + minScalar: 1 + maxCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 2 + time: 0 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + - serializedVersion: 2 + time: 1 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + minCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 2 + time: 0 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + - serializedVersion: 2 + time: 1 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + separateAxis: 0 + inWorldSpace: 0 + dampen: 1 + NoiseModule: + enabled: 1 + strength: + serializedVersion: 2 + minMaxState: 0 + scalar: 0.12 + minScalar: 1 + maxCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 2 + time: 0 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + - serializedVersion: 2 + time: 1 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + minCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 2 + time: 0 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + - serializedVersion: 2 + time: 1 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + strengthY: + serializedVersion: 2 + minMaxState: 0 + scalar: 1 + minScalar: 1 + maxCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 2 + time: 0 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + - serializedVersion: 2 + time: 1 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + minCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 2 + time: 0 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + - serializedVersion: 2 + time: 1 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + strengthZ: + serializedVersion: 2 + minMaxState: 0 + scalar: 1 + minScalar: 1 + maxCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 2 + time: 0 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + - serializedVersion: 2 + time: 1 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + minCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 2 + time: 0 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + - serializedVersion: 2 + time: 1 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + separateAxes: 0 + frequency: 0.5 + damping: 1 + octaves: 1 + octaveMultiplier: 0.5 + octaveScale: 2 + quality: 1 + scrollSpeed: + serializedVersion: 2 + minMaxState: 0 + scalar: 1 + minScalar: 0 + maxCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 2 + time: 0 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + - serializedVersion: 2 + time: 1 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + minCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 2 + time: 0 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + - serializedVersion: 2 + time: 1 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + remap: + serializedVersion: 2 + minMaxState: 1 + scalar: 1 + minScalar: 1 + maxCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 2 + time: 0 + value: 0 + inSlope: 0 + outSlope: 1 + tangentMode: 0 + - serializedVersion: 2 + time: 1 + value: 1 + inSlope: 1 + outSlope: 0 + tangentMode: 0 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + minCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 2 + time: 0 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + - serializedVersion: 2 + time: 1 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + remapY: + serializedVersion: 2 + minMaxState: 1 + scalar: 1 + minScalar: 1 + maxCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 2 + time: 0 + value: 0 + inSlope: 0 + outSlope: 1 + tangentMode: 0 + - serializedVersion: 2 + time: 1 + value: 1 + inSlope: 1 + outSlope: 0 + tangentMode: 0 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + minCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 2 + time: 0 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + - serializedVersion: 2 + time: 1 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + remapZ: + serializedVersion: 2 + minMaxState: 1 + scalar: 1 + minScalar: 1 + maxCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 2 + time: 0 + value: 0 + inSlope: 0 + outSlope: 1 + tangentMode: 0 + - serializedVersion: 2 + time: 1 + value: 1 + inSlope: 1 + outSlope: 0 + tangentMode: 0 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + minCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 2 + time: 0 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + - serializedVersion: 2 + time: 1 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + remapEnabled: 0 + SizeBySpeedModule: + enabled: 0 + curve: + serializedVersion: 2 + minMaxState: 1 + scalar: 1 + minScalar: 1 + maxCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 2 + time: 0 + value: 0 + inSlope: 0 + outSlope: 1 + tangentMode: 0 + - serializedVersion: 2 + time: 1 + value: 1 + inSlope: 1 + outSlope: 0 + tangentMode: 0 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + minCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 2 + time: 0 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + - serializedVersion: 2 + time: 1 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + y: + serializedVersion: 2 + minMaxState: 1 + scalar: 1 + minScalar: 1 + maxCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 2 + time: 0 + value: 0 + inSlope: 0 + outSlope: 1 + tangentMode: 0 + - serializedVersion: 2 + time: 1 + value: 1 + inSlope: 1 + outSlope: 0 + tangentMode: 0 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + minCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 2 + time: 0 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + - serializedVersion: 2 + time: 1 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + z: + serializedVersion: 2 + minMaxState: 1 + scalar: 1 + minScalar: 1 + maxCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 2 + time: 0 + value: 0 + inSlope: 0 + outSlope: 1 + tangentMode: 0 + - serializedVersion: 2 + time: 1 + value: 1 + inSlope: 1 + outSlope: 0 + tangentMode: 0 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + minCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 2 + time: 0 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + - serializedVersion: 2 + time: 1 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + range: {x: 0, y: 1} + separateAxes: 0 + RotationBySpeedModule: + enabled: 0 + x: + serializedVersion: 2 + minMaxState: 0 + scalar: 0 + minScalar: 0 + maxCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 2 + time: 0 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + - serializedVersion: 2 + time: 1 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + minCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 2 + time: 0 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + - serializedVersion: 2 + time: 1 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + y: + serializedVersion: 2 + minMaxState: 0 + scalar: 0 + minScalar: 0 + maxCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 2 + time: 0 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + - serializedVersion: 2 + time: 1 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + minCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 2 + time: 0 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + - serializedVersion: 2 + time: 1 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + curve: + serializedVersion: 2 + minMaxState: 0 + scalar: 0.7853982 + minScalar: 0.7853982 + maxCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 2 + time: 0 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + - serializedVersion: 2 + time: 1 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + minCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 2 + time: 0 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + - serializedVersion: 2 + time: 1 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + separateAxes: 0 + range: {x: 0, y: 1} + ColorBySpeedModule: + enabled: 0 + gradient: + serializedVersion: 2 + minMaxState: 1 + minColor: {r: 1, g: 1, b: 1, a: 1} + maxColor: {r: 1, g: 1, b: 1, a: 1} + maxGradient: + serializedVersion: 2 + key0: {r: 1, g: 1, b: 1, a: 1} + key1: {r: 1, g: 1, b: 1, a: 1} + key2: {r: 0, g: 0, b: 0, a: 0} + key3: {r: 0, g: 0, b: 0, a: 0} + key4: {r: 0, g: 0, b: 0, a: 0} + key5: {r: 0, g: 0, b: 0, a: 0} + key6: {r: 0, g: 0, b: 0, a: 0} + key7: {r: 0, g: 0, b: 0, a: 0} + ctime0: 0 + ctime1: 65535 + ctime2: 0 + ctime3: 0 + ctime4: 0 + ctime5: 0 + ctime6: 0 + ctime7: 0 + atime0: 0 + atime1: 65535 + atime2: 0 + atime3: 0 + atime4: 0 + atime5: 0 + atime6: 0 + atime7: 0 + m_Mode: 0 + m_NumColorKeys: 2 + m_NumAlphaKeys: 2 + minGradient: + serializedVersion: 2 + key0: {r: 1, g: 1, b: 1, a: 1} + key1: {r: 1, g: 1, b: 1, a: 1} + key2: {r: 0, g: 0, b: 0, a: 0} + key3: {r: 0, g: 0, b: 0, a: 0} + key4: {r: 0, g: 0, b: 0, a: 0} + key5: {r: 0, g: 0, b: 0, a: 0} + key6: {r: 0, g: 0, b: 0, a: 0} + key7: {r: 0, g: 0, b: 0, a: 0} + ctime0: 0 + ctime1: 65535 + ctime2: 0 + ctime3: 0 + ctime4: 0 + ctime5: 0 + ctime6: 0 + ctime7: 0 + atime0: 0 + atime1: 65535 + atime2: 0 + atime3: 0 + atime4: 0 + atime5: 0 + atime6: 0 + atime7: 0 + m_Mode: 0 + m_NumColorKeys: 2 + m_NumAlphaKeys: 2 + range: {x: 0, y: 1} + CollisionModule: + enabled: 0 + serializedVersion: 3 + type: 0 + collisionMode: 0 + plane0: {fileID: 0} + plane1: {fileID: 0} + plane2: {fileID: 0} + plane3: {fileID: 0} + plane4: {fileID: 0} + plane5: {fileID: 0} + m_Dampen: + serializedVersion: 2 + minMaxState: 0 + scalar: 0 + minScalar: 0 + maxCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 2 + time: 0 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + - serializedVersion: 2 + time: 1 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + minCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 2 + time: 0 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + - serializedVersion: 2 + time: 1 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + m_Bounce: + serializedVersion: 2 + minMaxState: 0 + scalar: 1 + minScalar: 1 + maxCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 2 + time: 0 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + - serializedVersion: 2 + time: 1 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + minCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 2 + time: 0 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + - serializedVersion: 2 + time: 1 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + m_EnergyLossOnCollision: + serializedVersion: 2 + minMaxState: 0 + scalar: 0 + minScalar: 0 + maxCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 2 + time: 0 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + - serializedVersion: 2 + time: 1 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + minCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 2 + time: 0 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + - serializedVersion: 2 + time: 1 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + minKillSpeed: 0 + maxKillSpeed: 10000 + radiusScale: 1 + collidesWith: + serializedVersion: 2 + m_Bits: 4294967295 + maxCollisionShapes: 256 + quality: 0 + voxelSize: 0.5 + collisionMessages: 0 + collidesWithDynamic: 1 + interiorCollisions: 1 + TriggerModule: + enabled: 0 + collisionShape0: {fileID: 0} + collisionShape1: {fileID: 0} + collisionShape2: {fileID: 0} + collisionShape3: {fileID: 0} + collisionShape4: {fileID: 0} + collisionShape5: {fileID: 0} + inside: 1 + outside: 0 + enter: 0 + exit: 0 + radiusScale: 1 + SubModule: + serializedVersion: 2 + enabled: 0 + subEmitters: + - emitter: {fileID: 0} + type: 0 + properties: 0 + LightsModule: + enabled: 0 + ratio: 0 + light: {fileID: 0} + randomDistribution: 1 + color: 1 + range: 1 + intensity: 1 + rangeCurve: + serializedVersion: 2 + minMaxState: 0 + scalar: 1 + minScalar: 1 + maxCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 2 + time: 0 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + - serializedVersion: 2 + time: 1 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + minCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 2 + time: 0 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + - serializedVersion: 2 + time: 1 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + intensityCurve: + serializedVersion: 2 + minMaxState: 0 + scalar: 1 + minScalar: 1 + maxCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 2 + time: 0 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + - serializedVersion: 2 + time: 1 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + minCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 2 + time: 0 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + - serializedVersion: 2 + time: 1 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + maxLights: 20 + TrailModule: + enabled: 1 + ratio: 1 + lifetime: + serializedVersion: 2 + minMaxState: 0 + scalar: 0.1 + minScalar: 1 + maxCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 2 + time: 0 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + - serializedVersion: 2 + time: 1 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + minCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 2 + time: 0 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + - serializedVersion: 2 + time: 1 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + minVertexDistance: 0.2 + textureMode: 0 + worldSpace: 0 + dieWithParticles: 1 + sizeAffectsWidth: 1 + sizeAffectsLifetime: 0 + inheritParticleColor: 0 + colorOverLifetime: + serializedVersion: 2 + minMaxState: 1 + minColor: {r: 1, g: 1, b: 1, a: 1} + maxColor: {r: 1, g: 1, b: 1, a: 1} + maxGradient: + serializedVersion: 2 + key0: {r: 0.8602941, g: 0.26567906, b: 0.26567906, a: 0.5019608} + key1: {r: 0.9852941, g: 0.94612217, b: 0.63029844, a: 1} + key2: {r: 0.9852941, g: 0.94612217, b: 0.63029844, a: 0.5019608} + key3: {r: 0.9852941, g: 0.94612217, b: 0.63029844, a: 0} + key4: {r: 0, g: 0, b: 0, a: 0} + key5: {r: 0, g: 0, b: 0, a: 0} + key6: {r: 0, g: 0, b: 0, a: 0} + key7: {r: 0, g: 0, b: 0, a: 0} + ctime0: 13685 + ctime1: 65535 + ctime2: 65535 + ctime3: 65535 + ctime4: 0 + ctime5: 0 + ctime6: 0 + ctime7: 0 + atime0: 0 + atime1: 32768 + atime2: 65535 + atime3: 0 + atime4: 0 + atime5: 0 + atime6: 0 + atime7: 0 + m_Mode: 0 + m_NumColorKeys: 2 + m_NumAlphaKeys: 3 + minGradient: + serializedVersion: 2 + key0: {r: 1, g: 1, b: 1, a: 1} + key1: {r: 1, g: 1, b: 1, a: 1} + key2: {r: 0, g: 0, b: 0, a: 0} + key3: {r: 0, g: 0, b: 0, a: 0} + key4: {r: 0, g: 0, b: 0, a: 0} + key5: {r: 0, g: 0, b: 0, a: 0} + key6: {r: 0, g: 0, b: 0, a: 0} + key7: {r: 0, g: 0, b: 0, a: 0} + ctime0: 0 + ctime1: 65535 + ctime2: 0 + ctime3: 0 + ctime4: 0 + ctime5: 0 + ctime6: 0 + ctime7: 0 + atime0: 0 + atime1: 65535 + atime2: 0 + atime3: 0 + atime4: 0 + atime5: 0 + atime6: 0 + atime7: 0 + m_Mode: 0 + m_NumColorKeys: 2 + m_NumAlphaKeys: 2 + widthOverTrail: + serializedVersion: 2 + minMaxState: 0 + scalar: 0.8 + minScalar: 1 + maxCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 2 + time: 0 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + - serializedVersion: 2 + time: 1 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + minCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 2 + time: 0 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + - serializedVersion: 2 + time: 1 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + colorOverTrail: + serializedVersion: 2 + minMaxState: 0 + minColor: {r: 1, g: 1, b: 1, a: 1} + maxColor: {r: 1, g: 1, b: 1, a: 1} + maxGradient: + serializedVersion: 2 + key0: {r: 1, g: 1, b: 1, a: 1} + key1: {r: 1, g: 1, b: 1, a: 1} + key2: {r: 0, g: 0, b: 0, a: 0} + key3: {r: 0, g: 0, b: 0, a: 0} + key4: {r: 0, g: 0, b: 0, a: 0} + key5: {r: 0, g: 0, b: 0, a: 0} + key6: {r: 0, g: 0, b: 0, a: 0} + key7: {r: 0, g: 0, b: 0, a: 0} + ctime0: 0 + ctime1: 65535 + ctime2: 0 + ctime3: 0 + ctime4: 0 + ctime5: 0 + ctime6: 0 + ctime7: 0 + atime0: 0 + atime1: 65535 + atime2: 0 + atime3: 0 + atime4: 0 + atime5: 0 + atime6: 0 + atime7: 0 + m_Mode: 0 + m_NumColorKeys: 2 + m_NumAlphaKeys: 2 + minGradient: + serializedVersion: 2 + key0: {r: 1, g: 1, b: 1, a: 1} + key1: {r: 1, g: 1, b: 1, a: 1} + key2: {r: 0, g: 0, b: 0, a: 0} + key3: {r: 0, g: 0, b: 0, a: 0} + key4: {r: 0, g: 0, b: 0, a: 0} + key5: {r: 0, g: 0, b: 0, a: 0} + key6: {r: 0, g: 0, b: 0, a: 0} + key7: {r: 0, g: 0, b: 0, a: 0} + ctime0: 0 + ctime1: 65535 + ctime2: 0 + ctime3: 0 + ctime4: 0 + ctime5: 0 + ctime6: 0 + ctime7: 0 + atime0: 0 + atime1: 65535 + atime2: 0 + atime3: 0 + atime4: 0 + atime5: 0 + atime6: 0 + atime7: 0 + m_Mode: 0 + m_NumColorKeys: 2 + m_NumAlphaKeys: 2 + CustomDataModule: + enabled: 0 + mode0: 0 + vectorComponentCount0: 4 + color0: + serializedVersion: 2 + minMaxState: 0 + minColor: {r: 1, g: 1, b: 1, a: 1} + maxColor: {r: 1, g: 1, b: 1, a: 1} + maxGradient: + serializedVersion: 2 + key0: {r: 1, g: 1, b: 1, a: 1} + key1: {r: 1, g: 1, b: 1, a: 1} + key2: {r: 0, g: 0, b: 0, a: 0} + key3: {r: 0, g: 0, b: 0, a: 0} + key4: {r: 0, g: 0, b: 0, a: 0} + key5: {r: 0, g: 0, b: 0, a: 0} + key6: {r: 0, g: 0, b: 0, a: 0} + key7: {r: 0, g: 0, b: 0, a: 0} + ctime0: 0 + ctime1: 65535 + ctime2: 0 + ctime3: 0 + ctime4: 0 + ctime5: 0 + ctime6: 0 + ctime7: 0 + atime0: 0 + atime1: 65535 + atime2: 0 + atime3: 0 + atime4: 0 + atime5: 0 + atime6: 0 + atime7: 0 + m_Mode: 0 + m_NumColorKeys: 2 + m_NumAlphaKeys: 2 + minGradient: + serializedVersion: 2 + key0: {r: 1, g: 1, b: 1, a: 1} + key1: {r: 1, g: 1, b: 1, a: 1} + key2: {r: 0, g: 0, b: 0, a: 0} + key3: {r: 0, g: 0, b: 0, a: 0} + key4: {r: 0, g: 0, b: 0, a: 0} + key5: {r: 0, g: 0, b: 0, a: 0} + key6: {r: 0, g: 0, b: 0, a: 0} + key7: {r: 0, g: 0, b: 0, a: 0} + ctime0: 0 + ctime1: 65535 + ctime2: 0 + ctime3: 0 + ctime4: 0 + ctime5: 0 + ctime6: 0 + ctime7: 0 + atime0: 0 + atime1: 65535 + atime2: 0 + atime3: 0 + atime4: 0 + atime5: 0 + atime6: 0 + atime7: 0 + m_Mode: 0 + m_NumColorKeys: 2 + m_NumAlphaKeys: 2 + vector0_0: + serializedVersion: 2 + minMaxState: 0 + scalar: 0 + minScalar: 0 + maxCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 2 + time: 0 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + - serializedVersion: 2 + time: 1 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + minCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 2 + time: 0 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + - serializedVersion: 2 + time: 1 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + vector0_1: + serializedVersion: 2 + minMaxState: 0 + scalar: 0 + minScalar: 0 + maxCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 2 + time: 0 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + - serializedVersion: 2 + time: 1 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + minCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 2 + time: 0 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + - serializedVersion: 2 + time: 1 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + vector0_2: + serializedVersion: 2 + minMaxState: 0 + scalar: 0 + minScalar: 0 + maxCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 2 + time: 0 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + - serializedVersion: 2 + time: 1 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + minCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 2 + time: 0 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + - serializedVersion: 2 + time: 1 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + vector0_3: + serializedVersion: 2 + minMaxState: 0 + scalar: 0 + minScalar: 0 + maxCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 2 + time: 0 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + - serializedVersion: 2 + time: 1 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + minCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 2 + time: 0 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + - serializedVersion: 2 + time: 1 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + mode1: 0 + vectorComponentCount1: 4 + color1: + serializedVersion: 2 + minMaxState: 0 + minColor: {r: 1, g: 1, b: 1, a: 1} + maxColor: {r: 1, g: 1, b: 1, a: 1} + maxGradient: + serializedVersion: 2 + key0: {r: 1, g: 1, b: 1, a: 1} + key1: {r: 1, g: 1, b: 1, a: 1} + key2: {r: 0, g: 0, b: 0, a: 0} + key3: {r: 0, g: 0, b: 0, a: 0} + key4: {r: 0, g: 0, b: 0, a: 0} + key5: {r: 0, g: 0, b: 0, a: 0} + key6: {r: 0, g: 0, b: 0, a: 0} + key7: {r: 0, g: 0, b: 0, a: 0} + ctime0: 0 + ctime1: 65535 + ctime2: 0 + ctime3: 0 + ctime4: 0 + ctime5: 0 + ctime6: 0 + ctime7: 0 + atime0: 0 + atime1: 65535 + atime2: 0 + atime3: 0 + atime4: 0 + atime5: 0 + atime6: 0 + atime7: 0 + m_Mode: 0 + m_NumColorKeys: 2 + m_NumAlphaKeys: 2 + minGradient: + serializedVersion: 2 + key0: {r: 1, g: 1, b: 1, a: 1} + key1: {r: 1, g: 1, b: 1, a: 1} + key2: {r: 0, g: 0, b: 0, a: 0} + key3: {r: 0, g: 0, b: 0, a: 0} + key4: {r: 0, g: 0, b: 0, a: 0} + key5: {r: 0, g: 0, b: 0, a: 0} + key6: {r: 0, g: 0, b: 0, a: 0} + key7: {r: 0, g: 0, b: 0, a: 0} + ctime0: 0 + ctime1: 65535 + ctime2: 0 + ctime3: 0 + ctime4: 0 + ctime5: 0 + ctime6: 0 + ctime7: 0 + atime0: 0 + atime1: 65535 + atime2: 0 + atime3: 0 + atime4: 0 + atime5: 0 + atime6: 0 + atime7: 0 + m_Mode: 0 + m_NumColorKeys: 2 + m_NumAlphaKeys: 2 + vector1_0: + serializedVersion: 2 + minMaxState: 0 + scalar: 0 + minScalar: 0 + maxCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 2 + time: 0 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + - serializedVersion: 2 + time: 1 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + minCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 2 + time: 0 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + - serializedVersion: 2 + time: 1 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + vector1_1: + serializedVersion: 2 + minMaxState: 0 + scalar: 0 + minScalar: 0 + maxCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 2 + time: 0 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + - serializedVersion: 2 + time: 1 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + minCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 2 + time: 0 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + - serializedVersion: 2 + time: 1 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + vector1_2: + serializedVersion: 2 + minMaxState: 0 + scalar: 0 + minScalar: 0 + maxCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 2 + time: 0 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + - serializedVersion: 2 + time: 1 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + minCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 2 + time: 0 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + - serializedVersion: 2 + time: 1 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + vector1_3: + serializedVersion: 2 + minMaxState: 0 + scalar: 0 + minScalar: 0 + maxCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 2 + time: 0 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + - serializedVersion: 2 + time: 1 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + minCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 2 + time: 0 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + - serializedVersion: 2 + time: 1 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 +--- !u!4 &1733954124 +Transform: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 1733954120} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: -1.92, y: -3.3652573, z: 3.59} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 7 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &1733954125 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 1733954120} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 9b6258aafd9a87344833937e5e546638, type: 3} + m_Name: + m_EditorClassIdentifier: + m_spline: {fileID: 126177801} + m_normalizedT: 0 + m_updatePosition: 1 + m_positionOffset: {x: 0, y: 0, z: 0} + m_updateRotation: 0 + m_rotationOffset: {x: 0, y: 0, z: 0} + executeInEditMode: 1 + prevSpline: {fileID: 126177801} +--- !u!1 &1762849794 +GameObject: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + serializedVersion: 5 + m_Component: + - component: {fileID: 1762849796} + - component: {fileID: 1762849795} + m_Layer: 0 + m_Name: Directional Light + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!108 &1762849795 +Light: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 1762849794} + m_Enabled: 1 + serializedVersion: 8 + m_Type: 1 + m_Color: {r: 1, g: 0.95686275, b: 0.8392157, a: 1} + m_Intensity: 1 + m_Range: 10 + m_SpotAngle: 30 + m_CookieSize: 10 + m_Shadows: + m_Type: 2 + m_Resolution: -1 + m_CustomResolution: -1 + m_Strength: 1 + m_Bias: 0.05 + m_NormalBias: 0.4 + m_NearPlane: 0.2 + m_Cookie: {fileID: 0} + m_DrawHalo: 0 + m_Flare: {fileID: 0} + m_RenderMode: 0 + m_CullingMask: + serializedVersion: 2 + m_Bits: 4294967295 + m_Lightmapping: 4 + m_AreaSize: {x: 1, y: 1} + m_BounceIntensity: 1 + m_ColorTemperature: 6570 + m_UseColorTemperature: 0 + m_ShadowRadius: 0 + m_ShadowAngle: 0 +--- !u!4 &1762849796 +Transform: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 1762849794} + m_LocalRotation: {x: 0.40821788, y: -0.23456968, z: 0.10938163, w: 0.8754261} + m_LocalPosition: {x: 100, y: 3, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 1 + m_LocalEulerAnglesHint: {x: 50, y: -30, z: 0} +--- !u!1 &1824258271 +GameObject: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + serializedVersion: 5 + m_Component: + - component: {fileID: 1824258276} + - component: {fileID: 1824258275} + - component: {fileID: 1824258272} + m_Layer: 0 + m_Name: Main Camera + m_TagString: MainCamera + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!81 &1824258272 +AudioListener: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 1824258271} + m_Enabled: 1 +--- !u!20 &1824258275 +Camera: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 1824258271} + m_Enabled: 1 + serializedVersion: 2 + m_ClearFlags: 1 + m_BackGroundColor: {r: 0.19215687, g: 0.3019608, b: 0.4745098, a: 0} + m_NormalizedViewPortRect: + serializedVersion: 2 + x: 0 + y: 0 + width: 1 + height: 1 + near clip plane: 0.3 + far clip plane: 1000 + field of view: 63 + orthographic: 0 + orthographic size: 5 + m_Depth: -1 + m_CullingMask: + serializedVersion: 2 + m_Bits: 4294967295 + m_RenderingPath: -1 + m_TargetTexture: {fileID: 0} + m_TargetDisplay: 0 + m_TargetEye: 3 + m_HDR: 0 + m_AllowMSAA: 1 + m_ForceIntoRT: 0 + m_OcclusionCulling: 1 + m_StereoConvergence: 10 + m_StereoSeparation: 0.022 + m_StereoMirrorMode: 0 +--- !u!4 &1824258276 +Transform: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 1824258271} + m_LocalRotation: {x: -0.228819, y: -0.11416553, z: 0.0270307, w: -0.9663733} + m_LocalPosition: {x: -4.9219103, y: 2.68957, z: -6.9780903} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 30, y: 0, z: 0} +--- !u!1 &1985424693 +GameObject: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + serializedVersion: 5 + m_Component: + - component: {fileID: 1985424694} + - component: {fileID: 1985424695} + m_Layer: 0 + m_Name: Point + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &1985424694 +Transform: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 1985424693} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: -0.094, y: -0, z: 0.53} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 126177802} + m_RootOrder: 3 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &1985424695 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 1985424693} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: b9cf9c5931a3b3c4ba456c8213d7ebfc, type: 3} + m_Name: + m_EditorClassIdentifier: + m_position: {x: -2.1254141, y: -0.021813512, z: 3.5899997} + m_precedingControlPointLocalPosition: {x: 0.22266664, y: -0.000000059604645, z: 0.00066667795} + m_precedingControlPointPosition: {x: -1.6388304, y: -0.020356536, z: 3.5899997} + m_followingControlPointLocalPosition: {x: -0.22266684, y: 0.000000059604645, z: -0.00066655874} + m_followingControlPointPosition: {x: -2.611998, y: -0.023270011, z: 3.5899994} + m_handleMode: 2 + m_normal: {x: 0, y: 1, z: 0} + m_autoCalculatedNormalAngleOffset: 0 + m_extraData: + c1: 0 + c2: 0 + c3: 0 + c4: 0 +--- !u!1 &2093860275 +GameObject: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + serializedVersion: 5 + m_Component: + - component: {fileID: 2093860276} + - component: {fileID: 2093860277} + m_Layer: 0 + m_Name: Point + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &2093860276 +Transform: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 2093860275} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0.270276, y: 0, z: -0.862274} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 728216727} + m_RootOrder: 6 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &2093860277 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 2093860275} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: b9cf9c5931a3b3c4ba456c8213d7ebfc, type: 3} + m_Name: + m_EditorClassIdentifier: + m_position: {x: 0.48204735, y: -1.2785811, z: -0.7370869} + m_precedingControlPointLocalPosition: {x: 0.022580685, y: -0, z: -0.045553397} + m_precedingControlPointPosition: {x: 0.5439292, y: -1.4211497, z: -0.72070634} + m_followingControlPointLocalPosition: {x: -0.022580685, y: 0, z: 0.045553397} + m_followingControlPointPosition: {x: 0.42016545, y: -1.1360133, z: -0.7534679} + m_handleMode: 2 + m_normal: {x: 0.7794916, y: 0.3942663, z: 0.48677203} + m_autoCalculatedNormalAngleOffset: 0 + m_extraData: + c1: 0 + c2: 0 + c3: 0 + c4: 0 +--- !u!1 &2095587044 +GameObject: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + serializedVersion: 5 + m_Component: + - component: {fileID: 2095587045} + - component: {fileID: 2095587046} + m_Layer: 0 + m_Name: Point + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &2095587045 +Transform: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 2095587044} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0.052717395, y: 0, z: -0.6439656} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 728216727} + m_RootOrder: 13 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &2095587046 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 2095587044} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: b9cf9c5931a3b3c4ba456c8213d7ebfc, type: 3} + m_Name: + m_EditorClassIdentifier: + m_position: {x: -0.10834992, y: -0.5778954, z: -0.9778185} + m_precedingControlPointLocalPosition: {x: -0.06764942, y: -0, z: 0.004849837} + m_precedingControlPointPosition: {x: -0.29027036, y: -0.5523063, z: -1.0763642} + m_followingControlPointLocalPosition: {x: 0.06764942, y: 0, z: -0.004849837} + m_followingControlPointPosition: {x: 0.07357052, y: -0.6034844, z: -0.8792728} + m_handleMode: 2 + m_normal: {x: -0.055507604, y: -0.98655623, z: -0.15370665} + m_autoCalculatedNormalAngleOffset: 0 + m_extraData: + c1: 0 + c2: 0 + c3: 0 + c4: 0 +--- !u!1 &2112567396 +GameObject: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + serializedVersion: 5 + m_Component: + - component: {fileID: 2112567398} + - component: {fileID: 2112567397} + m_Layer: 0 + m_Name: BezierSpline + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &2112567397 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 2112567396} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: a3dbf94c21a22d74d895b2051a04ba1e, type: 3} + m_Name: + m_EditorClassIdentifier: + m_loop: 1 + drawGizmos: 0 + gizmoColor: {r: 1, g: 1, b: 1, a: 1} + gizmoSmoothness: 4 + m_autoConstructMode: 3 + m_autoCalculateNormals: 1 + m_autoCalculatedNormalsAngle: 180 +--- !u!4 &2112567398 +Transform: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_GameObject: {fileID: 2112567396} + m_LocalRotation: {x: -0.5652521, y: 0.09897271, z: 0.12740806, w: 0.8089881} + m_LocalPosition: {x: -6.7, y: 0, z: 0} + m_LocalScale: {x: 1.354573, y: 1.3545724, z: 1.3545724} + m_Children: + - {fileID: 600501174} + - {fileID: 1060012330} + - {fileID: 955921218} + - {fileID: 895981910} + - {fileID: 131298669} + - {fileID: 413396498} + - {fileID: 762584197} + - {fileID: 731062954} + - {fileID: 122881951} + - {fileID: 1322218943} + m_Father: {fileID: 0} + m_RootOrder: 5 + m_LocalEulerAnglesHint: {x: -69.993004, y: 2.621, z: 15.698001} diff --git a/Assets/Plugins/BezierSolution/Demo/DemoScene.unity.meta b/Assets/Plugins/BezierSolution/Demo/DemoScene.unity.meta new file mode 100644 index 00000000..1c87afe7 --- /dev/null +++ b/Assets/Plugins/BezierSolution/Demo/DemoScene.unity.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 494545cd2e9cbec47adb2c1adf6066ab +timeCreated: 1472738252 +licenseType: Store +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/BezierSolution/Demo/OctopusArm.fbx b/Assets/Plugins/BezierSolution/Demo/OctopusArm.fbx new file mode 100644 index 00000000..8a04e2cf Binary files /dev/null and b/Assets/Plugins/BezierSolution/Demo/OctopusArm.fbx differ diff --git a/Assets/Plugins/BezierSolution/Demo/OctopusArm.fbx.meta b/Assets/Plugins/BezierSolution/Demo/OctopusArm.fbx.meta new file mode 100644 index 00000000..ad381f7a --- /dev/null +++ b/Assets/Plugins/BezierSolution/Demo/OctopusArm.fbx.meta @@ -0,0 +1,84 @@ +fileFormatVersion: 2 +guid: 44b1882f3e87f214ba0c12a8e3b15d36 +timeCreated: 1620040793 +licenseType: Store +ModelImporter: + serializedVersion: 19 + fileIDToRecycleName: + 100000: tentacle_6_geo + 100002: //RootNode + 400000: tentacle_6_geo + 400002: //RootNode + 2300000: tentacle_6_geo + 3300000: tentacle_6_geo + 4300000: tentacle_6_geo + materials: + importMaterials: 0 + materialName: 0 + materialSearch: 1 + animations: + legacyGenerateAnimations: 4 + bakeSimulation: 0 + resampleCurves: 1 + optimizeGameObjects: 0 + motionNodeName: + rigImportErrors: + rigImportWarnings: + animationImportErrors: + animationImportWarnings: + animationRetargetingWarnings: + animationDoRetargetingWarnings: 0 + animationCompression: 1 + animationRotationError: 0.5 + animationPositionError: 0.5 + animationScaleError: 0.5 + animationWrapMode: 0 + extraExposedTransformPaths: [] + clipAnimations: [] + isReadable: 1 + meshes: + lODScreenPercentages: [] + globalScale: 1 + meshCompression: 0 + addColliders: 0 + importBlendShapes: 1 + swapUVChannels: 0 + generateSecondaryUV: 0 + useFileUnits: 1 + optimizeMeshForGPU: 1 + keepQuads: 0 + weldVertices: 1 + secondaryUVAngleDistortion: 8 + secondaryUVAreaDistortion: 15.000001 + secondaryUVHardAngle: 88 + secondaryUVPackMargin: 4 + useFileScale: 1 + tangentSpace: + normalSmoothAngle: 60 + normalImportMode: 0 + tangentImportMode: 3 + importAnimation: 1 + copyAvatar: 0 + humanDescription: + serializedVersion: 2 + human: [] + skeleton: [] + armTwist: 0.5 + foreArmTwist: 0.5 + upperLegTwist: 0.5 + legTwist: 0.5 + armStretch: 0.05 + legStretch: 0.05 + feetSpacing: 0 + rootMotionBoneName: + rootMotionBoneRotation: {x: 0, y: 0, z: 0, w: 1} + hasTranslationDoF: 0 + hasExtraRoot: 0 + skeletonHasParents: 1 + lastHumanDescriptionAvatarSource: {instanceID: 0} + animationType: 0 + humanoidOversampling: 1 + additionalBone: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/BezierSolution/Demo/OctopusArm.mat b/Assets/Plugins/BezierSolution/Demo/OctopusArm.mat new file mode 100644 index 00000000..b4d89719 --- /dev/null +++ b/Assets/Plugins/BezierSolution/Demo/OctopusArm.mat @@ -0,0 +1,79 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!21 &2100000 +Material: + serializedVersion: 6 + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_Name: OctopusArm + m_Shader: {fileID: 10752, guid: 0000000000000000f000000000000000, type: 0} + m_ShaderKeywords: _NORMALMAP + m_LightmapFlags: 4 + m_EnableInstancingVariants: 0 + m_DoubleSidedGI: 0 + m_CustomRenderQueue: -1 + stringTagMap: {} + disabledShaderPasses: [] + m_SavedProperties: + serializedVersion: 3 + m_TexEnvs: + - _BumpMap: + m_Texture: {fileID: 2800000, guid: 89e1b1c005d29cf4598ea861deb35a80, type: 3} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DetailAlbedoMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DetailMask: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DetailNormalMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _EmissionMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _MainTex: + m_Texture: {fileID: 2800000, guid: cd20479f79180f440ad81177db5e0b12, type: 3} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _MetallicGlossMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _OcclusionMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _ParallaxMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + m_Floats: + - _BumpScale: 1 + - _Cutoff: 0.5 + - _DetailNormalMapScale: 1 + - _DstBlend: 0 + - _GlossMapScale: 1 + - _Glossiness: 0.5 + - _GlossyReflections: 1 + - _Metallic: 0 + - _Mode: 0 + - _OcclusionStrength: 1 + - _Parallax: 0.02 + - _SamplePoint: 0 + - _SmoothnessTextureChannel: 0 + - _SpecularHighlights: 1 + - _SrcBlend: 1 + - _UVSec: 0 + - _ZWrite: 1 + m_Colors: + - _Color: {r: 1, g: 1, b: 1, a: 1} + - _EmissionColor: {r: 0, g: 0, b: 0, a: 1} + - _SampleRange: {r: 0, g: 1, b: 0, a: 0} + - _VertexRange: {r: 0, g: 1, b: 0, a: 0} diff --git a/Assets/Plugins/BezierSolution/Demo/OctopusArm.mat.meta b/Assets/Plugins/BezierSolution/Demo/OctopusArm.mat.meta new file mode 100644 index 00000000..2770a902 --- /dev/null +++ b/Assets/Plugins/BezierSolution/Demo/OctopusArm.mat.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 6b88831b1ed3c38439c9be5ac64f87c1 +timeCreated: 1620040793 +licenseType: Store +NativeFormatImporter: + mainObjectFileID: 2100000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/BezierSolution/Demo/OctopusArm.png b/Assets/Plugins/BezierSolution/Demo/OctopusArm.png new file mode 100644 index 00000000..bec90948 Binary files /dev/null and b/Assets/Plugins/BezierSolution/Demo/OctopusArm.png differ diff --git a/Assets/Plugins/BezierSolution/Demo/OctopusArm.png.meta b/Assets/Plugins/BezierSolution/Demo/OctopusArm.png.meta new file mode 100644 index 00000000..e1579d59 --- /dev/null +++ b/Assets/Plugins/BezierSolution/Demo/OctopusArm.png.meta @@ -0,0 +1,68 @@ +fileFormatVersion: 2 +guid: cd20479f79180f440ad81177db5e0b12 +timeCreated: 1620724293 +licenseType: Store +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 4 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + sRGBTexture: 1 + linearTexture: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: 0.25 + normalMapFilter: 0 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + filterMode: -1 + aniso: -1 + mipBias: -1 + wrapMode: -1 + nPOTScale: 1 + lightmap: 0 + compressionQuality: 50 + spriteMode: 0 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaUsage: 1 + alphaIsTransparency: 0 + spriteTessellationDetail: -1 + textureType: 0 + textureShape: 1 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + platformSettings: + - buildTarget: DefaultTexturePlatform + maxTextureSize: 2048 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/BezierSolution/Editor.meta b/Assets/Plugins/BezierSolution/Editor.meta new file mode 100644 index 00000000..f58a9d59 --- /dev/null +++ b/Assets/Plugins/BezierSolution/Editor.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 519da3ae01006d64ea40c00e92df6614 +folderAsset: yes +timeCreated: 1472735538 +licenseType: Store +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/BezierSolution/Editor/BezierPointEditor.cs b/Assets/Plugins/BezierSolution/Editor/BezierPointEditor.cs new file mode 100644 index 00000000..4a26790b --- /dev/null +++ b/Assets/Plugins/BezierSolution/Editor/BezierPointEditor.cs @@ -0,0 +1,1308 @@ +using UnityEngine; +using UnityEditor; +using System.Collections.Generic; + +namespace BezierSolution.Extras +{ + [CustomEditor( typeof( BezierPoint ) )] + [CanEditMultipleObjects] + public class BezierPointEditor : Editor + { + private enum PointInsertionMode { None = 0, Simple = 1, PreserveShape = 2 }; + + private class SplineHolder + { + public BezierSpline spline; + public BezierPoint[] points; + + public SplineHolder( BezierSpline spline, BezierPoint[] points ) + { + this.spline = spline; + this.points = points; + } + + public void SortPoints( bool forwards ) + { + if( forwards ) + System.Array.Sort( points, CompareForwards ); + else + System.Array.Sort( points, CompareBackwards ); + } + + private int CompareForwards( BezierPoint x, BezierPoint y ) + { + return x.index.CompareTo( y.index ); + } + + private int CompareBackwards( BezierPoint x, BezierPoint y ) + { + return y.index.CompareTo( x.index ); + } + } + + private const float CONTROL_POINTS_MINIMUM_SAFE_DISTANCE_SQR = 0.05f * 0.05f; + + private static readonly Color RESET_POINT_BUTTON_COLOR = new Color( 1f, 1f, 0.65f, 1f ); + private static readonly Color REMOVE_POINT_BUTTON_COLOR = new Color( 1f, 0.65f, 0.65f, 1f ); + private static readonly GUIContent MULTI_EDIT_TIP = new GUIContent( "Tip: Hold Shift to affect all points' Transforms" ); + private static readonly GUIContent OPPOSITE_TRANSFORMATION_OFF_TIP = new GUIContent( "(in THE SAME direction - hit C to toggle)" ); + private static readonly GUIContent OPPOSITE_TRANSFORMATION_ON_TIP = new GUIContent( "(in OPPOSITE directions - hit C to toggle)" ); + private static readonly GUIContent INSERT_POINT_PRESERVE_SHAPE = new GUIContent( "Preserve Shape", "Spline's shape will be preserved but the neighboring end points' 'Handle Mode' will no longer be 'Mirrored'" ); + private static readonly GUIContent APPLY_TO_ALL_POINTS = new GUIContent( "All", "Apply to all points in the selected spline(s)" ); + private static readonly GUIContent HANDLE_MODE_TIP = new GUIContent( "Handle Mode", "Control points are handled in one of 3 ways:\n-Free: allows moving control points independently\n-Mirrored: places the control points opposite to each other\n-Aligned: ensures that both control points are aligned on a line that passes through the end point (unlike Mirrored mode, their distance to end point may differ)" ); + private static readonly GUIContent EXTRA_DATA_TIP = new GUIContent( "Extra Data", "Each end point can store additional data that holds 4 floats. You can interpolate between points' extra data via spline's GetExtraData function. For example, extra data can be used to assign a custom rotation value to each end point that can be read by BezierWalker components" ); + private static readonly GUIContent NORMALS_SET_TO_CAMERA_FORWARD = new GUIContent( "C", "Set to Scene camera's forward direction" ); + private static readonly GUIContent NORMALS_LOOK_AT_CAMERA = new GUIContent( "L", "Look towards Scene camera's current position" ); + private static readonly GUIContent NORMALIZE_NORMALS_TIP = new GUIContent( "Normalize Normals", "Sets normal vectors' length to 1" ); + private static readonly GUIContent EXTRA_DATA_SET_AS_CAMERA_FORWARD = new GUIContent( "C", "Set as Scene camera's current rotation" ); + private static readonly GUIContent EXTRA_DATA_VIEW_AS_FRUSTUM = new GUIContent( "V", "Visualize data as camera frustum in Scene" ); + + private SplineHolder[] selection; + internal BezierSpline[] allSplines; + private BezierPoint[] allPoints; + private int pointCount; + + private Vector3[] pointInitialPositions; + private Quaternion[] pointInitialRotations; + private Vector3[] pointInitialScales; + private Vector3[] precedingPointInitialPositions; + private Vector3[] followingPointInitialPositions; + private bool allPointsModified; + + private Quaternion[] precedingPointRotations; + private Quaternion[] followingPointRotations; + private bool controlPointRotationsInitialized; + + private Tool previousTool = Tool.None; + + public static BezierPointEditor ActiveEditor { get; private set; } + + private void OnEnable() + { + Object[] points = targets; + pointCount = points.Length; + allPoints = new BezierPoint[pointCount]; + + pointInitialPositions = new Vector3[pointCount]; + pointInitialRotations = new Quaternion[pointCount]; + pointInitialScales = new Vector3[pointCount]; + precedingPointInitialPositions = new Vector3[pointCount]; + followingPointInitialPositions = new Vector3[pointCount]; + + precedingPointRotations = new Quaternion[pointCount]; + followingPointRotations = new Quaternion[pointCount]; + controlPointRotationsInitialized = false; + + if( pointCount == 1 ) + { + BezierPoint point = (BezierPoint) points[0]; + + selection = new SplineHolder[1] { new SplineHolder( point.GetComponentInParent(), new BezierPoint[1] { point } ) }; + allSplines = selection[0].spline ? new BezierSpline[1] { selection[0].spline } : new BezierSpline[0]; + allPoints[0] = point; + } + else + { + Dictionary> lookupTable = new Dictionary>( pointCount ); + List nullSplinePoints = null; + + for( int i = 0; i < pointCount; i++ ) + { + BezierPoint point = (BezierPoint) points[i]; + BezierSpline spline = point.GetComponentInParent(); + if( !spline ) + { + spline = null; + + if( nullSplinePoints == null ) + nullSplinePoints = new List( pointCount ); + + nullSplinePoints.Add( point ); + } + else + { + List _points; + if( !lookupTable.TryGetValue( spline, out _points ) ) + { + _points = new List( pointCount ); + lookupTable[spline] = _points; + } + + _points.Add( point ); + } + + allPoints[i] = point; + } + + int index; + if( nullSplinePoints != null ) + { + index = 1; + selection = new SplineHolder[lookupTable.Count + 1]; + selection[0] = new SplineHolder( null, nullSplinePoints.ToArray() ); + } + else + { + index = 0; + selection = new SplineHolder[lookupTable.Count]; + } + + int index2 = 0; + allSplines = new BezierSpline[lookupTable.Count]; + + foreach( var element in lookupTable ) + { + selection[index++] = new SplineHolder( element.Key, element.Value.ToArray() ); + allSplines[index2++] = element.Key; + } + } + + for( int i = 0; i < selection.Length; i++ ) + { + selection[i].SortPoints( true ); + + if( selection[i].spline ) + selection[i].spline.Refresh(); + } + + ActiveEditor = this; + + Tools.hidden = true; + + if( BezierUtils.QuickEditSplineMode ) + { + EditorApplication.update -= SceneView.RepaintAll; + EditorApplication.update += SceneView.RepaintAll; + } + + Undo.undoRedoPerformed -= OnUndoRedo; + Undo.undoRedoPerformed += OnUndoRedo; + } + + private void OnDisable() + { + ActiveEditor = null; + Tools.hidden = false; + + Undo.undoRedoPerformed -= OnUndoRedo; + EditorApplication.update -= SceneView.RepaintAll; + } + + private void OnSceneGUI() + { + BezierPoint point = (BezierPoint) target; + if( !point ) + return; + + if( CheckCommands() ) + return; + + Event e = Event.current; + Tool tool = Tools.current; + + // OnSceneGUI is called separately for each selected point, make sure that the spline is drawn only once, not multiple times + if( point == allPoints[0] ) + { + for( int i = 0; i < selection.Length; i++ ) + { + BezierSpline spline = selection[i].spline; + if( spline ) + { + BezierPoint[] points = selection[i].points; + BezierUtils.DrawSplineDetailed( spline ); + for( int j = 0, k = 0; j < spline.Count; j++ ) + { + bool isSelected = spline[j] == points[k]; + if( isSelected && k < points.Length - 1 ) + k++; + + if( !isSelected ) + BezierUtils.DrawBezierPoint( spline[j], j + 1, false ); + } + } + } + + if( !BezierUtils.QuickEditSplineMode && allPoints.Length > 1 && ( tool == Tool.Move || tool == Tool.Rotate || tool == Tool.Scale ) ) + { + GUIStyle style = "PreOverlayLabel"; // Taken from: https://github.com/Unity-Technologies/UnityCsReference/blob/f78f4093c8a2b45949a847cdc704cf209dcf2f36/Editor/Mono/EditorGUI.cs#L629 + Rect multiEditTipRect = new Rect( Vector2.zero, style.CalcSize( MULTI_EDIT_TIP ) ); + + Handles.BeginGUI(); + + EditorGUI.DropShadowLabel( multiEditTipRect, MULTI_EDIT_TIP, style ); + if( tool == Tool.Move || tool == Tool.Rotate ) + { + Rect multiEditOppositeTransformationTipRect = new Rect( new Vector2( multiEditTipRect.width + 4f, 0f ), style.CalcSize( BezierSettings.MoveMultiplePointsInOppositeDirections ? OPPOSITE_TRANSFORMATION_ON_TIP : OPPOSITE_TRANSFORMATION_OFF_TIP ) ); + EditorGUI.DropShadowLabel( multiEditOppositeTransformationTipRect, BezierSettings.MoveMultiplePointsInOppositeDirections ? OPPOSITE_TRANSFORMATION_ON_TIP : OPPOSITE_TRANSFORMATION_OFF_TIP, style ); + } + + Handles.EndGUI(); + + if( e.type == EventType.KeyUp && e.keyCode == KeyCode.C && ( tool == Tool.Move || tool == Tool.Rotate ) ) + BezierSettings.MoveMultiplePointsInOppositeDirections = !BezierSettings.MoveMultiplePointsInOppositeDirections; + } + + if( e.type == EventType.MouseDown && e.button == 0 ) + { + // Cache initial Transform values of the points + for( int i = 0; i < allPoints.Length; i++ ) + { + BezierPoint p = allPoints[i]; + + pointInitialPositions[i] = p.position; + pointInitialRotations[i] = p.rotation; + pointInitialScales[i] = p.localScale; + precedingPointInitialPositions[i] = p.precedingControlPointPosition; + followingPointInitialPositions[i] = p.followingControlPointPosition; + } + + allPointsModified = false; + } + } + + // When Control key is pressed, BezierPoint gizmos should be drawn on top of Transform handles in order to allow selecting/deselecting points + // If Alt key is pressed, Transform handles aren't drawn at all, so BezierPoint gizmos can be drawn immediately + // When in point insertion mode, handles aren't drawn and BezierPoint gizmos must be drawn immediately + if( e.alt || !e.control || BezierUtils.QuickEditSplineMode ) + BezierUtils.DrawBezierPoint( point, point.index + 1, true ); + + if( BezierSettings.ShowEvenlySpacedPoints ) + { + if( point == allPoints[0] ) + { + for( int i = 0; i < allSplines.Length; i++ ) + BezierUtils.DrawSplineEvenlySpacedPoints( allSplines[i] ); + } + } + + if( BezierUtils.QuickEditSplineMode ) + { + // Execute quick edit mode's scene GUI only once (otherwise things can get ugly when multiple points are selected) + if( point == allPoints[0] ) + { + BezierUtils.QuickEditModeSceneGUI( allSplines ); + HandleUtility.AddDefaultControl( 0 ); + } + + return; + } + + // Camera rotates with Alt key, don't interfere + if( e.alt ) + return; + + int pointIndex = -1; + for( int i = 0; i < allPoints.Length; i++ ) + { + if( allPoints[i] == point ) + { + pointIndex = i; + break; + } + } + + if( previousTool != tool ) + { + controlPointRotationsInitialized = false; + previousTool = tool; + } + + // Draw Transform handles for control points + switch( Tools.current ) + { + case Tool.Move: + if( !controlPointRotationsInitialized ) + { + for( int i = 0; i < allPoints.Length; i++ ) + { + BezierPoint p = allPoints[i]; + + precedingPointRotations[i] = Quaternion.LookRotation( p.precedingControlPointPosition - p.position ); + followingPointRotations[i] = Quaternion.LookRotation( p.followingControlPointPosition - p.position ); + } + + controlPointRotationsInitialized = true; + } + + // No need to show gizmos for control points in Autoconstruct mode + Vector3 position; + if( BezierSettings.ShowControlPoints && ( !point.spline || point.spline.autoConstructMode == SplineAutoConstructMode.None ) ) + { + EditorGUI.BeginChangeCheck(); + position = Handles.PositionHandle( point.precedingControlPointPosition, Tools.pivotRotation == PivotRotation.Local ? precedingPointRotations[pointIndex] : Quaternion.identity ); + if( EditorGUI.EndChangeCheck() ) + { + Undo.RecordObject( point, "Move Control Point" ); + point.precedingControlPointPosition = position; + + if( e.shift && allPoints.Length > 1 ) + { + Vector3 delta = Matrix4x4.TRS( precedingPointInitialPositions[pointIndex], Tools.pivotRotation == PivotRotation.Local ? precedingPointRotations[pointIndex] : Quaternion.identity, Vector3.Distance( precedingPointInitialPositions[pointIndex], point.position ) * Vector3.one ).inverse.MultiplyPoint3x4( position ); + if( BezierSettings.MoveMultiplePointsInOppositeDirections ) + delta = -delta; + + for( int i = 0; i < allPoints.Length; i++ ) + { + if( i != pointIndex ) + { + Undo.RecordObject( allPoints[i], "Move Control Point" ); + allPoints[i].precedingControlPointPosition = Matrix4x4.TRS( precedingPointInitialPositions[i], Tools.pivotRotation == PivotRotation.Local ? precedingPointRotations[i] : Quaternion.identity, Vector3.Distance( precedingPointInitialPositions[i], allPoints[i].position ) * Vector3.one ).MultiplyPoint3x4( delta ); + } + } + + allPointsModified = true; + } + else if( !e.shift && allPointsModified ) // If shift is released before the left mouse button, reset other points' positions + { + for( int i = 0; i < allPoints.Length; i++ ) + { + if( i != pointIndex ) + { + Undo.RecordObject( allPoints[i], "Move Control Point" ); + allPoints[i].precedingControlPointPosition = precedingPointInitialPositions[i]; + } + } + + allPointsModified = false; + } + } + + EditorGUI.BeginChangeCheck(); + position = Handles.PositionHandle( point.followingControlPointPosition, Tools.pivotRotation == PivotRotation.Local ? followingPointRotations[pointIndex] : Quaternion.identity ); + if( EditorGUI.EndChangeCheck() ) + { + Undo.RecordObject( point, "Move Control Point" ); + point.followingControlPointPosition = position; + + if( e.shift && allPoints.Length > 1 ) + { + Vector3 delta = Matrix4x4.TRS( followingPointInitialPositions[pointIndex], Tools.pivotRotation == PivotRotation.Local ? followingPointRotations[pointIndex] : Quaternion.identity, Vector3.Distance( followingPointInitialPositions[pointIndex], point.position ) * Vector3.one ).inverse.MultiplyPoint3x4( position ); + if( BezierSettings.MoveMultiplePointsInOppositeDirections ) + delta = -delta; + + for( int i = 0; i < allPoints.Length; i++ ) + { + if( i != pointIndex ) + { + Undo.RecordObject( allPoints[i], "Move Control Point" ); + allPoints[i].followingControlPointPosition = Matrix4x4.TRS( followingPointInitialPositions[i], Tools.pivotRotation == PivotRotation.Local ? followingPointRotations[i] : Quaternion.identity, Vector3.Distance( followingPointInitialPositions[i], allPoints[i].position ) * Vector3.one ).MultiplyPoint3x4( delta ); + } + } + + allPointsModified = true; + } + else if( !e.shift && allPointsModified ) // If shift is released before the left mouse button, reset other points' positions + { + for( int i = 0; i < allPoints.Length; i++ ) + { + if( i != pointIndex ) + { + Undo.RecordObject( allPoints[i], "Move Control Point" ); + allPoints[i].followingControlPointPosition = followingPointInitialPositions[i]; + } + } + + allPointsModified = false; + } + } + } + + EditorGUI.BeginChangeCheck(); + position = Handles.PositionHandle( point.position, Tools.pivotRotation == PivotRotation.Local ? point.rotation : Quaternion.identity ); + if( EditorGUI.EndChangeCheck() ) + { + Undo.RecordObject( point, "Move Point" ); + Undo.RecordObject( point.transform, "Move Point" ); + point.position = position; + + if( e.shift && allPoints.Length > 1 ) + { + Vector3 delta = position - pointInitialPositions[pointIndex]; + if( BezierSettings.MoveMultiplePointsInOppositeDirections ) + delta = -delta; + + for( int i = 0; i < allPoints.Length; i++ ) + { + if( i != pointIndex ) + { + Undo.RecordObject( allPoints[i], "Move Point" ); + Undo.RecordObject( allPoints[i].transform, "Move Point" ); + allPoints[i].position = pointInitialPositions[i] + delta; + } + } + + allPointsModified = true; + } + else if( !e.shift && allPointsModified ) // If shift is released before the left mouse button, reset other points' positions + { + for( int i = 0; i < allPoints.Length; i++ ) + { + if( i != pointIndex ) + { + Undo.RecordObject( allPoints[i], "Move Point" ); + Undo.RecordObject( allPoints[i].transform, "Move Point" ); + allPoints[i].position = pointInitialPositions[i]; + } + } + + allPointsModified = false; + } + } + + break; + case Tool.Rotate: + Quaternion handleRotation; + if( Tools.pivotRotation == PivotRotation.Local ) + { + handleRotation = point.rotation; + controlPointRotationsInitialized = false; + } + else + { + if( !controlPointRotationsInitialized ) + { + for( int i = 0; i < allPoints.Length; i++ ) + precedingPointRotations[i] = Quaternion.identity; + + controlPointRotationsInitialized = true; + } + + handleRotation = precedingPointRotations[pointIndex]; + } + + EditorGUI.BeginChangeCheck(); + Quaternion rotation = Handles.RotationHandle( handleRotation, point.position ); + if( EditorGUI.EndChangeCheck() ) + { + // "rotation * Quaternion.Inverse( handleRotation )": World-space delta rotation + // "delta rotation * point.rotation": Applying world-space delta rotation to current rotation + Quaternion pointFinalRotation = rotation * Quaternion.Inverse( handleRotation ) * point.rotation; + + Undo.RecordObject( point.transform, "Rotate Point" ); + point.rotation = pointFinalRotation; + + if( e.shift && allPoints.Length > 1 ) + { + Quaternion delta = pointFinalRotation * Quaternion.Inverse( pointInitialRotations[pointIndex] ); + if( BezierSettings.MoveMultiplePointsInOppositeDirections ) + delta = Quaternion.Inverse( delta ); + + for( int i = 0; i < allPoints.Length; i++ ) + { + if( i != pointIndex ) + { + Undo.RecordObject( allPoints[i].transform, "Rotate Point" ); + allPoints[i].rotation = delta * pointInitialRotations[i]; + } + } + + allPointsModified = true; + } + else if( !e.shift && allPointsModified ) // If shift is released before the left mouse button, reset other points' rotations + { + for( int i = 0; i < allPoints.Length; i++ ) + { + if( i != pointIndex ) + { + Undo.RecordObject( allPoints[i].transform, "Rotate Point" ); + allPoints[i].rotation = pointInitialRotations[i]; + } + } + + allPointsModified = false; + } + + if( Tools.pivotRotation == PivotRotation.Global ) + precedingPointRotations[pointIndex] = rotation; + } + + break; + case Tool.Scale: + EditorGUI.BeginChangeCheck(); + Vector3 scale = Handles.ScaleHandle( point.localScale, point.position, point.rotation, HandleUtility.GetHandleSize( point.position ) ); + if( EditorGUI.EndChangeCheck() ) + { + Undo.RecordObject( point.transform, "Scale Point" ); + point.localScale = scale; + + if( e.shift && allPoints.Length > 1 ) + { + Vector3 delta = new Vector3( 1f, 1f, 1f ); + Vector3 prevScale = pointInitialScales[pointIndex]; + if( prevScale.x != 0f ) + delta.x = scale.x / prevScale.x; + if( prevScale.y != 0f ) + delta.y = scale.y / prevScale.y; + if( prevScale.z != 0f ) + delta.z = scale.z / prevScale.z; + + for( int i = 0; i < allPoints.Length; i++ ) + { + if( i != pointIndex ) + { + prevScale = pointInitialScales[i]; + prevScale.Scale( delta ); + + Undo.RecordObject( allPoints[i].transform, "Scale Point" ); + allPoints[i].localScale = prevScale; + } + } + + allPointsModified = true; + } + else if( !e.shift && allPointsModified ) // If shift is released before the left mouse button, reset other points' scales + { + for( int i = 0; i < allPoints.Length; i++ ) + { + if( i != pointIndex ) + { + Undo.RecordObject( allPoints[i].transform, "Scale Point" ); + allPoints[i].localScale = pointInitialScales[i]; + } + } + + allPointsModified = false; + } + } + + break; + } + + if( e.control ) + BezierUtils.DrawBezierPoint( point, point.index + 1, true ); + } + + public override void OnInspectorGUI() + { + if( CheckCommands() ) + GUIUtility.ExitGUI(); + + if( allSplines.Length == 0 ) + { + EditorGUILayout.HelpBox( "Selected point(s) aren't children of a BezierSpline!", MessageType.Error ); + + if( GUILayout.Button( "Refresh" ) ) + OnEnable(); + + return; + } + + BezierUtils.DrawSplineInspectorGUI( allSplines ); + + if( BezierUtils.QuickEditSplineMode ) + return; + + EditorGUILayout.Space(); + BezierUtils.DrawSeparator(); + + GUILayout.BeginHorizontal(); + + if( GUILayout.Button( "<-", BezierUtils.GL_WIDTH_45 ) ) + { + Object[] newSelection = new Object[pointCount]; + for( int i = 0, index = 0; i < selection.Length; i++ ) + { + BezierSpline spline = selection[i].spline; + BezierPoint[] points = selection[i].points; + + if( spline ) + { + for( int j = 0; j < points.Length; j++ ) + { + int prevIndex = points[j].index - 1; + if( prevIndex < 0 ) + prevIndex = spline.Count - 1; + + newSelection[index++] = spline[prevIndex].gameObject; + } + } + else + { + for( int j = 0; j < points.Length; j++ ) + newSelection[index++] = points[j].gameObject; + } + } + + Selection.objects = newSelection; + GUIUtility.ExitGUI(); + } + + string pointIndex = ( pointCount == 1 && selection[0].spline ) ? ( allPoints[0].index + 1 ).ToString() : "-"; + string splineLength = ( selection.Length == 1 && selection[0].spline ) ? selection[0].spline.Count.ToString() : "-"; + GUILayout.Box( "Selected Point: " + pointIndex + " / " + splineLength, GUILayout.ExpandWidth( true ) ); + + if( GUILayout.Button( "->", BezierUtils.GL_WIDTH_45 ) ) + { + Object[] newSelection = new Object[pointCount]; + for( int i = 0, index = 0; i < selection.Length; i++ ) + { + BezierSpline spline = selection[i].spline; + BezierPoint[] points = selection[i].points; + + if( spline ) + { + for( int j = 0; j < points.Length; j++ ) + { + int nextIndex = points[j].index + 1; + if( nextIndex >= spline.Count ) + nextIndex = 0; + + newSelection[index++] = spline[nextIndex].gameObject; + } + } + else + { + for( int j = 0; j < points.Length; j++ ) + newSelection[index++] = points[j].gameObject; + } + } + + Selection.objects = newSelection; + GUIUtility.ExitGUI(); + } + + GUILayout.EndHorizontal(); + + EditorGUILayout.Space(); + + if( GUILayout.Button( "Decrement Point's Index" ) ) + { + Undo.IncrementCurrentGroup(); + + for( int i = 0; i < selection.Length; i++ ) + { + BezierSpline spline = selection[i].spline; + if( spline ) + { + selection[i].SortPoints( true ); + + BezierPoint[] points = selection[i].points; + int[] newIndices = new int[points.Length]; + for( int j = 0; j < points.Length; j++ ) + { + int index = points[j].index; + int newIndex = index - 1; + if( newIndex < 0 ) + newIndex = spline.Count - 1; + + newIndices[j] = newIndex; + } + + for( int j = 0; j < points.Length; j++ ) + spline.ChangePointIndex( points[j].index, newIndices[j], "Change point index" ); + + selection[i].SortPoints( true ); + } + } + + SceneView.RepaintAll(); + } + + if( GUILayout.Button( "Increment Point's Index" ) ) + { + Undo.IncrementCurrentGroup(); + + for( int i = 0; i < selection.Length; i++ ) + { + BezierSpline spline = selection[i].spline; + if( spline ) + { + selection[i].SortPoints( false ); + + BezierPoint[] points = selection[i].points; + int[] newIndices = new int[points.Length]; + for( int j = 0; j < points.Length; j++ ) + { + int index = points[j].index; + int newIndex = index + 1; + if( newIndex >= spline.Count ) + newIndex = 0; + + newIndices[j] = newIndex; + } + + for( int j = 0; j < points.Length; j++ ) + spline.ChangePointIndex( points[j].index, newIndices[j], "Change point index" ); + + selection[i].SortPoints( true ); + } + } + + SceneView.RepaintAll(); + } + + EditorGUILayout.Space(); + + bool allSplinesUsingAutoConstructMode = !System.Array.Find( allSplines, ( s ) => s.autoConstructMode == SplineAutoConstructMode.None ); + bool anySplineUsingAutoCalculateNormals = System.Array.Find( allSplines, ( s ) => s.autoCalculateNormals ); + + GUILayout.BeginHorizontal(); + if( GUILayout.Button( "Insert Point Before" ) ) + InsertNewPoints( false, false ); + if( !allSplinesUsingAutoConstructMode && GUILayout.Button( INSERT_POINT_PRESERVE_SHAPE, EditorGUIUtility.wideMode ? BezierUtils.GL_WIDTH_155 : BezierUtils.GL_WIDTH_100 ) ) + InsertNewPoints( false, true ); + GUILayout.EndHorizontal(); + + GUILayout.BeginHorizontal(); + if( GUILayout.Button( "Insert Point After" ) ) + InsertNewPoints( true, false ); + if( !allSplinesUsingAutoConstructMode && GUILayout.Button( INSERT_POINT_PRESERVE_SHAPE, EditorGUIUtility.wideMode ? BezierUtils.GL_WIDTH_155 : BezierUtils.GL_WIDTH_100 ) ) + InsertNewPoints( true, true ); + GUILayout.EndHorizontal(); + + EditorGUILayout.Space(); + + if( GUILayout.Button( "Duplicate Point" ) ) + DuplicateSelectedPoints(); + + EditorGUILayout.Space(); + + GUI.enabled = !allSplinesUsingAutoConstructMode; + + EditorGUI.showMixedValue = HasMultipleDifferentValues( ( p1, p2 ) => p1.handleMode == p2.handleMode ); + EditorGUI.BeginChangeCheck(); + BezierPoint.HandleMode handleMode = (BezierPoint.HandleMode) EditorGUILayout.EnumPopup( HANDLE_MODE_TIP, allPoints[0].handleMode ); + if( EditorGUI.EndChangeCheck() ) + { + for( int i = 0; i < allPoints.Length; i++ ) + { + Undo.RecordObject( allPoints[i], "Change Point Handle Mode" ); + allPoints[i].handleMode = handleMode; + } + + SceneView.RepaintAll(); + } + + EditorGUILayout.Space(); + + EditorGUI.showMixedValue = HasMultipleDifferentValues( ( p1, p2 ) => p1.precedingControlPointLocalPosition == p2.precedingControlPointLocalPosition ); + EditorGUI.BeginChangeCheck(); + Vector3 precedingControlPointLocalPosition = EditorGUILayout.Vector3Field( "Preceding Control Point Local Position", allPoints[0].precedingControlPointLocalPosition ); + if( EditorGUI.EndChangeCheck() ) + { + for( int i = 0; i < allPoints.Length; i++ ) + { + Undo.RecordObject( allPoints[i], "Change Point Position" ); + allPoints[i].precedingControlPointLocalPosition = precedingControlPointLocalPosition; + } + + SceneView.RepaintAll(); + } + + EditorGUI.showMixedValue = HasMultipleDifferentValues( ( p1, p2 ) => p1.followingControlPointLocalPosition == p2.followingControlPointLocalPosition ); + EditorGUI.BeginChangeCheck(); + Vector3 followingControlPointLocalPosition = EditorGUILayout.Vector3Field( "Following Control Point Local Position", allPoints[0].followingControlPointLocalPosition ); + if( EditorGUI.EndChangeCheck() ) + { + for( int i = 0; i < allPoints.Length; i++ ) + { + Undo.RecordObject( allPoints[i], "Change Point Position" ); + allPoints[i].followingControlPointLocalPosition = followingControlPointLocalPosition; + } + + SceneView.RepaintAll(); + } + + bool showControlPointDistanceWarning = false; + for( int i = 0; i < allPoints.Length; i++ ) + { + BezierPoint point = allPoints[i]; + if( ( point.position - point.precedingControlPointPosition ).sqrMagnitude < CONTROL_POINTS_MINIMUM_SAFE_DISTANCE_SQR || + ( point.position - point.followingControlPointPosition ).sqrMagnitude < CONTROL_POINTS_MINIMUM_SAFE_DISTANCE_SQR ) + { + showControlPointDistanceWarning = true; + break; + } + } + + if( showControlPointDistanceWarning ) + EditorGUILayout.HelpBox( "Positions of control point(s) shouldn't be very close to (0,0,0), this might result in unpredictable behaviour while moving along the spline with constant speed.", MessageType.Warning ); + + EditorGUILayout.Space(); + + GUILayout.BeginHorizontal(); + if( GUILayout.Button( "Swap Control Points" ) ) + { + SwapControlPoints( allPoints ); + SceneView.RepaintAll(); + } + if( GUILayout.Button( APPLY_TO_ALL_POINTS, BezierUtils.GL_WIDTH_60 ) ) + { + for( int i = 0; i < allSplines.Length; i++ ) + SwapControlPoints( allSplines[i].endPoints ); + + SceneView.RepaintAll(); + } + GUILayout.EndHorizontal(); + + GUI.enabled = true; + + EditorGUILayout.Space(); + BezierUtils.DrawSeparator(); + + GUI.enabled = !anySplineUsingAutoCalculateNormals; + + GUILayout.BeginHorizontal(); + EditorGUI.showMixedValue = HasMultipleDifferentValues( ( p1, p2 ) => p1.normal == p2.normal ); + EditorGUI.BeginChangeCheck(); + Rect normalRect = EditorGUILayout.GetControlRect( false, EditorGUIUtility.singleLineHeight ); // When using GUILayout, button isn't vertically centered + normalRect.width -= 65f; + Vector3 normal = EditorGUI.Vector3Field( normalRect, "Normal", allPoints[0].normal ); + normalRect.x += normalRect.width + 5f; + normalRect.width = 30f; + if( GUI.Button( normalRect, NORMALS_SET_TO_CAMERA_FORWARD ) ) + normal = SceneView.lastActiveSceneView.camera.transform.forward; + if( EditorGUI.EndChangeCheck() ) + { + for( int i = 0; i < allPoints.Length; i++ ) + allPoints[i].SetNormalAndResetIntermediateNormals( normal, "Change Normal" ); + + SceneView.RepaintAll(); + } + + normalRect.x += 30f; + if( GUI.Button( normalRect, NORMALS_LOOK_AT_CAMERA ) ) + { + Vector3 cameraPos = SceneView.lastActiveSceneView.camera.transform.position; + for( int i = 0; i < allPoints.Length; i++ ) + allPoints[i].SetNormalAndResetIntermediateNormals( ( cameraPos - allPoints[i].position ).normalized, "Change Normal" ); + + SceneView.RepaintAll(); + } + GUILayout.EndHorizontal(); + + if( !EditorGUIUtility.wideMode ) + GUILayout.Space( EditorGUIUtility.singleLineHeight ); + + if( anySplineUsingAutoCalculateNormals ) + { + GUI.enabled = true; + + EditorGUI.showMixedValue = HasMultipleDifferentValues( ( p1, p2 ) => p1.autoCalculatedNormalAngleOffset == p2.autoCalculatedNormalAngleOffset ); + EditorGUI.BeginChangeCheck(); + float autoCalculatedNormalAngleOffset = EditorGUILayout.FloatField( "Normal Angle", allPoints[0].autoCalculatedNormalAngleOffset ); + if( EditorGUI.EndChangeCheck() ) + { + for( int i = 0; i < allPoints.Length; i++ ) + { + Undo.RecordObject( allPoints[i], "Change Normal Angle" ); + allPoints[i].autoCalculatedNormalAngleOffset = autoCalculatedNormalAngleOffset; + } + + for( int i = 0; i < allSplines.Length; i++ ) + BezierUtils.SetSplineDirtyWithUndo( allSplines[i], "Change Normal Angle", InternalDirtyFlags.NormalOffsetChange ); + + SceneView.RepaintAll(); + } + + GUI.enabled = false; + } + else + { + EditorGUI.BeginChangeCheck(); + float normalRotationAngle = EditorGUILayout.FloatField( "Rotate Normal (Drag Here)", 0f ); + if( EditorGUI.EndChangeCheck() && !Mathf.Approximately( normalRotationAngle, 0f ) ) + { + for( int i = 0; i < allPoints.Length; i++ ) + { + BezierSpline spline = allPoints[i].spline; + int index = allPoints[i].index; + + if( spline ) + { + Vector3 tangent; + if( index < spline.Count - 1 ) + tangent = new BezierSpline.Segment( spline[index], spline[index + 1], 0f ).GetTangent(); + else if( spline.loop ) + tangent = new BezierSpline.Segment( spline[index], spline[0], 0f ).GetTangent(); + else + tangent = new BezierSpline.Segment( spline[index - 1], spline[index], 1f ).GetTangent(); + + allPoints[i].SetNormalAndResetIntermediateNormals( Quaternion.AngleAxis( normalRotationAngle, tangent ) * allPoints[i].normal, "Change Normal Rotate Angle" ); + } + } + + SceneView.RepaintAll(); + } + } + + EditorGUILayout.Space(); + + GUILayout.BeginHorizontal(); + if( GUILayout.Button( "Flip Normals" ) ) + { + FlipNormals( allPoints ); + SceneView.RepaintAll(); + } + if( GUILayout.Button( APPLY_TO_ALL_POINTS, BezierUtils.GL_WIDTH_60 ) ) + { + for( int i = 0; i < allSplines.Length; i++ ) + FlipNormals( allSplines[i].endPoints ); + + SceneView.RepaintAll(); + } + GUILayout.EndHorizontal(); + + GUILayout.BeginHorizontal(); + if( GUILayout.Button( NORMALIZE_NORMALS_TIP ) ) + { + NormalizeNormals( allPoints ); + SceneView.RepaintAll(); + } + if( GUILayout.Button( APPLY_TO_ALL_POINTS, BezierUtils.GL_WIDTH_60 ) ) + { + for( int i = 0; i < allSplines.Length; i++ ) + NormalizeNormals( allSplines[i].endPoints ); + + SceneView.RepaintAll(); + } + GUILayout.EndHorizontal(); + + GUILayout.BeginHorizontal(); + if( GUILayout.Button( "Reset Normals" ) ) + { + ResetNormals( allPoints ); + SceneView.RepaintAll(); + } + if( GUILayout.Button( APPLY_TO_ALL_POINTS, BezierUtils.GL_WIDTH_60 ) ) + { + for( int i = 0; i < allSplines.Length; i++ ) + ResetNormals( allSplines[i].endPoints ); + + SceneView.RepaintAll(); + } + GUILayout.EndHorizontal(); + + GUI.enabled = true; + + EditorGUILayout.Space(); + BezierUtils.DrawSeparator(); + + GUILayout.BeginHorizontal(); + EditorGUI.showMixedValue = HasMultipleDifferentValues( ( p1, p2 ) => p1.extraData == p2.extraData ); + EditorGUI.BeginChangeCheck(); + Rect extraDataRect = EditorGUILayout.GetControlRect( false, EditorGUIUtility.singleLineHeight ); // When using GUILayout, button isn't vertically centered + extraDataRect.width -= 65f; + BezierPoint.ExtraData extraData = EditorGUI.Vector4Field( extraDataRect, EXTRA_DATA_TIP, allPoints[0].extraData ); + extraDataRect.x += extraDataRect.width + 5f; + extraDataRect.width = 30f; + if( GUI.Button( extraDataRect, EXTRA_DATA_SET_AS_CAMERA_FORWARD ) ) + extraData = SceneView.lastActiveSceneView.camera.transform.rotation; + if( EditorGUI.EndChangeCheck() ) + { + for( int i = 0; i < allPoints.Length; i++ ) + { + Undo.RecordObject( allPoints[i], "Change Extra Data" ); + allPoints[i].extraData = extraData; + } + + SceneView.RepaintAll(); + } + + EditorGUI.showMixedValue = false; + + extraDataRect.x += 30f; + EditorGUI.BeginChangeCheck(); + bool visualizeExtraDataAsFrustum = GUI.Toggle( extraDataRect, BezierSettings.VisualizeExtraDataAsFrustum, EXTRA_DATA_VIEW_AS_FRUSTUM, GUI.skin.button ); + if( EditorGUI.EndChangeCheck() ) + { + BezierSettings.VisualizeExtraDataAsFrustum = visualizeExtraDataAsFrustum; + SceneView.RepaintAll(); + } + GUILayout.EndHorizontal(); + + if( !EditorGUIUtility.wideMode ) + GUILayout.Space( EditorGUIUtility.singleLineHeight ); + + BezierUtils.DrawSeparator(); + EditorGUILayout.Space(); + + Color c = GUI.backgroundColor; + GUI.backgroundColor = RESET_POINT_BUTTON_COLOR; + + if( GUILayout.Button( "Reset Point" ) ) + { + for( int i = 0; i < allPoints.Length; i++ ) + { + Undo.RecordObject( allPoints[i].transform, "Reset Point" ); + Undo.RecordObject( allPoints[i], "Reset Point" ); + + allPoints[i].Reset(); + } + + SceneView.RepaintAll(); + } + + EditorGUILayout.Space(); + + GUI.backgroundColor = REMOVE_POINT_BUTTON_COLOR; + + if( GUILayout.Button( "Remove Point" ) ) + { + RemoveSelectedPoints(); + GUIUtility.ExitGUI(); + } + + GUI.backgroundColor = c; + + for( int i = 0; i < allSplines.Length; i++ ) + allSplines[i].CheckDirty(); + } + + private bool CheckCommands() + { + Event e = Event.current; + if( e.type == EventType.ValidateCommand ) + { + if( e.commandName == "Delete" ) + { + RemoveSelectedPoints(); + e.type = EventType.Ignore; + + return true; + } + else if( e.commandName == "Duplicate" ) + { + DuplicateSelectedPoints(); + e.type = EventType.Ignore; + + return true; + } + } + + if( e.isKey && e.type == EventType.KeyDown && e.keyCode == KeyCode.Delete ) + { + RemoveSelectedPoints(); + e.Use(); + + return true; + } + + return false; + } + + private bool HasMultipleDifferentValues( System.Func comparer ) + { + if( allPoints.Length <= 1 ) + return false; + + for( int i = 1; i < allPoints.Length; i++ ) + { + if( !comparer( allPoints[0], allPoints[i] ) ) + return true; + } + + return false; + } + + private void InsertNewPoints( bool insertAfter, bool preserveShape ) + { + Undo.IncrementCurrentGroup(); + + Object[] newSelection = new Object[pointCount]; + for( int i = 0, index = 0; i < selection.Length; i++ ) + { + BezierSpline spline = selection[i].spline; + BezierPoint[] points = selection[i].points; + + for( int j = 0; j < points.Length; j++ ) + { + BezierPoint newPoint; + if( spline ) + { + int pointIndex = points[j].index; + if( insertAfter ) + pointIndex++; + + Vector3 position, followingControlPointPosition; + if( spline.Count >= 2 ) + { + if( !spline.loop && pointIndex == 0 ) + { + position = spline[0].position - Vector3.Distance( spline[1].position, spline[0].position ) * spline.GetTangent( 0f ).normalized; + followingControlPointPosition = position - ( position - spline[0].position ) * 0.5f; + } + else if( !spline.loop && pointIndex == spline.Count ) + { + position = spline[pointIndex - 1].position + Vector3.Distance( spline[pointIndex - 1].position, spline[pointIndex - 2].position ) * spline.GetTangent( 1f ).normalized; + followingControlPointPosition = position + ( position - spline[pointIndex - 1].position ) * 0.5f; + } + else + { + // Insert point in the middle without affecting the spline's shape + BezierPoint point1 = ( pointIndex == 0 || pointIndex == spline.Count ) ? spline[spline.Count - 1] : spline[pointIndex - 1]; + BezierPoint point2 = ( pointIndex == 0 || pointIndex == spline.Count ) ? spline[0] : spline[pointIndex]; + + Vector3 precedingControlPointPosition; + CalculateInsertedPointPosition( point1, point2, 0.5f, preserveShape, out position, out precedingControlPointPosition, out followingControlPointPosition ); + } + } + else if( spline.Count == 1 ) + { + position = pointIndex == 0 ? spline[0].position - Vector3.forward : spline[0].position + Vector3.forward; + followingControlPointPosition = position + ( spline[0].followingControlPointPosition - spline[0].position ); + } + else + { + position = spline.transform.position; + followingControlPointPosition = Vector3.right; + } + + newPoint = spline.InsertNewPointAt( pointIndex ); + newPoint.position = position; + newPoint.followingControlPointPosition = followingControlPointPosition; + } + else + newPoint = Instantiate( points[j], points[j].transform.parent ); + + Undo.RegisterCreatedObjectUndo( newPoint.gameObject, "Insert Point" ); + if( newPoint.transform.parent ) + Undo.RegisterCompleteObjectUndo( newPoint.transform.parent, "Insert Point" ); + + newSelection[index++] = newPoint.gameObject; + } + } + + Selection.objects = newSelection; + SceneView.RepaintAll(); + } + + private void DuplicateSelectedPoints() + { + Undo.IncrementCurrentGroup(); + + Object[] newSelection = new Object[pointCount]; + for( int i = 0, index = 0; i < selection.Length; i++ ) + { + BezierSpline spline = selection[i].spline; + BezierPoint[] points = selection[i].points; + + for( int j = 0; j < points.Length; j++ ) + { + BezierPoint newPoint; + if( spline ) + newPoint = spline.DuplicatePointAt( points[j].index ); + else + newPoint = Instantiate( points[j], points[j].transform.parent ); + + Undo.RegisterCreatedObjectUndo( newPoint.gameObject, "Duplicate Point" ); + if( newPoint.transform.parent ) + Undo.RegisterCompleteObjectUndo( newPoint.transform.parent, "Duplicate Point" ); + + newSelection[index++] = newPoint.gameObject; + } + } + + Selection.objects = newSelection; + SceneView.RepaintAll(); + } + + private void RemoveSelectedPoints() + { + Undo.IncrementCurrentGroup(); + + Object[] newSelection = new Object[selection.Length]; + for( int i = 0; i < selection.Length; i++ ) + { + BezierSpline spline = selection[i].spline; + BezierPoint[] points = selection[i].points; + + for( int j = 0; j < points.Length; j++ ) + Undo.DestroyObjectImmediate( points[j].gameObject ); + + if( spline ) + newSelection[i] = spline.gameObject; + } + + Selection.objects = newSelection; + SceneView.RepaintAll(); + } + + private void SwapControlPoints( IList points ) + { + for( int i = 0; i < points.Count; i++ ) + { + Undo.RecordObject( points[i], "Swap Control Points" ); + Vector3 temp = points[i].precedingControlPointLocalPosition; + points[i].precedingControlPointLocalPosition = points[i].followingControlPointLocalPosition; + points[i].followingControlPointLocalPosition = temp; + } + } + + // Credit: https://stackoverflow.com/a/2614028/2373034 + internal static void CalculateInsertedPointPosition( BezierPoint neighbor1, BezierPoint neighbor2, float localT, bool preserveShape, out Vector3 position, out Vector3 precedingControlPointPosition, out Vector3 followingControlPointPosition ) + { + float oneMinusLocalT = 1f - localT; + Vector3 P0_1 = oneMinusLocalT * neighbor1.position + localT * neighbor1.followingControlPointPosition; + Vector3 P1_2 = oneMinusLocalT * neighbor1.followingControlPointPosition + localT * neighbor2.precedingControlPointPosition; + Vector3 P2_3 = oneMinusLocalT * neighbor2.precedingControlPointPosition + localT * neighbor2.position; + + precedingControlPointPosition = oneMinusLocalT * P0_1 + localT * P1_2; + followingControlPointPosition = oneMinusLocalT * P1_2 + localT * P2_3; + + position = oneMinusLocalT * precedingControlPointPosition + localT * followingControlPointPosition; + + // We need to change neighboring end points' handleModes if we want to truly preserve the spline's shape + if( preserveShape ) + { + Undo.RecordObject( neighbor1, "Insert Point" ); + Undo.RecordObject( neighbor2, "Insert Point" ); + + if( neighbor1.handleMode == BezierPoint.HandleMode.Mirrored ) + neighbor1.handleMode = BezierPoint.HandleMode.Aligned; + if( neighbor2.handleMode == BezierPoint.HandleMode.Mirrored ) + neighbor2.handleMode = BezierPoint.HandleMode.Aligned; + + neighbor1.followingControlPointPosition = P0_1; + neighbor2.precedingControlPointPosition = P2_3; + } + } + + private void FlipNormals( IList points ) + { + for( int i = 0; i < points.Count; i++ ) + points[i].SetNormalAndResetIntermediateNormals( -points[i].normal, "Flip Normals" ); + } + + private void NormalizeNormals( IList points ) + { + for( int i = 0; i < points.Count; i++ ) + { + if( points[i].normal != Vector3.zero ) + points[i].SetNormalAndResetIntermediateNormals( points[i].normal.normalized, "Normalize Normals" ); + } + } + + private void ResetNormals( IList points ) + { + for( int i = 0; i < points.Count; i++ ) + points[i].SetNormalAndResetIntermediateNormals( Vector3.up, "Reset Normals" ); + } + + private void OnUndoRedo() + { + controlPointRotationsInitialized = false; + + for( int i = 0; i < selection.Length; i++ ) + { + if( selection[i].spline ) + { + selection[i].spline.dirtyFlags |= InternalDirtyFlags.All; + selection[i].spline.Refresh(); + } + } + + Repaint(); + } + + private bool HasFrameBounds() + { + return !serializedObject.isEditingMultipleObjects; + } + + private Bounds OnGetFrameBounds() + { + return new Bounds( ( (BezierPoint) target ).position, new Vector3( 1f, 1f, 1f ) ); + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/BezierSolution/Editor/BezierPointEditor.cs.meta b/Assets/Plugins/BezierSolution/Editor/BezierPointEditor.cs.meta new file mode 100644 index 00000000..25f7afc2 --- /dev/null +++ b/Assets/Plugins/BezierSolution/Editor/BezierPointEditor.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 9d0566a88081c1b46b6236e5b2575a7c +timeCreated: 1472737433 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/BezierSolution/Editor/BezierPointExtraDataDrawer.cs b/Assets/Plugins/BezierSolution/Editor/BezierPointExtraDataDrawer.cs new file mode 100644 index 00000000..126ab15e --- /dev/null +++ b/Assets/Plugins/BezierSolution/Editor/BezierPointExtraDataDrawer.cs @@ -0,0 +1,28 @@ +using UnityEditor; +using UnityEngine; + +namespace BezierSolution.Extras +{ + [CustomPropertyDrawer( typeof( BezierPoint.ExtraData ) )] + public class BezierPointExtraDataDrawer : PropertyDrawer + { + public override void OnGUI( Rect position, SerializedProperty property, GUIContent label ) + { + EditorGUI.BeginProperty( position, label, property ); + position = EditorGUI.PrefixLabel( position, GUIUtility.GetControlID( FocusType.Passive ), label ); + + float quarterWidth = position.width * 0.25f; + Rect c1Rect = new Rect( position.x, position.y, quarterWidth, position.height ); + Rect c2Rect = new Rect( position.x + quarterWidth, position.y, quarterWidth, position.height ); + Rect c3Rect = new Rect( position.x + 2f * quarterWidth, position.y, quarterWidth, position.height ); + Rect c4Rect = new Rect( position.x + 3f * quarterWidth, position.y, quarterWidth, position.height ); + + EditorGUI.PropertyField( c1Rect, property.FindPropertyRelative( "c1" ), GUIContent.none ); + EditorGUI.PropertyField( c2Rect, property.FindPropertyRelative( "c2" ), GUIContent.none ); + EditorGUI.PropertyField( c3Rect, property.FindPropertyRelative( "c3" ), GUIContent.none ); + EditorGUI.PropertyField( c4Rect, property.FindPropertyRelative( "c4" ), GUIContent.none ); + + EditorGUI.EndProperty(); + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/BezierSolution/Editor/BezierPointExtraDataDrawer.cs.meta b/Assets/Plugins/BezierSolution/Editor/BezierPointExtraDataDrawer.cs.meta new file mode 100644 index 00000000..54d185b2 --- /dev/null +++ b/Assets/Plugins/BezierSolution/Editor/BezierPointExtraDataDrawer.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: d6fe536a44fc10242a73e0114a06befa +timeCreated: 1520266844 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/BezierSolution/Editor/BezierSettings.cs b/Assets/Plugins/BezierSolution/Editor/BezierSettings.cs new file mode 100644 index 00000000..a93cb4ef --- /dev/null +++ b/Assets/Plugins/BezierSolution/Editor/BezierSettings.cs @@ -0,0 +1,757 @@ +using UnityEditor; +using UnityEngine; + +namespace BezierSolution.Extras +{ + public static class BezierSettings + { + #region Colors + private static Color? m_splineColor = null; + public static Color NormalSplineColor + { + get + { + if( m_splineColor == null ) + m_splineColor = GetColor( "BezierSolution_SplineColor", new Color( 0.8f, 0.6f, 0.8f, 1f ) ); + + return m_splineColor.Value; + } + set + { + m_splineColor = value; + SetColor( "BezierSolution_SplineColor", value ); + } + } + + private static Color? m_selectedSplineColor = null; + public static Color SelectedSplineColor + { + get + { + if( m_selectedSplineColor == null ) + m_selectedSplineColor = GetColor( "BezierSolution_SelectedSplineColor", new Color( 0.8f, 0.6f, 0.8f, 1f ) ); + + return m_selectedSplineColor.Value; + } + set + { + m_selectedSplineColor = value; + SetColor( "BezierSolution_SelectedSplineColor", value ); + } + } + + private static Color? m_endPointColor = null; + public static Color NormalEndPointColor + { + get + { + if( m_endPointColor == null ) + m_endPointColor = GetColor( "BezierSolution_EndPointColor", Color.white ); + + return m_endPointColor.Value; + } + set + { + m_endPointColor = value; + SetColor( "BezierSolution_EndPointColor", value ); + } + } + + private static Color? m_selectedEndPointColor = null; + public static Color SelectedEndPointColor + { + get + { + if( m_selectedEndPointColor == null ) + m_selectedEndPointColor = GetColor( "BezierSolution_SelectedEndPointColor", Color.yellow ); + + return m_selectedEndPointColor.Value; + } + set + { + m_selectedEndPointColor = value; + SetColor( "BezierSolution_SelectedEndPointColor", value ); + } + } + + private static Color? m_controlPointColor = null; + public static Color NormalControlPointColor + { + get + { + if( m_controlPointColor == null ) + m_controlPointColor = GetColor( "BezierSolution_ControlPointColor", Color.white ); + + return m_controlPointColor.Value; + } + set + { + m_controlPointColor = value; + SetColor( "BezierSolution_ControlPointColor", value ); + } + } + + private static Color? m_selectedControlPointColor = null; + public static Color SelectedControlPointColor + { + get + { + if( m_selectedControlPointColor == null ) + m_selectedControlPointColor = GetColor( "BezierSolution_SelectedControlPointColor", Color.green ); + + return m_selectedControlPointColor.Value; + } + set + { + m_selectedControlPointColor = value; + SetColor( "BezierSolution_SelectedControlPointColor", value ); + } + } + + private static Color? m_quickEditModeNewEndPointColor = null; + public static Color QuickEditModeNewEndPointColor + { + get + { + if( m_quickEditModeNewEndPointColor == null ) + m_quickEditModeNewEndPointColor = GetColor( "BezierSolution_QuickEditNewPointColor", Color.cyan ); + + return m_quickEditModeNewEndPointColor.Value; + } + set + { + m_quickEditModeNewEndPointColor = value; + SetColor( "BezierSolution_QuickEditNewPointColor", value ); + } + } + + private static Color? m_quickEditModeDeleteEndPointColor = null; + public static Color QuickEditModeDeleteEndPointColor + { + get + { + if( m_quickEditModeDeleteEndPointColor == null ) + m_quickEditModeDeleteEndPointColor = GetColor( "BezierSolution_QuickEditDeletePointColor", Color.red ); + + return m_quickEditModeDeleteEndPointColor.Value; + } + set + { + m_quickEditModeDeleteEndPointColor = value; + SetColor( "BezierSolution_QuickEditDeletePointColor", value ); + } + } + + private static Color? m_normalsPreviewColor = null; + public static Color NormalsPreviewColor + { + get + { + if( m_normalsPreviewColor == null ) + m_normalsPreviewColor = GetColor( "BezierSolution_NormalsPreviewColor", Color.blue ); + + return m_normalsPreviewColor.Value; + } + set + { + m_normalsPreviewColor = value; + SetColor( "BezierSolution_NormalsPreviewColor", value ); + } + } + + private static Color? m_evenlySpacedPointsColor = null; + public static Color EvenlySpacedPointsColor + { + get + { + if( m_evenlySpacedPointsColor == null ) + m_evenlySpacedPointsColor = GetColor( "BezierSolution_EvenlySpacedPointsColor", Color.white ); + + return m_evenlySpacedPointsColor.Value; + } + set + { + m_evenlySpacedPointsColor = value; + SetColor( "BezierSolution_EvenlySpacedPointsColor", value ); + } + } + #endregion + + #region Size Adjustments + private static float? m_splineThickness = null; + public static float SplineThickness + { + get + { + if( m_splineThickness == null ) + m_splineThickness = EditorPrefs.GetFloat( "BezierSolution_SplineThickness", 8f ); + + return m_splineThickness.Value; + } + set + { + m_splineThickness = value; + EditorPrefs.SetFloat( "BezierSolution_SplineThickness", value ); + } + } + + private static float? m_endPointSize = null; + public static float EndPointSize + { + get + { + if( m_endPointSize == null ) + m_endPointSize = EditorPrefs.GetFloat( "BezierSolution_EndPointSize", 0.075f ); + + return m_endPointSize.Value; + } + set + { + m_endPointSize = value; + EditorPrefs.SetFloat( "BezierSolution_EndPointSize", value ); + } + } + + private static float? m_selectedEndPointSize = null; + public static float SelectedEndPointSize + { + get + { + if( m_selectedEndPointSize == null ) + m_selectedEndPointSize = EditorPrefs.GetFloat( "BezierSolution_SelectedEndPointSize", 0.075f * 1.5f ); + + return m_selectedEndPointSize.Value; + } + set + { + m_selectedEndPointSize = value; + EditorPrefs.SetFloat( "BezierSolution_SelectedEndPointSize", value ); + } + } + + private static float? m_controlPointSize = null; + public static float ControlPointSize + { + get + { + if( m_controlPointSize == null ) + m_controlPointSize = EditorPrefs.GetFloat( "BezierSolution_ControlPointSize", 0.05f ); + + return m_controlPointSize.Value; + } + set + { + m_controlPointSize = value; + EditorPrefs.SetFloat( "BezierSolution_ControlPointSize", value ); + } + } + + private static float? m_quickEditModeNewEndPointSize = null; + public static float QuickEditModeNewEndPointSize + { + get + { + if( m_quickEditModeNewEndPointSize == null ) + m_quickEditModeNewEndPointSize = EditorPrefs.GetFloat( "BezierSolution_QuickEditNewEndPointSize", 0.075f ); + + return m_quickEditModeNewEndPointSize.Value; + } + set + { + m_quickEditModeNewEndPointSize = value; + EditorPrefs.SetFloat( "BezierSolution_QuickEditNewEndPointSize", value ); + } + } + + private static float? m_normalsPreviewLength = null; + public static float NormalsPreviewLength + { + get + { + if( m_normalsPreviewLength == null ) + m_normalsPreviewLength = EditorPrefs.GetFloat( "BezierSolution_NormalsPreviewLength", 0.35f ); + + return m_normalsPreviewLength.Value; + } + set + { + value = Mathf.Max( value, 0f ); + m_normalsPreviewLength = value; + EditorPrefs.SetFloat( "BezierSolution_NormalsPreviewLength", value ); + } + } + + private static float? m_evenlySpacedPointsSize = null; + public static float EvenlySpacedPointsSize + { + get + { + if( m_evenlySpacedPointsSize == null ) + m_evenlySpacedPointsSize = EditorPrefs.GetFloat( "BezierSolution_EvenlySpacedPointsSize", 0.1f ); + + return m_evenlySpacedPointsSize.Value; + } + set + { + m_evenlySpacedPointsSize = value; + EditorPrefs.SetFloat( "BezierSolution_EvenlySpacedPointsSize", value ); + } + } + + private static float? m_extraDataAsFrustumSize = null; + public static float ExtraDataAsFrustumSize + { + get + { + if( m_extraDataAsFrustumSize == null ) + m_extraDataAsFrustumSize = EditorPrefs.GetFloat( "BezierSolution_ExtraDataFrustumSize", 2.2f ); + + return m_extraDataAsFrustumSize.Value; + } + set + { + m_extraDataAsFrustumSize = value; + EditorPrefs.SetFloat( "BezierSolution_ExtraDataFrustumSize", value ); + } + } + #endregion + + #region Other Settings + private static float? m_splineSmoothness = null; + public static float SplineSmoothness + { + get + { + if( m_splineSmoothness == null ) + m_splineSmoothness = EditorPrefs.GetFloat( "BezierSolution_SplineSmoothness", 10f ); + + return m_splineSmoothness.Value; + } + set + { + value = Mathf.Max( value, 1f ); + m_splineSmoothness = value; + EditorPrefs.SetFloat( "BezierSolution_SplineSmoothness", value ); + } + } + + private static int? m_displayedIntermediateNormalsCount = null; + public static int DisplayedIntermediateNormalsCount + { + get + { + if( m_displayedIntermediateNormalsCount == null ) + m_displayedIntermediateNormalsCount = EditorPrefs.GetInt( "BezierSolution_IntermediateNormals", 8 ); + + return m_displayedIntermediateNormalsCount.Value; + } + set + { + value = Mathf.Clamp( value, 0, 999 ); + m_displayedIntermediateNormalsCount = value; + EditorPrefs.SetInt( "BezierSolution_IntermediateNormals", value ); + } + } + + private static bool? m_moveMultiplePointsInOppositeDirections = null; + public static bool MoveMultiplePointsInOppositeDirections + { + get + { + if( m_moveMultiplePointsInOppositeDirections == null ) + m_moveMultiplePointsInOppositeDirections = EditorPrefs.GetBool( "BezierSolution_OppositeTransformation", false ); + + return m_moveMultiplePointsInOppositeDirections.Value; + } + set + { + m_moveMultiplePointsInOppositeDirections = value; + EditorPrefs.SetBool( "BezierSolution_OppositeTransformation", value ); + } + } + + private static bool? m_quickEditSplineModifyNormals = null; + public static bool QuickEditSplineModifyNormals + { + get + { + if( m_quickEditSplineModifyNormals == null ) + m_quickEditSplineModifyNormals = EditorPrefs.GetBool( "BezierSolution_QuickEditModifyNormals", true ); + + return m_quickEditSplineModifyNormals.Value; + } + set + { + m_quickEditSplineModifyNormals = value; + EditorPrefs.SetBool( "BezierSolution_QuickEditModifyNormals", value ); + } + } + + private static bool? m_quickEditSplinePreserveShape = null; + public static bool QuickEditSplinePreserveShape + { + get + { + if( m_quickEditSplinePreserveShape == null ) + m_quickEditSplinePreserveShape = EditorPrefs.GetBool( "BezierSolution_QuickEditPreserveShape", false ); + + return m_quickEditSplinePreserveShape.Value; + } + set + { + m_quickEditSplinePreserveShape = value; + EditorPrefs.SetBool( "BezierSolution_QuickEditPreserveShape", value ); + } + } + #endregion + + #region Visibility Settings + private static bool? m_showControlPoints = null; + public static bool ShowControlPoints + { + get + { + if( m_showControlPoints == null ) + m_showControlPoints = EditorPrefs.GetBool( "BezierSolution_ShowControlPoints", true ); + + return m_showControlPoints.Value; + } + set + { + m_showControlPoints = value; + EditorPrefs.SetBool( "BezierSolution_ShowControlPoints", value ); + } + } + + private static bool? m_showControlPointDirections = null; + public static bool ShowControlPointDirections + { + get + { + if( m_showControlPointDirections == null ) + m_showControlPointDirections = EditorPrefs.GetBool( "BezierSolution_ShowControlPointDirs", true ); + + return m_showControlPointDirections.Value; + } + set + { + m_showControlPointDirections = value; + EditorPrefs.SetBool( "BezierSolution_ShowControlPointDirs", value ); + } + } + + private static bool? m_showEndPointLabels = null; + public static bool ShowEndPointLabels + { + get + { + if( m_showEndPointLabels == null ) + m_showEndPointLabels = EditorPrefs.GetBool( "BezierSolution_ShowEndPointLabels", true ); + + return m_showEndPointLabels.Value; + } + set + { + m_showEndPointLabels = value; + EditorPrefs.SetBool( "BezierSolution_ShowEndPointLabels", value ); + } + } + + private static bool? m_showNormals = null; + public static bool ShowNormals + { + get + { + if( m_showNormals == null ) + m_showNormals = EditorPrefs.GetBool( "BezierSolution_ShowNormals", true ); + + return m_showNormals.Value; + } + set + { + m_showNormals = value; + EditorPrefs.SetBool( "BezierSolution_ShowNormals", value ); + } + } + + private static bool? m_showEvenlySpacedPoints = null; + public static bool ShowEvenlySpacedPoints + { + get + { + if( m_showEvenlySpacedPoints == null ) + m_showEvenlySpacedPoints = EditorPrefs.GetBool( "BezierSolution_ShowEvenlySpacedPoints", false ); + + return m_showEvenlySpacedPoints.Value; + } + set + { + m_showEvenlySpacedPoints = value; + EditorPrefs.SetBool( "BezierSolution_ShowEvenlySpacedPoints", value ); + } + } + + private static bool? m_visualizeExtraDataAsFrustum = null; + public static bool VisualizeExtraDataAsFrustum + { + get + { + if( m_visualizeExtraDataAsFrustum == null ) + m_visualizeExtraDataAsFrustum = EditorPrefs.GetBool( "BezierSolution_VisualizeFrustum", false ); + + return m_visualizeExtraDataAsFrustum.Value; + } + set + { + m_visualizeExtraDataAsFrustum = value; + EditorPrefs.SetBool( "BezierSolution_VisualizeFrustum", value ); + } + } + #endregion + +#if UNITY_2018_3_OR_NEWER + [SettingsProvider] + public static SettingsProvider CreatePreferencesGUI() + { + return new SettingsProvider( "Project/yasirkula/Bezier Solution", SettingsScope.Project ) + { + guiHandler = ( searchContext ) => PreferencesGUI(), + keywords = new System.Collections.Generic.HashSet() { "Bezier", "Spline", "Point", "Normals", "Color", "Size" } + }; + } + + [MenuItem( "CONTEXT/BezierSpline/Open Settings" )] + [MenuItem( "CONTEXT/BezierPoint/Open Settings" )] + private static void OpenPreferencesWindow( MenuCommand command ) + { + SettingsService.OpenProjectSettings( "yasirkula/Bezier Solution" ); + } +#endif + +#if !UNITY_2018_3_OR_NEWER + [PreferenceItem( "Bezier Solution" )] +#endif + public static void PreferencesGUI() + { + Color c; + float f; + int i; + bool b; + + float labelWidth = EditorGUIUtility.labelWidth; + EditorGUIUtility.labelWidth += 50f; + + EditorGUI.BeginChangeCheck(); + + EditorGUI.BeginChangeCheck(); + c = ColorField( "Selected Spline Color", SelectedSplineColor, new Color( 0.8f, 0.6f, 0.8f, 1f ) ); + if( EditorGUI.EndChangeCheck() ) + SelectedSplineColor = c; + + EditorGUI.BeginChangeCheck(); + c = ColorField( "Unselected Spline Color", NormalSplineColor, new Color( 0.8f, 0.6f, 0.8f, 1f ) ); + if( EditorGUI.EndChangeCheck() ) + NormalSplineColor = c; + + EditorGUI.BeginChangeCheck(); + f = FloatField( "Selected Spline Thickness", SplineThickness, 8f ); + if( EditorGUI.EndChangeCheck() ) + SplineThickness = f; + + EditorGUI.BeginChangeCheck(); + f = FloatField( "Unselected Spline Smoothness", SplineSmoothness, 10f ); + if( EditorGUI.EndChangeCheck() ) + SplineSmoothness = f; + + EditorGUILayout.Space(); + + EditorGUI.BeginChangeCheck(); + c = ColorField( "Selected End Points Color", SelectedEndPointColor, Color.yellow ); + if( EditorGUI.EndChangeCheck() ) + SelectedEndPointColor = c; + + EditorGUI.BeginChangeCheck(); + c = ColorField( "Unselected End Point Color", NormalEndPointColor, Color.white ); + if( EditorGUI.EndChangeCheck() ) + NormalEndPointColor = c; + + EditorGUI.BeginChangeCheck(); + f = FloatField( "Selected End Points Size", SelectedEndPointSize, 0.075f * 1.5f ); + if( EditorGUI.EndChangeCheck() ) + SelectedEndPointSize = f; + + EditorGUI.BeginChangeCheck(); + f = FloatField( "Unselected End Points Size", EndPointSize, 0.075f ); + if( EditorGUI.EndChangeCheck() ) + EndPointSize = f; + + EditorGUI.BeginChangeCheck(); + b = EditorGUILayout.Toggle( "Show End Point Labels", ShowEndPointLabels ); + if( EditorGUI.EndChangeCheck() ) + ShowEndPointLabels = b; + + EditorGUILayout.Space(); + + EditorGUI.BeginChangeCheck(); + b = EditorGUILayout.Toggle( "Show Control Points", ShowControlPoints ); + if( EditorGUI.EndChangeCheck() ) + ShowControlPoints = b; + + EditorGUI.indentLevel++; + + EditorGUI.BeginChangeCheck(); + b = EditorGUILayout.Toggle( "Show Control Point Directions", ShowControlPointDirections ); + if( EditorGUI.EndChangeCheck() ) + ShowControlPointDirections = b; + + EditorGUI.BeginChangeCheck(); + c = ColorField( "Selected Control Point Color", SelectedControlPointColor, Color.green ); + if( EditorGUI.EndChangeCheck() ) + SelectedControlPointColor = c; + + EditorGUI.BeginChangeCheck(); + c = ColorField( "Unselected Control Point Color", NormalControlPointColor, Color.white ); + if( EditorGUI.EndChangeCheck() ) + NormalControlPointColor = c; + + EditorGUI.BeginChangeCheck(); + f = FloatField( "Control Points Size", ControlPointSize, 0.05f ); + if( EditorGUI.EndChangeCheck() ) + ControlPointSize = f; + + EditorGUI.indentLevel--; + + EditorGUILayout.Space(); + + EditorGUI.BeginChangeCheck(); + b = EditorGUILayout.Toggle( "Show Normals", ShowNormals ); + if( EditorGUI.EndChangeCheck() ) + ShowNormals = b; + + EditorGUI.indentLevel++; + + EditorGUI.BeginChangeCheck(); + i = IntField( "Displayed Intermediate Normals", DisplayedIntermediateNormalsCount, 8 ); + if( EditorGUI.EndChangeCheck() ) + DisplayedIntermediateNormalsCount = i; + + EditorGUI.BeginChangeCheck(); + c = ColorField( "Normals Preview Color", NormalsPreviewColor, Color.blue ); + if( EditorGUI.EndChangeCheck() ) + NormalsPreviewColor = c; + + EditorGUI.BeginChangeCheck(); + f = FloatField( "Normals Preview Length", NormalsPreviewLength, 0.35f ); + if( EditorGUI.EndChangeCheck() ) + NormalsPreviewLength = f; + + EditorGUI.indentLevel--; + + EditorGUILayout.Space(); + + EditorGUI.BeginChangeCheck(); + b = EditorGUILayout.Toggle( "Visualize Evenly Spaced Points", ShowEvenlySpacedPoints ); + if( EditorGUI.EndChangeCheck() ) + ShowEvenlySpacedPoints = b; + + EditorGUI.indentLevel++; + + EditorGUI.BeginChangeCheck(); + c = ColorField( "Evenly Spaced Points Color", EvenlySpacedPointsColor, Color.white ); + if( EditorGUI.EndChangeCheck() ) + EvenlySpacedPointsColor = c; + + EditorGUI.BeginChangeCheck(); + f = FloatField( "Evenly Spaced Points Size", EvenlySpacedPointsSize, 0.1f ); + if( EditorGUI.EndChangeCheck() ) + EvenlySpacedPointsSize = f; + + EditorGUI.indentLevel--; + + EditorGUILayout.Space(); + + EditorGUI.BeginChangeCheck(); + c = ColorField( "Quick Edit New Point Color", QuickEditModeNewEndPointColor, Color.cyan ); + if( EditorGUI.EndChangeCheck() ) + QuickEditModeNewEndPointColor = c; + + EditorGUI.BeginChangeCheck(); + c = ColorField( "Quick Edit Delete Point Color", QuickEditModeDeleteEndPointColor, Color.red ); + if( EditorGUI.EndChangeCheck() ) + QuickEditModeDeleteEndPointColor = c; + + EditorGUI.BeginChangeCheck(); + f = FloatField( "Quick Edit New Point Size", QuickEditModeNewEndPointSize, 0.075f ); + if( EditorGUI.EndChangeCheck() ) + QuickEditModeNewEndPointSize = f; + + EditorGUILayout.Space(); + + EditorGUI.BeginChangeCheck(); + b = EditorGUILayout.Toggle( new GUIContent( "Visualize Extra Data As Frustum", "Visualize end points' Extra Data as camera frustum in Scene window" ), VisualizeExtraDataAsFrustum ); + if( EditorGUI.EndChangeCheck() ) + VisualizeExtraDataAsFrustum = b; + + EditorGUI.indentLevel++; + + EditorGUI.BeginChangeCheck(); + f = FloatField( "Frustum Size", ExtraDataAsFrustumSize, 2.2f ); + if( EditorGUI.EndChangeCheck() ) + ExtraDataAsFrustumSize = f; + + EditorGUI.indentLevel--; + + EditorGUIUtility.labelWidth = labelWidth; + + if( EditorGUI.EndChangeCheck() ) + SceneView.RepaintAll(); + } + + private static Color ColorField( string label, Color value, Color defaultValue ) + { + GUILayout.BeginHorizontal(); + Color result = EditorGUILayout.ColorField( label, value ); + if( GUILayout.Button( "Reset", BezierUtils.GL_WIDTH_60 ) ) + result = defaultValue; + GUILayout.EndHorizontal(); + + return result; + } + + private static float FloatField( string label, float value, float defaultValue ) + { + GUILayout.BeginHorizontal(); + float result = EditorGUILayout.FloatField( label, value ); + if( GUILayout.Button( "Reset", BezierUtils.GL_WIDTH_60 ) ) + result = defaultValue; + GUILayout.EndHorizontal(); + + return result; + } + + private static int IntField( string label, int value, int defaultValue ) + { + GUILayout.BeginHorizontal(); + int result = EditorGUILayout.IntField( label, value ); + if( GUILayout.Button( "Reset", BezierUtils.GL_WIDTH_60 ) ) + result = defaultValue; + GUILayout.EndHorizontal(); + + return result; + } + + private static Color GetColor( string pref, Color defaultColor ) + { + if( !EditorPrefs.HasKey( pref ) ) + return defaultColor; + + string[] parts = EditorPrefs.GetString( pref ).Split( ';' ); + return new Color32( byte.Parse( parts[0] ), byte.Parse( parts[1] ), byte.Parse( parts[2] ), byte.Parse( parts[3] ) ); + } + + private static void SetColor( string pref, Color32 value ) + { + EditorPrefs.SetString( pref, string.Concat( value.r.ToString(), ";", value.g.ToString(), ";", value.b.ToString(), ";", value.a.ToString() ) ); + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/BezierSolution/Editor/BezierSettings.cs.meta b/Assets/Plugins/BezierSolution/Editor/BezierSettings.cs.meta new file mode 100644 index 00000000..f032605a --- /dev/null +++ b/Assets/Plugins/BezierSolution/Editor/BezierSettings.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: e751cb465841a4f43b9297b7be55dcd0 +timeCreated: 1620207781 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/BezierSolution/Editor/BezierSolution.Editor.asmdef b/Assets/Plugins/BezierSolution/Editor/BezierSolution.Editor.asmdef new file mode 100644 index 00000000..664b56e0 --- /dev/null +++ b/Assets/Plugins/BezierSolution/Editor/BezierSolution.Editor.asmdef @@ -0,0 +1,17 @@ +{ + "name": "BezierSolution.Editor", + "references": [ + "BezierSolution.Runtime" + ], + "includePlatforms": [ + "Editor" + ], + "excludePlatforms": [], + "allowUnsafeCode": false, + "overrideReferences": false, + "precompiledReferences": [], + "autoReferenced": true, + "defineConstraints": [], + "versionDefines": [], + "noEngineReferences": false +} \ No newline at end of file diff --git a/Assets/Plugins/BezierSolution/Editor/BezierSolution.Editor.asmdef.meta b/Assets/Plugins/BezierSolution/Editor/BezierSolution.Editor.asmdef.meta new file mode 100644 index 00000000..4e9eea1a --- /dev/null +++ b/Assets/Plugins/BezierSolution/Editor/BezierSolution.Editor.asmdef.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: b99279c3e8f544f4d83dd26b3a9b5715 +AssemblyDefinitionImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/BezierSolution/Editor/BezierSplineEditor.cs b/Assets/Plugins/BezierSolution/Editor/BezierSplineEditor.cs new file mode 100644 index 00000000..8a9202f8 --- /dev/null +++ b/Assets/Plugins/BezierSolution/Editor/BezierSplineEditor.cs @@ -0,0 +1,103 @@ +using UnityEngine; +using UnityEditor; + +namespace BezierSolution.Extras +{ + [CustomEditor( typeof( BezierSpline ) )] + [CanEditMultipleObjects] + public class BezierSplineEditor : Editor + { + internal BezierSpline[] allSplines; + + public static BezierSplineEditor ActiveEditor { get; private set; } + + private void OnEnable() + { + Object[] splines = targets; + allSplines = new BezierSpline[splines.Length]; + for( int i = 0; i < splines.Length; i++ ) + { + BezierSpline spline = (BezierSpline) splines[i]; + if( spline ) + spline.Refresh(); + + allSplines[i] = spline; + } + + ActiveEditor = this; + + if( BezierUtils.QuickEditSplineMode ) + { + Tools.hidden = true; + + EditorApplication.update -= SceneView.RepaintAll; + EditorApplication.update += SceneView.RepaintAll; + } + + Undo.undoRedoPerformed -= OnUndoRedo; + Undo.undoRedoPerformed += OnUndoRedo; + } + + private void OnDisable() + { + ActiveEditor = null; + Tools.hidden = false; + + Undo.undoRedoPerformed -= OnUndoRedo; + EditorApplication.update -= SceneView.RepaintAll; + } + + private void OnSceneGUI() + { + BezierSpline spline = (BezierSpline) target; + BezierUtils.DrawSplineDetailed( spline ); + + for( int i = 0; i < spline.Count; i++ ) + BezierUtils.DrawBezierPoint( spline[i], i + 1, false ); + + if( BezierSettings.ShowEvenlySpacedPoints ) + BezierUtils.DrawSplineEvenlySpacedPoints( spline ); + + if( BezierUtils.QuickEditSplineMode ) + { + // Execute quick edit mode's scene GUI only once (otherwise things can get ugly when multiple splines are selected) + if( spline == allSplines[0] ) + { + BezierUtils.QuickEditModeSceneGUI( allSplines ); + HandleUtility.AddDefaultControl( 0 ); + } + + return; + } + } + + public override void OnInspectorGUI() + { + BezierUtils.DrawSplineInspectorGUI( allSplines ); + } + + private void OnUndoRedo() + { + for( int i = 0; i < allSplines.Length; i++ ) + { + if( allSplines[i] ) + { + allSplines[i].dirtyFlags |= InternalDirtyFlags.All; + allSplines[i].Refresh(); + } + } + + Repaint(); + } + + private bool HasFrameBounds() + { + return !serializedObject.isEditingMultipleObjects; + } + + private Bounds OnGetFrameBounds() + { + return new Bounds( ( (BezierSpline) target ).transform.position, new Vector3( 1f, 1f, 1f ) ); + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/BezierSolution/Editor/BezierSplineEditor.cs.meta b/Assets/Plugins/BezierSolution/Editor/BezierSplineEditor.cs.meta new file mode 100644 index 00000000..696e64ed --- /dev/null +++ b/Assets/Plugins/BezierSolution/Editor/BezierSplineEditor.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 0b74ad81d1f30ec479543aea0a27f6ef +timeCreated: 1472737433 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/BezierSolution/Editor/BezierUtils.cs b/Assets/Plugins/BezierSolution/Editor/BezierUtils.cs new file mode 100644 index 00000000..beca93c0 --- /dev/null +++ b/Assets/Plugins/BezierSolution/Editor/BezierUtils.cs @@ -0,0 +1,1003 @@ +using System; +using UnityEngine; +using UnityEditor; +using Object = UnityEngine.Object; +using System.Reflection; + +namespace BezierSolution.Extras +{ + public static class BezierUtils + { + private const string PRECEDING_CONTROL_POINT_LABEL = " <--"; + private const string FOLLOWING_CONTROL_POINT_LABEL = " -->"; + + private static readonly Color AUTO_CONSTRUCT_SPLINE_BUTTON_COLOR = new Color( 0.65f, 1f, 0.65f ); + + private static readonly GUIContent LOOP_TEXT = new GUIContent( "Loop", "Connects the first end point and the last end point of the spline" ); + private static readonly GUIContent DRAW_RUNTIME_GIZMOS_TEXT = new GUIContent( "Draw Runtime Gizmos", "Draws the spline during gameplay" ); + private static readonly GUIContent SHOW_CONTROL_POINTS_TEXT = new GUIContent( "Show Control Points", "Shows control points of the end points in Scene window" ); + private static readonly GUIContent SHOW_DIRECTIONS_TEXT = new GUIContent( "Show Directions", "Shows control points' directions in Scene window" ); + private static readonly GUIContent SHOW_POINT_INDICES_TEXT = new GUIContent( "Show Point Indices", "Shows end points' indices in Scene window" ); + private static readonly GUIContent SHOW_NORMALS_TEXT = new GUIContent( "Show Normals", "Shows end points' normal vectors in Scene window" ); + private static readonly GUIContent DISPLAYED_INTERMEDIATE_NORMALS_COUNT_TEXT = new GUIContent( "Displayed Intermediate Normals", "The number of normal vectors to display in-between each end point pair" ); + private static readonly GUIContent AUTO_CALCULATED_NORMALS_ANGLE_TEXT = new GUIContent( "Auto Calculated Normals Angle", "When 'Auto Calculate Normals' button is clicked, all normals will be rotated around their Z axis by the specified amount (each end point's rotation angle can further be customized from the end point's Inspector)" ); + private static readonly GUIContent AUTO_CALCULATED_INTERMEDIATE_NORMALS_TEXT = new GUIContent( "Auto Calculated Intermediate Normals", "When 'Auto Calculate Normals' button is clicked, this many intermediate normal vectors will be calculated and stored for each end point pair. If no intermediate normal vectors are calculated (0), normals of end point pairs will be lerped to estimate the intermediate values" ); + private static readonly GUIContent EVENLY_SPACED_POINTS_RESOLUTION_TEXT = new GUIContent( "Evenly Spaced Points Resolution", "Determines approximately how many points will be calculated per each segment of the spline while generating 'evenlySpacedPoints'. Evenly spaced points are used by numerous utility components when their 'High Quality' option is enabled" ); + private static readonly GUIContent EVENLY_SPACED_POINTS_ACCURACY_TEXT = new GUIContent( "Evenly Spaced Points Accuracy", "Determines how accurate the uniform spacing of 'evenlySpacedPoints' will be" ); + private static readonly GUIContent POINT_CACHE_RESOLUTION_TEXT = new GUIContent( "Point Cache Resolution", "Determines how many uniformly distributed points 'pointCache' will have" ); + private static readonly GUIContent CONSTRUCT_LINEAR_PATH_TEXT = new GUIContent( "Construct Linear Path", "Constructs a completely linear path (end points' Handle Mode will be set to Free)" ); + private static readonly GUIContent AUTO_CONSTRUCT_SPLINE_TEXT = new GUIContent( "Auto Construct Spline", "Constructs a smooth path" ); + private static readonly GUIContent AUTO_CONSTRUCT_SPLINE_2_TEXT = new GUIContent( "Auto Construct Spline 2", "Constructs a smooth path (another algorithm)" ); + private static readonly GUIContent AUTO_CALCULATE_NORMALS_TEXT = new GUIContent( "Auto Calculate Normals", "Attempts to automatically calculate the end points' normal vectors" ); + private static readonly GUIContent AUTO_CONSTRUCT_ALWAYS_TEXT = new GUIContent( "Always", "Applies this method automatically as spline's points change" ); + private static readonly GUIContent QUICK_EDIT_MODE_TEXT = new GUIContent( "Quick Edit Mode", "Quickly add new points to the spline or snap existing points to the scene geometry" ); + private static readonly GUIContent QUICK_EDIT_MODIFY_NORMALS_TEXT = new GUIContent( "Use Raycast Normals", "While dragging a point or adding a new point, the point's Normal vector will be set to the normal of the scene geometry under the cursor" ); + private static readonly GUIContent QUICK_EDIT_PRESERVE_SPLINE_SHAPE_TEXT = new GUIContent( "Preserve Spline Shape", "While inserting new points along the spline, the spline's shape will be preserved but the neighboring end points' 'Handle Mode' will no longer be 'Mirrored'" ); + + public static readonly GUILayoutOption GL_WIDTH_45 = GUILayout.Width( 45f ); + public static readonly GUILayoutOption GL_WIDTH_60 = GUILayout.Width( 60f ); + public static readonly GUILayoutOption GL_WIDTH_100 = GUILayout.Width( 100f ); + public static readonly GUILayoutOption GL_WIDTH_155 = GUILayout.Width( 155f ); + + private static readonly MethodInfo intersectRayMeshMethod = typeof( HandleUtility ).GetMethod( "IntersectRayMesh", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static ); + + public static bool QuickEditSplineMode { get; private set; } + + [MenuItem( "GameObject/Bezier Spline", priority = 35 )] + private static void NewSpline( MenuCommand command ) + { + GameObject spline = new GameObject( "BezierSpline", typeof( BezierSpline ) ); + Undo.RegisterCreatedObjectUndo( spline, "Create Spline" ); + if( command.context ) + Undo.SetTransformParent( spline.transform, ( (GameObject) command.context ).transform, "Create Spline" ); + + spline.transform.localPosition = new Vector3( 0f, 0f, 0f ); + spline.transform.localRotation = Quaternion.identity; + spline.transform.localScale = new Vector3( 1f, 1f, 1f ); + + Selection.activeTransform = spline.transform; + } + + [DrawGizmo( GizmoType.NonSelected | GizmoType.Pickable )] + private static void DrawSplineGizmo( BezierSpline spline, GizmoType gizmoType ) + { + if( spline.Count < 2 ) + return; + + // Make sure that none of the points of the spline are selected + if( BezierPointEditor.ActiveEditor && Array.IndexOf( BezierPointEditor.ActiveEditor.allSplines, spline ) >= 0 ) + return; + + Gizmos.color = BezierSettings.NormalSplineColor; + + Vector3 lastPos = spline[0].position; + float increaseAmount = 1f / ( spline.Count * BezierSettings.SplineSmoothness ); + + for( float i = increaseAmount; i < 1f; i += increaseAmount ) + { + Vector3 pos = spline.GetPoint( i ); + Gizmos.DrawLine( lastPos, pos ); + lastPos = pos; + } + + Gizmos.DrawLine( lastPos, spline.GetPoint( 1f ) ); + } + + [DrawGizmo( GizmoType.Selected | GizmoType.NonSelected )] + private static void DrawPointExtraDataFrustumGizmo( BezierPoint point, GizmoType gizmoType ) + { + if( !BezierSettings.VisualizeExtraDataAsFrustum ) + return; + + // If the either the point or its spline isn't selected, don't show frustum of the point + if( ( !BezierSplineEditor.ActiveEditor || Array.IndexOf( BezierSplineEditor.ActiveEditor.allSplines, point.spline ) < 0 ) && + ( !BezierPointEditor.ActiveEditor || Array.IndexOf( BezierPointEditor.ActiveEditor.allSplines, point.spline ) < 0 ) ) + return; + + Quaternion rotation = point.extraData; + if( Mathf.Approximately( rotation.x * rotation.x + rotation.y * rotation.y + rotation.z * rotation.z + rotation.w * rotation.w, 1f ) ) + { + Matrix4x4 temp = Gizmos.matrix; + Gizmos.matrix = Matrix4x4.TRS( point.position, rotation, Vector3.one * ( BezierSettings.ExtraDataAsFrustumSize * HandleUtility.GetHandleSize( point.position ) ) ); + Gizmos.DrawFrustum( new Vector3( 0f, 0f, 0f ), 60f, 0.18f, 0.01f, 1.5f ); + Gizmos.matrix = temp; + } + } + + public static void DrawSplineDetailed( BezierSpline spline ) + { + if( spline.Count < 2 ) + return; + + BezierPoint endPoint0 = null, endPoint1 = null; + for( int i = 0; i < spline.Count - 1; i++ ) + { + endPoint0 = spline[i]; + endPoint1 = spline[i + 1]; + + DrawBezier( endPoint0, endPoint1 ); + } + + if( spline.loop && endPoint1 != null ) + DrawBezier( endPoint1, spline[0] ); + + // Draw tangent lines on scene view + //Color _tmp = Handles.color; + //Handles.color = Color.cyan; + //for( float i = 0f; i < 1f; i += 0.05f ) + //{ + // Handles.DrawLine( spline.GetPoint( i ), spline.GetPoint( i ) + spline.GetTangent( i ) ); + //} + //Handles.color = _tmp; + } + + public static void DrawSplineEvenlySpacedPoints( BezierSpline spline ) + { + if( Event.current.type == EventType.Repaint ) + { + Color c = Handles.color; + Handles.color = BezierSettings.EvenlySpacedPointsColor; + + float[] evenlySpacedNormalizedTs = spline.evenlySpacedPoints.uniformNormalizedTs; + for( int i = 0; i < evenlySpacedNormalizedTs.Length; i++ ) + { + Vector3 evenlySpacedPoint = spline.GetPoint( evenlySpacedNormalizedTs[i] ); + Handles.SphereHandleCap( 0, evenlySpacedPoint, Quaternion.identity, HandleUtility.GetHandleSize( evenlySpacedPoint ) * BezierSettings.EvenlySpacedPointsSize, EventType.Repaint ); + } + + Handles.color = c; + } + } + + public static void DrawSplineInspectorGUI( BezierSpline[] splines ) + { + if( splines.Length == 0 ) + return; + + for( int i = 0; i < splines.Length; i++ ) + { + if( splines[i].Count < 2 ) + { + if( GUILayout.Button( "Initialize Spline" ) ) + { + Object[] selection = Selection.objects; + for( int j = 0; j < splines.Length; j++ ) + { + BezierSpline spline = splines[j]; + if( spline.Count < 2 ) + { + bool isSplineSelected = false; + for( int k = 0; k < selection.Length; k++ ) + { + if( selection[k] == spline || selection[k] == spline.transform || selection[k] == spline.gameObject ) + { + isSplineSelected = true; + break; + } + } + + spline.Reset(); + + // Try to continue showing spline's scene gizmos after initialization by keeping + // either the spline or a point of it selected + if( !isSplineSelected ) + { + Array.Resize( ref selection, selection.Length + 1 ); + selection[selection.Length - 1] = spline[0].gameObject; + } + } + } + + Selection.objects = selection; + GUIUtility.ExitGUI(); + } + + return; + } + } + + Color c = GUI.backgroundColor; + + EditorGUI.showMixedValue = HasMultipleDifferentValues( splines, ( s1, s2 ) => s1.loop == s2.loop ); + EditorGUI.BeginChangeCheck(); + bool loop = EditorGUILayout.Toggle( LOOP_TEXT, splines[0].loop ); + if( EditorGUI.EndChangeCheck() ) + { + for( int i = 0; i < splines.Length; i++ ) + { + BezierSpline spline = splines[i]; + Undo.RecordObject( spline, "Toggle Loop" ); + spline.loop = loop; + SetSplineDirtyWithUndo( spline, "Toggle Loop", InternalDirtyFlags.EndPointTransformChange | InternalDirtyFlags.ControlPointPositionChange ); + } + + SceneView.RepaintAll(); + } + + EditorGUI.showMixedValue = HasMultipleDifferentValues( splines, ( s1, s2 ) => s1.drawGizmos == s2.drawGizmos ); + EditorGUI.BeginChangeCheck(); + bool drawGizmos = EditorGUILayout.Toggle( DRAW_RUNTIME_GIZMOS_TEXT, splines[0].drawGizmos ); + if( EditorGUI.EndChangeCheck() ) + { + for( int i = 0; i < splines.Length; i++ ) + { + Undo.RecordObject( splines[i], "Toggle Draw Gizmos" ); + splines[i].drawGizmos = drawGizmos; + } + + SceneView.RepaintAll(); + } + + if( drawGizmos ) + { + EditorGUI.indentLevel++; + + EditorGUI.showMixedValue = HasMultipleDifferentValues( splines, ( s1, s2 ) => s1.gizmoColor == s2.gizmoColor ); + EditorGUI.BeginChangeCheck(); + Color gizmoColor = EditorGUILayout.ColorField( "Gizmo Color", splines[0].gizmoColor ); + if( EditorGUI.EndChangeCheck() ) + { + for( int i = 0; i < splines.Length; i++ ) + { + Undo.RecordObject( splines[i], "Change Gizmo Color" ); + splines[i].gizmoColor = gizmoColor; + } + + SceneView.RepaintAll(); + } + + EditorGUI.showMixedValue = HasMultipleDifferentValues( splines, ( s1, s2 ) => s1.gizmoSmoothness == s2.gizmoSmoothness ); + EditorGUI.BeginChangeCheck(); + int gizmoSmoothness = EditorGUILayout.IntSlider( "Gizmo Smoothness", splines[0].gizmoSmoothness, 1, 30 ); + if( EditorGUI.EndChangeCheck() ) + { + for( int i = 0; i < splines.Length; i++ ) + { + Undo.RecordObject( splines[i], "Change Gizmo Smoothness" ); + splines[i].gizmoSmoothness = gizmoSmoothness; + } + + SceneView.RepaintAll(); + } + + EditorGUI.indentLevel--; + } + + EditorGUI.showMixedValue = false; + + EditorGUI.BeginChangeCheck(); + bool showControlPoints = EditorGUILayout.Toggle( SHOW_CONTROL_POINTS_TEXT, BezierSettings.ShowControlPoints ); + if( EditorGUI.EndChangeCheck() ) + { + BezierSettings.ShowControlPoints = showControlPoints; + SceneView.RepaintAll(); + } + + if( showControlPoints ) + { + EditorGUI.indentLevel++; + EditorGUI.BeginChangeCheck(); + bool showControlPointDirections = EditorGUILayout.Toggle( SHOW_DIRECTIONS_TEXT, BezierSettings.ShowControlPointDirections ); + if( EditorGUI.EndChangeCheck() ) + { + BezierSettings.ShowControlPointDirections = showControlPointDirections; + SceneView.RepaintAll(); + } + EditorGUI.indentLevel--; + } + + EditorGUI.BeginChangeCheck(); + bool showEndPointLabels = EditorGUILayout.Toggle( SHOW_POINT_INDICES_TEXT, BezierSettings.ShowEndPointLabels ); + if( EditorGUI.EndChangeCheck() ) + { + BezierSettings.ShowEndPointLabels = showEndPointLabels; + SceneView.RepaintAll(); + } + + EditorGUI.BeginChangeCheck(); + bool showNormals = EditorGUILayout.Toggle( SHOW_NORMALS_TEXT, BezierSettings.ShowNormals ); + if( EditorGUI.EndChangeCheck() ) + { + BezierSettings.ShowNormals = showNormals; + SceneView.RepaintAll(); + } + + if( showNormals ) + { + EditorGUI.indentLevel++; + + EditorGUI.BeginChangeCheck(); + Color normalsPreviewColor = EditorGUILayout.ColorField( "Color", BezierSettings.NormalsPreviewColor ); + if( EditorGUI.EndChangeCheck() ) + { + BezierSettings.NormalsPreviewColor = normalsPreviewColor; + SceneView.RepaintAll(); + } + + EditorGUI.BeginChangeCheck(); + float normalsPreviewLength = EditorGUILayout.FloatField( "Length", BezierSettings.NormalsPreviewLength ); + if( EditorGUI.EndChangeCheck() ) + { + BezierSettings.NormalsPreviewLength = normalsPreviewLength; + SceneView.RepaintAll(); + } + + EditorGUI.BeginChangeCheck(); + int displayedIntermediateNormalsCount = EditorGUILayout.IntField( DISPLAYED_INTERMEDIATE_NORMALS_COUNT_TEXT, BezierSettings.DisplayedIntermediateNormalsCount ); + if( EditorGUI.EndChangeCheck() ) + { + BezierSettings.DisplayedIntermediateNormalsCount = displayedIntermediateNormalsCount; + SceneView.RepaintAll(); + } + + EditorGUI.indentLevel--; + } + + EditorGUILayout.Space(); + + EditorGUI.showMixedValue = HasMultipleDifferentValues( splines, ( s1, s2 ) => s1.autoCalculatedNormalsAngle == s2.autoCalculatedNormalsAngle ); + EditorGUI.BeginChangeCheck(); + float autoCalculatedNormalsAngle = EditorGUILayout.FloatField( AUTO_CALCULATED_NORMALS_ANGLE_TEXT, splines[0].autoCalculatedNormalsAngle ); + if( EditorGUI.EndChangeCheck() ) + { + for( int i = 0; i < splines.Length; i++ ) + { + Undo.RecordObject( splines[i], "Change Normals Angle" ); + splines[i].autoCalculatedNormalsAngle = autoCalculatedNormalsAngle; + SetSplineDirtyWithUndo( splines[i], "Change Normals Angle", InternalDirtyFlags.NormalOffsetChange ); + } + + SceneView.RepaintAll(); + } + + EditorGUI.showMixedValue = HasMultipleDifferentValues( splines, ( s1, s2 ) => s1.autoCalculatedIntermediateNormalsCount == s2.autoCalculatedIntermediateNormalsCount ); + EditorGUI.BeginChangeCheck(); + int autoCalculatedIntermediateNormalsCount = EditorGUILayout.IntField( AUTO_CALCULATED_INTERMEDIATE_NORMALS_TEXT, splines[0].autoCalculatedIntermediateNormalsCount ); + if( EditorGUI.EndChangeCheck() ) + { + for( int i = 0; i < splines.Length; i++ ) + { + Undo.RecordObject( splines[i], "Change Intermediate Normals Count" ); + splines[i].autoCalculatedIntermediateNormalsCount = autoCalculatedIntermediateNormalsCount; + SetSplineDirtyWithUndo( splines[i], "Change Intermediate Normals Count", InternalDirtyFlags.NormalOffsetChange ); + } + + SceneView.RepaintAll(); + } + + EditorGUILayout.Space(); + + EditorGUI.showMixedValue = HasMultipleDifferentValues( splines, ( s1, s2 ) => s1.evenlySpacedPointsResolution == s2.evenlySpacedPointsResolution ); + EditorGUI.BeginChangeCheck(); + float evenlySpacedPointsResolution = EditorGUILayout.FloatField( EVENLY_SPACED_POINTS_RESOLUTION_TEXT, splines[0].evenlySpacedPointsResolution ); + if( EditorGUI.EndChangeCheck() ) + { + for( int i = 0; i < splines.Length; i++ ) + { + Undo.RecordObject( splines[i], "Change Evenly Spaced Points Resolution" ); + splines[i].evenlySpacedPointsResolution = evenlySpacedPointsResolution; + SetSplineDirtyWithUndo( splines[i], "Change Evenly Spaced Points Resolution", InternalDirtyFlags.All ); + } + + SceneView.RepaintAll(); + } + + EditorGUI.showMixedValue = HasMultipleDifferentValues( splines, ( s1, s2 ) => s1.evenlySpacedPointsAccuracy == s2.evenlySpacedPointsAccuracy ); + EditorGUI.BeginChangeCheck(); + float evenlySpacedPointsAccuracy = EditorGUILayout.FloatField( EVENLY_SPACED_POINTS_ACCURACY_TEXT, splines[0].evenlySpacedPointsAccuracy ); + if( EditorGUI.EndChangeCheck() ) + { + for( int i = 0; i < splines.Length; i++ ) + { + Undo.RecordObject( splines[i], "Change Evenly Spaced Points Accuracy" ); + splines[i].evenlySpacedPointsAccuracy = evenlySpacedPointsAccuracy; + SetSplineDirtyWithUndo( splines[i], "Change Evenly Spaced Points Accuracy", InternalDirtyFlags.All ); + } + + SceneView.RepaintAll(); + } + + EditorGUI.showMixedValue = HasMultipleDifferentValues( splines, ( s1, s2 ) => s1.pointCacheResolution == s2.pointCacheResolution ); + EditorGUI.BeginChangeCheck(); + int pointCacheResolution = EditorGUILayout.IntField( POINT_CACHE_RESOLUTION_TEXT, splines[0].pointCacheResolution ); + if( EditorGUI.EndChangeCheck() ) + { + for( int i = 0; i < splines.Length; i++ ) + { + Undo.RecordObject( splines[i], "Change Point Cache Resolution" ); + splines[i].pointCacheResolution = pointCacheResolution; + SetSplineDirtyWithUndo( splines[i], "Change Point Cache Resolution", InternalDirtyFlags.All ); + } + + SceneView.RepaintAll(); + } + + EditorGUI.showMixedValue = false; + + EditorGUI.BeginChangeCheck(); + bool showEvenlySpacedPoints = EditorGUILayout.Toggle( "Visualize Evenly Spaced Points", BezierSettings.ShowEvenlySpacedPoints ); + if( EditorGUI.EndChangeCheck() ) + { + BezierSettings.ShowEvenlySpacedPoints = showEvenlySpacedPoints; + SceneView.RepaintAll(); + } + + if( showEvenlySpacedPoints ) + { + EditorGUI.indentLevel++; + + EditorGUI.BeginChangeCheck(); + Color evenlySpacedPointsColor = EditorGUILayout.ColorField( "Color", BezierSettings.EvenlySpacedPointsColor ); + if( EditorGUI.EndChangeCheck() ) + { + BezierSettings.EvenlySpacedPointsColor = evenlySpacedPointsColor; + SceneView.RepaintAll(); + } + + EditorGUI.BeginChangeCheck(); + float evenlySpacedPointsSize = EditorGUILayout.FloatField( "Size", BezierSettings.EvenlySpacedPointsSize ); + if( EditorGUI.EndChangeCheck() ) + { + BezierSettings.EvenlySpacedPointsSize = evenlySpacedPointsSize; + SceneView.RepaintAll(); + } + + EditorGUI.indentLevel--; + } + + EditorGUILayout.Space(); + + GUI.backgroundColor = AUTO_CONSTRUCT_SPLINE_BUTTON_COLOR; + ShowAutoConstructButton( splines, CONSTRUCT_LINEAR_PATH_TEXT, SplineAutoConstructMode.Linear ); + ShowAutoConstructButton( splines, AUTO_CONSTRUCT_SPLINE_TEXT, SplineAutoConstructMode.Smooth1 ); + ShowAutoConstructButton( splines, AUTO_CONSTRUCT_SPLINE_2_TEXT, SplineAutoConstructMode.Smooth2 ); + + GUILayout.BeginHorizontal(); + if( GUILayout.Button( AUTO_CALCULATE_NORMALS_TEXT ) ) + { + for( int i = 0; i < splines.Length; i++ ) + { + BezierSpline spline = splines[i]; + Undo.RecordObject( spline, "Auto Calculate Normals" ); + + try + { + spline.autoCalculateNormals = true; + SetSplineDirtyWithUndo( spline, "Auto Calculate Normals", InternalDirtyFlags.NormalOffsetChange ); + } + finally + { + spline.autoCalculateNormals = false; + } + } + + SceneView.RepaintAll(); + } + + EditorGUI.BeginChangeCheck(); + bool autoCalculateNormalsEnabled = GUILayout.Toggle( Array.Find( splines, ( s ) => s.autoCalculateNormals ), AUTO_CONSTRUCT_ALWAYS_TEXT, GUI.skin.button, EditorGUIUtility.wideMode ? GL_WIDTH_100 : GL_WIDTH_60 ); + if( EditorGUI.EndChangeCheck() ) + { + for( int i = 0; i < splines.Length; i++ ) + { + BezierSpline spline = splines[i]; + Undo.RecordObject( spline, "Change Auto Calculate Normals" ); + spline.autoCalculateNormals = autoCalculateNormalsEnabled; + + if( autoCalculateNormalsEnabled ) + SetSplineDirtyWithUndo( spline, "Change Auto Calculate Normals", InternalDirtyFlags.NormalOffsetChange ); + } + + SceneView.RepaintAll(); + } + GUILayout.EndHorizontal(); + + GUI.backgroundColor = c; + + EditorGUILayout.Space(); + + EditorGUI.BeginChangeCheck(); + QuickEditSplineMode = GUILayout.Toggle( QuickEditSplineMode, QUICK_EDIT_MODE_TEXT, GUI.skin.button ); + if( EditorGUI.EndChangeCheck() ) + { + EditorApplication.update -= SceneView.RepaintAll; + + if( QuickEditSplineMode ) + { + Tools.hidden = true; + EditorApplication.update += SceneView.RepaintAll; + } + else if( BezierSplineEditor.ActiveEditor ) + Tools.hidden = false; + + SceneView.RepaintAll(); + } + + if( QuickEditSplineMode ) + { + EditorGUILayout.HelpBox( "- Dragging a point: snaps the dragged point to the scene geometry under the cursor\n- CTRL+Left Click: adds a new point to the end of the spline\n- CTRL+Shift+Left Click: inserts a new point along the spline\n- Shift+Left Click: deletes clicked point", MessageType.Info ); + + if( Array.Find( splines, ( s ) => !s.autoCalculateNormals ) ) + { + EditorGUI.indentLevel++; + BezierSettings.QuickEditSplineModifyNormals = EditorGUILayout.Toggle( QUICK_EDIT_MODIFY_NORMALS_TEXT, BezierSettings.QuickEditSplineModifyNormals ); + EditorGUI.indentLevel--; + } + + if( Array.Find( splines, ( s ) => s.autoConstructMode == SplineAutoConstructMode.None ) ) + { + EditorGUI.indentLevel++; + BezierSettings.QuickEditSplinePreserveShape = EditorGUILayout.Toggle( QUICK_EDIT_PRESERVE_SPLINE_SHAPE_TEXT, BezierSettings.QuickEditSplinePreserveShape ); + EditorGUI.indentLevel--; + } + } + } + + public static void DrawBezierPoint( BezierPoint point, int pointIndex, bool isSelected ) + { + Color c = Handles.color; + Event e = Event.current; + + if( QuickEditSplineMode ) + isSelected = false; + + Handles.color = isSelected ? BezierSettings.SelectedEndPointColor : BezierSettings.NormalEndPointColor; + float size = isSelected ? BezierSettings.SelectedEndPointSize : BezierSettings.EndPointSize; + + if( QuickEditSplineMode ) + { + if( e.alt || e.control ) + Handles.DotHandleCap( 0, point.position, Quaternion.identity, HandleUtility.GetHandleSize( point.position ) * size, EventType.Repaint ); + else if( !e.shift ) + { + // Shift isn't held: move dragged points + + // Draw a ScaleValueHandle for the sole purpose of detecting drag input + EditorGUI.BeginChangeCheck(); + Handles.ScaleValueHandle( 1f, point.position, Quaternion.identity, HandleUtility.GetHandleSize( point.position ) * size * 6.5f, Handles.DotHandleCap, 1f ); + if( EditorGUI.EndChangeCheck() ) + { + // Point is dragged, snap it to the scene geometry + Vector3 sceneHitPoint, sceneHitNormal; + RaycastAgainstScene( point.spline[point.spline.Count - 1], out sceneHitPoint, out sceneHitNormal ); + + Undo.RecordObject( point.transform, "Move point" ); + point.transform.position = sceneHitPoint; + + if( BezierSettings.QuickEditSplineModifyNormals && !point.spline.autoCalculateNormals ) + point.SetNormalAndResetIntermediateNormals( sceneHitNormal, "Move point" ); + } + } + else + { + // Shift is held: delete clicked points + + // Disallow deleting points from splines with only 2 or less points + if( point.spline.Count <= 2 ) + Handles.DotHandleCap( 0, point.position, Quaternion.identity, HandleUtility.GetHandleSize( point.position ) * size, EventType.Repaint ); + else + { + Handles.color = BezierSettings.QuickEditModeDeleteEndPointColor; + + if( Handles.Button( point.position, Quaternion.identity, HandleUtility.GetHandleSize( point.position ) * size, size, Handles.DotHandleCap ) ) + { + // When the selected point is deleted, automatically select the next point so that there is still an active BezierPointEditor + // to continue editing this spline + Object[] selection = Selection.objects; + int pointIndexInSelection = Array.IndexOf( selection, point.gameObject ); + if( pointIndexInSelection >= 0 ) + selection[pointIndexInSelection] = point.spline[( point.index + 1 ) % point.spline.Count].gameObject; + + Undo.DestroyObjectImmediate( point.gameObject ); + + if( pointIndexInSelection >= 0 ) + Selection.objects = selection; + } + } + } + } + else if( e.alt || e.button > 0 || ( isSelected && !e.control ) ) + Handles.DotHandleCap( 0, point.position, Quaternion.identity, HandleUtility.GetHandleSize( point.position ) * size, EventType.Repaint ); + else if( Handles.Button( point.position, Quaternion.identity, HandleUtility.GetHandleSize( point.position ) * size, size, Handles.DotHandleCap ) ) + { + if( !e.shift && !e.control ) + Selection.activeTransform = point.transform; + else + { + Object[] selection = Selection.objects; + if( !isSelected ) + { + // If point's spline is included in current selection, remove the spline + // from selection since its Scene handles interfere with points' scene handles + bool splineIncludedInSelection = false; + if( point.spline ) + { + for( int i = 0; i < selection.Length; i++ ) + { + if( selection[i] == point.spline || selection[i] == point.spline.transform || selection[i] == point.spline.gameObject ) + { + selection[i] = point.gameObject; + splineIncludedInSelection = true; + break; + } + } + } + + if( !splineIncludedInSelection ) + { + Array.Resize( ref selection, selection.Length + 1 ); + selection[selection.Length - 1] = point.gameObject; + } + } + else + { + for( int i = 0; i < selection.Length; i++ ) + { + if( selection[i] == point || selection[i] == point.transform || selection[i] == point.gameObject ) + { + if( selection.Length == 1 ) + { + // When all points are deselected, select the spline automatically + if( point.spline ) + { + selection[0] = point.spline.gameObject; + break; + } + } + + for( int j = i + 1; j < selection.Length; j++ ) + selection[j - 1] = selection[j]; + + Array.Resize( ref selection, selection.Length - 1 ); + break; + } + } + } + + Selection.objects = selection; + } + } + + Handles.color = c; + + if( BezierSettings.ShowControlPoints ) + { + Handles.DrawLine( point.position, point.precedingControlPointPosition ); + Handles.DrawLine( point.position, point.followingControlPointPosition ); + + Handles.color = isSelected ? BezierSettings.SelectedControlPointColor : BezierSettings.NormalControlPointColor; + + Handles.RectangleHandleCap( 0, point.precedingControlPointPosition, SceneView.lastActiveSceneView.rotation, HandleUtility.GetHandleSize( point.precedingControlPointPosition ) * BezierSettings.ControlPointSize, EventType.Repaint ); + Handles.RectangleHandleCap( 0, point.followingControlPointPosition, SceneView.lastActiveSceneView.rotation, HandleUtility.GetHandleSize( point.followingControlPointPosition ) * BezierSettings.ControlPointSize, EventType.Repaint ); + + Handles.color = c; + } + + if( BezierSettings.ShowEndPointLabels ) + Handles.Label( point.position, "Point" + pointIndex ); + + if( BezierSettings.ShowControlPoints && BezierSettings.ShowControlPointDirections ) + { + Handles.Label( point.precedingControlPointPosition, PRECEDING_CONTROL_POINT_LABEL ); + Handles.Label( point.followingControlPointPosition, FOLLOWING_CONTROL_POINT_LABEL ); + } + + if( BezierSettings.ShowNormals ) + { + Handles.color = BezierSettings.NormalsPreviewColor; + Handles.DrawLine( point.position, point.position + point.normal * HandleUtility.GetHandleSize( point.position ) * BezierSettings.NormalsPreviewLength ); + + if( BezierSettings.DisplayedIntermediateNormalsCount > 0 && point.spline && point.nextPoint ) + { + BezierSpline.Segment segment = new BezierSpline.Segment( point, point.nextPoint, 0f ); + float localTMultiplier = 1f / ( BezierSettings.DisplayedIntermediateNormalsCount + 1 ); + for( int i = BezierSettings.DisplayedIntermediateNormalsCount; i > 0; i-- ) + { + float localT = i * localTMultiplier; + Vector3 segmentPosition = segment.GetPoint( localT ); + Handles.DrawLine( segmentPosition, segmentPosition + segment.GetNormal( localT ) * HandleUtility.GetHandleSize( segmentPosition ) * BezierSettings.NormalsPreviewLength * 0.75f ); + } + } + + Handles.color = c; + } + } + + public static void QuickEditModeSceneGUI( BezierSpline[] splines ) + { + Event e = Event.current; + GUIContent QUICK_EDIT_MODE_TEXT = new GUIContent( "QUICK EDIT SPLINE MODE" ); + + GUIStyle style = "PreOverlayLabel"; // Taken from: https://github.com/Unity-Technologies/UnityCsReference/blob/f78f4093c8a2b45949a847cdc704cf209dcf2f36/Editor/Mono/EditorGUI.cs#L629 + Rect multiEditTipRect = new Rect( new Vector2( 0f, 5f ), style.CalcSize( QUICK_EDIT_MODE_TEXT ) ); + multiEditTipRect.x = ( EditorGUIUtility.currentViewWidth - multiEditTipRect.width ) * 0.5f; // Center the text + + Handles.BeginGUI(); + EditorGUI.DropShadowLabel( multiEditTipRect, QUICK_EDIT_MODE_TEXT, style ); + Handles.EndGUI(); + + if( splines.Length == 0 || e.alt || !e.control || GUIUtility.hotControl != 0 ) + return; + + if( !e.shift ) + { + // Shift isn't held: add new point to the closest spline when LMB is pressed + + // Get a line that starts from Scene camera's position and goes at cursor's direction + Ray ray = HandleUtility.GUIPointToWorldRay( e.mousePosition ); + Vector3 lineStart = ray.origin; + Vector3 lineEnd = lineStart + ray.direction * 2500f; + + // Find the spline end point closest to this line + BezierPoint closestEndPoint = null; + float closestEndPointDistance = float.PositiveInfinity; + for( int i = 0; i < splines.Length; i++ ) + { + BezierPoint point = splines[i][splines[i].Count - 1]; + float pointDistance = HandleUtility.DistancePointLine( point.position, lineStart, lineEnd ); + if( pointDistance <= closestEndPointDistance ) + { + closestEndPoint = point; + closestEndPointDistance = pointDistance; + } + } + + if( closestEndPoint ) + { + Vector3 sceneHitPoint, sceneHitNormal; + RaycastAgainstScene( closestEndPoint, out sceneHitPoint, out sceneHitNormal ); + + // Draw a line from the closest end point to the raycast hit point + Color c = Handles.color; + Handles.color = BezierSettings.QuickEditModeNewEndPointColor; + Handles.DotHandleCap( 0, sceneHitPoint, Quaternion.identity, HandleUtility.GetHandleSize( sceneHitPoint ) * BezierSettings.QuickEditModeNewEndPointSize, EventType.Repaint ); + Handles.DrawLine( sceneHitPoint, closestEndPoint.position ); + Handles.color = c; + + // When left clicked, insert a point at the highlighted position + if( e.type == EventType.MouseDown && e.button == 0 ) + { + BezierPoint newPoint = closestEndPoint.spline.InsertNewPointAt( closestEndPoint.spline.Count ); + newPoint.position = sceneHitPoint; + if( BezierSettings.QuickEditSplineModifyNormals && !closestEndPoint.spline.autoCalculateNormals ) + newPoint.SetNormalAndResetIntermediateNormals( sceneHitNormal, null ); + + // Rotate the previous point's followingControlPointPosition in the direction of the new point and assign the resulting vector + // to the new point's followingControlPointPosition + Vector3 directionToNewPoint = sceneHitPoint - closestEndPoint.position; + Quaternion controlPointDeltaRotation = Quaternion.FromToRotation( closestEndPoint.followingControlPointPosition - closestEndPoint.position, directionToNewPoint ); + newPoint.followingControlPointPosition = sceneHitPoint + controlPointDeltaRotation * ( directionToNewPoint * 0.35f ); + + Undo.RegisterCreatedObjectUndo( newPoint.gameObject, "Insert Point" ); + if( newPoint.transform.parent ) + Undo.RegisterCompleteObjectUndo( newPoint.transform.parent, "Insert Point" ); + + e.Use(); + } + } + } + else + { + // Shift is held: insert point to closest spline when LMB is pressed + + // Get a line that starts from Scene camera's position and goes at cursor's direction + Ray ray = HandleUtility.GUIPointToWorldRay( e.mousePosition ); + Vector3 lineStart = ray.origin; + Vector3 lineEnd = lineStart + ray.direction * 2500f; + + // Find the spline point closest to this line + BezierSpline closestSpline = null; + Vector3 closestPointOnSpline = Vector3.zero; + float closestPointDistance = float.PositiveInfinity; + float closestPointNormalizedT = 0f; + for( int i = 0; i < splines.Length; i++ ) + { + Vector3 pointOnLine; + Vector3 pointOnSpline = splines[i].FindNearestPointToLine( lineStart, lineEnd, out pointOnLine, out closestPointNormalizedT ); + float pointDistance = ( pointOnLine - pointOnSpline ).sqrMagnitude; + if( pointDistance <= closestPointDistance ) + { + closestSpline = splines[i]; + closestPointOnSpline = pointOnSpline; + closestPointDistance = pointDistance; + } + } + + if( closestSpline ) + { + Color c = Handles.color; + Handles.color = BezierSettings.QuickEditModeNewEndPointColor; + Handles.DotHandleCap( 0, closestPointOnSpline, Quaternion.identity, HandleUtility.GetHandleSize( closestPointOnSpline ) * BezierSettings.QuickEditModeNewEndPointSize, EventType.Repaint ); + Handles.color = c; + + // When left clicked, insert a point at the highlighted position + if( e.type == EventType.MouseDown && e.button == 0 ) + { + BezierSpline.Segment segment = closestSpline.GetSegmentAt( closestPointNormalizedT ); + bool preserveSplineShape = BezierSettings.QuickEditSplinePreserveShape && closestSpline.autoConstructMode == SplineAutoConstructMode.None; + + Vector3 position, precedingControlPointPosition, followingControlPointPosition; + BezierPointEditor.CalculateInsertedPointPosition( segment.point1, segment.point2, segment.localT, preserveSplineShape, out position, out precedingControlPointPosition, out followingControlPointPosition ); + + BezierPoint newPoint = closestSpline.InsertNewPointAt( segment.point2.index ); + newPoint.position = position; + if( preserveSplineShape ) + { + newPoint.handleMode = BezierPoint.HandleMode.Aligned; + newPoint.precedingControlPointPosition = precedingControlPointPosition; + newPoint.followingControlPointPosition = followingControlPointPosition; + } + else + { + Vector3 precedingDirection = precedingControlPointPosition - position; + Vector3 followingDirection = followingControlPointPosition - position; + newPoint.followingControlPointPosition = position + followingDirection.normalized * Mathf.Min( precedingDirection.magnitude, followingDirection.magnitude ); + } + + Undo.RegisterCreatedObjectUndo( newPoint.gameObject, "Insert Point" ); + if( newPoint.transform.parent ) + Undo.RegisterCompleteObjectUndo( newPoint.transform.parent, "Insert Point" ); + + e.Use(); + } + } + } + } + + private static void ShowAutoConstructButton( BezierSpline[] splines, GUIContent label, SplineAutoConstructMode mode ) + { + GUILayout.BeginHorizontal(); + if( GUILayout.Button( label ) ) + { + for( int i = 0; i < splines.Length; i++ ) + { + BezierSpline spline = splines[i]; + Undo.RecordObject( spline, label.text ); + + try + { + spline.autoConstructMode = mode; + SetSplineDirtyWithUndo( spline, label.text, InternalDirtyFlags.EndPointTransformChange | InternalDirtyFlags.ControlPointPositionChange ); + } + finally + { + spline.autoConstructMode = SplineAutoConstructMode.None; + } + } + + SceneView.RepaintAll(); + } + + EditorGUI.BeginChangeCheck(); + bool autoConstructEnabled = GUILayout.Toggle( Array.Find( splines, ( s ) => s.autoConstructMode == mode ), AUTO_CONSTRUCT_ALWAYS_TEXT, GUI.skin.button, EditorGUIUtility.wideMode ? GL_WIDTH_100 : GL_WIDTH_60 ); + if( EditorGUI.EndChangeCheck() ) + { + for( int i = 0; i < splines.Length; i++ ) + { + BezierSpline spline = splines[i]; + Undo.RecordObject( spline, "Change Autoconstruct Mode" ); + + if( autoConstructEnabled ) + { + spline.autoConstructMode = mode; + SetSplineDirtyWithUndo( spline, "Change Autoconstruct Mode", InternalDirtyFlags.EndPointTransformChange | InternalDirtyFlags.ControlPointPositionChange ); + } + else + spline.autoConstructMode = SplineAutoConstructMode.None; + } + + SceneView.RepaintAll(); + } + GUILayout.EndHorizontal(); + } + + internal static void SetSplineDirtyWithUndo( BezierSpline spline, string undo, InternalDirtyFlags dirtyFlags ) + { + if( spline.autoCalculateNormals || spline.autoConstructMode != SplineAutoConstructMode.None ) + { + for( int i = 0; i < spline.Count; i++ ) + { + Undo.RecordObject( spline[i], undo ); + Undo.RecordObject( spline[i].transform, undo ); + } + } + + spline.dirtyFlags |= dirtyFlags; + spline.CheckDirty(); + } + + private static void RaycastAgainstScene( BezierPoint referencePoint, out Vector3 position, out Vector3 normal ) + { + EventType eventType = Event.current.type; + Ray ray = HandleUtility.GUIPointToWorldRay( Event.current.mousePosition ); + + // First, try raycasting against scene geometry with or without colliders (it doesn't matter) + // Credit: https://forum.unity.com/threads/editor-raycast-against-scene-meshes-without-collider-editor-select-object-using-gui-coordinate.485502 + if( intersectRayMeshMethod != null && eventType != EventType.Layout && eventType != EventType.Repaint ) // HandleUtility.PickGameObject doesn't work with Layout and Repaint events in OnSceneGUI + { + GameObject gameObjectUnderCursor = HandleUtility.PickGameObject( Event.current.mousePosition, false ); + if( gameObjectUnderCursor ) + { + Mesh meshUnderCursor = null; + MeshFilter meshFilter = gameObjectUnderCursor.GetComponent(); + if( meshFilter ) + meshUnderCursor = meshFilter.sharedMesh; + + if( !meshUnderCursor ) + { + SkinnedMeshRenderer skinnedMeshRenderer = gameObjectUnderCursor.GetComponent(); + if( skinnedMeshRenderer ) + meshUnderCursor = skinnedMeshRenderer.sharedMesh; + } + + if( meshUnderCursor ) + { + object[] rayMeshParameters = new object[] { ray, meshUnderCursor, gameObjectUnderCursor.transform.localToWorldMatrix, null }; + if( (bool) intersectRayMeshMethod.Invoke( null, rayMeshParameters ) ) + { + RaycastHit hit = (RaycastHit) rayMeshParameters[3]; + position = hit.point; + normal = hit.normal.normalized; + + return; + } + } + } + } + + // Raycast against scene geometry with colliders + object raycastResult = HandleUtility.RaySnap( ray ); + if( raycastResult != null && raycastResult is RaycastHit ) + { + position = ( (RaycastHit) raycastResult ).point; + normal = ( (RaycastHit) raycastResult ).normal.normalized; + + return; + } + + // Raycast against a plane that goes through referencePoint + if( referencePoint ) + { + Plane plane = new Plane( referencePoint.normal, referencePoint.position ); + float enter; + if( plane.Raycast( ray, out enter ) ) + { + position = ray.GetPoint( enter ); + normal = referencePoint.normal; + + return; + } + } + + position = ray.GetPoint( 5f ); + normal = Vector3.up; + } + + public static void DrawSeparator() + { + GUILayout.Box( "", GUILayout.Height( 2f ), GUILayout.ExpandWidth( true ) ); + } + + private static void DrawBezier( BezierPoint endPoint0, BezierPoint endPoint1 ) + { + Handles.DrawBezier( endPoint0.position, endPoint1.position, + endPoint0.followingControlPointPosition, + endPoint1.precedingControlPointPosition, + BezierSettings.SelectedSplineColor, null, BezierSettings.SplineThickness ); + } + + private static bool HasMultipleDifferentValues( BezierSpline[] splines, Func comparer ) + { + if( splines.Length <= 1 ) + return false; + + for( int i = 1; i < splines.Length; i++ ) + { + if( !comparer( splines[0], splines[i] ) ) + return true; + } + + return false; + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/BezierSolution/Editor/BezierUtils.cs.meta b/Assets/Plugins/BezierSolution/Editor/BezierUtils.cs.meta new file mode 100644 index 00000000..e839541d --- /dev/null +++ b/Assets/Plugins/BezierSolution/Editor/BezierUtils.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: f472603c7062a4747bc569c7740ca872 +timeCreated: 1473158123 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/BezierSolution/Editor/BezierWalkerEditor.cs b/Assets/Plugins/BezierSolution/Editor/BezierWalkerEditor.cs new file mode 100644 index 00000000..725e748e --- /dev/null +++ b/Assets/Plugins/BezierSolution/Editor/BezierWalkerEditor.cs @@ -0,0 +1,120 @@ +using System.Collections.Generic; +using UnityEditor; +using UnityEngine; + +namespace BezierSolution.Extras +{ + public abstract class BezierWalkerEditor : Editor + { + protected Object[] walkers; + + private bool simulateInEditor; + private double lastUpdateTime; + + protected bool hasInitialData; + protected List initialPositions = new List( 0 ); + protected List initialRotations = new List( 0 ); + protected List initialNormalizedTs = new List( 0 ); + + private void OnEnable() + { + walkers = targets; + + if( simulateInEditor ) + StartSimulateInEditor(); + } + + private void OnDisable() + { + StopSimulateInEditor(); + } + + public override void OnInspectorGUI() + { + base.OnInspectorGUI(); + + BezierUtils.DrawSeparator(); + EditorGUI.BeginChangeCheck(); + simulateInEditor = GUILayout.Toggle( simulateInEditor, "Simulate In Editor", GUI.skin.button ); + if( EditorGUI.EndChangeCheck() ) + { + if( simulateInEditor ) + StartSimulateInEditor(); + else + StopSimulateInEditor(); + } + } + + private void StartSimulateInEditor() + { + SaveInitialData(); + + lastUpdateTime = EditorApplication.timeSinceStartup; + EditorApplication.update -= SimulateInEditor; + EditorApplication.update += SimulateInEditor; + } + + private void StopSimulateInEditor() + { + EditorApplication.update -= SimulateInEditor; + + if( hasInitialData ) + { + hasInitialData = false; + RestoreInitialData(); + } + + simulateInEditor = false; + } + + protected virtual void SaveInitialData() + { + initialPositions.Clear(); + initialRotations.Clear(); + initialNormalizedTs.Clear(); + + for( int i = 0; i < walkers.Length; i++ ) + { + initialPositions.Add( ( (Component) walkers[i] ).transform.position ); + initialRotations.Add( ( (Component) walkers[i] ).transform.rotation ); + initialNormalizedTs.Add( ( (BezierWalker) walkers[i] ).NormalizedT ); + } + + hasInitialData = true; + } + + protected virtual void RestoreInitialData() + { + for( int i = 0; i < walkers.Length; i++ ) + { + if( walkers[i] ) + { + ( (Component) walkers[i] ).transform.position = initialPositions[i]; + ( (Component) walkers[i] ).transform.rotation = initialRotations[i]; + ( (BezierWalker) walkers[i] ).NormalizedT = initialNormalizedTs[i]; + } + } + } + + private void SimulateInEditor() + { + if( EditorApplication.isPlayingOrWillChangePlaymode && !EditorApplication.isPlaying ) + { + // Stop the simulation if we are about to enter Play mode + StopSimulateInEditor(); + } + else + { + double time = EditorApplication.timeSinceStartup; + Simulate( (float) ( time - lastUpdateTime ) ); + lastUpdateTime = time; + } + } + + protected virtual void Simulate( float deltaTime ) + { + for( int i = 0; i < walkers.Length; i++ ) + ( (BezierWalker) walkers[i] ).Execute( deltaTime ); + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/BezierSolution/Editor/BezierWalkerEditor.cs.meta b/Assets/Plugins/BezierSolution/Editor/BezierWalkerEditor.cs.meta new file mode 100644 index 00000000..a7a32a84 --- /dev/null +++ b/Assets/Plugins/BezierSolution/Editor/BezierWalkerEditor.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 0c496a7cc8ad6654f891021f652a8e5f +timeCreated: 1520346477 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/BezierSolution/Editor/BezierWalkerLocomotionEditor.cs b/Assets/Plugins/BezierSolution/Editor/BezierWalkerLocomotionEditor.cs new file mode 100644 index 00000000..d339a2a3 --- /dev/null +++ b/Assets/Plugins/BezierSolution/Editor/BezierWalkerLocomotionEditor.cs @@ -0,0 +1,56 @@ +using System.Collections.Generic; +using UnityEditor; +using UnityEngine; + +namespace BezierSolution.Extras +{ + [CustomEditor( typeof( BezierWalkerLocomotion ) )] + [CanEditMultipleObjects] + public class BezierWalkerLocomotionEditor : BezierWalkerEditor + { + private int tailSaveDataStartIndex; + + protected override void SaveInitialData() + { + base.SaveInitialData(); + tailSaveDataStartIndex = initialPositions.Count; + + for( int i = 0; i < walkers.Length; i++ ) + { + List tail = ( (BezierWalkerLocomotion) walkers[i] ).Tail; + for( int j = 0; j < tail.Count; j++ ) + { + initialPositions.Add( tail[j].position ); + initialRotations.Add( tail[j].rotation ); + } + } + } + + protected override void RestoreInitialData() + { + base.RestoreInitialData(); + + int index = tailSaveDataStartIndex; + for( int i = 0; i < walkers.Length; i++ ) + { + if( walkers[i] ) + { + List tail = ( (BezierWalkerLocomotion) walkers[i] ).Tail; + for( int j = 0; j < tail.Count; j++, index++ ) + { + tail[j].position = initialPositions[index]; + tail[j].rotation = initialRotations[index]; + } + } + } + } + + protected override void Simulate( float deltaTime ) + { + for( int i = 0; i < walkers.Length; i++ ) + ( (BezierWalkerLocomotion) walkers[i] ).walker.Execute( deltaTime ); + + base.Simulate( deltaTime ); + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/BezierSolution/Editor/BezierWalkerLocomotionEditor.cs.meta b/Assets/Plugins/BezierSolution/Editor/BezierWalkerLocomotionEditor.cs.meta new file mode 100644 index 00000000..944d6a86 --- /dev/null +++ b/Assets/Plugins/BezierSolution/Editor/BezierWalkerLocomotionEditor.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: afc4ab3119c2b58498c79718b6945348 +timeCreated: 1520346477 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/BezierSolution/Editor/BezierWalkerWithSpeedEditor.cs b/Assets/Plugins/BezierSolution/Editor/BezierWalkerWithSpeedEditor.cs new file mode 100644 index 00000000..72b9770e --- /dev/null +++ b/Assets/Plugins/BezierSolution/Editor/BezierWalkerWithSpeedEditor.cs @@ -0,0 +1,10 @@ +using UnityEditor; + +namespace BezierSolution.Extras +{ + [CustomEditor( typeof( BezierWalkerWithSpeed ) )] + [CanEditMultipleObjects] + public class BezierWalkerWithSpeedEditor : BezierWalkerEditor + { + } +} \ No newline at end of file diff --git a/Assets/Plugins/BezierSolution/Editor/BezierWalkerWithSpeedEditor.cs.meta b/Assets/Plugins/BezierSolution/Editor/BezierWalkerWithSpeedEditor.cs.meta new file mode 100644 index 00000000..96cada99 --- /dev/null +++ b/Assets/Plugins/BezierSolution/Editor/BezierWalkerWithSpeedEditor.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: aba64e4e7209c9b44ae73ece7f2c7164 +timeCreated: 1520346477 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/BezierSolution/Editor/BezierWalkerWithTimeEditor.cs b/Assets/Plugins/BezierSolution/Editor/BezierWalkerWithTimeEditor.cs new file mode 100644 index 00000000..eacff568 --- /dev/null +++ b/Assets/Plugins/BezierSolution/Editor/BezierWalkerWithTimeEditor.cs @@ -0,0 +1,10 @@ +using UnityEditor; + +namespace BezierSolution.Extras +{ + [CustomEditor( typeof( BezierWalkerWithTime ) )] + [CanEditMultipleObjects] + public class BezierWalkerWithTimeEditor : BezierWalkerEditor + { + } +} \ No newline at end of file diff --git a/Assets/Plugins/BezierSolution/Editor/BezierWalkerWithTimeEditor.cs.meta b/Assets/Plugins/BezierSolution/Editor/BezierWalkerWithTimeEditor.cs.meta new file mode 100644 index 00000000..625fa2d7 --- /dev/null +++ b/Assets/Plugins/BezierSolution/Editor/BezierWalkerWithTimeEditor.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: e24aeb71e708e4043b77585635edfe8d +timeCreated: 1520346477 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/BezierSolution/Editor/ParticlesFollowBezierEditor.cs b/Assets/Plugins/BezierSolution/Editor/ParticlesFollowBezierEditor.cs new file mode 100644 index 00000000..23b53787 --- /dev/null +++ b/Assets/Plugins/BezierSolution/Editor/ParticlesFollowBezierEditor.cs @@ -0,0 +1,46 @@ +using UnityEditor; +using UnityEngine; + +namespace BezierSolution.Extras +{ + // This class is used for resetting the particle system attached to a ParticlesFollowBezier + // component when it is selected. Otherwise, particles move in a chaotic way for a while + [CustomEditor( typeof( ParticlesFollowBezier ) )] + [CanEditMultipleObjects] + public class ParticlesFollowBezierEditor : Editor + { + private int particlesReset; + + private void OnEnable() + { + particlesReset = 3; + } + + public override void OnInspectorGUI() + { + base.OnInspectorGUI(); + + if( Application.isPlaying ) + return; + + if( particlesReset > 0 && --particlesReset == 0 ) + { + foreach( Object target in targets ) + { + ResetParticles( ( (ParticlesFollowBezier) target ).GetComponentsInParent() ); + ResetParticles( ( (ParticlesFollowBezier) target ).GetComponentsInChildren() ); + } + } + } + + private void ResetParticles( ParticlesFollowBezier[] targets ) + { + foreach( ParticlesFollowBezier target in targets ) + { + ParticleSystem particleSystem = target.GetComponent(); + if( target.spline != null && particleSystem != null && target.enabled ) + particleSystem.Clear(); + } + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/BezierSolution/Editor/ParticlesFollowBezierEditor.cs.meta b/Assets/Plugins/BezierSolution/Editor/ParticlesFollowBezierEditor.cs.meta new file mode 100644 index 00000000..66e12a0c --- /dev/null +++ b/Assets/Plugins/BezierSolution/Editor/ParticlesFollowBezierEditor.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 652ad8d00b278c04fbf4252c46b7a10f +timeCreated: 1520346477 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/BezierSolution/Other.meta b/Assets/Plugins/BezierSolution/Other.meta new file mode 100644 index 00000000..ff905c5a --- /dev/null +++ b/Assets/Plugins/BezierSolution/Other.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 34eb947ee3a327b45911b699fb81c1f5 +folderAsset: yes +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/BezierSolution/Other/BezierDataStructures.cs b/Assets/Plugins/BezierSolution/Other/BezierDataStructures.cs new file mode 100644 index 00000000..c312f3ff --- /dev/null +++ b/Assets/Plugins/BezierSolution/Other/BezierDataStructures.cs @@ -0,0 +1,344 @@ +using UnityEngine; + +namespace BezierSolution +{ + public enum SplineAutoConstructMode { None = 0, Linear = 1, Smooth1 = 2, Smooth2 = 3 }; + + [System.Flags] + internal enum InternalDirtyFlags + { + None = 0, + EndPointTransformChange = 1 << 1, + ControlPointPositionChange = 1 << 2, + NormalChange = 1 << 3, + NormalOffsetChange = 1 << 4, + ExtraDataChange = 1 << 5, + All = EndPointTransformChange | ControlPointPositionChange | NormalChange | NormalOffsetChange | ExtraDataChange + }; + + [System.Flags] + public enum DirtyFlags + { + None = 0, + SplineShapeChanged = 1 << 1, + NormalsChanged = 1 << 2, + ExtraDataChanged = 1 << 3, + All = SplineShapeChanged | NormalsChanged | ExtraDataChanged + }; + + [System.Flags] + public enum PointCacheFlags + { + None = 0, + Positions = 1 << 1, + Normals = 1 << 2, + Tangents = 1 << 3, + Bitangents = 1 << 4, + ExtraDatas = 1 << 5, + All = Positions | Normals | Tangents | Bitangents | ExtraDatas + }; + + public delegate void SplineChangeDelegate( BezierSpline spline, DirtyFlags dirtyFlags ); + public delegate BezierPoint.ExtraData ExtraDataLerpFunction( BezierPoint.ExtraData data1, BezierPoint.ExtraData data2, float normalizedT ); + + public partial class BezierSpline + { + private static readonly ExtraDataLerpFunction defaultExtraDataLerpFunction = BezierPoint.ExtraData.LerpUnclamped; + + public struct Segment + { + public readonly BezierPoint point1, point2; + public readonly float localT; + + public Segment( BezierPoint point1, BezierPoint point2, float localT ) + { + this.point1 = point1; + this.point2 = point2; + this.localT = localT; + } + + public float GetNormalizedT() { return GetNormalizedT( localT ); } + public float GetNormalizedT( float localT ) + { + BezierSpline spline = point1.spline; + return ( point1.index + localT ) / ( spline.m_loop ? spline.Count : ( spline.Count - 1 ) ); + } + + public Vector3 GetPoint() { return GetPoint( localT ); } + public Vector3 GetPoint( float localT ) + { + float oneMinusLocalT = 1f - localT; + + return oneMinusLocalT * oneMinusLocalT * oneMinusLocalT * point1.position + + 3f * oneMinusLocalT * oneMinusLocalT * localT * point1.followingControlPointPosition + + 3f * oneMinusLocalT * localT * localT * point2.precedingControlPointPosition + + localT * localT * localT * point2.position; + } + + public Vector3 GetTangent() { return GetTangent( localT ); } + public Vector3 GetTangent( float localT ) + { + float oneMinusLocalT = 1f - localT; + + return 3f * oneMinusLocalT * oneMinusLocalT * ( point1.followingControlPointPosition - point1.position ) + + 6f * oneMinusLocalT * localT * ( point2.precedingControlPointPosition - point1.followingControlPointPosition ) + + 3f * localT * localT * ( point2.position - point2.precedingControlPointPosition ); + } + + public Vector3 GetNormal() { return GetNormal( localT ); } + public Vector3 GetNormal( float localT ) + { + Vector3[] intermediateNormals = point1.intermediateNormals; + if( intermediateNormals != null && intermediateNormals.Length > 0 ) + { + localT = Mathf.Clamp01( localT ) * ( intermediateNormals.Length - 1 ); + int localStartIndex = (int) localT; + + return ( localStartIndex < intermediateNormals.Length - 1 ) ? Vector3.LerpUnclamped( intermediateNormals[localStartIndex], intermediateNormals[localStartIndex + 1], localT - localStartIndex ) : intermediateNormals[localStartIndex]; + } + + Vector3 startNormal = point1.normal; + Vector3 endNormal = point2.normal; + + Vector3 normal = Vector3.LerpUnclamped( startNormal, endNormal, localT ); + if( normal.y == 0f && normal.x == 0f && normal.z == 0f ) + { + // Don't return Vector3.zero as normal + normal = Vector3.LerpUnclamped( startNormal, endNormal, localT > 0.01f ? ( localT - 0.01f ) : ( localT + 0.01f ) ); + if( normal.y == 0f && normal.x == 0f && normal.z == 0f ) + normal = Vector3.up; + } + + return normal; + } + + public BezierPoint.ExtraData GetExtraData() { return defaultExtraDataLerpFunction( point1.extraData, point2.extraData, localT ); } + public BezierPoint.ExtraData GetExtraData( float localT ) { return defaultExtraDataLerpFunction( point1.extraData, point2.extraData, localT ); } + public BezierPoint.ExtraData GetExtraData( ExtraDataLerpFunction lerpFunction ) { return lerpFunction( point1.extraData, point2.extraData, localT ); } + public BezierPoint.ExtraData GetExtraData( float localT, ExtraDataLerpFunction lerpFunction ) { return lerpFunction( point1.extraData, point2.extraData, localT ); } + } + + public class EvenlySpacedPointsHolder + { + public readonly BezierSpline spline; + public readonly float splineLength; + public readonly float[] uniformNormalizedTs; + + public EvenlySpacedPointsHolder( BezierSpline spline, float splineLength, float[] uniformNormalizedTs ) + { + this.spline = spline; + this.splineLength = splineLength; + this.uniformNormalizedTs = uniformNormalizedTs; + } + + public float GetNormalizedTAtDistance( float distance ) + { + return GetNormalizedTAtPercentage( distance / splineLength ); + } + + public float GetNormalizedTAtPercentage( float percentage ) + { + if( !spline.loop ) + { + if( percentage <= 0f ) + return 0f; + else if( percentage >= 1f ) + return 1f; + } + else + { + while( percentage < 0f ) + percentage += 1f; + while( percentage >= 1f ) + percentage -= 1f; + } + + float indexRaw = ( uniformNormalizedTs.Length - 1 ) * percentage; + int index = (int) indexRaw; + return Mathf.LerpUnclamped( uniformNormalizedTs[index], uniformNormalizedTs[index + 1], indexRaw - index ); + } + + public float GetPercentageAtNormalizedT( float normalizedT ) + { + if( !spline.loop ) + { + if( normalizedT <= 0f ) + return 0f; + else if( normalizedT >= 1f ) + return 1f; + } + else + { + if( normalizedT < 0f ) + normalizedT += 1f; + if( normalizedT >= 1f ) + normalizedT -= 1f; + } + + // Perform binary search + int lowerBound = 0; + int upperBound = uniformNormalizedTs.Length - 1; + while( lowerBound <= upperBound ) + { + int index = lowerBound + ( ( upperBound - lowerBound ) >> 1 ); + float arrElement = uniformNormalizedTs[index]; + if( arrElement < normalizedT ) + lowerBound = index + 1; + else if( arrElement > normalizedT ) + upperBound = index - 1; + else + return index / (float) ( uniformNormalizedTs.Length - 1 ); + } + + float inverseLerp = ( normalizedT - uniformNormalizedTs[lowerBound] ) / ( uniformNormalizedTs[lowerBound - 1] - uniformNormalizedTs[lowerBound] ); + return ( lowerBound - inverseLerp ) / ( uniformNormalizedTs.Length - 1 ); + } + } + + public class PointCache + { + public readonly Vector3[] positions, normals, tangents, bitangents; + public readonly BezierPoint.ExtraData[] extraDatas; + public readonly bool loop; + + public PointCache( Vector3[] positions, Vector3[] normals, Vector3[] tangents, Vector3[] bitangents, BezierPoint.ExtraData[] extraDatas, bool loop ) + { + this.positions = positions; + this.normals = normals; + this.tangents = tangents; + this.bitangents = bitangents; + this.extraDatas = extraDatas; + this.loop = loop; + } + + public Vector3 GetPoint( float percentage ) { return LerpArray( positions, percentage ); } + public Vector3 GetNormal( float percentage ) { return LerpArray( normals, percentage ); } + public Vector3 GetTangent( float percentage ) { return LerpArray( tangents, percentage ); } + public Vector3 GetBitangent( float percentage ) { return LerpArray( bitangents, percentage ); } + + public BezierPoint.ExtraData GetExtraData( float percentage ) { return GetExtraData( percentage, defaultExtraDataLerpFunction ); } + public BezierPoint.ExtraData GetExtraData( float percentage, ExtraDataLerpFunction lerpFunction ) + { + if( !loop ) + { + if( percentage <= 0f ) + return extraDatas[0]; + else if( percentage >= 1f ) + return extraDatas[extraDatas.Length - 1]; + } + else + { + if( percentage < 0f ) + percentage += 1f; + if( percentage >= 1f ) + percentage -= 1f; + } + + float t = percentage * ( loop ? extraDatas.Length : ( extraDatas.Length - 1 ) ); + + int startIndex = (int) t; + int endIndex = startIndex + 1; + + if( endIndex == extraDatas.Length ) + endIndex = 0; + + return lerpFunction( extraDatas[startIndex], extraDatas[endIndex], t - startIndex ); + } + + private Vector3 LerpArray( Vector3[] array, float percentage ) + { + if( !loop ) + { + if( percentage <= 0f ) + return array[0]; + else if( percentage >= 1f ) + return array[array.Length - 1]; + } + else + { + if( percentage < 0f ) + percentage += 1f; + if( percentage >= 1f ) + percentage -= 1f; + } + + float t = percentage * ( loop ? array.Length : ( array.Length - 1 ) ); + + int startIndex = (int) t; + int endIndex = startIndex + 1; + + if( endIndex == array.Length ) + endIndex = 0; + + return Vector3.LerpUnclamped( array[startIndex], array[endIndex], t - startIndex ); + } + } + } + + public partial class BezierPoint + { + public enum HandleMode { Free, Aligned, Mirrored }; + + [System.Serializable] + public struct ExtraData + { + public float c1, c2, c3, c4; + + public ExtraData( float c1 = 0f, float c2 = 0f, float c3 = 0f, float c4 = 0f ) + { + this.c1 = c1; + this.c2 = c2; + this.c3 = c3; + this.c4 = c4; + } + + public static ExtraData Lerp( ExtraData a, ExtraData b, float t ) + { + t = Mathf.Clamp01( t ); + return new ExtraData( + a.c1 + ( b.c1 - a.c1 ) * t, + a.c2 + ( b.c2 - a.c2 ) * t, + a.c3 + ( b.c3 - a.c3 ) * t, + a.c4 + ( b.c4 - a.c4 ) * t ); + } + + public static ExtraData LerpUnclamped( ExtraData a, ExtraData b, float t ) + { + return new ExtraData( + a.c1 + ( b.c1 - a.c1 ) * t, + a.c2 + ( b.c2 - a.c2 ) * t, + a.c3 + ( b.c3 - a.c3 ) * t, + a.c4 + ( b.c4 - a.c4 ) * t ); + } + + public static implicit operator ExtraData( Vector2 v ) { return new ExtraData( v.x, v.y ); } + public static implicit operator ExtraData( Vector3 v ) { return new ExtraData( v.x, v.y, v.z ); } + public static implicit operator ExtraData( Vector4 v ) { return new ExtraData( v.x, v.y, v.z, v.w ); } + public static implicit operator ExtraData( Quaternion q ) { return new ExtraData( q.x, q.y, q.z, q.w ); } + public static implicit operator ExtraData( Rect r ) { return new ExtraData( r.xMin, r.yMin, r.width, r.height ); } +#if UNITY_2017_2_OR_NEWER + public static implicit operator ExtraData( Vector2Int v ) { return new ExtraData( v.x, v.y ); } + public static implicit operator ExtraData( Vector3Int v ) { return new ExtraData( v.x, v.y, v.z ); } + public static implicit operator ExtraData( RectInt r ) { return new ExtraData( r.xMin, r.yMin, r.width, r.height ); } +#endif + + public static implicit operator Vector2( ExtraData v ) { return new Vector2( v.c1, v.c2 ); } + public static implicit operator Vector3( ExtraData v ) { return new Vector3( v.c1, v.c2, v.c3 ); } + public static implicit operator Vector4( ExtraData v ) { return new Vector4( v.c1, v.c2, v.c3, v.c4 ); } + public static implicit operator Quaternion( ExtraData v ) { return new Quaternion( v.c1, v.c2, v.c3, v.c4 ); } + public static implicit operator Rect( ExtraData v ) { return new Rect( v.c1, v.c2, v.c3, v.c4 ); } +#if UNITY_2017_2_OR_NEWER + public static implicit operator Vector2Int( ExtraData v ) { return new Vector2Int( Mathf.RoundToInt( v.c1 ), Mathf.RoundToInt( v.c2 ) ); } + public static implicit operator Vector3Int( ExtraData v ) { return new Vector3Int( Mathf.RoundToInt( v.c1 ), Mathf.RoundToInt( v.c2 ), Mathf.RoundToInt( v.c3 ) ); } + public static implicit operator RectInt( ExtraData v ) { return new RectInt( Mathf.RoundToInt( v.c1 ), Mathf.RoundToInt( v.c2 ), Mathf.RoundToInt( v.c3 ), Mathf.RoundToInt( v.c4 ) ); } +#endif + + public static bool operator ==( ExtraData d1, ExtraData d2 ) { return d1.c1 == d2.c1 && d1.c2 == d2.c2 && d1.c3 == d2.c3 && d1.c4 == d2.c4; } + public static bool operator !=( ExtraData d1, ExtraData d2 ) { return d1.c1 != d2.c1 || d1.c2 != d2.c2 || d1.c3 != d2.c3 || d1.c4 != d2.c4; } + + public override bool Equals( object obj ) { return obj is ExtraData && this == (ExtraData) obj; } + public override int GetHashCode() { return unchecked((int) ( ( ( ( 17 * 23 + c1 ) * 23 + c2 ) * 23 + c3 ) * 23 + c4 )); } + public override string ToString() { return ( (Vector4) this ).ToString(); } + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/BezierSolution/Other/BezierDataStructures.cs.meta b/Assets/Plugins/BezierSolution/Other/BezierDataStructures.cs.meta new file mode 100644 index 00000000..12d9dbbc --- /dev/null +++ b/Assets/Plugins/BezierSolution/Other/BezierDataStructures.cs.meta @@ -0,0 +1,10 @@ +fileFormatVersion: 2 +guid: 4cf39235e4779904896b58210ade2e37 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/BezierSolution/README.txt b/Assets/Plugins/BezierSolution/README.txt new file mode 100644 index 00000000..09260a59 --- /dev/null +++ b/Assets/Plugins/BezierSolution/README.txt @@ -0,0 +1,36 @@ += Bezier Solution = + +Online documentation & example code available at: https://github.com/yasirkula/UnityBezierSolution +E-mail: yasirkula@gmail.com + +### ABOUT +This plugin helps you create bezier splines either visually in editor or by code during gameplay. Includes some utility functions like finding the closest point on the spline or travelling the spline with constant speed. It is built upon Catlike Coding's spline tutorial: https://catlikecoding.com/unity/tutorials/curves-and-splines/ + + +### HOW TO +To create a new spline in the editor, click "GameObject - Bezier Spline". Now you can select the end points of the spline in the Scene view and move/rotate/scale or delete/duplicate them as you wish (each end point also has 2 control points that can be moved around). Most variables have explanatory tooltips. + +You can tweak the Scene view gizmos via "Project Settings/yasirkula/Bezier Solution" page (on older versions, this menu is located at "Preferences" window). + +The plugin comes with some additional components that may help you move objects or particles along splines. These components are located in the Utilities folder: + +- BezierWalkerWithSpeed: Moves an object along a spline with constant speed. There are 3 travel modes: Once, Ping Pong and Loop. If Look At is Forward, the object will always face forwards. If it is SplineExtraData, the extra data stored in the spline's end points is used to determine the rotation. You can modify this extra data from the points' Inspector. The smoothness of the rotation can be adjusted via Rotation Lerp Modifier. Normalized T determines the starting point. Each time the object completes a lap, its On Path Completed () event is invoked. To see this component in action without entering Play mode, click the "Simulate In Editor" button. + +- BezierWalkerWithTime: Travels a spline in Travel Time seconds. Movement Lerp Modifier parameter defines the smoothness applied to the position of the object. If High Quality is enabled, the spline will be traversed with constant speed but the calculations can be more expensive. + +- BezierWalkerLocomotion: Allows you to move a number of objects together with this object on a spline. This component must be attached to an object with a BezierWalker component (tail objects don't need a BezierWalker, though). Look At, Movement Lerp Modifier and Rotation Lerp Modifier parameters affect the tail objects. If tail objects jitter too much, enabling High Quality may help greatly but the calculations can be more expensive. + +- ParticlesFollowBezier: Moves particles of a Particle System in the direction of a spline. It is recommended to set the Simulation Space of the Particle System to Local for increased performance. This component affects particles in one of two ways: +-- Strict: particles will strictly follow the spline. They will always be aligned to the spline and will reach the end of the spline at the end of their lifetime. This mode performs slightly better than Relaxed mode +-- Relaxed: properties of the particle system like speed, Noise and Shape will affect the movement of the particles. Particles in this mode will usually look more interesting. If you want the particles to stick with the spline, though, set their speed to 0 + +- BezierAttachment: Snaps an object to the specified point of the spline. You can snap the object's position and/or rotation values, optionally with some offsets. Rotation can be snapped in one of two ways: +-- Use Spline Normals: spline's normal vectors will be used to determine the object's rotation +-- Use End Point Rotations: the Transform rotation values of the spline's end points will be used to determine the object's rotation + +- BezierLineRenderer: Automatically positions a Line Renderer's points so that its shape matches the target spline's shape. It is possible to match the shape of only a portion of the spline by tweaking the Spline Sample Range property. If Line Renderer's "Use World Space" property is enabled, then its points will be placed at the spline's current position. Otherwise, the points will be placed relative to the Line Renderer's position and they will rotate/scale with the Line Renderer. + +- BendMeshAlongBezier: Modifies a MeshFilter's mesh to bend it in the direction of a spline (make sure that the spline's normals are perpendicular to the spline; Auto Calculate Normals may help). If High Quality is enabled, evenly spaced bezier points will be used so that the mesh bends uniformly but the calculations will be more expensive. If Auto Refresh is enabled, the mesh will be refreshed automatically when the spline is modified (at runtime, this has the same effect with disabling the component but in edit mode, disabling the component will restore the original mesh instead). Mesh's normal and tangent vectors can optionally be recalculated in one of two ways: +-- Modify Originals: the original mesh's normal and tangent vectors will be rotated with the spline +-- Recalculate From Scratch: Unity's RecalculateNormals and/or RecalculateTangents functions will be invoked to recalculate these vectors from scratch +Note that this component doesn't add new vertices to the original mesh, so if the original mesh doesn't have enough vertices in its bend axis, then the bent mesh will have jagged edges on complex splines. \ No newline at end of file diff --git a/Assets/Plugins/BezierSolution/README.txt.meta b/Assets/Plugins/BezierSolution/README.txt.meta new file mode 100644 index 00000000..9eb681b7 --- /dev/null +++ b/Assets/Plugins/BezierSolution/README.txt.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 90c5928df0356a746a1423cce53181b9 +timeCreated: 1562520040 +licenseType: Store +TextScriptImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/BezierSolution/Utilities.meta b/Assets/Plugins/BezierSolution/Utilities.meta new file mode 100644 index 00000000..7bdf4900 --- /dev/null +++ b/Assets/Plugins/BezierSolution/Utilities.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 86440575d46397c488152ba57ee62ed4 +folderAsset: yes +timeCreated: 1473251123 +licenseType: Store +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/BezierSolution/Utilities/BendMeshAlongBezier.cs b/Assets/Plugins/BezierSolution/Utilities/BendMeshAlongBezier.cs new file mode 100644 index 00000000..03e52b49 --- /dev/null +++ b/Assets/Plugins/BezierSolution/Utilities/BendMeshAlongBezier.cs @@ -0,0 +1,607 @@ +using UnityEngine; +#if UNITY_EDITOR +using UnityEditor; +using UnityEditor.SceneManagement; +#if UNITY_2018_3_OR_NEWER +using PrefabStage = UnityEditor.Experimental.SceneManagement.PrefabStage; +using PrefabStageUtility = UnityEditor.Experimental.SceneManagement.PrefabStageUtility; +#endif +#endif + +namespace BezierSolution +{ + [AddComponentMenu( "Bezier Solution/Bend Mesh Along Bezier" )] + [HelpURL( "https://github.com/yasirkula/UnityBezierSolution" )] + [RequireComponent( typeof( MeshFilter ) )] + [ExecuteInEditMode] + public class BendMeshAlongBezier : MonoBehaviour + { + public enum VectorMode { DontModify = 0, ModifyOriginals = 1, RecalculateFromScratch = 2 }; + public enum Axis { X = 0, Y = 1, Z = 2 }; + +#pragma warning disable 0649 + [SerializeField] + private BezierSpline m_spline; + public BezierSpline spline + { + get { return m_spline; } + set + { + if( m_spline != value ) + { + if( m_spline ) + m_spline.onSplineChanged -= OnSplineChanged; + + m_spline = value; + + if( m_spline && isActiveAndEnabled ) + { + m_spline.onSplineChanged -= OnSplineChanged; + m_spline.onSplineChanged += OnSplineChanged; + + OnSplineChanged( m_spline, DirtyFlags.All ); + } + } + } + } + + [SerializeField] + [MinMaxRange( 0f, 1f )] + private Vector2 m_splineSampleRange = new Vector2( 0f, 1f ); + public Vector2 SplineSampleRange + { + get { return m_splineSampleRange; } + set + { + value.x = Mathf.Clamp01( value.x ); + value.y = Mathf.Clamp01( value.y ); + + if( m_splineSampleRange != value ) + { + m_splineSampleRange = value; + OnSplineChanged( m_spline, DirtyFlags.All ); + } + } + } + + [Header( "Bend Options" )] + [SerializeField] + private bool m_highQuality = false; + public bool highQuality + { + get { return m_highQuality; } + set + { + if( m_highQuality != value ) + { + m_highQuality = value; + OnSplineChanged( m_spline, DirtyFlags.All ); + } + } + } + + [SerializeField] + private Axis m_bendAxis = Axis.Y; + public Axis bendAxis + { + + get { return m_bendAxis; } + set + { + if( m_bendAxis != value ) + { + m_bendAxis = value; + + RecalculateVertexRange(); + OnSplineChanged( m_spline, DirtyFlags.All ); + } + } + } + + [SerializeField] + [Range( 0f, 360f )] + private float m_extraRotation = 0f; + public float extraRotation + { + get { return m_extraRotation; } + set + { + value = Mathf.Clamp( value, 0f, 360f ); + + if( m_extraRotation != value ) + { + m_extraRotation = value; + OnSplineChanged( m_spline, DirtyFlags.All ); + } + } + } + + [SerializeField] + private bool m_invertDirection = false; + public bool invertDirection + { + get { return m_invertDirection; } + set + { + if( m_invertDirection != value ) + { + m_invertDirection = value; + OnSplineChanged( m_spline, DirtyFlags.All ); + } + } + } + + [SerializeField] + private Vector2 m_thicknessMultiplier = Vector2.one; + public Vector2 thicknessMultiplier + { + get { return m_thicknessMultiplier; } + set + { + if( m_thicknessMultiplier != value ) + { + m_thicknessMultiplier = value; + OnSplineChanged( m_spline, DirtyFlags.All ); + } + } + } + + [Header( "Vertex Attributes" )] + [SerializeField] + private VectorMode m_normalsMode = VectorMode.ModifyOriginals; + public VectorMode normalsMode + { + get { return m_normalsMode; } + set + { + if( m_normalsMode != value ) + { + m_normalsMode = value; + + if( mesh ) + { + if( m_normalsMode == VectorMode.DontModify && originalNormals != null ) + { + mesh.normals = originalNormals; + originalNormals = null; + } + + if( m_normalsMode != VectorMode.ModifyOriginals ) + normals = null; + } + + OnSplineChanged( m_spline, DirtyFlags.All ); + } + } + } + + [SerializeField] + private VectorMode m_tangentsMode = VectorMode.ModifyOriginals; + public VectorMode tangentsMode + { + get { return m_tangentsMode; } + set + { + if( m_tangentsMode != value ) + { + m_tangentsMode = value; + + if( mesh ) + { + if( m_tangentsMode == VectorMode.DontModify && originalTangents != null ) + { + mesh.tangents = originalTangents; + originalTangents = null; + } + + if( m_tangentsMode != VectorMode.ModifyOriginals ) + tangents = null; + } + + OnSplineChanged( m_spline, DirtyFlags.All ); + } + } + } + + [Header( "Other Settings" )] + [SerializeField] + private bool m_autoRefresh = true; + public bool autoRefresh + { + get { return m_autoRefresh; } + set + { + if( m_autoRefresh != value ) + { + m_autoRefresh = value; + OnSplineChanged( m_spline, DirtyFlags.All ); + } + } + } + +#if UNITY_EDITOR + [SerializeField] + private bool executeInEditMode = false; + + [SerializeField, HideInInspector] + private BezierSpline prevSpline; + [SerializeField, HideInInspector] + private VectorMode prevNormalsMode, prevTangentsMode; + [SerializeField, HideInInspector] + private bool prevHighQuality; +#endif + + [SerializeField, HideInInspector] + private Mesh originalMesh; // If this isn't serialized, then sometimes exceptions occur on undo/redo +#pragma warning restore 0649 + + private MeshFilter meshFilter; + + private Mesh mesh; + private Vector3[] vertices, originalVertices; + private Vector3[] normals, originalNormals; + private Vector4[] tangents, originalTangents; + + private float minVertex, _1OverVertexRange; + + private void OnEnable() + { +#if UNITY_EDITOR + // Restore normals and tangents after assembly reload if they are set to DontModify because otherwise they become null automatically (i.e. information gets lost) + if( mesh && originalMesh ) + { + if( m_normalsMode == VectorMode.DontModify ) + mesh.normals = originalMesh.normals; + if( m_tangentsMode == VectorMode.DontModify ) + mesh.tangents = originalMesh.tangents; + } + + EditorSceneManager.sceneSaving -= OnSceneSaving; + EditorSceneManager.sceneSaving += OnSceneSaving; + EditorSceneManager.sceneSaved -= OnSceneSaved; + EditorSceneManager.sceneSaved += OnSceneSaved; +#endif + + if( m_spline ) + { + m_spline.onSplineChanged -= OnSplineChanged; + m_spline.onSplineChanged += OnSplineChanged; + + OnSplineChanged( m_spline, DirtyFlags.All ); + } + } + + private void OnDisable() + { + if( m_spline ) + m_spline.onSplineChanged -= OnSplineChanged; + +#if UNITY_EDITOR + EditorSceneManager.sceneSaving -= OnSceneSaving; + EditorSceneManager.sceneSaved -= OnSceneSaved; + + if( !EditorApplication.isPlaying ) + OnDestroy(); +#endif + } + + private void OnDestroy() + { + MeshFilter _meshFilter = meshFilter; + meshFilter = null; + + if( _meshFilter && originalMesh ) + _meshFilter.sharedMesh = originalMesh; + + if( mesh ) + DestroyImmediate( mesh ); + +#if UNITY_EDITOR && UNITY_2018_3_OR_NEWER + // This allows removing the 'modified' flag of Mesh Filter's Mesh property but these sorts of things + // may cause new problems in edge cases so it is commented out + //if( !EditorApplication.isPlaying && _meshFilter && originalMesh ) + //{ + // // Revert modified status of the prefab instance's MeshFilter Mesh if possible + // MeshFilter prefabMeshFilter = null; + // if( PrefabUtility.GetPrefabInstanceStatus( _meshFilter ) == PrefabInstanceStatus.Connected ) + // prefabMeshFilter = PrefabUtility.GetCorrespondingObjectFromSource( _meshFilter ) as MeshFilter; + + // if( prefabMeshFilter && prefabMeshFilter.sharedMesh == originalMesh ) + // PrefabUtility.RevertPropertyOverride( new SerializedObject( _meshFilter ).FindProperty( "m_Mesh" ), InteractionMode.AutomatedAction ); + //} +#endif + } + + public void Activate() + { + enabled = true; + } + + public void Deactivate() + { + OnDestroy(); + enabled = false; + } + +#if UNITY_EDITOR + private void OnValidate() + { + EditorApplication.update -= OnValidateImplementation; + EditorApplication.update += OnValidateImplementation; + } + + // Calling this code inside OnValidate throws "SendMessage cannot be called during Awake, CheckConsistency, or OnValidate" warnings + private void OnValidateImplementation() + { + EditorApplication.update -= OnValidateImplementation; + + if( !this ) + return; + + BezierSpline _spline = m_spline; + m_spline = prevSpline; + spline = prevSpline = _spline; + + bool _highQuality = m_highQuality; + m_highQuality = prevHighQuality; + highQuality = prevHighQuality = _highQuality; + + VectorMode _normalsMode = m_normalsMode; + m_normalsMode = prevNormalsMode; + normalsMode = prevNormalsMode = _normalsMode; + + VectorMode _tangentsMode = m_tangentsMode; + m_tangentsMode = prevTangentsMode; + tangentsMode = prevTangentsMode = _tangentsMode; + + RecalculateVertexRange(); + + if( !executeInEditMode && !EditorApplication.isPlaying ) + OnDestroy(); + else if( isActiveAndEnabled ) + OnSplineChanged( m_spline, DirtyFlags.All ); + + SceneView.RepaintAll(); + } + + private void OnSceneSaving( UnityEngine.SceneManagement.Scene scene, string path ) + { + // Restore original mesh before saving the scene + if( scene == gameObject.scene ) + OnDestroy(); + } + + private void OnSceneSaved( UnityEngine.SceneManagement.Scene scene ) + { + // Restore modified mesh after saving the scene + if( scene == gameObject.scene && isActiveAndEnabled ) + OnSplineChanged( m_spline, DirtyFlags.All ); + } +#endif + + private void OnSplineChanged( BezierSpline spline, DirtyFlags dirtyFlags ) + { +#if UNITY_EDITOR + if( !executeInEditMode && !EditorApplication.isPlaying ) + return; + + if( BuildPipeline.isBuildingPlayer ) + return; + +#if UNITY_2018_3_OR_NEWER + // Don't execute the script in prefab mode + PrefabStage openPrefabStage = PrefabStageUtility.GetCurrentPrefabStage(); + if( openPrefabStage != null && openPrefabStage.IsPartOfPrefabContents( gameObject ) ) + return; +#endif +#endif + + if( m_autoRefresh && ( dirtyFlags & ( DirtyFlags.SplineShapeChanged | DirtyFlags.NormalsChanged ) ) != DirtyFlags.None ) + Refresh(); + } + + private void Initialize() + { + meshFilter = GetComponent(); + if( meshFilter.sharedMesh ) // It can sometimes be null during undo&redo which causes issues + originalMesh = meshFilter.sharedMesh; + + if( !originalMesh ) + return; + + if( mesh ) + DestroyImmediate( mesh ); + + mesh = Instantiate( originalMesh ); + meshFilter.sharedMesh = mesh; + +#if UNITY_EDITOR + if( !EditorApplication.isPlaying ) + mesh.hideFlags = HideFlags.DontSave; +#endif + + originalVertices = mesh.vertices; + originalNormals = null; + originalTangents = null; + + RecalculateVertexRange(); + } + + private void RecalculateVertexRange() + { + if( originalVertices == null ) + return; + + minVertex = float.PositiveInfinity; + float maxVertex = float.NegativeInfinity; + + switch( m_bendAxis ) + { + case Axis.X: + for( int i = 0; i < originalVertices.Length; i++ ) + { + float vertex = originalVertices[i].x; + if( vertex < minVertex ) + minVertex = originalVertices[i].x; + if( vertex > maxVertex ) + maxVertex = originalVertices[i].x; + } + break; + case Axis.Y: + for( int i = 0; i < originalVertices.Length; i++ ) + { + float vertex = originalVertices[i].y; + if( vertex < minVertex ) + minVertex = originalVertices[i].y; + if( vertex > maxVertex ) + maxVertex = originalVertices[i].y; + } + break; + case Axis.Z: + for( int i = 0; i < originalVertices.Length; i++ ) + { + float vertex = originalVertices[i].z; + if( vertex < minVertex ) + minVertex = originalVertices[i].z; + if( vertex > maxVertex ) + maxVertex = originalVertices[i].z; + } + break; + } + + _1OverVertexRange = 1f / ( maxVertex - minVertex ); + } + + public void Refresh() + { + if( !m_spline ) + return; + + if( !meshFilter || ( meshFilter.sharedMesh && meshFilter.sharedMesh != mesh && meshFilter.sharedMesh != originalMesh ) ) + Initialize(); + + if( !originalMesh ) + return; + + if( vertices == null || vertices.Length != originalVertices.Length ) + vertices = new Vector3[originalVertices.Length]; + + if( m_normalsMode == VectorMode.ModifyOriginals ) + { + if( originalNormals == null ) + originalNormals = originalMesh.normals; + + if( originalNormals == null || originalNormals.Length < originalVertices.Length ) // If somehow above statement returned null + normals = null; + else if( normals == null || normals.Length != originalNormals.Length ) + normals = new Vector3[originalNormals.Length]; + } + else + normals = null; + + if( m_tangentsMode == VectorMode.ModifyOriginals ) + { + if( originalTangents == null ) + originalTangents = originalMesh.tangents; + + if( originalTangents == null || originalTangents.Length < originalVertices.Length ) // If somehow above statement returned null + tangents = null; + else if( tangents == null || tangents.Length != originalTangents.Length ) + tangents = new Vector4[originalTangents.Length]; + } + else + tangents = null; + + Vector2 _splineSampleRange = m_splineSampleRange; + if( m_invertDirection ) + { + float temp = _splineSampleRange.x; + _splineSampleRange.x = _splineSampleRange.y; + _splineSampleRange.y = temp; + } + + bool isSampleRangeForwards = _splineSampleRange.x <= _splineSampleRange.y; + float splineSampleLength = _splineSampleRange.y - _splineSampleRange.x; + bool dontInvertModifiedVertexAttributes = ( m_thicknessMultiplier.x > 0f && m_thicknessMultiplier.y > 0f ); + + BezierSpline.EvenlySpacedPointsHolder evenlySpacedPoints = m_highQuality ? m_spline.evenlySpacedPoints : null; + + Vector3 initialPoint = m_spline.GetPoint( 0f ); + for( int i = 0; i < originalVertices.Length; i++ ) + { + Vector3 vertex = originalVertices[i]; + + float vertexPosition; + Vector3 vertexOffset; + switch( m_bendAxis ) + { + case Axis.X: + vertexPosition = vertex.x; + vertexOffset = new Vector3( vertex.z * m_thicknessMultiplier.x, 0f, vertex.y * m_thicknessMultiplier.y ); + break; + case Axis.Y: + default: + vertexPosition = vertex.y; + vertexOffset = new Vector3( vertex.x * m_thicknessMultiplier.x, 0f, vertex.z * m_thicknessMultiplier.y ); + break; + case Axis.Z: + vertexPosition = vertex.z; + vertexOffset = new Vector3( vertex.y * m_thicknessMultiplier.x, 0f, vertex.x * m_thicknessMultiplier.y ); + break; + } + + float normalizedT = _splineSampleRange.x + ( vertexPosition - minVertex ) * _1OverVertexRange * splineSampleLength; // Remap from [minVertex,maxVertex] to _splineSampleRange + if( m_highQuality ) + normalizedT = evenlySpacedPoints.GetNormalizedTAtPercentage( normalizedT ); + + BezierSpline.Segment segment = m_spline.GetSegmentAt( normalizedT ); + + Vector3 point = segment.GetPoint() - initialPoint; + Vector3 tangent = isSampleRangeForwards ? segment.GetTangent() : -segment.GetTangent(); + Quaternion rotation = Quaternion.AngleAxis( m_extraRotation, tangent ) * Quaternion.LookRotation( segment.GetNormal(), tangent ); + + Vector3 direction = rotation * vertexOffset; + vertices[i] = point + direction; + + if( normals != null ) // The only case this happens is when Normals Mode is ModifyOriginals and the original mesh has normals + normals[i] = rotation * ( dontInvertModifiedVertexAttributes ? originalNormals[i] : -originalNormals[i] ); + if( tangents != null ) // The only case this happens is when Tangents Mode is ModifyOriginals and the original mesh has tangents + { + float tangentW = originalTangents[i].w; + tangents[i] = rotation * ( dontInvertModifiedVertexAttributes ? originalTangents[i] : -originalTangents[i] ); + tangents[i].w = tangentW; + } + } + + mesh.vertices = vertices; + if( m_normalsMode == VectorMode.ModifyOriginals ) + mesh.normals = normals; + if( m_tangentsMode == VectorMode.ModifyOriginals ) + mesh.tangents = tangents; + + if( m_normalsMode == VectorMode.RecalculateFromScratch ) + { + mesh.RecalculateNormals(); + +#if UNITY_EDITOR + // Cache original normals so that we can reset normals in OnValidate when normals are reset back to DontModify + if( originalNormals == null ) + originalNormals = originalMesh.normals; +#endif + } + + if( m_tangentsMode == VectorMode.RecalculateFromScratch ) + { + mesh.RecalculateTangents(); + +#if UNITY_EDITOR + // Cache original tangents so that we can reset tangents in OnValidate when tangents are reset back to DontModify + if( originalTangents == null ) + originalTangents = originalMesh.tangents; +#endif + } + + mesh.RecalculateBounds(); + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/BezierSolution/Utilities/BendMeshAlongBezier.cs.meta b/Assets/Plugins/BezierSolution/Utilities/BendMeshAlongBezier.cs.meta new file mode 100644 index 00000000..2e851f31 --- /dev/null +++ b/Assets/Plugins/BezierSolution/Utilities/BendMeshAlongBezier.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 0e815427364673446939224ffdf5e5fd +timeCreated: 1620245307 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/BezierSolution/Utilities/BezierAttachment.cs b/Assets/Plugins/BezierSolution/Utilities/BezierAttachment.cs new file mode 100644 index 00000000..98939c58 --- /dev/null +++ b/Assets/Plugins/BezierSolution/Utilities/BezierAttachment.cs @@ -0,0 +1,231 @@ +using UnityEngine; + +namespace BezierSolution +{ + [AddComponentMenu( "Bezier Solution/Bezier Attachment" )] + [HelpURL( "https://github.com/yasirkula/UnityBezierSolution" )] + [ExecuteInEditMode] + public class BezierAttachment : MonoBehaviour + { + public enum RotationMode { No = 0, UseSplineNormals = 1, UseEndPointRotations = 2 }; + +#pragma warning disable 0649 + [SerializeField] + private BezierSpline m_spline; + public BezierSpline spline + { + get { return m_spline; } + set + { + if( m_spline != value ) + { + if( m_spline ) + m_spline.onSplineChanged -= OnSplineChanged; + + m_spline = value; + + if( m_spline && isActiveAndEnabled ) + { + m_spline.onSplineChanged -= OnSplineChanged; + m_spline.onSplineChanged += OnSplineChanged; + + OnSplineChanged( m_spline, DirtyFlags.All ); + } + } + } + } + + [SerializeField] + [Range( 0f, 1f )] + private float m_normalizedT = 0f; + public float normalizedT + { + get { return m_normalizedT; } + set + { + value = Mathf.Clamp01( value ); + + if( m_normalizedT != value ) + { + m_normalizedT = value; + + if( isActiveAndEnabled ) + OnSplineChanged( m_spline, DirtyFlags.All ); + } + } + } + + [Header( "Position" )] + [SerializeField] + private bool m_updatePosition = true; + public bool updatePosition + { + get { return m_updatePosition; } + set + { + if( m_updatePosition != value ) + { + m_updatePosition = value; + + if( m_updatePosition && isActiveAndEnabled ) + OnSplineChanged( m_spline, DirtyFlags.SplineShapeChanged ); + } + } + } + + [SerializeField] + private Vector3 m_positionOffset; + public Vector3 positionOffset + { + get { return m_positionOffset; } + set + { + if( m_positionOffset != value ) + { + m_positionOffset = value; + + if( m_updatePosition && isActiveAndEnabled ) + OnSplineChanged( m_spline, DirtyFlags.SplineShapeChanged ); + } + } + } + + [Header( "Rotation" )] + [SerializeField] + private RotationMode m_updateRotation = RotationMode.UseSplineNormals; + public RotationMode updateRotation + { + get { return m_updateRotation; } + set + { + if( m_updateRotation != value ) + { + m_updateRotation = value; + + if( m_updateRotation != RotationMode.No && isActiveAndEnabled ) + OnSplineChanged( m_spline, DirtyFlags.SplineShapeChanged ); + } + } + } + + [SerializeField] + private Vector3 m_rotationOffset; + public Vector3 rotationOffset + { + get { return m_rotationOffset; } + set + { + if( m_rotationOffset != value ) + { + m_rotationOffset = value; + + if( m_updateRotation != RotationMode.No && isActiveAndEnabled ) + OnSplineChanged( m_spline, DirtyFlags.SplineShapeChanged ); + } + } + } + +#if UNITY_EDITOR + [Header( "Other Settings" )] + [SerializeField] + private bool executeInEditMode = false; + + [SerializeField, HideInInspector] + private BezierSpline prevSpline; +#endif +#pragma warning restore 0649 + + private void OnEnable() + { + if( m_spline ) + { + m_spline.onSplineChanged -= OnSplineChanged; + m_spline.onSplineChanged += OnSplineChanged; + + OnSplineChanged( m_spline, DirtyFlags.All ); + } + } + + private void OnDisable() + { + if( m_spline ) + m_spline.onSplineChanged -= OnSplineChanged; + } + +#if UNITY_EDITOR + private void OnValidate() + { + UnityEditor.Undo.RecordObject( transform, "Modify BezierAttachment" ); + + BezierSpline _spline = m_spline; + m_spline = prevSpline; + spline = prevSpline = _spline; + + if( isActiveAndEnabled ) + OnSplineChanged( m_spline, DirtyFlags.All ); + } + + private void LateUpdate() + { + if( transform.hasChanged ) + OnSplineChanged( m_spline, DirtyFlags.All ); + } +#endif + + private void OnSplineChanged( BezierSpline spline, DirtyFlags dirtyFlags ) + { +#if UNITY_EDITOR + if( !executeInEditMode && !UnityEditor.EditorApplication.isPlaying ) + return; +#endif + + RefreshInternal( dirtyFlags ); + } + + public void Refresh() + { + RefreshInternal( DirtyFlags.All ); + } + + private void RefreshInternal( DirtyFlags dirtyFlags ) + { + if( !m_spline || m_spline.Count < 2 ) + return; + + if( !m_updatePosition && m_updateRotation == RotationMode.No ) + return; + + BezierSpline.Segment segment = m_spline.GetSegmentAt( m_normalizedT ); + + switch( m_updateRotation ) + { + case RotationMode.UseSplineNormals: + if( m_rotationOffset == Vector3.zero ) + transform.rotation = Quaternion.LookRotation( segment.GetTangent(), segment.GetNormal() ); + else + transform.rotation = Quaternion.LookRotation( segment.GetTangent(), segment.GetNormal() ) * Quaternion.Euler( m_rotationOffset ); + + break; + case RotationMode.UseEndPointRotations: + if( m_rotationOffset == Vector3.zero ) + transform.rotation = Quaternion.LerpUnclamped( segment.point1.rotation, segment.point2.rotation, segment.localT ); + else + transform.rotation = Quaternion.LerpUnclamped( segment.point1.rotation, segment.point2.rotation, segment.localT ) * Quaternion.Euler( m_rotationOffset ); + + break; + } + + if( m_updatePosition && ( dirtyFlags & DirtyFlags.SplineShapeChanged ) == DirtyFlags.SplineShapeChanged ) + { + if( m_positionOffset == Vector3.zero ) + transform.position = segment.GetPoint(); + else + transform.position = segment.GetPoint() + transform.rotation * m_positionOffset; + } + +#if UNITY_EDITOR + transform.hasChanged = false; +#endif + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/BezierSolution/Utilities/BezierAttachment.cs.meta b/Assets/Plugins/BezierSolution/Utilities/BezierAttachment.cs.meta new file mode 100644 index 00000000..f178cb3f --- /dev/null +++ b/Assets/Plugins/BezierSolution/Utilities/BezierAttachment.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 9b6258aafd9a87344833937e5e546638 +timeCreated: 1620400687 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/BezierSolution/Utilities/BezierLineRenderer.cs b/Assets/Plugins/BezierSolution/Utilities/BezierLineRenderer.cs new file mode 100644 index 00000000..27154b01 --- /dev/null +++ b/Assets/Plugins/BezierSolution/Utilities/BezierLineRenderer.cs @@ -0,0 +1,206 @@ +using UnityEngine; + +namespace BezierSolution +{ + [AddComponentMenu( "Bezier Solution/Bezier Line Renderer" )] + [HelpURL( "https://github.com/yasirkula/UnityBezierSolution" )] + [RequireComponent( typeof( LineRenderer ) )] + [ExecuteInEditMode] + public class BezierLineRenderer : MonoBehaviour + { +#pragma warning disable 0649 + [SerializeField] + private BezierSpline m_spline; + public BezierSpline spline + { + get { return m_spline; } + set + { + if( m_spline != value ) + { + if( m_spline ) + m_spline.onSplineChanged -= OnSplineChanged; + + m_spline = value; + + if( m_spline && isActiveAndEnabled ) + { + m_spline.onSplineChanged -= OnSplineChanged; + m_spline.onSplineChanged += OnSplineChanged; + + OnSplineChanged( m_spline, DirtyFlags.All ); + } + } + } + } + + [SerializeField] + [MinMaxRange( 0f, 1f )] + private Vector2 m_splineSampleRange = new Vector2( 0f, 1f ); + public Vector2 SplineSampleRange + { + get { return m_splineSampleRange; } + set + { + value.x = Mathf.Clamp01( value.x ); + value.y = Mathf.Clamp01( value.y ); + + if( m_splineSampleRange != value ) + { + m_splineSampleRange = value; + + if( isActiveAndEnabled ) + OnSplineChanged( m_spline, DirtyFlags.All ); + } + } + } + + [Header( "Line Options" )] + [SerializeField] + [Range( 0, 30 )] + private int m_smoothness = 5; + public int smoothness + { + get { return m_smoothness; } + set + { + if( m_smoothness != value ) + { + m_smoothness = value; + + if( isActiveAndEnabled ) + OnSplineChanged( m_spline, DirtyFlags.All ); + } + } + } + +#if UNITY_EDITOR + [Header( "Other Settings" )] + [SerializeField] + private bool executeInEditMode = false; + + [SerializeField, HideInInspector] + private BezierSpline prevSpline; +#endif +#pragma warning restore 0649 + + private LineRenderer lineRenderer; + private Vector3[] lineRendererPoints; +#if UNITY_EDITOR + private bool lineRendererUseWorldSpace = true; +#endif + + private void OnEnable() + { + if( m_spline ) + { + m_spline.onSplineChanged -= OnSplineChanged; + m_spline.onSplineChanged += OnSplineChanged; + + OnSplineChanged( m_spline, DirtyFlags.All ); + } + } + + private void OnDisable() + { + if( m_spline ) + m_spline.onSplineChanged -= OnSplineChanged; + } + +#if UNITY_EDITOR + private void Update() + { + if( lineRenderer && lineRenderer.useWorldSpace != lineRendererUseWorldSpace ) + { + lineRendererUseWorldSpace = !lineRendererUseWorldSpace; + + if( isActiveAndEnabled ) + OnSplineChanged( m_spline, DirtyFlags.All ); + } + } + + private void OnValidate() + { + BezierSpline _spline = m_spline; + m_spline = prevSpline; + spline = prevSpline = _spline; + + if( isActiveAndEnabled ) + OnSplineChanged( m_spline, DirtyFlags.All ); + } +#endif + + private void OnSplineChanged( BezierSpline spline, DirtyFlags dirtyFlags ) + { +#if UNITY_EDITOR + if( !executeInEditMode && !UnityEditor.EditorApplication.isPlaying ) + return; +#endif + + if( ( dirtyFlags & DirtyFlags.SplineShapeChanged ) == DirtyFlags.SplineShapeChanged ) + Refresh( m_smoothness ); + } + + public void Refresh( int smoothness ) + { + if( !m_spline || m_spline.Count < 2 ) + return; + + if( !lineRenderer ) + lineRenderer = GetComponent(); + + smoothness = Mathf.Clamp( smoothness, 1, 30 ); + + int numberOfPoints = ( m_spline.Count - 1 ) * smoothness; + if( !m_spline.loop ) + numberOfPoints++; // spline.GetPoint( 1f ) + else + numberOfPoints += smoothness; // Final point is connected to the first point via lineRenderer.loop, so no "numberOfPoints++" here + + if( lineRendererPoints == null || lineRendererPoints.Length != numberOfPoints ) + lineRendererPoints = new Vector3[numberOfPoints]; + + if( m_splineSampleRange.x <= 0f && m_splineSampleRange.y >= 1f ) + { + int pointIndex = 0; + float smoothnessStep = 1f / smoothness; + for( int i = 0; i < m_spline.Count - 1; i++ ) + { + BezierSpline.Segment segment = new BezierSpline.Segment( m_spline[i], m_spline[i + 1], 0f ); + for( int j = 0; j < smoothness; j++, pointIndex++ ) + lineRendererPoints[pointIndex] = segment.GetPoint( j * smoothnessStep ); + } + + if( !m_spline.loop ) + lineRendererPoints[numberOfPoints - 1] = m_spline.GetPoint( 1f ); + else + { + BezierSpline.Segment segment = new BezierSpline.Segment( m_spline[m_spline.Count - 1], m_spline[0], 0f ); + for( int j = 0; j < smoothness; j++, pointIndex++ ) + lineRendererPoints[pointIndex] = segment.GetPoint( j * smoothnessStep ); + } + } + else + { + float smoothnessStep = ( m_splineSampleRange.y - m_splineSampleRange.x ) / ( numberOfPoints - 1 ); + for( int i = 0; i < numberOfPoints; i++ ) + lineRendererPoints[i] = spline.GetPoint( m_splineSampleRange.x + i * smoothnessStep ); + } + +#if UNITY_EDITOR + lineRendererUseWorldSpace = lineRenderer.useWorldSpace; +#endif + if( !lineRenderer.useWorldSpace ) + { + Vector3 initialPoint = m_spline.GetPoint( 0f ); + for( int i = 0; i < numberOfPoints; i++ ) + lineRendererPoints[i] -= initialPoint; + } + + lineRenderer.positionCount = lineRendererPoints.Length; + lineRenderer.SetPositions( lineRendererPoints ); + lineRenderer.loop = m_spline.loop && m_splineSampleRange.x <= 0f && m_splineSampleRange.y >= 1f; + + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/BezierSolution/Utilities/BezierLineRenderer.cs.meta b/Assets/Plugins/BezierSolution/Utilities/BezierLineRenderer.cs.meta new file mode 100644 index 00000000..82d9ffd7 --- /dev/null +++ b/Assets/Plugins/BezierSolution/Utilities/BezierLineRenderer.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 09bf7d81c21c8564abb7c13d3e848e94 +timeCreated: 1620206953 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/BezierSolution/Utilities/BezierWalker.cs b/Assets/Plugins/BezierSolution/Utilities/BezierWalker.cs new file mode 100644 index 00000000..479d2729 --- /dev/null +++ b/Assets/Plugins/BezierSolution/Utilities/BezierWalker.cs @@ -0,0 +1,23 @@ +using UnityEngine; + +namespace BezierSolution +{ + public enum TravelMode { Once = 0, Loop = 1, PingPong = 2 }; + public enum LookAtMode { None = 0, Forward = 1, SplineExtraData = 2 } + + public abstract class BezierWalker : MonoBehaviour + { + public abstract BezierSpline Spline { get; } + public abstract bool MovingForward { get; } + public abstract float NormalizedT { get; set; } + + public abstract void Execute( float deltaTime ); + + public static readonly ExtraDataLerpFunction extraDataLerpAsQuaternionFunction = InterpolateExtraDataAsQuaternion; + + private static BezierPoint.ExtraData InterpolateExtraDataAsQuaternion( BezierPoint.ExtraData data1, BezierPoint.ExtraData data2, float normalizedT ) + { + return Quaternion.LerpUnclamped( data1, data2, normalizedT ); + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/BezierSolution/Utilities/BezierWalker.cs.meta b/Assets/Plugins/BezierSolution/Utilities/BezierWalker.cs.meta new file mode 100644 index 00000000..f6316c56 --- /dev/null +++ b/Assets/Plugins/BezierSolution/Utilities/BezierWalker.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 2e3fd6f386de3644ba3090712795517d +timeCreated: 1542623772 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/BezierSolution/Utilities/BezierWalkerLocomotion.cs b/Assets/Plugins/BezierSolution/Utilities/BezierWalkerLocomotion.cs new file mode 100644 index 00000000..e0fc799a --- /dev/null +++ b/Assets/Plugins/BezierSolution/Utilities/BezierWalkerLocomotion.cs @@ -0,0 +1,155 @@ +using System.Collections.Generic; +using UnityEngine; + +namespace BezierSolution +{ + [AddComponentMenu( "Bezier Solution/Bezier Walker Locomotion" )] + [HelpURL( "https://github.com/yasirkula/UnityBezierSolution" )] + public class BezierWalkerLocomotion : BezierWalker + { + public BezierWalker walker; + +#pragma warning disable 0649 + [SerializeField] + private List tailObjects; + public List Tail { get { return tailObjects; } } + + [SerializeField] + private List tailObjectDistances; + public List TailDistances { get { return tailObjectDistances; } } +#pragma warning restore 0649 + + public bool highQuality = true; // true by default because when it is set to false, tail objects can jitter too much + + public float movementLerpModifier = 10f; + public float rotationLerpModifier = 10f; + + public LookAtMode lookAt = LookAtMode.Forward; + + public override BezierSpline Spline { get { return walker.Spline; } } + public override bool MovingForward { get { return walker.MovingForward; } } + public override float NormalizedT + { + get { return walker.NormalizedT; } + set { walker.NormalizedT = value; } + } + + private void Start() + { + if( !walker ) + { + Debug.LogError( "Need to attach BezierWalkerLocomotion to a BezierWalker!" ); + Destroy( this ); + } + + if( tailObjects.Count != tailObjectDistances.Count ) + { + Debug.LogError( "One distance per tail object is needed!" ); + Destroy( this ); + } + } + + private void LateUpdate() + { + Execute( Time.deltaTime ); + } + + public override void Execute( float deltaTime ) + { + BezierSpline spline = Spline; + float t = highQuality ? spline.evenlySpacedPoints.GetPercentageAtNormalizedT( NormalizedT ) : NormalizedT; + bool forward = MovingForward; + + for( int i = 0; i < tailObjects.Count; i++ ) + { + Transform tailObject = tailObjects[i]; + Vector3 tailPosition; + float tailNormalizedT; + if( highQuality ) + { + if( forward ) + t -= tailObjectDistances[i] / spline.evenlySpacedPoints.splineLength; + else + t += tailObjectDistances[i] / spline.evenlySpacedPoints.splineLength; + + tailNormalizedT = spline.evenlySpacedPoints.GetNormalizedTAtPercentage( t ); + tailPosition = spline.GetPoint( tailNormalizedT ); + } + else + { + tailPosition = spline.MoveAlongSpline( ref t, forward ? -tailObjectDistances[i] : tailObjectDistances[i] ); + tailNormalizedT = t; + } + + tailObject.position = Vector3.Lerp( tailObject.position, tailPosition, movementLerpModifier * deltaTime ); + + if( lookAt == LookAtMode.Forward ) + { + BezierSpline.Segment segment = spline.GetSegmentAt( tailNormalizedT ); + tailObject.rotation = Quaternion.Lerp( tailObject.rotation, Quaternion.LookRotation( forward ? segment.GetTangent() : -segment.GetTangent(), segment.GetNormal() ), rotationLerpModifier * deltaTime ); + } + else if( lookAt == LookAtMode.SplineExtraData ) + tailObject.rotation = Quaternion.Lerp( tailObject.rotation, spline.GetExtraData( tailNormalizedT, extraDataLerpAsQuaternionFunction ), rotationLerpModifier * deltaTime ); + } + } + + public void AddToTail( Transform transform, float distanceToPreviousObject ) + { + if( transform == null ) + { + Debug.LogError( "Object is null!" ); + return; + } + + tailObjects.Add( transform ); + tailObjectDistances.Add( distanceToPreviousObject ); + } + + public void InsertIntoTail( int index, Transform transform, float distanceToPreviousObject ) + { + if( transform == null ) + { + Debug.LogError( "Object is null!" ); + return; + } + + tailObjects.Insert( index, transform ); + tailObjectDistances.Insert( index, distanceToPreviousObject ); + } + + public void RemoveFromTail( Transform transform ) + { + if( transform == null ) + { + Debug.LogError( "Object is null!" ); + return; + } + + for( int i = 0; i < tailObjects.Count; i++ ) + { + if( tailObjects[i] == transform ) + { + tailObjects.RemoveAt( i ); + tailObjectDistances.RemoveAt( i ); + + return; + } + } + } + +#if UNITY_EDITOR + private void Reset() + { + BezierWalker[] walkerComponents = GetComponents(); + for( int i = 0; i < walkerComponents.Length; i++ ) + { + if( !( walkerComponents[i] is BezierWalkerLocomotion ) && ( (MonoBehaviour) walkerComponents[i] ).enabled ) + { + walker = walkerComponents[i]; + break; + } + } + } +#endif + } +} \ No newline at end of file diff --git a/Assets/Plugins/BezierSolution/Utilities/BezierWalkerLocomotion.cs.meta b/Assets/Plugins/BezierSolution/Utilities/BezierWalkerLocomotion.cs.meta new file mode 100644 index 00000000..569606f2 --- /dev/null +++ b/Assets/Plugins/BezierSolution/Utilities/BezierWalkerLocomotion.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 17b675957a920ef4e8da909ede6d0d04 +timeCreated: 1542623444 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/BezierSolution/Utilities/BezierWalkerWithSpeed.cs b/Assets/Plugins/BezierSolution/Utilities/BezierWalkerWithSpeed.cs new file mode 100644 index 00000000..277fe1dc --- /dev/null +++ b/Assets/Plugins/BezierSolution/Utilities/BezierWalkerWithSpeed.cs @@ -0,0 +1,126 @@ +using UnityEngine; +using UnityEngine.Events; + +namespace BezierSolution +{ + [AddComponentMenu( "Bezier Solution/Bezier Walker With Speed" )] + [HelpURL( "https://github.com/yasirkula/UnityBezierSolution" )] + public class BezierWalkerWithSpeed : BezierWalker + { + public BezierSpline spline; + public TravelMode travelMode; + + public float speed = 5f; + [SerializeField] + [Range( 0f, 1f )] + private float m_normalizedT = 0f; + + public override BezierSpline Spline { get { return spline; } } + + public override float NormalizedT + { + get { return m_normalizedT; } + set { m_normalizedT = value; } + } + + //public float movementLerpModifier = 10f; + public float rotationLerpModifier = 10f; + + public LookAtMode lookAt = LookAtMode.Forward; + + private bool isGoingForward = true; + public override bool MovingForward { get { return ( speed > 0f ) == isGoingForward; } } + + public UnityEvent onPathCompleted = new UnityEvent(); + private bool onPathCompletedCalledAt1 = false; + private bool onPathCompletedCalledAt0 = false; + + private void Update() + { + Execute( Time.deltaTime ); + } + + public override void Execute( float deltaTime ) + { + float targetSpeed = ( isGoingForward ) ? speed : -speed; + + Vector3 targetPos = spline.MoveAlongSpline( ref m_normalizedT, targetSpeed * deltaTime ); + + transform.position = targetPos; + //transform.position = Vector3.Lerp( transform.position, targetPos, movementLerpModifier * deltaTime ); + + bool movingForward = MovingForward; + + if( lookAt == LookAtMode.Forward ) + { + BezierSpline.Segment segment = spline.GetSegmentAt( m_normalizedT ); + Quaternion targetRotation; + if( movingForward ) + targetRotation = Quaternion.LookRotation( segment.GetTangent(), segment.GetNormal() ); + else + targetRotation = Quaternion.LookRotation( -segment.GetTangent(), segment.GetNormal() ); + + transform.rotation = Quaternion.Lerp( transform.rotation, targetRotation, rotationLerpModifier * deltaTime ); + } + else if( lookAt == LookAtMode.SplineExtraData ) + transform.rotation = Quaternion.Lerp( transform.rotation, spline.GetExtraData( m_normalizedT, extraDataLerpAsQuaternionFunction ), rotationLerpModifier * deltaTime ); + + if( movingForward ) + { + if( m_normalizedT >= 1f ) + { + if( travelMode == TravelMode.Once ) + m_normalizedT = 1f; + else if( travelMode == TravelMode.Loop ) + m_normalizedT -= 1f; + else + { + m_normalizedT = 2f - m_normalizedT; + isGoingForward = !isGoingForward; + } + + if( !onPathCompletedCalledAt1 ) + { + onPathCompletedCalledAt1 = true; +#if UNITY_EDITOR + if( UnityEditor.EditorApplication.isPlaying ) +#endif + onPathCompleted.Invoke(); + } + } + else + { + onPathCompletedCalledAt1 = false; + } + } + else + { + if( m_normalizedT <= 0f ) + { + if( travelMode == TravelMode.Once ) + m_normalizedT = 0f; + else if( travelMode == TravelMode.Loop ) + m_normalizedT += 1f; + else + { + m_normalizedT = -m_normalizedT; + isGoingForward = !isGoingForward; + } + + if( !onPathCompletedCalledAt0 ) + { + onPathCompletedCalledAt0 = true; +#if UNITY_EDITOR + if( UnityEditor.EditorApplication.isPlaying ) +#endif + onPathCompleted.Invoke(); + } + } + else + { + onPathCompletedCalledAt0 = false; + } + } + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/BezierSolution/Utilities/BezierWalkerWithSpeed.cs.meta b/Assets/Plugins/BezierSolution/Utilities/BezierWalkerWithSpeed.cs.meta new file mode 100644 index 00000000..3662dcb3 --- /dev/null +++ b/Assets/Plugins/BezierSolution/Utilities/BezierWalkerWithSpeed.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 148310ac13c958d4c93f53cdfe985375 +timeCreated: 1473251134 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/BezierSolution/Utilities/BezierWalkerWithTime.cs b/Assets/Plugins/BezierSolution/Utilities/BezierWalkerWithTime.cs new file mode 100644 index 00000000..7f4dfab7 --- /dev/null +++ b/Assets/Plugins/BezierSolution/Utilities/BezierWalkerWithTime.cs @@ -0,0 +1,127 @@ +using UnityEngine; +using UnityEngine.Events; + +namespace BezierSolution +{ + [AddComponentMenu( "Bezier Solution/Bezier Walker With Time" )] + [HelpURL( "https://github.com/yasirkula/UnityBezierSolution" )] + public class BezierWalkerWithTime : BezierWalker + { + public BezierSpline spline; + public TravelMode travelMode; + + public float travelTime = 5f; + [SerializeField] + [Range( 0f, 1f )] + private float m_normalizedT = 0f; + + public bool highQuality = false; + + public override BezierSpline Spline { get { return spline; } } + + public override float NormalizedT + { + get { return m_normalizedT; } + set { m_normalizedT = value; } + } + + public float movementLerpModifier = 10f; + public float rotationLerpModifier = 10f; + + public LookAtMode lookAt = LookAtMode.Forward; + + private bool isGoingForward = true; + public override bool MovingForward { get { return isGoingForward; } } + + public UnityEvent onPathCompleted = new UnityEvent(); + private bool onPathCompletedCalledAt1 = false; + private bool onPathCompletedCalledAt0 = false; + + private void Update() + { + Execute( Time.deltaTime ); + } + + public override void Execute( float deltaTime ) + { + float _normalizedT = highQuality ? spline.evenlySpacedPoints.GetNormalizedTAtPercentage( m_normalizedT ) : m_normalizedT; + + transform.position = Vector3.Lerp( transform.position, spline.GetPoint( _normalizedT ), movementLerpModifier * deltaTime ); + + if( lookAt == LookAtMode.Forward ) + { + BezierSpline.Segment segment = spline.GetSegmentAt( _normalizedT ); + Quaternion targetRotation; + if( isGoingForward ) + targetRotation = Quaternion.LookRotation( segment.GetTangent(), segment.GetNormal() ); + else + targetRotation = Quaternion.LookRotation( -segment.GetTangent(), segment.GetNormal() ); + + transform.rotation = Quaternion.Lerp( transform.rotation, targetRotation, rotationLerpModifier * deltaTime ); + } + else if( lookAt == LookAtMode.SplineExtraData ) + transform.rotation = Quaternion.Lerp( transform.rotation, spline.GetExtraData( _normalizedT, extraDataLerpAsQuaternionFunction ), rotationLerpModifier * deltaTime ); + + if( isGoingForward ) + { + m_normalizedT += deltaTime / travelTime; + + if( m_normalizedT > 1f ) + { + if( travelMode == TravelMode.Once ) + m_normalizedT = 1f; + else if( travelMode == TravelMode.Loop ) + m_normalizedT -= 1f; + else + { + m_normalizedT = 2f - m_normalizedT; + isGoingForward = false; + } + + if( !onPathCompletedCalledAt1 ) + { + onPathCompletedCalledAt1 = true; +#if UNITY_EDITOR + if( UnityEditor.EditorApplication.isPlaying ) +#endif + onPathCompleted.Invoke(); + } + } + else + { + onPathCompletedCalledAt1 = false; + } + } + else + { + m_normalizedT -= deltaTime / travelTime; + + if( m_normalizedT < 0f ) + { + if( travelMode == TravelMode.Once ) + m_normalizedT = 0f; + else if( travelMode == TravelMode.Loop ) + m_normalizedT += 1f; + else + { + m_normalizedT = -m_normalizedT; + isGoingForward = true; + } + + if( !onPathCompletedCalledAt0 ) + { + onPathCompletedCalledAt0 = true; +#if UNITY_EDITOR + if( UnityEditor.EditorApplication.isPlaying ) +#endif + onPathCompleted.Invoke(); + } + } + else + { + onPathCompletedCalledAt0 = false; + } + } + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/BezierSolution/Utilities/BezierWalkerWithTime.cs.meta b/Assets/Plugins/BezierSolution/Utilities/BezierWalkerWithTime.cs.meta new file mode 100644 index 00000000..c66590a8 --- /dev/null +++ b/Assets/Plugins/BezierSolution/Utilities/BezierWalkerWithTime.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 46d12b9f97514694e962a3395a73e638 +timeCreated: 1473251134 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Plugins/BezierSolution/Utilities/ParticlesFollowBezier.cs b/Assets/Plugins/BezierSolution/Utilities/ParticlesFollowBezier.cs new file mode 100644 index 00000000..fefa1dff --- /dev/null +++ b/Assets/Plugins/BezierSolution/Utilities/ParticlesFollowBezier.cs @@ -0,0 +1,106 @@ +using System.Collections.Generic; +using UnityEngine; + +namespace BezierSolution +{ + [AddComponentMenu( "Bezier Solution/Particles Follow Bezier" )] + [HelpURL( "https://github.com/yasirkula/UnityBezierSolution" )] + [RequireComponent( typeof( ParticleSystem ) )] + [ExecuteInEditMode] + public class ParticlesFollowBezier : MonoBehaviour + { + private const int MAX_PARTICLE_COUNT = 25000; + + public enum FollowMode { Relaxed, Strict }; + + public BezierSpline spline; + public FollowMode followMode = FollowMode.Relaxed; + + private Transform cachedTransform; + private ParticleSystem cachedPS; + private ParticleSystem.MainModule cachedMainModule; + + private ParticleSystem.Particle[] particles; + private List particleData; + + private void Awake() + { + cachedTransform = transform; + cachedPS = GetComponent(); + + cachedMainModule = cachedPS.main; + particles = new ParticleSystem.Particle[cachedMainModule.maxParticles]; + + if( followMode == FollowMode.Relaxed ) + particleData = new List( particles.Length ); + } + +#if UNITY_EDITOR + private void OnEnable() + { + Awake(); + } +#endif + +#if UNITY_EDITOR + private void LateUpdate() + { + if( !UnityEditor.EditorApplication.isPlaying ) + FixedUpdate(); + } +#endif + + private void FixedUpdate() + { + if( spline == null || cachedPS == null ) + return; + + if( particles.Length < cachedMainModule.maxParticles && particles.Length < MAX_PARTICLE_COUNT ) + System.Array.Resize( ref particles, Mathf.Min( cachedMainModule.maxParticles, MAX_PARTICLE_COUNT ) ); + + bool isLocalSpace = cachedMainModule.simulationSpace != ParticleSystemSimulationSpace.World; + int aliveParticles = cachedPS.GetParticles( particles ); + + Vector3 initialPoint = spline.GetPoint( 0f ); + if( followMode == FollowMode.Relaxed ) + { + if( particleData == null ) + particleData = new List( particles.Length ); + + cachedPS.GetCustomParticleData( particleData, ParticleSystemCustomData.Custom1 ); + + // Credit: https://forum.unity3d.com/threads/access-to-the-particle-system-lifecycle-events.328918/#post-2295977 + for( int i = 0; i < aliveParticles; i++ ) + { + Vector4 particleDat = particleData[i]; + Vector3 point = spline.GetPoint( 1f - ( particles[i].remainingLifetime / particles[i].startLifetime ) ); + if( !isLocalSpace ) + point = cachedTransform.TransformPoint( point - initialPoint ); + + // Move particles alongside the spline + if( particleDat.w != 0f ) + particles[i].position += point - (Vector3) particleDat; + + particleDat = point; + particleDat.w = 1f; + particleData[i] = particleDat; + } + + cachedPS.SetCustomParticleData( particleData, ParticleSystemCustomData.Custom1 ); + } + else + { + for( int i = 0; i < aliveParticles; i++ ) + { + Vector3 point = spline.GetPoint( 1f - ( particles[i].remainingLifetime / particles[i].startLifetime ) ) - initialPoint; + if( !isLocalSpace ) + point = cachedTransform.TransformPoint( point ); + + particles[i].position = point; + } + } + + cachedPS.SetParticles( particles, aliveParticles ); + } + } +} \ No newline at end of file diff --git a/Assets/Plugins/BezierSolution/Utilities/ParticlesFollowBezier.cs.meta b/Assets/Plugins/BezierSolution/Utilities/ParticlesFollowBezier.cs.meta new file mode 100644 index 00000000..2cd51ab6 --- /dev/null +++ b/Assets/Plugins/BezierSolution/Utilities/ParticlesFollowBezier.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 954f54b0dafe0cf488e4e15934cae013 +timeCreated: 1510521621 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Resources/Games/spaceSoccer.prefab b/Assets/Resources/Games/spaceSoccer.prefab index 90969ffa..334adef4 100644 --- a/Assets/Resources/Games/spaceSoccer.prefab +++ b/Assets/Resources/Games/spaceSoccer.prefab @@ -29,7 +29,7 @@ Transform: m_LocalScale: {x: 17.777779, y: 10, z: 1} m_Children: [] m_Father: {fileID: 3584310800769874311} - m_RootOrder: 2 + m_RootOrder: 3 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!212 &5950750627008429748 SpriteRenderer: @@ -82,6 +82,88 @@ SpriteRenderer: m_WasSpriteAssigned: 1 m_MaskInteraction: 0 m_SpriteSortPoint: 0 +--- !u!1 &126459604059149218 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 2597336706312687925} + - component: {fileID: 1594801102112547458} + m_Layer: 0 + m_Name: Head + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &2597336706312687925 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 126459604059149218} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 2.733, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 4741428524146264548} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!212 &1594801102112547458 +SpriteRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 126459604059149218} + m_Enabled: 1 + m_CastShadows: 0 + m_ReceiveShadows: 0 + m_DynamicOccludee: 1 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_RayTracingMode: 0 + m_RayTraceProcedural: 0 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 10754, guid: 0000000000000000f000000000000000, type: 0} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_ReceiveGI: 1 + m_PreserveUVs: 0 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_StitchLightmapSeams: 1 + m_SelectedEditorRenderState: 0 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: 5 + m_Sprite: {fileID: -4901794926734046506, guid: ed47c3fa4e916ff478c0f1b6fb057aa4, type: 3} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_FlipX: 0 + m_FlipY: 0 + m_DrawMode: 0 + m_Size: {x: 2.8695652, y: 2.8695652} + m_AdaptiveModeThreshold: 0.5 + m_SpriteTileMode: 0 + m_WasSpriteAssigned: 1 + m_MaskInteraction: 0 + m_SpriteSortPoint: 0 --- !u!1 &257854180901420889 GameObject: m_ObjectHideFlags: 0 @@ -329,6 +411,88 @@ SpriteRenderer: m_WasSpriteAssigned: 1 m_MaskInteraction: 0 m_SpriteSortPoint: 0 +--- !u!1 &513974513029822140 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 5800452789097860970} + - component: {fileID: 5271445086610401838} + m_Layer: 0 + m_Name: Hand + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &5800452789097860970 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 513974513029822140} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: -0.466, y: -1.285, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 1112741999930566093} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!212 &5271445086610401838 +SpriteRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 513974513029822140} + m_Enabled: 1 + m_CastShadows: 0 + m_ReceiveShadows: 0 + m_DynamicOccludee: 1 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_RayTracingMode: 0 + m_RayTraceProcedural: 0 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 10754, guid: 0000000000000000f000000000000000, type: 0} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_ReceiveGI: 1 + m_PreserveUVs: 0 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_StitchLightmapSeams: 1 + m_SelectedEditorRenderState: 0 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: 6 + m_Sprite: {fileID: -8520199780486872010, guid: ed47c3fa4e916ff478c0f1b6fb057aa4, type: 3} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_FlipX: 0 + m_FlipY: 0 + m_DrawMode: 0 + m_Size: {x: 0.9782609, y: 2.8913043} + m_AdaptiveModeThreshold: 0.5 + m_SpriteTileMode: 0 + m_WasSpriteAssigned: 1 + m_MaskInteraction: 0 + m_SpriteSortPoint: 0 --- !u!1 &846200884479471224 GameObject: m_ObjectHideFlags: 0 @@ -376,6 +540,89 @@ MonoBehaviour: handleType: 0 leftHandleLocalPosition: {x: -1.668371, y: 12.237039, z: 0} rightHandleLocalPosition: {x: 1.668371, y: -12.237039, z: -0} +--- !u!1 &1186670969632253619 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1112741999930566093} + - component: {fileID: 4606031668259690326} + m_Layer: 0 + m_Name: LeftArm + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &1112741999930566093 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1186670969632253619} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0.29, y: 0.41, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: + - {fileID: 5800452789097860970} + m_Father: {fileID: 4741428524146264548} + m_RootOrder: 3 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!212 &4606031668259690326 +SpriteRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1186670969632253619} + m_Enabled: 1 + m_CastShadows: 0 + m_ReceiveShadows: 0 + m_DynamicOccludee: 1 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_RayTracingMode: 0 + m_RayTraceProcedural: 0 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 10754, guid: 0000000000000000f000000000000000, type: 0} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_ReceiveGI: 1 + m_PreserveUVs: 0 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_StitchLightmapSeams: 1 + m_SelectedEditorRenderState: 0 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: 5 + m_Sprite: {fileID: 4622036528870278122, guid: ed47c3fa4e916ff478c0f1b6fb057aa4, type: 3} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_FlipX: 0 + m_FlipY: 0 + m_DrawMode: 0 + m_Size: {x: 0.9782609, y: 2.8913043} + m_AdaptiveModeThreshold: 0.5 + m_SpriteTileMode: 0 + m_WasSpriteAssigned: 1 + m_MaskInteraction: 0 + m_SpriteSortPoint: 0 --- !u!1 &1349843762207368530 GameObject: m_ObjectHideFlags: 0 @@ -392,7 +639,7 @@ GameObject: m_Icon: {fileID: 0} m_NavMeshLayer: 0 m_StaticEditorFlags: 0 - m_IsActive: 1 + m_IsActive: 0 --- !u!4 &1867556290772299826 Transform: m_ObjectHideFlags: 0 @@ -407,7 +654,7 @@ Transform: - {fileID: 7081006468625576063} - {fileID: 7261590481062326926} m_Father: {fileID: 6448989353494316845} - m_RootOrder: 4 + m_RootOrder: 3 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!114 &8336007186072323660 MonoBehaviour: @@ -445,7 +692,7 @@ GameObject: m_Icon: {fileID: 0} m_NavMeshLayer: 0 m_StaticEditorFlags: 0 - m_IsActive: 1 + m_IsActive: 0 --- !u!4 &1919782781487675894 Transform: m_ObjectHideFlags: 0 @@ -460,7 +707,7 @@ Transform: - {fileID: 468275958178749560} - {fileID: 3613487704117567916} m_Father: {fileID: 6448989353494316845} - m_RootOrder: 3 + m_RootOrder: 2 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!114 &5471456891558289981 MonoBehaviour: @@ -822,7 +1069,7 @@ MonoBehaviour: handleType: 0 leftHandleLocalPosition: {x: -1.437256, y: 8.345654, z: 0} rightHandleLocalPosition: {x: 1.437256, y: -8.345654, z: -0} ---- !u!1 &2777969959294955712 +--- !u!1 &2462896292002896175 GameObject: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} @@ -830,51 +1077,179 @@ GameObject: m_PrefabAsset: {fileID: 0} serializedVersion: 6 m_Component: - - component: {fileID: 2353202814549098793} - - component: {fileID: 6429945450899169262} + - component: {fileID: 2164813961289054792} + - component: {fileID: 3650667165709929962} m_Layer: 0 - m_Name: DispenseCurve + m_Name: Point 1 m_TagString: Untagged m_Icon: {fileID: 0} m_NavMeshLayer: 0 m_StaticEditorFlags: 0 m_IsActive: 1 ---- !u!4 &2353202814549098793 +--- !u!4 &2164813961289054792 Transform: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 2777969959294955712} - m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} - m_LocalPosition: {x: -2.78, y: -6.08, z: 0} + m_GameObject: {fileID: 2462896292002896175} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0.19491553, y: -4.016786, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} - m_Children: - - {fileID: 6801291441445583370} - - {fileID: 2366440973703065964} - m_Father: {fileID: 6448989353494316845} + m_Children: [] + m_Father: {fileID: 1240551230645966165} m_RootOrder: 1 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!114 &6429945450899169262 +--- !u!114 &3650667165709929962 MonoBehaviour: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 2777969959294955712} + m_GameObject: {fileID: 2462896292002896175} m_Enabled: 1 m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 066a41e004f415b4eb74d5e61a2aadbe, type: 3} + m_Script: {fileID: 11500000, guid: b0cca3244f403c24f819a870f31cdc29, type: 3} m_Name: m_EditorClassIdentifier: - curveColor: {r: 0, g: 1, b: 0, a: 1} - startPointColor: {r: 1, g: 0, b: 0, a: 1} - endPointColor: {r: 0, g: 0, b: 1, a: 1} - sampling: 25 - keyPoints: - - {fileID: 6595947080087458025} - - {fileID: 7957000915275159968} - normalizedTime: 0.5 + curve: {fileID: 5209060163867140866} + handleType: 0 + leftHandleLocalPosition: {x: -2.0985024, y: 13.181166, z: 0} + rightHandleLocalPosition: {x: 2.0985024, y: -13.181166, z: -0} +--- !u!1 &2645204244655293704 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 316676739078874036} + - component: {fileID: 8424307941362801760} + m_Layer: 0 + m_Name: SpaceKickerHolder (1) + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 0 +--- !u!4 &316676739078874036 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2645204244655293704} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: + - {fileID: 6367340212329602264} + m_Father: {fileID: 3584310800769874311} + m_RootOrder: 6 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!95 &8424307941362801760 +Animator: + serializedVersion: 3 + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 2645204244655293704} + m_Enabled: 1 + m_Avatar: {fileID: 0} + m_Controller: {fileID: 9100000, guid: 8c23103d97f33c64b9f025dcee60ae53, type: 2} + m_CullingMode: 0 + m_UpdateMode: 0 + m_ApplyRootMotion: 0 + m_LinearVelocityBlending: 0 + m_WarningMessage: + m_HasTransformHierarchy: 1 + m_AllowConstantClipSamplingOptimization: 1 + m_KeepAnimatorControllerStateOnDisable: 0 +--- !u!1 &3096634651814846373 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 5925726351136398731} + - component: {fileID: 1339328572081299005} + m_Layer: 0 + m_Name: RightArm + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &5925726351136398731 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 3096634651814846373} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: -0.84800005, y: 0.212, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: + - {fileID: 2478993094730025810} + m_Father: {fileID: 4741428524146264548} + m_RootOrder: 4 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!212 &1339328572081299005 +SpriteRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 3096634651814846373} + m_Enabled: 1 + m_CastShadows: 0 + m_ReceiveShadows: 0 + m_DynamicOccludee: 1 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_RayTracingMode: 0 + m_RayTraceProcedural: 0 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 10754, guid: 0000000000000000f000000000000000, type: 0} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_ReceiveGI: 1 + m_PreserveUVs: 0 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_StitchLightmapSeams: 1 + m_SelectedEditorRenderState: 0 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: -5 + m_Sprite: {fileID: 4622036528870278122, guid: ed47c3fa4e916ff478c0f1b6fb057aa4, type: 3} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_FlipX: 0 + m_FlipY: 0 + m_DrawMode: 0 + m_Size: {x: 0.9782609, y: 2.8913043} + m_AdaptiveModeThreshold: 0.5 + m_SpriteTileMode: 0 + m_WasSpriteAssigned: 1 + m_MaskInteraction: 0 + m_SpriteSortPoint: 0 --- !u!1 &3165868780509730864 GameObject: m_ObjectHideFlags: 0 @@ -904,7 +1279,7 @@ Transform: m_LocalScale: {x: 17.777779, y: 10, z: 1} m_Children: [] m_Father: {fileID: 3584310800769874311} - m_RootOrder: 1 + m_RootOrder: 2 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!212 &7523367628103144026 SpriteRenderer: @@ -1019,7 +1394,10 @@ MonoBehaviour: kickLeft: 0 dispenserBeat: 0 kickTimes: 0 + player: 0 ball: {fileID: 0} + rightLeg: {fileID: 0} + leftLeg: {fileID: 0} --- !u!95 &8083744449129749329 Animator: serializedVersion: 3 @@ -1070,7 +1448,7 @@ Transform: - {fileID: 5033391922196318299} - {fileID: 399794634660151948} m_Father: {fileID: 6448989353494316845} - m_RootOrder: 2 + m_RootOrder: 1 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!114 &1507665286932590801 MonoBehaviour: @@ -1174,6 +1552,170 @@ SpriteRenderer: m_WasSpriteAssigned: 1 m_MaskInteraction: 0 m_SpriteSortPoint: 0 +--- !u!1 &3412780235512967252 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 49380959276385573} + - component: {fileID: 4777463049816540825} + m_Layer: 0 + m_Name: LowerTorso + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &49380959276385573 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 3412780235512967252} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: -0.035000086, y: -0.847, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 4741428524146264548} + m_RootOrder: 2 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!212 &4777463049816540825 +SpriteRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 3412780235512967252} + m_Enabled: 1 + m_CastShadows: 0 + m_ReceiveShadows: 0 + m_DynamicOccludee: 1 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_RayTracingMode: 0 + m_RayTraceProcedural: 0 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 10754, guid: 0000000000000000f000000000000000, type: 0} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_ReceiveGI: 1 + m_PreserveUVs: 0 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_StitchLightmapSeams: 1 + m_SelectedEditorRenderState: 0 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: 0 + m_Sprite: {fileID: -1720273043946688001, guid: ed47c3fa4e916ff478c0f1b6fb057aa4, type: 3} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_FlipX: 0 + m_FlipY: 0 + m_DrawMode: 0 + m_Size: {x: 2.8695652, y: 2.8695652} + m_AdaptiveModeThreshold: 0.5 + m_SpriteTileMode: 0 + m_WasSpriteAssigned: 1 + m_MaskInteraction: 0 + m_SpriteSortPoint: 0 +--- !u!1 &3541833856435882186 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 2478993094730025810} + - component: {fileID: 6147503571173905877} + m_Layer: 0 + m_Name: Hand + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &2478993094730025810 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 3541833856435882186} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: -0.199, y: -0.968, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 5925726351136398731} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!212 &6147503571173905877 +SpriteRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 3541833856435882186} + m_Enabled: 1 + m_CastShadows: 0 + m_ReceiveShadows: 0 + m_DynamicOccludee: 1 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_RayTracingMode: 0 + m_RayTraceProcedural: 0 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 10754, guid: 0000000000000000f000000000000000, type: 0} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_ReceiveGI: 1 + m_PreserveUVs: 0 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_StitchLightmapSeams: 1 + m_SelectedEditorRenderState: 0 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: -4 + m_Sprite: {fileID: -764308301054040961, guid: ed47c3fa4e916ff478c0f1b6fb057aa4, type: 3} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_FlipX: 0 + m_FlipY: 0 + m_DrawMode: 0 + m_Size: {x: 0.9782609, y: 2.8913043} + m_AdaptiveModeThreshold: 0.5 + m_SpriteTileMode: 0 + m_WasSpriteAssigned: 1 + m_MaskInteraction: 0 + m_SpriteSortPoint: 0 --- !u!1 &3584310800769874308 GameObject: m_ObjectHideFlags: 0 @@ -1202,11 +1744,14 @@ Transform: m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} m_Children: + - {fileID: 5817910513783836992} - {fileID: 8782824659731654599} - {fileID: 1635378899211822444} - {fileID: 5569079104020273780} + - {fileID: 6448989353494316845} - {fileID: 1133941631262721853} - - {fileID: 5817910513783836992} + - {fileID: 316676739078874036} + - {fileID: 2021733110626493915} m_Father: {fileID: 0} m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} @@ -1225,12 +1770,95 @@ MonoBehaviour: EligibleHits: [] firstEnable: 0 ballRef: {fileID: 4170571896107082579} - kicker: {fileID: 2934863208182244691} + kickers: + - {fileID: 2934863208182244691} Background: {fileID: 7001609152551886569} backgroundSprite: - {fileID: -7443756053782179069, guid: 8a95e066b3562f64eb8ec3bcfe316752, type: 3} - {fileID: -3192133289119773823, guid: 8a95e066b3562f64eb8ec3bcfe316752, type: 3} ballDispensed: 0 +--- !u!1 &3903730068035578964 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 8114618383031241504} + - component: {fileID: 8087436512537505271} + m_Layer: 0 + m_Name: Platform + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &8114618383031241504 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 3903730068035578964} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: -0.364, y: -5.264, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 4741428524146264548} + m_RootOrder: 7 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!212 &8087436512537505271 +SpriteRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 3903730068035578964} + m_Enabled: 1 + m_CastShadows: 0 + m_ReceiveShadows: 0 + m_DynamicOccludee: 1 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_RayTracingMode: 0 + m_RayTraceProcedural: 0 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 10754, guid: 0000000000000000f000000000000000, type: 0} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_ReceiveGI: 1 + m_PreserveUVs: 0 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_StitchLightmapSeams: 1 + m_SelectedEditorRenderState: 0 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: 0 + m_Sprite: {fileID: -2652118799199010490, guid: ed47c3fa4e916ff478c0f1b6fb057aa4, type: 3} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_FlipX: 0 + m_FlipY: 0 + m_DrawMode: 0 + m_Size: {x: 2.98, y: 2.66} + m_AdaptiveModeThreshold: 0.5 + m_SpriteTileMode: 0 + m_WasSpriteAssigned: 1 + m_MaskInteraction: 0 + m_SpriteSortPoint: 0 --- !u!1 &3994873901200315503 GameObject: m_ObjectHideFlags: 0 @@ -1389,12 +2017,12 @@ Transform: m_LocalScale: {x: 1, y: 1, z: 1} m_Children: - {fileID: 2191273313861422334} - - {fileID: 2353202814549098793} - {fileID: 3207667626390582044} - {fileID: 1919782781487675894} - {fileID: 1867556290772299826} - m_Father: {fileID: 1133941631262721853} - m_RootOrder: 1 + - {fileID: 1240551230645966165} + m_Father: {fileID: 3584310800769874311} + m_RootOrder: 4 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!114 &6562488500519841852 MonoBehaviour: @@ -1411,7 +2039,8 @@ MonoBehaviour: kicker: {fileID: 2934863208182244691} holder: {fileID: 7976131226454805035} spriteHolder: {fileID: 6132156590540490080} - dispenseCurve: {fileID: 6429945450899169262} + kickFX: {fileID: 4365805729759623217} + dispenseCurve: {fileID: 5209060163867140866} kickCurve: {fileID: 1507665286932590801} highKickCurve: {fileID: 5471456891558289981} toeCurve: {fileID: 8336007186072323660} @@ -1419,6 +2048,102 @@ MonoBehaviour: dispensing: 0 hitTimes: 0 canKick: 0 +--- !u!1 &4365805729759623217 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 2021733110626493915} + - component: {fileID: 9095461183267835975} + - component: {fileID: 8422221005665590405} + m_Layer: 0 + m_Name: kickFX + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 0 +--- !u!4 &2021733110626493915 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4365805729759623217} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 1.67, y: -1.05, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 3584310800769874311} + m_RootOrder: 7 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!212 &9095461183267835975 +SpriteRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4365805729759623217} + m_Enabled: 1 + m_CastShadows: 0 + m_ReceiveShadows: 0 + m_DynamicOccludee: 1 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_RayTracingMode: 0 + m_RayTraceProcedural: 0 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 10754, guid: 0000000000000000f000000000000000, type: 0} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_ReceiveGI: 1 + m_PreserveUVs: 0 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_StitchLightmapSeams: 1 + m_SelectedEditorRenderState: 0 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: 9 + m_Sprite: {fileID: -6047660829741247071, guid: ed47c3fa4e916ff478c0f1b6fb057aa4, type: 3} + m_Color: {r: 1, g: 1, b: 1, a: 0.48235294} + m_FlipX: 0 + m_FlipY: 0 + m_DrawMode: 0 + m_Size: {x: 1, y: 1} + m_AdaptiveModeThreshold: 0.5 + m_SpriteTileMode: 0 + m_WasSpriteAssigned: 1 + m_MaskInteraction: 0 + m_SpriteSortPoint: 0 +--- !u!114 &8422221005665590405 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4365805729759623217} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 54588eb7ee0680643aeaf61dcf609903, type: 3} + m_Name: + m_EditorClassIdentifier: + time: 0.08 --- !u!1 &4407241422380325920 GameObject: m_ObjectHideFlags: 0 @@ -1501,6 +2226,44 @@ SpriteRenderer: m_WasSpriteAssigned: 1 m_MaskInteraction: 0 m_SpriteSortPoint: 0 +--- !u!1 &4419198583557123835 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 4741428524146264548} + m_Layer: 0 + m_Name: Holder + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &4741428524146264548 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 4419198583557123835} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: + - {fileID: 2597336706312687925} + - {fileID: 2980827159788922073} + - {fileID: 49380959276385573} + - {fileID: 1112741999930566093} + - {fileID: 5925726351136398731} + - {fileID: 8914157674764446515} + - {fileID: 2342595285577858197} + - {fileID: 8114618383031241504} + m_Father: {fileID: 6367340212329602264} + m_RootOrder: 1 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!1 &4832865564766322567 GameObject: m_ObjectHideFlags: 0 @@ -1536,6 +2299,7 @@ Transform: - {fileID: 3237786401105490046} - {fileID: 7610738728473273518} - {fileID: 4638361389140214827} + - {fileID: 9007446780794364221} m_Father: {fileID: 482351987616570803} m_RootOrder: 1 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} @@ -1568,7 +2332,7 @@ Transform: m_LocalScale: {x: 1, y: 1, z: 1} m_Children: [] m_Father: {fileID: 3584310800769874311} - m_RootOrder: 0 + m_RootOrder: 1 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!212 &1170956544158466603 SpriteRenderer: @@ -1785,6 +2549,88 @@ SpriteRenderer: m_WasSpriteAssigned: 1 m_MaskInteraction: 0 m_SpriteSortPoint: 0 +--- !u!1 &5476605465947111534 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 8914157674764446515} + - component: {fileID: 5052934216751376059} + m_Layer: 0 + m_Name: RightLeg + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &8914157674764446515 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 5476605465947111534} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: -0.702, y: -2.468, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 4741428524146264548} + m_RootOrder: 5 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!212 &5052934216751376059 +SpriteRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 5476605465947111534} + m_Enabled: 1 + m_CastShadows: 0 + m_ReceiveShadows: 0 + m_DynamicOccludee: 1 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_RayTracingMode: 0 + m_RayTraceProcedural: 0 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 10754, guid: 0000000000000000f000000000000000, type: 0} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_ReceiveGI: 1 + m_PreserveUVs: 0 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_StitchLightmapSeams: 1 + m_SelectedEditorRenderState: 0 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: 2 + m_Sprite: {fileID: 2628347725180641456, guid: ed47c3fa4e916ff478c0f1b6fb057aa4, type: 3} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_FlipX: 0 + m_FlipY: 0 + m_DrawMode: 0 + m_Size: {x: 2.8695652, y: 2.8695652} + m_AdaptiveModeThreshold: 0.5 + m_SpriteTileMode: 0 + m_WasSpriteAssigned: 1 + m_MaskInteraction: 0 + m_SpriteSortPoint: 0 --- !u!1 &5507516930464598683 GameObject: m_ObjectHideFlags: 0 @@ -1867,6 +2713,88 @@ SpriteRenderer: m_WasSpriteAssigned: 1 m_MaskInteraction: 0 m_SpriteSortPoint: 0 +--- !u!1 &5822757368502791924 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 9007446780794364221} + - component: {fileID: 155042501272231659} + m_Layer: 0 + m_Name: toeFX + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 0 +--- !u!4 &9007446780794364221 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 5822757368502791924} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: -1.49, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 7679098324972434340} + m_RootOrder: 8 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!212 &155042501272231659 +SpriteRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 5822757368502791924} + m_Enabled: 1 + m_CastShadows: 0 + m_ReceiveShadows: 0 + m_DynamicOccludee: 1 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_RayTracingMode: 0 + m_RayTraceProcedural: 0 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 10754, guid: 0000000000000000f000000000000000, type: 0} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_ReceiveGI: 1 + m_PreserveUVs: 0 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_StitchLightmapSeams: 1 + m_SelectedEditorRenderState: 0 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: 7 + m_Sprite: {fileID: -1664293819527379378, guid: ed47c3fa4e916ff478c0f1b6fb057aa4, type: 3} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_FlipX: 0 + m_FlipY: 0 + m_DrawMode: 0 + m_Size: {x: 1, y: 1} + m_AdaptiveModeThreshold: 0.5 + m_SpriteTileMode: 0 + m_WasSpriteAssigned: 1 + m_MaskInteraction: 0 + m_SpriteSortPoint: 0 --- !u!1 &6132156590540490080 GameObject: m_ObjectHideFlags: 0 @@ -1949,6 +2877,223 @@ SpriteRenderer: m_WasSpriteAssigned: 1 m_MaskInteraction: 0 m_SpriteSortPoint: 0 +--- !u!1 &6205346010011601170 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 2342595285577858197} + - component: {fileID: 1292735087548974339} + m_Layer: 0 + m_Name: LeftLeg + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &2342595285577858197 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 6205346010011601170} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0.04699993, y: -2.655, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 4741428524146264548} + m_RootOrder: 6 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!212 &1292735087548974339 +SpriteRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 6205346010011601170} + m_Enabled: 1 + m_CastShadows: 0 + m_ReceiveShadows: 0 + m_DynamicOccludee: 1 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_RayTracingMode: 0 + m_RayTraceProcedural: 0 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 10754, guid: 0000000000000000f000000000000000, type: 0} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_ReceiveGI: 1 + m_PreserveUVs: 0 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_StitchLightmapSeams: 1 + m_SelectedEditorRenderState: 0 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: 3 + m_Sprite: {fileID: 31104100975739196, guid: ed47c3fa4e916ff478c0f1b6fb057aa4, type: 3} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_FlipX: 0 + m_FlipY: 0 + m_DrawMode: 0 + m_Size: {x: 2.8695652, y: 2.8695652} + m_AdaptiveModeThreshold: 0.5 + m_SpriteTileMode: 0 + m_WasSpriteAssigned: 1 + m_MaskInteraction: 0 + m_SpriteSortPoint: 0 +--- !u!1 &6337537596710339609 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1240551230645966165} + - component: {fileID: 5209060163867140866} + m_Layer: 0 + m_Name: DispenseCurve + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &1240551230645966165 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 6337537596710339609} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 2.34, y: -2.1, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: + - {fileID: 7039114078560482225} + - {fileID: 2164813961289054792} + m_Father: {fileID: 6448989353494316845} + m_RootOrder: 4 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &5209060163867140866 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 6337537596710339609} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 066a41e004f415b4eb74d5e61a2aadbe, type: 3} + m_Name: + m_EditorClassIdentifier: + curveColor: {r: 0, g: 1, b: 0, a: 1} + startPointColor: {r: 1, g: 0, b: 0, a: 1} + endPointColor: {r: 0, g: 0, b: 1, a: 1} + sampling: 25 + keyPoints: + - {fileID: 2039331194922578974} + - {fileID: 3650667165709929962} + normalizedTime: 0.5 +--- !u!1 &6589086020994959743 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 2253978134027466150} + - component: {fileID: 7494481852734406023} + m_Layer: 0 + m_Name: Square (3) + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 0 +--- !u!4 &2253978134027466150 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 6589086020994959743} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: -3.384, y: 0, z: 0} + m_LocalScale: {x: 2, y: 2, z: 1} + m_Children: [] + m_Father: {fileID: 6367340212329602264} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!212 &7494481852734406023 +SpriteRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 6589086020994959743} + m_Enabled: 1 + m_CastShadows: 0 + m_ReceiveShadows: 0 + m_DynamicOccludee: 1 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_RayTracingMode: 0 + m_RayTraceProcedural: 0 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 10754, guid: 0000000000000000f000000000000000, type: 0} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_ReceiveGI: 1 + m_PreserveUVs: 0 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_StitchLightmapSeams: 1 + m_SelectedEditorRenderState: 0 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: 171 + m_Sprite: {fileID: 21300000, guid: 1b0659d8d10ac0949a0827538b1ca2fd, type: 3} + m_Color: {r: 0.72156864, g: 0.53333336, b: 0.9725491, a: 0.4627451} + m_FlipX: 0 + m_FlipY: 0 + m_DrawMode: 0 + m_Size: {x: 1, y: 1} + m_AdaptiveModeThreshold: 0.5 + m_SpriteTileMode: 0 + m_WasSpriteAssigned: 0 + m_MaskInteraction: 0 + m_SpriteSortPoint: 0 --- !u!1 &7001609152551886569 GameObject: m_ObjectHideFlags: 0 @@ -1974,7 +3119,7 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 7001609152551886569} - m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} m_Children: @@ -1984,7 +3129,7 @@ Transform: - {fileID: 5972595949109897037} - {fileID: 4610982973295183759} m_Father: {fileID: 3584310800769874311} - m_RootOrder: 4 + m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!114 &4826091915340610528 MonoBehaviour: @@ -1998,8 +3143,8 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: 45eb7daf344474546ba5079bf18eae01, type: 3} m_Name: m_EditorClassIdentifier: - scrollSpeedX: 4 - scrollSpeedY: -10 + scrollSpeedX: 1.5 + scrollSpeedY: -13 lengthX: 24.2 lengthY: 43.20976 --- !u!212 &7055647918200424894 @@ -2053,6 +3198,135 @@ SpriteRenderer: m_WasSpriteAssigned: 1 m_MaskInteraction: 0 m_SpriteSortPoint: 0 +--- !u!1 &7069818529303637873 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 2980827159788922073} + - component: {fileID: 3948134998626780115} + m_Layer: 0 + m_Name: Torso + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &2980827159788922073 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 7069818529303637873} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 0.753, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 4741428524146264548} + m_RootOrder: 1 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!212 &3948134998626780115 +SpriteRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 7069818529303637873} + m_Enabled: 1 + m_CastShadows: 0 + m_ReceiveShadows: 0 + m_DynamicOccludee: 1 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_RayTracingMode: 0 + m_RayTraceProcedural: 0 + m_RenderingLayerMask: 1 + m_RendererPriority: 0 + m_Materials: + - {fileID: 10754, guid: 0000000000000000f000000000000000, type: 0} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_ReceiveGI: 1 + m_PreserveUVs: 0 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_StitchLightmapSeams: 1 + m_SelectedEditorRenderState: 0 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: 1 + m_Sprite: {fileID: 4316165930547777794, guid: ed47c3fa4e916ff478c0f1b6fb057aa4, type: 3} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_FlipX: 0 + m_FlipY: 0 + m_DrawMode: 0 + m_Size: {x: 2.8695652, y: 2.8695652} + m_AdaptiveModeThreshold: 0.5 + m_SpriteTileMode: 0 + m_WasSpriteAssigned: 1 + m_MaskInteraction: 0 + m_SpriteSortPoint: 0 +--- !u!1 &7204248277449664948 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 7039114078560482225} + - component: {fileID: 2039331194922578974} + m_Layer: 0 + m_Name: Point 0 + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &7039114078560482225 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 7204248277449664948} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: -6.240663, y: -4.200388, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 1240551230645966165} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &2039331194922578974 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 7204248277449664948} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: b0cca3244f403c24f819a870f31cdc29, type: 3} + m_Name: + m_EditorClassIdentifier: + curve: {fileID: 5209060163867140866} + handleType: 0 + leftHandleLocalPosition: {x: -2.8053336, y: -13.386384, z: -0} + rightHandleLocalPosition: {x: 2.8053336, y: 13.386384, z: 0} --- !u!1 &7718399668199529040 GameObject: m_ObjectHideFlags: 0 @@ -2178,53 +3452,6 @@ Transform: m_Father: {fileID: 6448989353494316845} m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!1 &8003547861966795618 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 2366440973703065964} - - component: {fileID: 7957000915275159968} - m_Layer: 0 - m_Name: Point 1 - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!4 &2366440973703065964 -Transform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 8003547861966795618} - m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} - m_LocalPosition: {x: 5.39, y: 0, z: 0} - m_LocalScale: {x: 1, y: 1, z: 1} - m_Children: [] - m_Father: {fileID: 2353202814549098793} - m_RootOrder: 1 - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!114 &7957000915275159968 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 8003547861966795618} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: b0cca3244f403c24f819a870f31cdc29, type: 3} - m_Name: - m_EditorClassIdentifier: - curve: {fileID: 6429945450899169262} - handleType: 0 - leftHandleLocalPosition: {x: -2.191154, y: 12.986072, z: 0} - rightHandleLocalPosition: {x: 2.191154, y: -12.986072, z: -0} --- !u!1 &8302891755395531529 GameObject: m_ObjectHideFlags: 0 @@ -2583,9 +3810,8 @@ Transform: m_LocalScale: {x: 1, y: 1, z: 1} m_Children: - {fileID: 482351987616570803} - - {fileID: 6448989353494316845} m_Father: {fileID: 3584310800769874311} - m_RootOrder: 3 + m_RootOrder: 5 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!95 &1608285238974590329 Animator: @@ -2606,7 +3832,7 @@ Animator: m_HasTransformHierarchy: 1 m_AllowConstantClipSamplingOptimization: 1 m_KeepAnimatorControllerStateOnDisable: 0 ---- !u!1 &8974367849771788725 +--- !u!1 &9212397065671421790 GameObject: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} @@ -2614,42 +3840,80 @@ GameObject: m_PrefabAsset: {fileID: 0} serializedVersion: 6 m_Component: - - component: {fileID: 6801291441445583370} - - component: {fileID: 6595947080087458025} + - component: {fileID: 6367340212329602264} + - component: {fileID: 5191272571638092902} + - component: {fileID: 1038451285876923768} m_Layer: 0 - m_Name: Point 0 + m_Name: Space Kicker m_TagString: Untagged m_Icon: {fileID: 0} m_NavMeshLayer: 0 m_StaticEditorFlags: 0 m_IsActive: 1 ---- !u!4 &6801291441445583370 +--- !u!4 &6367340212329602264 Transform: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 8974367849771788725} + m_GameObject: {fileID: 9212397065671421790} m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} - m_LocalPosition: {x: -1, y: 0, z: 0} + m_LocalPosition: {x: -4.51, y: 1.39, z: 4} m_LocalScale: {x: 1, y: 1, z: 1} - m_Children: [] - m_Father: {fileID: 2353202814549098793} + m_Children: + - {fileID: 2253978134027466150} + - {fileID: 4741428524146264548} + m_Father: {fileID: 316676739078874036} m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!114 &6595947080087458025 +--- !u!114 &5191272571638092902 MonoBehaviour: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 8974367849771788725} + m_GameObject: {fileID: 9212397065671421790} m_Enabled: 1 m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: b0cca3244f403c24f819a870f31cdc29, type: 3} + m_Script: {fileID: 11500000, guid: 848efddf5f5eaa94eacf8601e36f81bf, type: 3} m_Name: m_EditorClassIdentifier: - curve: {fileID: 6429945450899169262} - handleType: 0 - leftHandleLocalPosition: {x: -2.66308, y: -13.201346, z: -0} - rightHandleLocalPosition: {x: 2.66308, y: 13.201346, z: 0} + inList: 0 + lastState: 0 + state: + gameObject: {fileID: 0} + early: 0 + perfect: 0 + late: 0 + createBeat: 0 + isEligible: 0 + eligibleHitsList: [] + aceTimes: 0 + canKick: 0 + canHighKick: 0 + kickLeft: 0 + dispenserBeat: 0 + kickTimes: 0 + player: 0 + ball: {fileID: 0} + rightLeg: {fileID: 0} + leftLeg: {fileID: 0} +--- !u!95 &1038451285876923768 +Animator: + serializedVersion: 3 + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 9212397065671421790} + m_Enabled: 1 + m_Avatar: {fileID: 0} + m_Controller: {fileID: 9100000, guid: 1727bb7e16d136b4d8d253268eb21960, type: 2} + m_CullingMode: 0 + m_UpdateMode: 0 + m_ApplyRootMotion: 0 + m_LinearVelocityBlending: 0 + m_WarningMessage: + m_HasTransformHierarchy: 1 + m_AllowConstantClipSamplingOptimization: 1 + m_KeepAnimatorControllerStateOnDisable: 0 diff --git a/Assets/Resources/Sprites/Editor/UI/fullscreen.png b/Assets/Resources/Sprites/Editor/UI/fullscreen.png new file mode 100644 index 00000000..e75b81d9 Binary files /dev/null and b/Assets/Resources/Sprites/Editor/UI/fullscreen.png differ diff --git a/Assets/Resources/Sprites/Editor/UI/fullscreen.png.meta b/Assets/Resources/Sprites/Editor/UI/fullscreen.png.meta new file mode 100644 index 00000000..168d6946 --- /dev/null +++ b/Assets/Resources/Sprites/Editor/UI/fullscreen.png.meta @@ -0,0 +1,96 @@ +fileFormatVersion: 2 +guid: 55bb46a7614176b4c941a5caf846f7e8 +TextureImporter: + internalIDToNameTable: [] + externalObjects: {} + serializedVersion: 11 + mipmaps: + mipMapMode: 0 + enableMipMap: 0 + sRGBTexture: 1 + linearTexture: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapsPreserveCoverage: 0 + alphaTestReferenceValue: 0.5 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: 0.25 + normalMapFilter: 0 + isReadable: 0 + streamingMipmaps: 0 + streamingMipmapsPriority: 0 + vTOnly: 0 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: 1 + aniso: 1 + mipBias: 0 + wrapU: 1 + wrapV: 1 + wrapW: 1 + nPOTScale: 0 + lightmap: 0 + compressionQuality: 50 + spriteMode: 1 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spritePixelsToUnits: 100 + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spriteGenerateFallbackPhysicsShape: 1 + alphaUsage: 1 + alphaIsTransparency: 1 + spriteTessellationDetail: -1 + textureType: 8 + textureShape: 1 + singleChannelComponent: 0 + flipbookRows: 1 + flipbookColumns: 1 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + ignorePngGamma: 0 + applyGammaDecoding: 0 + platformSettings: + - serializedVersion: 3 + buildTarget: DefaultTexturePlatform + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + physicsShape: [] + bones: [] + spriteID: 5e97eb03825dee720800000000000000 + internalID: 0 + vertices: [] + indices: + edges: [] + weights: [] + secondaryTextures: [] + spritePackingTag: + pSDRemoveMatte: 0 + pSDShowRemoveMatteOption: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Resources/Sprites/Games/SpaceSoccer/Animations/HighKickLeft_0.anim b/Assets/Resources/Sprites/Games/SpaceSoccer/Animations/HighKickLeft_0.anim index a9df166b..d258ba42 100644 --- a/Assets/Resources/Sprites/Games/SpaceSoccer/Animations/HighKickLeft_0.anim +++ b/Assets/Resources/Sprites/Games/SpaceSoccer/Animations/HighKickLeft_0.anim @@ -534,6 +534,17 @@ AnimationClip: path: Holder/LowerTorso classID: 212 script: {fileID: 0} + - curve: + - time: 0 + value: {fileID: -4339478730206458095, guid: ed47c3fa4e916ff478c0f1b6fb057aa4, type: 3} + - time: 0.1 + value: {fileID: -4756013695868691969, guid: ed47c3fa4e916ff478c0f1b6fb057aa4, type: 3} + - time: 0.26666668 + value: {fileID: -4901794926734046506, guid: ed47c3fa4e916ff478c0f1b6fb057aa4, type: 3} + attribute: m_Sprite + path: Holder/Head + classID: 212 + script: {fileID: 0} m_SampleRate: 60 m_WrapMode: 0 m_Bounds: @@ -653,6 +664,13 @@ AnimationClip: typeID: 212 customType: 23 isPPtrCurve: 1 + - serializedVersion: 2 + path: 862337961 + attribute: 0 + script: {fileID: 0} + typeID: 212 + customType: 23 + isPPtrCurve: 1 pptrCurveMapping: - {fileID: 8448038167059441282, guid: ed47c3fa4e916ff478c0f1b6fb057aa4, type: 3} - {fileID: -8827699967261475670, guid: ed47c3fa4e916ff478c0f1b6fb057aa4, type: 3} @@ -688,6 +706,9 @@ AnimationClip: - {fileID: -1720273043946688001, guid: ed47c3fa4e916ff478c0f1b6fb057aa4, type: 3} - {fileID: 3897377649561355716, guid: ed47c3fa4e916ff478c0f1b6fb057aa4, type: 3} - {fileID: -1720273043946688001, guid: ed47c3fa4e916ff478c0f1b6fb057aa4, type: 3} + - {fileID: -4339478730206458095, guid: ed47c3fa4e916ff478c0f1b6fb057aa4, type: 3} + - {fileID: -4756013695868691969, guid: ed47c3fa4e916ff478c0f1b6fb057aa4, type: 3} + - {fileID: -4901794926734046506, guid: ed47c3fa4e916ff478c0f1b6fb057aa4, type: 3} m_AnimationClipSettings: serializedVersion: 2 m_AdditiveReferencePoseClip: {fileID: 0} diff --git a/Assets/Resources/Sprites/Games/SpaceSoccer/Animations/HighKickRight_0.anim b/Assets/Resources/Sprites/Games/SpaceSoccer/Animations/HighKickRight_0.anim index 38888f80..73f76040 100644 --- a/Assets/Resources/Sprites/Games/SpaceSoccer/Animations/HighKickRight_0.anim +++ b/Assets/Resources/Sprites/Games/SpaceSoccer/Animations/HighKickRight_0.anim @@ -525,6 +525,17 @@ AnimationClip: path: Holder/LowerTorso classID: 212 script: {fileID: 0} + - curve: + - time: 0 + value: {fileID: -4339478730206458095, guid: ed47c3fa4e916ff478c0f1b6fb057aa4, type: 3} + - time: 0.1 + value: {fileID: -4756013695868691969, guid: ed47c3fa4e916ff478c0f1b6fb057aa4, type: 3} + - time: 0.26666668 + value: {fileID: -4901794926734046506, guid: ed47c3fa4e916ff478c0f1b6fb057aa4, type: 3} + attribute: m_Sprite + path: Holder/Head + classID: 212 + script: {fileID: 0} m_SampleRate: 60 m_WrapMode: 0 m_Bounds: @@ -637,6 +648,13 @@ AnimationClip: typeID: 212 customType: 23 isPPtrCurve: 1 + - serializedVersion: 2 + path: 862337961 + attribute: 0 + script: {fileID: 0} + typeID: 212 + customType: 23 + isPPtrCurve: 1 - serializedVersion: 2 path: 354493626 attribute: 1 @@ -679,6 +697,9 @@ AnimationClip: - {fileID: -1720273043946688001, guid: ed47c3fa4e916ff478c0f1b6fb057aa4, type: 3} - {fileID: 3897377649561355716, guid: ed47c3fa4e916ff478c0f1b6fb057aa4, type: 3} - {fileID: -1720273043946688001, guid: ed47c3fa4e916ff478c0f1b6fb057aa4, type: 3} + - {fileID: -4339478730206458095, guid: ed47c3fa4e916ff478c0f1b6fb057aa4, type: 3} + - {fileID: -4756013695868691969, guid: ed47c3fa4e916ff478c0f1b6fb057aa4, type: 3} + - {fileID: -4901794926734046506, guid: ed47c3fa4e916ff478c0f1b6fb057aa4, type: 3} m_AnimationClipSettings: serializedVersion: 2 m_AdditiveReferencePoseClip: {fileID: 0} diff --git a/Assets/Resources/Sprites/Games/SpaceSoccer/Animations/ToeLeft.anim b/Assets/Resources/Sprites/Games/SpaceSoccer/Animations/ToeLeft.anim index 68da1a31..79b096e6 100644 --- a/Assets/Resources/Sprites/Games/SpaceSoccer/Animations/ToeLeft.anim +++ b/Assets/Resources/Sprites/Games/SpaceSoccer/Animations/ToeLeft.anim @@ -404,6 +404,22 @@ AnimationClip: m_PostInfinity: 2 m_RotationOrder: 4 path: Holder/LowerTorso + - curve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: {x: -2.36, y: -1.87, z: 0} + inSlope: {x: 0, y: 0, z: 0} + outSlope: {x: 0, y: 0, z: 0} + tangentMode: 0 + weightedMode: 0 + inWeight: {x: 0, y: 0.33333334, z: 0.33333334} + outWeight: {x: 0, y: 0.33333334, z: 0.33333334} + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + path: Holder/toeFX m_ScaleCurves: [] m_FloatCurves: - curve: @@ -444,6 +460,34 @@ AnimationClip: path: Holder/RightArm/Hand classID: 1 script: {fileID: 0} + - curve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 1 + inSlope: Infinity + outSlope: Infinity + tangentMode: 103 + weightedMode: 0 + inWeight: 0 + outWeight: 0 + - serializedVersion: 3 + time: 0.033333335 + value: 0 + inSlope: Infinity + outSlope: Infinity + tangentMode: 103 + weightedMode: 0 + inWeight: 0 + outWeight: 0 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + attribute: m_IsActive + path: Holder/toeFX + classID: 1 + script: {fileID: 0} m_PPtrCurves: - curve: - time: 0 @@ -655,6 +699,13 @@ AnimationClip: typeID: 1 customType: 0 isPPtrCurve: 0 + - serializedVersion: 2 + path: 3009155107 + attribute: 2086281974 + script: {fileID: 0} + typeID: 1 + customType: 0 + isPPtrCurve: 0 - serializedVersion: 2 path: 2827832259 attribute: 0 @@ -704,6 +755,13 @@ AnimationClip: typeID: 212 customType: 23 isPPtrCurve: 1 + - serializedVersion: 2 + path: 3009155107 + attribute: 1 + script: {fileID: 0} + typeID: 4 + customType: 0 + isPPtrCurve: 0 pptrCurveMapping: - {fileID: 21300000, guid: c5b59e91368953049893b676adf67b31, type: 3} - {fileID: 21300000, guid: 90f0b2f80c7edac43b09f918f1ff580b, type: 3} @@ -2052,6 +2110,91 @@ AnimationClip: path: Holder/LowerTorso classID: 4 script: {fileID: 0} + - curve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: -2.36 + inSlope: 0 + outSlope: 0 + tangentMode: 136 + weightedMode: 0 + inWeight: 0 + outWeight: 0 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + attribute: m_LocalPosition.x + path: Holder/toeFX + classID: 4 + script: {fileID: 0} + - curve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: -1.87 + inSlope: 0 + outSlope: 0 + tangentMode: 136 + weightedMode: 0 + inWeight: 0 + outWeight: 0 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + attribute: m_LocalPosition.y + path: Holder/toeFX + classID: 4 + script: {fileID: 0} + - curve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 136 + weightedMode: 0 + inWeight: 0 + outWeight: 0 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + attribute: m_LocalPosition.z + path: Holder/toeFX + classID: 4 + script: {fileID: 0} + - curve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 1 + inSlope: Infinity + outSlope: Infinity + tangentMode: 103 + weightedMode: 0 + inWeight: 0 + outWeight: 0 + - serializedVersion: 3 + time: 0.033333335 + value: 0 + inSlope: Infinity + outSlope: Infinity + tangentMode: 103 + weightedMode: 0 + inWeight: 0 + outWeight: 0 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + attribute: m_IsActive + path: Holder/toeFX + classID: 1 + script: {fileID: 0} m_EulerEditorCurves: - curve: serializedVersion: 2 diff --git a/Assets/Resources/Sprites/Games/SpaceSoccer/Animations/ToeRight.anim b/Assets/Resources/Sprites/Games/SpaceSoccer/Animations/ToeRight.anim index a587cecc..18d1e747 100644 --- a/Assets/Resources/Sprites/Games/SpaceSoccer/Animations/ToeRight.anim +++ b/Assets/Resources/Sprites/Games/SpaceSoccer/Animations/ToeRight.anim @@ -433,6 +433,22 @@ AnimationClip: m_PostInfinity: 2 m_RotationOrder: 4 path: Holder/Torso + - curve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: {x: -2.441, y: -1.702, z: 0} + inSlope: {x: 0, y: 0, z: 0} + outSlope: {x: 0, y: 0, z: 0} + tangentMode: 0 + weightedMode: 0 + inWeight: {x: 0, y: 0.33333334, z: 0.33333334} + outWeight: {x: 0, y: 0.33333334, z: 0.33333334} + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + path: Holder/toeFX m_ScaleCurves: [] m_FloatCurves: - curve: @@ -473,6 +489,34 @@ AnimationClip: path: Holder/RightArm/Hand classID: 1 script: {fileID: 0} + - curve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 1 + inSlope: Infinity + outSlope: Infinity + tangentMode: 103 + weightedMode: 0 + inWeight: 0 + outWeight: 0 + - serializedVersion: 3 + time: 0.033333335 + value: 0 + inSlope: Infinity + outSlope: Infinity + tangentMode: 103 + weightedMode: 0 + inWeight: 0 + outWeight: 0 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + attribute: m_IsActive + path: Holder/toeFX + classID: 1 + script: {fileID: 0} m_PPtrCurves: - curve: - time: 0 @@ -679,6 +723,13 @@ AnimationClip: typeID: 1 customType: 0 isPPtrCurve: 0 + - serializedVersion: 2 + path: 3009155107 + attribute: 2086281974 + script: {fileID: 0} + typeID: 1 + customType: 0 + isPPtrCurve: 0 - serializedVersion: 2 path: 862337961 attribute: 0 @@ -728,6 +779,13 @@ AnimationClip: typeID: 212 customType: 23 isPPtrCurve: 1 + - serializedVersion: 2 + path: 3009155107 + attribute: 1 + script: {fileID: 0} + typeID: 4 + customType: 0 + isPPtrCurve: 0 pptrCurveMapping: - {fileID: 1450434439674949499, guid: ed47c3fa4e916ff478c0f1b6fb057aa4, type: 3} - {fileID: -2516537432793170592, guid: ed47c3fa4e916ff478c0f1b6fb057aa4, type: 3} @@ -2155,6 +2213,91 @@ AnimationClip: path: Holder/Torso classID: 4 script: {fileID: 0} + - curve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: -2.441 + inSlope: 0 + outSlope: 0 + tangentMode: 136 + weightedMode: 0 + inWeight: 0 + outWeight: 0 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + attribute: m_LocalPosition.x + path: Holder/toeFX + classID: 4 + script: {fileID: 0} + - curve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: -1.702 + inSlope: 0 + outSlope: 0 + tangentMode: 136 + weightedMode: 0 + inWeight: 0 + outWeight: 0 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + attribute: m_LocalPosition.y + path: Holder/toeFX + classID: 4 + script: {fileID: 0} + - curve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 136 + weightedMode: 0 + inWeight: 0 + outWeight: 0 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + attribute: m_LocalPosition.z + path: Holder/toeFX + classID: 4 + script: {fileID: 0} + - curve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 3 + time: 0 + value: 1 + inSlope: Infinity + outSlope: Infinity + tangentMode: 103 + weightedMode: 0 + inWeight: 0 + outWeight: 0 + - serializedVersion: 3 + time: 0.033333335 + value: 0 + inSlope: Infinity + outSlope: Infinity + tangentMode: 103 + weightedMode: 0 + inWeight: 0 + outWeight: 0 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + attribute: m_IsActive + path: Holder/toeFX + classID: 1 + script: {fileID: 0} m_EulerEditorCurves: - curve: serializedVersion: 2 diff --git a/Assets/Resources/Sprites/Games/SpaceSoccer/spaceSoccer_main.png b/Assets/Resources/Sprites/Games/SpaceSoccer/spaceSoccer_main.png index c47bf050..aa5dfe1a 100644 Binary files a/Assets/Resources/Sprites/Games/SpaceSoccer/spaceSoccer_main.png and b/Assets/Resources/Sprites/Games/SpaceSoccer/spaceSoccer_main.png differ diff --git a/Assets/Resources/Sprites/Games/SpaceSoccer/spaceSoccer_main.png.meta b/Assets/Resources/Sprites/Games/SpaceSoccer/spaceSoccer_main.png.meta index 6b0900f0..55f672fd 100644 --- a/Assets/Resources/Sprites/Games/SpaceSoccer/spaceSoccer_main.png.meta +++ b/Assets/Resources/Sprites/Games/SpaceSoccer/spaceSoccer_main.png.meta @@ -7,10 +7,10 @@ TextureImporter: second: platform_0 - first: 213: -6047660829741247071 - second: platform_1 + second: kick_fx - first: 213: -1664293819527379378 - second: platform_2 + second: toe_fx - first: 213: -4901794926734046506 second: kicker_head_0 @@ -206,7 +206,7 @@ TextureImporter: maxTextureSize: 2048 textureSettings: serializedVersion: 2 - filterMode: 1 + filterMode: 0 aniso: 1 mipBias: 0 wrapU: 1 @@ -1452,6 +1452,48 @@ TextureImporter: indices: edges: [] weights: [] + - serializedVersion: 2 + name: kick_fx + rect: + serializedVersion: 2 + x: 532 + y: 566 + width: 184 + height: 120 + alignment: 0 + pivot: {x: 0.5, y: 0.5} + border: {x: 0, y: 0, z: 0, w: 0} + outline: [] + physicsShape: [] + tessellationDetail: 0 + bones: [] + spriteID: 1a59a396484621ca0800000000000000 + internalID: -6047660829741247071 + vertices: [] + indices: + edges: [] + weights: [] + - serializedVersion: 2 + name: toe_fx + rect: + serializedVersion: 2 + x: 720 + y: 334 + width: 241 + height: 264 + alignment: 0 + pivot: {x: 0, y: 0} + border: {x: 0, y: 0, z: 0, w: 0} + outline: [] + physicsShape: [] + tessellationDetail: 0 + bones: [] + spriteID: e464135c69d37e8e0800000000000000 + internalID: -1664293819527379378 + vertices: [] + indices: + edges: [] + weights: [] outline: [] physicsShape: [] bones: [] diff --git a/Assets/Scenes/Editor.unity b/Assets/Scenes/Editor.unity index 0c6c7bcb..ba7b605f 100644 --- a/Assets/Scenes/Editor.unity +++ b/Assets/Scenes/Editor.unity @@ -775,7 +775,7 @@ RectTransform: m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 1, y: 0.5} m_AnchorMax: {x: 1, y: 0.5} - m_AnchoredPosition: {x: -50, y: 0} + m_AnchoredPosition: {x: -95, y: 0} m_SizeDelta: {x: 39.99997, y: 40} m_Pivot: {x: 1, y: 0.5} --- !u!114 &121871281 @@ -915,7 +915,7 @@ RectTransform: m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_AnchorMin: {x: 1, y: 0.5} m_AnchorMax: {x: 1, y: 0.5} - m_AnchoredPosition: {x: -5, y: 0} + m_AnchoredPosition: {x: -50, y: 0} m_SizeDelta: {x: 39.99997, y: 40} m_Pivot: {x: 1, y: 0.5} --- !u!114 &129013734 @@ -1000,6 +1000,139 @@ CanvasRenderer: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 129013732} m_CullTransparentMesh: 1 +--- !u!1 &151246936 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 151246937} + - component: {fileID: 151246940} + - component: {fileID: 151246939} + - component: {fileID: 151246938} + m_Layer: 5 + m_Name: FullscreenBTN + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &151246937 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 151246936} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: + - {fileID: 1981150264} + m_Father: {fileID: 1709317943} + m_RootOrder: 5 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 1, y: 0.5} + m_AnchorMax: {x: 1, y: 0.5} + m_AnchoredPosition: {x: -5, y: 0} + m_SizeDelta: {x: 39.99997, y: 40} + m_Pivot: {x: 1, y: 0.5} +--- !u!114 &151246938 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 151246936} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 4e29b1a8efbd4b44bb3f3716e73f07ff, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Navigation: + m_Mode: 0 + m_WrapAround: 0 + m_SelectOnUp: {fileID: 0} + m_SelectOnDown: {fileID: 0} + m_SelectOnLeft: {fileID: 0} + m_SelectOnRight: {fileID: 0} + m_Transition: 1 + m_Colors: + m_NormalColor: {r: 1, g: 1, b: 1, a: 1} + m_HighlightedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1} + m_PressedColor: {r: 0.7490196, g: 1, b: 1, a: 1} + m_SelectedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1} + m_DisabledColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 0.5019608} + m_ColorMultiplier: 1 + m_FadeDuration: 0 + m_SpriteState: + m_HighlightedSprite: {fileID: 0} + m_PressedSprite: {fileID: 0} + m_SelectedSprite: {fileID: 0} + m_DisabledSprite: {fileID: 0} + m_AnimationTriggers: + m_NormalTrigger: Normal + m_HighlightedTrigger: Highlighted + m_PressedTrigger: Pressed + m_SelectedTrigger: Selected + m_DisabledTrigger: Disabled + m_Interactable: 1 + m_TargetGraphic: {fileID: 151246939} + m_OnClick: + m_PersistentCalls: + m_Calls: + - m_Target: {fileID: 1423699437} + m_TargetAssemblyTypeName: RhythmHeavenMania.Editor.Editor, Assembly-CSharp + m_MethodName: Fullscreen + m_Mode: 1 + m_Arguments: + m_ObjectArgument: {fileID: 0} + m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine + m_IntArgument: 0 + m_FloatArgument: 0 + m_StringArgument: + m_BoolArgument: 0 + m_CallState: 2 +--- !u!114 &151246939 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 151246936} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_Sprite: {fileID: 0} + m_Type: 1 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 + m_PixelsPerUnitMultiplier: 10 +--- !u!222 &151246940 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 151246936} + m_CullTransparentMesh: 1 --- !u!1 &151438063 GameObject: m_ObjectHideFlags: 0 @@ -9686,6 +9819,7 @@ MonoBehaviour: MusicSelectBTN: {fileID: 1055877579} EditorSettingsBTN: {fileID: 3236232} EditorThemeBTN: {fileID: 528192061} + FullScreenBTN: {fileID: 151246938} --- !u!114 &1423699438 MonoBehaviour: m_ObjectHideFlags: 0 @@ -11116,6 +11250,7 @@ RectTransform: - {fileID: 1783491358} - {fileID: 121871280} - {fileID: 129013733} + - {fileID: 151246937} m_Father: {fileID: 1110073995} m_RootOrder: 1 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} @@ -12655,6 +12790,81 @@ CanvasRenderer: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1964271230} m_CullTransparentMesh: 1 +--- !u!1 &1981150263 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 1981150264} + - component: {fileID: 1981150266} + - component: {fileID: 1981150265} + m_Layer: 5 + m_Name: Graphic + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &1981150264 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1981150263} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 151246937} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0.5, y: 0.5} + m_AnchorMax: {x: 0.5, y: 0.5} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 40, y: 40} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &1981150265 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1981150263} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 0.3254717, g: 1, b: 0.4334381, a: 1} + m_RaycastTarget: 1 + m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_Sprite: {fileID: 21300000, guid: 55bb46a7614176b4c941a5caf846f7e8, type: 3} + m_Type: 0 + m_PreserveAspect: 0 + m_FillCenter: 1 + m_FillMethod: 4 + m_FillAmount: 1 + m_FillClockwise: 1 + m_FillOrigin: 0 + m_UseSpriteMesh: 0 + m_PixelsPerUnitMultiplier: 1 +--- !u!222 &1981150266 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 1981150263} + m_CullTransparentMesh: 1 --- !u!1 &1997273392 GameObject: m_ObjectHideFlags: 0 @@ -13047,8 +13257,7 @@ GameObject: - component: {fileID: 2047408676} - component: {fileID: 2047408675} - component: {fileID: 2047408674} - - component: {fileID: 2047408677} - - component: {fileID: 2047408678} + - component: {fileID: 2047408679} m_Layer: 0 m_Name: Main Camera m_TagString: MainCamera @@ -13121,7 +13330,7 @@ Transform: m_Father: {fileID: 0} m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!114 &2047408677 +--- !u!114 &2047408679 MonoBehaviour: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} @@ -13130,21 +13339,30 @@ MonoBehaviour: m_GameObject: {fileID: 2047408673} m_Enabled: 1 m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: a66fbd5ffe9b9d64da304996f1919f40, type: 3} - m_Name: - m_EditorClassIdentifier: ---- !u!114 &2047408678 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 2047408673} - m_Enabled: 0 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: e55bddfe16e69224c8c4b4eb165695d4, type: 3} + m_Script: {fileID: 11500000, guid: a79441f348de89743a2939f4d699eac1, type: 3} m_Name: m_EditorClassIdentifier: + m_RenderShadows: 1 + m_RequiresDepthTextureOption: 2 + m_RequiresOpaqueTextureOption: 2 + m_CameraType: 0 + m_Cameras: [] + m_RendererIndex: -1 + m_VolumeLayerMask: + serializedVersion: 2 + m_Bits: 1 + m_VolumeTrigger: {fileID: 0} + m_VolumeFrameworkUpdateModeOption: 2 + m_RenderPostProcessing: 0 + m_Antialiasing: 0 + m_AntialiasingQuality: 2 + m_StopNaN: 0 + m_Dithering: 0 + m_ClearDepth: 1 + m_AllowXRRendering: 1 + m_RequiresDepthTexture: 0 + m_RequiresColorTexture: 0 + m_Version: 2 --- !u!1 &2051557110 GameObject: m_ObjectHideFlags: 0 diff --git a/Assets/Scripts/GameManager.cs b/Assets/Scripts/GameManager.cs index e31f8e25..f8491632 100644 --- a/Assets/Scripts/GameManager.cs +++ b/Assets/Scripts/GameManager.cs @@ -51,13 +51,13 @@ namespace RhythmHeavenMania public void Init() { - this.transform.localScale = new Vector3(3000, 3000); + this.transform.localScale = new Vector3(30000000, 30000000); SpriteRenderer sp = this.gameObject.AddComponent(); sp.enabled = false; sp.color = Color.black; sp.sprite = Resources.Load("Sprites/GeneralPurpose/Square"); sp.sortingOrder = 30000; - this.gameObject.layer = 3; + // this.gameObject.layer = 3; if (txt != null) { diff --git a/Assets/Scripts/Games/PlayerActionObject.cs b/Assets/Scripts/Games/PlayerActionObject.cs index 52941e80..8ed6a2b8 100644 --- a/Assets/Scripts/Games/PlayerActionObject.cs +++ b/Assets/Scripts/Games/PlayerActionObject.cs @@ -27,14 +27,15 @@ namespace RhythmHeavenMania.Games autoPlayEnabledOnStart = GameManager.instance.autoplay; } - private void CheckForAce(float normalizedBeat) + private void CheckForAce(float normalizedBeat, bool autoPlay = false) { if (aceTimes == 0) { - if (GameManager.instance.autoplay && normalizedBeat > 0.99f) + if (GameManager.instance.autoplay && normalizedBeat > 0.99f || autoPlay && normalizedBeat > 0.99f) { OnAce(); - AceVisuals(); + if (!autoPlay) + AceVisuals(); // aceTimes++; } } @@ -52,9 +53,9 @@ namespace RhythmHeavenMania.Games } // could possibly add support for custom early, perfect, and end times if needed. - public void StateCheck(float normalizedBeat) + public void StateCheck(float normalizedBeat, bool autoPlay = false) { - CheckForAce(normalizedBeat); + CheckForAce(normalizedBeat, autoPlay); if (normalizedBeat > Minigame.EarlyTime() && normalizedBeat < Minigame.PerfectTime() && lastState == 0) { MakeEligible(true, false, false); diff --git a/Assets/Scripts/Games/SpaceSoccer/Ball.cs b/Assets/Scripts/Games/SpaceSoccer/Ball.cs index 209a6aef..0fc6a90b 100644 --- a/Assets/Scripts/Games/SpaceSoccer/Ball.cs +++ b/Assets/Scripts/Games/SpaceSoccer/Ball.cs @@ -10,9 +10,10 @@ namespace RhythmHeavenMania.Games.SpaceSoccer public class Ball : MonoBehaviour { [Header("Components")] - [SerializeField] private Kicker kicker; + [HideInInspector] public Kicker kicker; [SerializeField] private GameObject holder; [SerializeField] private GameObject spriteHolder; + [SerializeField] private GameObject kickFX; [Space(10)] [SerializeField] private BezierCurve3D dispenseCurve; [SerializeField] private BezierCurve3D kickCurve; @@ -30,8 +31,13 @@ namespace RhythmHeavenMania.Games.SpaceSoccer public GameEvent toe = new GameEvent(); private bool lastKickLeft; - public void Kick() + private void Start() { + } + + public void Kick(bool player) + { + if (player) Jukebox.PlayOneShotGame("spaceSoccer/ballHit"); lastSpriteRot = spriteHolder.transform.eulerAngles.z; @@ -54,6 +60,8 @@ namespace RhythmHeavenMania.Games.SpaceSoccer kickCurve.transform.localScale = new Vector3(1, 1); } kickCurve.KeyPoints[0].transform.position = holder.transform.position; + + HitFX(); } public void HighKick() @@ -68,6 +76,9 @@ namespace RhythmHeavenMania.Games.SpaceSoccer highKicked.startBeat = Conductor.instance.songPositionInBeats; highKickCurve.KeyPoints[0].transform.position = holder.transform.position; + + + HitFX(); } public void Toe() @@ -81,7 +92,7 @@ namespace RhythmHeavenMania.Games.SpaceSoccer toe.enabled = true; toe.startBeat = Conductor.instance.songPositionInBeats; - + toeCurve.KeyPoints[0].transform.position = holder.transform.position; if (lastKickLeft) { @@ -91,6 +102,9 @@ namespace RhythmHeavenMania.Games.SpaceSoccer { toeCurve.KeyPoints[1].transform.localPosition = new Vector3(6.49f, 0); } + + + HitFX(); } private void Update() @@ -98,6 +112,10 @@ namespace RhythmHeavenMania.Games.SpaceSoccer if (dispensing) { float normalizedBeatAnim = Conductor.instance.GetLoopPositionFromBeat(dispensedBeat, 2.35f); + + dispenseCurve.KeyPoints[0].transform.position = new Vector3(kicker.transform.position.x - 6f, kicker.transform.position.y - 6f); + dispenseCurve.KeyPoints[1].transform.position = new Vector3(kicker.transform.position.x - 1f, kicker.transform.position.y - 6f); + holder.transform.localPosition = dispenseCurve.GetPoint(normalizedBeatAnim); spriteHolder.transform.eulerAngles = new Vector3(0, 0, Mathf.Lerp(0f, -1440f, normalizedBeatAnim)); @@ -112,16 +130,20 @@ namespace RhythmHeavenMania.Games.SpaceSoccer else if (kicked.enabled) { float normalizedBeatAnim = Conductor.instance.GetLoopPositionFromBeat(kicked.startBeat, 1.5f); - holder.transform.localPosition = kickCurve.GetPoint(normalizedBeatAnim); + if (!lastKickLeft) { + kickCurve.KeyPoints[1].transform.position = new Vector3(kicker.transform.position.x + 0.5f, kicker.transform.position.y - 6f); spriteHolder.transform.eulerAngles = new Vector3(0, 0, Mathf.Lerp(lastSpriteRot, lastSpriteRot - 360f, normalizedBeatAnim)); } else { + kickCurve.KeyPoints[1].transform.position = new Vector3(kicker.transform.position.x - 2.5f, kicker.transform.position.y - 6f); spriteHolder.transform.eulerAngles = new Vector3(0, 0, Mathf.Lerp(lastSpriteRot, lastSpriteRot + 360f, normalizedBeatAnim)); } + holder.transform.localPosition = kickCurve.GetPoint(normalizedBeatAnim); + /*if (PlayerInput.Pressed()) { if (state.perfect) @@ -141,6 +163,9 @@ namespace RhythmHeavenMania.Games.SpaceSoccer else if (highKicked.enabled) { float normalizedBeatAnim = Conductor.instance.GetLoopPositionFromBeat(highKicked.startBeat, 1.8f); + + highKickCurve.KeyPoints[1].transform.position = new Vector3(kicker.transform.position.x - 3.5f, kicker.transform.position.y - 6f); + holder.transform.localPosition = highKickCurve.GetPoint(normalizedBeatAnim); spriteHolder.transform.eulerAngles = new Vector3(0, 0, Mathf.Lerp(lastSpriteRot, lastSpriteRot + 360f, normalizedBeatAnim)); @@ -165,9 +190,28 @@ namespace RhythmHeavenMania.Games.SpaceSoccer else if (toe.enabled) { float normalizedBeatAnim = Conductor.instance.GetLoopPositionFromBeat(toe.startBeat, 1.85f); + + if (!lastKickLeft) + { + toeCurve.KeyPoints[1].transform.position = new Vector3(kicker.transform.position.x + 0.5f, kicker.transform.position.y - 6f); + } + else + { + toeCurve.KeyPoints[1].transform.position = new Vector3(kicker.transform.position.x - 0.7f, kicker.transform.position.y - 6f); + } + holder.transform.localPosition = toeCurve.GetPoint(normalizedBeatAnim); spriteHolder.transform.eulerAngles = new Vector3(0, 0, Mathf.Lerp(lastSpriteRot, -860f, normalizedBeatAnim)); } + + holder.transform.position = new Vector3(holder.transform.position.x, holder.transform.position.y, kicker.transform.localPosition.z); + } + + private void HitFX() + { + GameObject kickfx = Instantiate(kickFX.gameObject, SpaceSoccer.instance.transform); + kickfx.SetActive(true); + kickfx.transform.position = holder.transform.position; } } } \ No newline at end of file diff --git a/Assets/Scripts/Games/SpaceSoccer/Kicker.cs b/Assets/Scripts/Games/SpaceSoccer/Kicker.cs index e1c55511..4bed6f6e 100644 --- a/Assets/Scripts/Games/SpaceSoccer/Kicker.cs +++ b/Assets/Scripts/Games/SpaceSoccer/Kicker.cs @@ -15,14 +15,27 @@ namespace RhythmHeavenMania.Games.SpaceSoccer public bool kickLeft; public float dispenserBeat; public int kickTimes = 0; + public bool player; [Header("Components")] private Animator anim; public Ball ball; + public Transform rightLeg; + public Transform leftLeg; private void Start() { anim = GetComponent(); + GameObject rightLeg = new GameObject(); + rightLeg.transform.SetParent(this.transform); + rightLeg.transform.position = new Vector3(-0.67f, -1.48f); + + GameObject leftLeg = new GameObject("leftLeg"); + leftLeg.transform.SetParent(this.transform); + leftLeg.transform.position = new Vector3(0f, -1.48f); + + this.rightLeg = rightLeg.transform; + this.leftLeg = leftLeg.transform; } public override void OnAce() @@ -56,7 +69,8 @@ namespace RhythmHeavenMania.Games.SpaceSoccer kickTimes++; aceTimes = 0; - Jukebox.PlayOneShotGame("spaceSoccer/kick"); + if (player) + Jukebox.PlayOneShotGame("spaceSoccer/kick"); if (highKick) { @@ -86,7 +100,7 @@ namespace RhythmHeavenMania.Games.SpaceSoccer if (highKick == false) { if (ball != null && hit) - ball.Kick(); + ball.Kick(player); } else { @@ -109,14 +123,17 @@ namespace RhythmHeavenMania.Games.SpaceSoccer anim.Play("HighKickRight_0", 0, 0); } - if (ball && hit) + if (hit && ball) { - Jukebox.PlayOneShotGame("spaceSoccer/highkicktoe1_hit"); ball.HighKick(); + + if (player) + Jukebox.PlayOneShotGame("spaceSoccer/highkicktoe1_hit"); } else { - Jukebox.PlayOneShotGame("spaceSoccer/highkicktoe1"); + if (player) + Jukebox.PlayOneShotGame("spaceSoccer/highkicktoe1"); } ResetState(); @@ -133,15 +150,20 @@ namespace RhythmHeavenMania.Games.SpaceSoccer anim.Play("ToeRight", 0, 0); } + if (player) + { + if (hit && ball) + { + Jukebox.PlayOneShotGame("spaceSoccer/highkicktoe3_hit"); + } + else + { + Jukebox.PlayOneShotGame("spaceSoccer/highkicktoe3"); + } + } + if (hit && ball) - { - Jukebox.PlayOneShotGame("spaceSoccer/highkicktoe3_hit"); ball.Toe(); - } - else - { - Jukebox.PlayOneShotGame("spaceSoccer/highkicktoe3"); - } kickPrepare = false; ResetState(); @@ -149,7 +171,6 @@ namespace RhythmHeavenMania.Games.SpaceSoccer private void Update() { - if (kickTimes % 2 == 0) { kickLeft = false; @@ -193,36 +214,42 @@ namespace RhythmHeavenMania.Games.SpaceSoccer if (ball.dispensing) { float normalizedBeat = Conductor.instance.GetLoopPositionFromBeat(ball.dispensedBeat, 2f); - StateCheck(normalizedBeat); + StateCheck(normalizedBeat, !player); CheckIfFall(normalizedBeat); - if (PlayerInput.Pressed()) + if (player) { - if (state.perfect) + if (PlayerInput.Pressed()) { - KickCheck(true); - } - else - { - KickCheck(false, true); + if (state.perfect) + { + KickCheck(true); + } + else + { + KickCheck(false, true); + } } } } else if (ball.kicked.enabled) { float normalizedBeat = Conductor.instance.GetLoopPositionFromBeat(ball.kicked.startBeat, 1f); - StateCheck(normalizedBeat); + StateCheck(normalizedBeat, !player); CheckIfFall(normalizedBeat); - if (PlayerInput.Pressed()) + if (player) { - if (state.perfect) + if (PlayerInput.Pressed()) { - KickCheck(true); - } - else - { - KickCheck(false, true); + if (state.perfect) + { + KickCheck(true); + } + else + { + KickCheck(false, true); + } } } } @@ -232,28 +259,34 @@ namespace RhythmHeavenMania.Games.SpaceSoccer if (!kickPrepare) { float normalizedBeatPrepare = Conductor.instance.GetLoopPositionFromBeat(ball.highKicked.startBeat, 1f); - StateCheck(normalizedBeatPrepare); + StateCheck(normalizedBeatPrepare, !player); CheckIfFall(normalizedBeat); - if (PlayerInput.AltPressed()) + if (player) { - Kick(false, true); + if (PlayerInput.AltPressed()) + { + Kick(false, true); + } } } else { - StateCheck(normalizedBeat); + StateCheck(normalizedBeat, !player); CheckIfFall(normalizedBeat); - if (PlayerInput.AltPressedUp()) + if (player) { - if (state.perfect) + if (PlayerInput.AltPressedUp()) { - Toe(true); - } - else - { - Toe(false); + if (state.perfect) + { + Toe(true); + } + else + { + Toe(false); + } } } } @@ -261,27 +294,33 @@ namespace RhythmHeavenMania.Games.SpaceSoccer else if (ball.toe.enabled) { float normalizedBeat = Conductor.instance.GetLoopPositionFromBeat(ball.toe.startBeat, 1.5f); - StateCheck(normalizedBeat); + StateCheck(normalizedBeat, !player); CheckIfFall(normalizedBeat); - if (PlayerInput.Pressed()) + if (player) { - if (state.perfect) + if (PlayerInput.Pressed()) { - KickCheck(true); - } - else - { - KickCheck(false, true); + if (state.perfect) + { + KickCheck(true); + } + else + { + KickCheck(false, true); + } } } } } else { - if (PlayerInput.Pressed()) + if (player) { - KickCheck(false, true); + if (PlayerInput.Pressed()) + { + KickCheck(false, true); + } } } } diff --git a/Assets/Scripts/Games/SpaceSoccer/SpaceSoccer.cs b/Assets/Scripts/Games/SpaceSoccer/SpaceSoccer.cs index 7f5cb54c..9ebdc789 100644 --- a/Assets/Scripts/Games/SpaceSoccer/SpaceSoccer.cs +++ b/Assets/Scripts/Games/SpaceSoccer/SpaceSoccer.cs @@ -10,7 +10,7 @@ namespace RhythmHeavenMania.Games.SpaceSoccer { [Header("Components")] [SerializeField] private GameObject ballRef; - [SerializeField] private Kicker kicker; + [SerializeField] private List kickers; [SerializeField] private GameObject Background; [SerializeField] private Sprite[] backgroundSprite; @@ -26,7 +26,7 @@ namespace RhythmHeavenMania.Games.SpaceSoccer private void Start() { - for (int x = 0; x < Random.Range(9, 12); x++) + /*for (int x = 0; x < Random.Range(9, 12); x++) { for (int y = 0; y < Random.Range(6, 9); y++) { @@ -37,30 +37,35 @@ namespace RhythmHeavenMania.Games.SpaceSoccer test.transform.localPosition = new Vector3(Random.Range(-15f, 15f), Random.Range(-15f, 15f)); test.transform.localScale = new Vector3(0.52f, 0.52f); } - } + }*/ } private void Update() { if (ballDispensed) { - } - - + } } public void Dispense(float beat) { - if (kicker.ball != null) return; - ballDispensed = true; + for (int i = 0; i < kickers.Count; i++) + { + Kicker kicker = kickers[i]; + if (i == 0) kicker.player = true; - GameObject ball = Instantiate(ballRef, this.transform); - Ball ball_ = ball.GetComponent(); - ball_.dispensedBeat = beat; - ball_.dispensing = true; - kicker.ball = ball_; - kicker.dispenserBeat = beat; - kicker.kickTimes = 0; + if (kicker.ball != null) return; + ballDispensed = true; + + GameObject ball = Instantiate(ballRef, transform); + Ball ball_ = ball.GetComponent(); + ball_.kicker = kicker; + ball_.dispensedBeat = beat; + ball_.dispensing = true; + kicker.ball = ball_; + kicker.dispenserBeat = beat; + kicker.kickTimes = 0; + } MultiSound.Play(new MultiSound.Sound[] { diff --git a/Assets/Scripts/LevelEditor/Editor.cs b/Assets/Scripts/LevelEditor/Editor.cs index c3fb8bf7..6d8ee8a0 100644 --- a/Assets/Scripts/LevelEditor/Editor.cs +++ b/Assets/Scripts/LevelEditor/Editor.cs @@ -46,11 +46,13 @@ namespace RhythmHeavenMania.Editor [SerializeField] private Button MusicSelectBTN; [SerializeField] private Button EditorSettingsBTN; [SerializeField] private Button EditorThemeBTN; + [SerializeField] private Button FullScreenBTN; [Header("Properties")] private bool changedMusic = false; private string currentRemixPath = ""; private int lastEditorObjectsCount = 0; + private bool fullscreen; public static Editor instance { get; private set; } @@ -85,6 +87,7 @@ namespace RhythmHeavenMania.Editor Tooltip.AddTooltip(MusicSelectBTN.gameObject, "Music Select"); Tooltip.AddTooltip(EditorSettingsBTN.gameObject, "Editor Settings [Ctrl+Shift+O]"); Tooltip.AddTooltip(EditorThemeBTN.gameObject, "Editor Theme"); + Tooltip.AddTooltip(FullScreenBTN.gameObject, "Preview [Tab]"); UpdateEditorStatus(true); } @@ -105,6 +108,11 @@ namespace RhythmHeavenMania.Editor GetComponent().enabled = true; }*/ + if (Input.GetKeyDown(KeyCode.Tab)) + { + Fullscreen(); + } + if (Input.GetKeyDown(KeyCode.Delete)) { List ev = new List(); @@ -368,6 +376,25 @@ namespace RhythmHeavenMania.Editor #endregion + public void Fullscreen() + { + if (fullscreen == false) + { + MainCanvas.enabled = false; + EditorCamera.enabled = false; + GameManager.instance.GameCamera.targetTexture = null; + // GameManager.instance.GameCamera.transform.parent.GetChild(1).GetComponent().enabled = false; + fullscreen = true; + } + else + { + MainCanvas.enabled = true; + EditorCamera.enabled = true; + GameManager.instance.GameCamera.targetTexture = ScreenRenderTexture; + // GameManager.instance.GameCamera.transform.parent.GetChild(1).GetComponent().enabled = true; + fullscreen = false; + } + } private void UpdateEditorStatus(bool updateTime) { diff --git a/ProjectSettings/GraphicsSettings.asset b/ProjectSettings/GraphicsSettings.asset index dcc5a443..c165afb2 100644 --- a/ProjectSettings/GraphicsSettings.asset +++ b/ProjectSettings/GraphicsSettings.asset @@ -39,7 +39,7 @@ GraphicsSettings: - {fileID: 10783, guid: 0000000000000000f000000000000000, type: 0} m_PreloadedShaders: [] m_SpritesDefaultMaterial: {fileID: 10754, guid: 0000000000000000f000000000000000, type: 0} - m_CustomRenderPipeline: {fileID: 11400000, guid: 101cb6f0eda36514fa0bb49e41c8fae1, type: 2} + m_CustomRenderPipeline: {fileID: 0} m_TransparencySortMode: 0 m_TransparencySortAxis: {x: 0, y: 0, z: 1} m_DefaultRenderingPath: 1