/// <summary> /// Converts a distance to a TF value /// </summary> /// <param name="distance">distance in the range 0..Length</param> /// <param name="clamping">Clamping to use</param> /// <returns>a TF value in the range 0..1</returns> public override float DistanceToTF(float distance, CurvyClamping clamping) { float localDistance; CurvySpline spl = DistanceToSpline(distance, out localDistance, clamping); return((spl) ? SplineToTF(spl, spl.DistanceToTF(localDistance)) : 0); }
/// <summary> /// Gets the segment and the local F for a certain TF /// </summary> /// <param name="tf">the TF value in the range 0..1</param> /// <param name="localF">gets the remaining localF in the range 0..1</param> /// <param name="clamping">Clamping to use</param> /// <returns>the segment the given TF is inside</returns> public override CurvySplineSegment TFToSegment(float tf, out float localF, CurvyClamping clamping) { float localTF; localF = 0; int idx = TFToSplineIndex(tf, out localTF, clamping); return((idx == -1) ? null : this[idx].TFToSegment(localTF, out localF)); }
/// <summary> /// Converts a group TF value to a group distance /// </summary> /// <param name="tf">a TF value in the range 0..1</param> /// <param name="clamping">Clamping to use</param> /// <returns>distance from the first spline's first segment's Control Point</returns> public override float TFToDistance(float tf, CurvyClamping clamping) { if (Count == 0) { return(0); } float localTF; int idx = TFToSplineIndex(tf, out localTF); return(Distances[idx] + this[idx].TFToDistance(localTF)); }
/// <summary> /// Clamps relative position /// </summary> public static float ClampTF(float tf, CurvyClamping clamping) { switch (clamping) { case CurvyClamping.Loop: return Mathf.Repeat(tf, 1); case CurvyClamping.PingPong: return Mathf.PingPong(tf, 1); default: return Mathf.Clamp01(tf); } }
/// <summary> /// Alter TF to move until the curvation reached angle. /// </summary> /// <param name="tf">the current TF value</param> /// <param name="direction">the current direction, 1 or -1</param> /// <param name="angle">the angle in degrees</param> /// <param name="clamping">the clamping mode. CurvyClamping.PingPong isn't supported!</param> /// <param name="stepSize">stepSize defines the accuracy</param> /// <returns>the interpolated position</returns> public virtual Vector3 MoveByAngle(ref float tf, ref int direction, float angle, CurvyClamping clamping, float stepSize) { if (clamping == CurvyClamping.PingPong) { Debug.LogError("CurvySplineBase.MoveByAngle: PingPong clamping isn't supported!"); return(Vector3.zero); } stepSize = Mathf.Max(0.0001f, stepSize); float initialTF = tf; Vector3 initialP = Interpolate(tf); Vector3 initialT = GetTangent(tf, initialP); Vector3 P2 = Vector3.zero; Vector3 T2; int deadlock = 10000; while (deadlock-- > 0) { tf += stepSize * direction; if (tf > 1) { if (clamping == CurvyClamping.Loop) { tf -= 1; } else { tf = 1; return(Interpolate(1)); } } else if (tf < 0) { if (clamping == CurvyClamping.Loop) { tf += 1; } else { tf = 0; return(Interpolate(0)); } } P2 = Interpolate(tf); T2 = P2 - initialP; float accAngle = Vector3.Angle(initialT, T2); if (accAngle >= angle) { tf = initialTF + (tf - initialTF) * angle / accAngle; return(Interpolate(tf)); } } return(P2); }
/// <summary> /// Clamps relative position /// </summary> public static float ClampTF(float tf, CurvyClamping clamping) { switch (clamping) { case CurvyClamping.Loop: return(Mathf.Repeat(tf, 1)); case CurvyClamping.PingPong: return(Mathf.PingPong(tf, 1)); default: return(Mathf.Clamp01(tf)); } }
/// <summary> /// Clamps relative position and sets new direction /// </summary> public static float ClampTF(float tf, ref int dir, CurvyClamping clamping) { switch (clamping) { case CurvyClamping.Loop: return Mathf.Repeat(tf, 1); case CurvyClamping.PingPong: if (Mathf.FloorToInt(tf) % 2 != 0) dir *= -1; return Mathf.PingPong(tf, 1); default: return Mathf.Clamp01(tf); } }
public override void Reset() { base.Reset(); GameObject = null; Spline = null; SetOrientation = true; UseCache = false; Position = 0; Space = Space.World; PositionMode = CurvyPositionMode.Relative; Clamping = CurvyClamping.Clamp; everyFrame = false; updateType = PlayMakerActionsUtils.EveryFrameUpdateSelector.OnUpdate; }
/// <summary> /// Clamps a float to a range /// </summary> public static float ClampValue(float tf, CurvyClamping clamping, float minTF, float maxTF) { switch (clamping) { case CurvyClamping.Loop: float v1 = DTMath.MapValue(0, 1, tf, minTF, maxTF); return DTMath.MapValue(minTF,maxTF,Mathf.Repeat(v1, 1),0,1); case CurvyClamping.PingPong: float v2 = DTMath.MapValue(0, 1, tf, minTF, maxTF); return DTMath.MapValue(minTF,maxTF,Mathf.PingPong(v2, 1),0,1); default: return Mathf.Clamp(tf, minTF, maxTF); } }
/// <summary> /// Clamps a float to a range /// </summary> public static float ClampValue(float tf, CurvyClamping clamping, float minTF, float maxTF) { switch (clamping) { case CurvyClamping.Loop: float v1 = DTMath.MapValue(0, 1, tf, minTF, maxTF); return(DTMath.MapValue(minTF, maxTF, Mathf.Repeat(v1, 1), 0, 1)); case CurvyClamping.PingPong: float v2 = DTMath.MapValue(0, 1, tf, minTF, maxTF); return(DTMath.MapValue(minTF, maxTF, Mathf.PingPong(v2, 1), 0, 1)); default: return(Mathf.Clamp(tf, minTF, maxTF)); } }
/// <summary> /// Gets the spline a certain distance lies within /// </summary> /// <param name="distance">a distance in the range 0..Length</param> /// <param name="localDistance">gets the remaining distance inside the spline</param> /// <param name="clamping">Clamping to use</param> /// <returns>a spline or null</returns> public CurvySpline DistanceToSpline(float distance, out float localDistance, CurvyClamping clamping = CurvyClamping.Clamp) { distance = CurvyUtility.ClampDistance(distance, clamping, Length); localDistance = 0; for (int i = 1; i < Count; i++) { if (Distances[i] >= distance) { localDistance = distance - Distances[i - 1]; return(this[i - 1]); } } localDistance = distance - Distances[Count - 1]; return(this[Count - 1]); }
/// <summary> /// Clamps relative position and sets new direction /// </summary> public static float ClampTF(float tf, ref int dir, CurvyClamping clamping, float minTF, float maxTF) { minTF = Mathf.Clamp01(minTF); maxTF = Mathf.Clamp(maxTF, minTF, 1); switch (clamping) { case CurvyClamping.Loop: return minTF + Mathf.Repeat(tf, maxTF - minTF); case CurvyClamping.PingPong: if (Mathf.FloorToInt(tf / (maxTF - minTF)) % 2 != 0) dir *= -1; return minTF + Mathf.PingPong(tf, maxTF - minTF); default: return Mathf.Clamp(tf, minTF, maxTF); } }
/// <summary> /// Clamps absolute position /// </summary> public static float ClampDistance(float distance, CurvyClamping clamping, float length) { if (length == 0) { return(0); } switch (clamping) { case CurvyClamping.Loop: return(Mathf.Repeat(distance, length)); case CurvyClamping.PingPong: return(Mathf.PingPong(distance, length)); default: return(Mathf.Clamp(distance, 0, length)); } }
protected override void Advance(ref float tf, ref int direction, CurvyController.MoveModeEnum mode, float absSpeed, CurvyClamping clamping) { base.Advance(ref tf, ref direction, mode, absSpeed, clamping); // Get directional vector var tan = GetTangent(tf); float acc; // accelerate when going down, deccelerate when going up if (tan.y < 0) acc = Down * tan.y * Fric; else acc = Up * -tan.y * Fric; // alter speed Speed = Mathf.Clamp(Speed + Mass * acc * DeltaTime,MinSpeed,MaxSpeed); // stop at spline's end if (tf == 1) Speed = 0; }
/// <summary> /// Clamps relative position and sets new direction /// </summary> public static float ClampTF(float tf, ref int dir, CurvyClamping clamping) { switch (clamping) { case CurvyClamping.Loop: return(Mathf.Repeat(tf, 1)); case CurvyClamping.PingPong: if (Mathf.FloorToInt(tf) % 2 != 0) { dir *= -1; } return(Mathf.PingPong(tf, 1)); default: return(Mathf.Clamp01(tf)); } }
int TFToSplineIndex(float tf, out float localTF, CurvyClamping clamping = CurvyClamping.Clamp) { tf = CurvyUtility.ClampTF(tf, clamping); localTF = 0; if (Count == 0) { return(-1); } float f = tf * Count; int idx = (int)f; localTF = f - idx; if (idx == Count) { idx--; localTF = 1; } return(idx); }
/// <summary> /// Clamps absolute position /// </summary> public static float ClampDistance(float distance, CurvyClamping clamping, float length, float min, float max) { if (length == 0) { return(0); } min = Mathf.Clamp(min, 0, length); max = Mathf.Clamp(max, min, length); switch (clamping) { case CurvyClamping.Loop: return(min + Mathf.Repeat(distance, max - min)); case CurvyClamping.PingPong: return(min + Mathf.PingPong(distance, max - min)); default: return(Mathf.Clamp(distance, min, max)); } }
/// <summary> /// Clamps relative position and sets new direction /// </summary> public static float ClampTF(float tf, ref int dir, CurvyClamping clamping, float minTF, float maxTF) { minTF = Mathf.Clamp01(minTF); maxTF = Mathf.Clamp(maxTF, minTF, 1); switch (clamping) { case CurvyClamping.Loop: return(minTF + Mathf.Repeat(tf, maxTF - minTF)); case CurvyClamping.PingPong: if (Mathf.FloorToInt(tf / (maxTF - minTF)) % 2 != 0) { dir *= -1; } return(minTF + Mathf.PingPong(tf, maxTF - minTF)); default: return(Mathf.Clamp(tf, minTF, maxTF)); } }
/// <summary> /// Clamps absolute position and sets new direction /// </summary> public static float ClampDistance(float distance, ref int dir, CurvyClamping clamping, float length) { if (length == 0) { return(0); } switch (clamping) { case CurvyClamping.Loop: return(Mathf.Repeat(distance, length)); case CurvyClamping.PingPong: if (Mathf.FloorToInt(distance / length) % 2 != 0) { dir *= -1; } return(Mathf.PingPong(distance, length)); default: return(Mathf.Clamp(distance, 0, length)); } }
/*! \cond PRIVATE */ /*! @name Internal Public * Don't use them unless you know what you're doing! */ //@{ protected virtual bool ClampTF(ref float tf, ref int dir, CurvyClamping clamping) { switch (clamping) { case CurvyClamping.Loop: if (tf < 0) { tf = 1 - Mathf.Abs(tf % 1); return(true); } else if (tf > 1) { tf = tf % 1; return(true); } break; case CurvyClamping.PingPong: if (tf < 0) { tf = (tf % 1) * -1; dir *= -1; return(true); } else if (tf > 1) { tf = 1 - tf % 1; dir *= -1; return(true); } break; default: // Clamp tf = Mathf.Clamp01(tf); break; } return(false); }
/// <summary> /// Advance the controller and return the new position /// </summary> /// <param name="virtualPosition">the current virtual position (either TF or World Units) </param> /// <param name="direction">the current direction</param> /// <param name="mode">movement mode</param> /// <param name="absSpeed">speed, always positive</param> /// <param name="clamping">clamping mode</param> protected override void Advance(ref float virtualPosition, ref int direction, MoveModeEnum mode, float absSpeed, CurvyClamping clamping) { switch (mode) { case MoveModeEnum.Relative: VolumeData.Move(ref virtualPosition, ref direction, absSpeed, clamping); break; default: VolumeData.MoveBy(ref virtualPosition, ref direction, absSpeed, clamping); break; } }
/// <summary> /// Alter TF to reflect a movement over a certain distance. Unlike MoveBy, a linear approximation will be used /// </summary> /// <param name="tf">the current TF value</param> /// <param name="direction">the current direction, 1 or -1</param> /// <param name="distance">the distance in world units to move</param> /// <param name="clamping">clamping mode</param> /// <returns>the interpolated position</returns> public virtual Vector3 MoveByFast(ref float tf, ref int direction, float distance, CurvyClamping clamping) { return(MoveByFast(ref tf, ref direction, distance, clamping, 0.002f)); }
/// <summary> /// Alter TF to reflect a movement over a certain distance. /// </summary> /// <remarks>MoveByLengthFast works by using actual lengths</remarks> /// <param name="tf">the current TF value</param> /// <param name="direction">the current direction, 1 or -1</param> /// <param name="distance">the distance in world units to move</param> /// <param name="clamping">clamping mode</param> /// <returns>the interpolated position</returns> public virtual Vector3 MoveByLengthFast(ref float tf, ref int direction, float distance, CurvyClamping clamping) { float dist = ClampDistance(TFToDistance(tf) + distance * direction, ref direction, clamping); tf = DistanceToTF(dist); return(InterpolateFast(tf)); }
/// <summary> /// Advance the controller and return the new position /// </summary> /// <param name="tf">the current virtual position (either TF or World Units)</param> /// <param name="direction">the current direction</param> /// <param name="mode">movement mode</param> /// <param name="absSpeed">speed, always positive</param> /// <param name="clamping">clamping mode</param> protected override void Advance(ref float tf, ref int direction, MoveModeEnum mode, float absSpeed, CurvyClamping clamping) { _active = this; switch (mode) { case MoveModeEnum.AbsoluteExtrapolate: if (UseCache) { Spline.MoveByFast(ref tf, ref direction, absSpeed, Clamping); if (IsSwitching) { mSwitchEventArgs.Spline.MoveByFast(ref mSwitchEventArgs.TF, ref mSwitchEventArgs.Direction, absSpeed, Clamping); onSwitchEvent(mSwitchEventArgs); } } else { Spline.MoveBy(ref tf, ref direction, absSpeed, Clamping); if (IsSwitching) { mSwitchEventArgs.Spline.MoveBy(ref mSwitchEventArgs.TF, ref mSwitchEventArgs.Direction, absSpeed, Clamping); onSwitchEvent(mSwitchEventArgs); } } break; case MoveModeEnum.AbsolutePrecise: Spline.MoveByLengthFast(ref tf, ref direction, absSpeed, Clamping); if (IsSwitching) { mSwitchEventArgs.Spline.MoveByLengthFast(ref mSwitchEventArgs.TF, ref mSwitchEventArgs.Direction, absSpeed, Clamping); onSwitchEvent(mSwitchEventArgs); } break; default: // Relative if (UseCache) { Spline.MoveFast(ref tf, ref direction, absSpeed, Clamping); if (IsSwitching) { mSwitchEventArgs.Spline.MoveFast(ref mSwitchEventArgs.TF, ref mSwitchEventArgs.Direction, absSpeed, Clamping); onSwitchEvent(mSwitchEventArgs); } } else { Spline.Move(ref tf, ref direction, absSpeed, Clamping); if (IsSwitching) { mSwitchEventArgs.Spline.Move(ref mSwitchEventArgs.TF, ref mSwitchEventArgs.Direction, absSpeed, Clamping); onSwitchEvent(mSwitchEventArgs); } } break; } _active = null; }
/// <summary> /// Converts a distance to a TF value /// </summary> /// <param name="distance">distance</param> /// <param name="clamping">Clamping to use</param> /// <returns>a TF value in the range 0..1</returns> public virtual float DistanceToTF(float distance, CurvyClamping clamping) { return(0); }
/// <summary> /// Gets the segment for a certain TF /// </summary> /// <param name="tf">the TF value</param> /// <param name="clamping">Clamping to use</param> /// <returns>the segment the given TF is inside</returns> public CurvySplineSegment TFToSegment(float tf, CurvyClamping clamping) { float f; return(TFToSegment(tf, out f, clamping)); }
/// <summary> /// Clamps absolute position /// </summary> public static float ClampDistance(float distance, CurvyClamping clamping, float length) { if (length == 0) return 0; switch (clamping) { case CurvyClamping.Loop: return Mathf.Repeat(distance, length); case CurvyClamping.PingPong: return Mathf.PingPong(distance, length); default: return Mathf.Clamp(distance, 0, length); } }
bool ClampTF(ref float tf, ref int dir, CurvyClamping clamping) { switch (clamping) { case CurvyClamping.Loop: if (tf < 0) { tf = 1 - tf; return true; } else if (tf > 1) { tf -= 1; return true; } break; case CurvyClamping.PingPong: if (tf < 0) { tf *= -1; dir *= -1; return true; } else if (tf > 1) { tf = 2 - tf; dir *= -1; return true; } break; default: // Clamp tf = Mathf.Clamp01(tf); break; } return false; }
/// <summary> /// Alter TF to move until the curvation reached angle. Unlike MoveByAngle, a linear approximation will be used /// </summary> /// <param name="tf">the current TF value</param> /// <param name="direction">the current direction, 1 or -1</param> /// <param name="angle">the angle in degrees</param> /// <param name="clamping">the clamping mode. CurvyClamping.PingPong isn't supported!</param> /// <param name="stepSize">stepSize defines the accuracy</param> /// <returns>the interpolated position</returns> public Vector3 MoveByAngleFast(ref float tf, ref int direction, float angle, CurvyClamping clamping, float stepSize) { if (clamping == CurvyClamping.PingPong) { Debug.LogError("CurvySpline.MoveByAngle: PingPong clamping isn't supported!"); return Vector3.zero; } stepSize = Mathf.Max(0.0001f, stepSize); Vector3 initialP = InterpolateFast(tf); Vector3 initialT = GetTangentFast(tf); Vector3 P2 = Vector3.zero; Vector3 T2; int deadlock = 10000; while (deadlock-- > 0) { tf += stepSize * direction; if (tf > 1) { if (clamping == CurvyClamping.Loop) tf -= 1; else { tf = 1; return InterpolateFast(1); } } else if (tf < 0) { if (clamping == CurvyClamping.Loop) tf += 1; else { tf = 0; return InterpolateFast(0); } } P2 = InterpolateFast(tf); T2 = P2 - initialP; if (Vector3.Angle(initialT, T2) >= angle) return P2; } return P2; }
/// <summary> /// Alter TF to move until the curvation reached angle. /// </summary> /// <param name="tf">the current TF value</param> /// <param name="direction">the current direction, 1 or -1</param> /// <param name="angle">the angle in degrees</param> /// <param name="clamping">the clamping mode. CurvyClamping.PingPong isn't supported!</param> /// <param name="stepSize">stepSize defines the accuracy</param> /// <returns>the interpolated position</returns> public virtual Vector3 MoveByAngle(ref float tf, ref int direction, float angle, CurvyClamping clamping, float stepSize) { if (clamping == CurvyClamping.PingPong) { Debug.LogError("CurvySplineBase.MoveByAngle: PingPong clamping isn't supported!"); return Vector3.zero; } stepSize = Mathf.Max(0.0001f, stepSize); float initialTF = tf; Vector3 initialP = Interpolate(tf); Vector3 initialT = GetTangent(tf, initialP); Vector3 P2 = Vector3.zero; Vector3 T2; int deadlock = 10000; while (deadlock-- > 0) { tf += stepSize * direction; if (tf > 1) { if (clamping == CurvyClamping.Loop) tf -= 1; else { tf = 1; return Interpolate(1); } } else if (tf < 0) { if (clamping == CurvyClamping.Loop) tf += 1; else { tf = 0; return Interpolate(0); } } P2 = Interpolate(tf); T2 = P2 - initialP; float accAngle = Vector3.Angle(initialT, T2); if (accAngle >= angle) { tf = initialTF + (tf - initialTF) * angle / accAngle; return Interpolate(tf); } } return P2; }
/// <summary> /// Alter TF to reflect a movement over a certain distance. Unlike MoveBy, a linear approximation will be used /// </summary> /// <param name="tf">the current TF value</param> /// <param name="direction">the current direction, 1 or -1</param> /// <param name="distance">the distance in world units to move</param> /// <param name="clamping">clamping mode</param> /// <param name="stepSize">stepSize defines the accuracy</param> /// <returns>the interpolated position</returns> public Vector3 MoveByFast(ref float tf, ref int direction, float distance, CurvyClamping clamping, float stepSize) { stepSize = Mathf.Max(0.0001f, stepSize); Vector3 p = InterpolateFast(tf); if (Mathf.Approximately(distance, 0)) return p; float tf1 = tf + stepSize * direction; // Handle Clamping when end of spline is reached if (tf1 < 0) { float magpart; switch (clamping) { case CurvyClamping.Clamp: tf = 0; return InterpolateFast(0); case CurvyClamping.PingPong: magpart = (Interpolate(0) - p).magnitude; direction *= -1; tf = 0; return MoveByFast(ref tf, ref direction, distance - magpart, clamping); case CurvyClamping.Loop: magpart = (Interpolate(0) - p).magnitude; tf = 1; return MoveByFast(ref tf, ref direction, distance - magpart, clamping); } } else if (tf1 > 1) { float magpart; switch (clamping) { case CurvyClamping.Clamp: tf = 1; return InterpolateFast(1); case CurvyClamping.PingPong: magpart = (InterpolateFast(1) - p).magnitude; direction *= -1; tf = 1; return MoveByFast(ref tf, ref direction, distance - magpart, clamping); case CurvyClamping.Loop: magpart = (InterpolateFast(1) - p).magnitude; tf = 0; return MoveByFast(ref tf, ref direction, distance - magpart, clamping); } } // inside spline, calculate normal Vector3 p1 = InterpolateFast(tf1); float mag = (p1 - p).magnitude; if (mag != 0) tf += (1 / mag) * stepSize * distance * direction; return InterpolateFast(tf); }
/// <summary> /// Alter TF to reflect a movement over a certain distance. Unlike MoveBy, a linear approximation will be used /// </summary> /// <param name="tf">the current TF value</param> /// <param name="direction">the current direction, 1 or -1</param> /// <param name="distance">the distance in world units to move</param> /// <param name="clamping">clamping mode</param> /// <returns>the interpolated position</returns> public Vector3 MoveByFast(ref float tf, ref int direction, float distance, CurvyClamping clamping) { return MoveByFast(ref tf, ref direction, distance, clamping, 0.002f); }
/// <summary> /// Alter TF to reflect a movement over a certain portion of the spline, respecting Clamping. Unlike Move() a linear approximation will be used /// </summary> /// <remarks>fDistance relates to the total spline, so longer splines will result in faster movement for constant fDistance</remarks> /// <param name="tf">the current TF value</param> /// <param name="direction">the current direction, 1 or -1</param> /// <param name="fDistance">the percentage of the spline to move</param> /// <param name="clamping">clamping mode</param> /// <returns>the interpolated position</returns> public Vector3 MoveFast(ref float tf, ref int direction, float fDistance, CurvyClamping clamping) { tf += fDistance * direction; ClampTF(ref tf, ref direction,clamping); return InterpolateFast(tf); }
/// <summary> /// Alter TF to reflect a movement over a certain distance. /// </summary> /// <remarks>MoveByLengthFast works by using actual lengths</remarks> /// <param name="tf">the current TF value</param> /// <param name="direction">the current direction, 1 or -1</param> /// <param name="distance">the distance in world units to move</param> /// <param name="clamping">clamping mode</param> /// <returns>the interpolated position</returns> public virtual Vector3 MoveByLengthFast(ref float tf, ref int direction, float distance, CurvyClamping clamping) { float dist = TFToDistance(tf); float delta = (clamping != CurvyClamping.Clamp) ? (distance % Length) * direction : distance * direction; float newDist = dist + delta; if (newDist > Length || newDist < 0) { switch (clamping) { case CurvyClamping.Clamp: tf = (delta < 0) ? 0 : 1; break; case CurvyClamping.PingPong: if (delta < 0) { newDist *= -1; } else { newDist -= delta - Length; } direction *= -1; tf = DistanceToTF(newDist); break; case CurvyClamping.Loop: if (newDist < 0) { newDist += Length; } else { newDist -= Length; } tf = DistanceToTF(newDist); break; } } else { tf = DistanceToTF(newDist); } return(InterpolateFast(tf)); }
/// <summary> /// Alter TF to reflect a movement over a certain distance. /// </summary> /// <remarks>MoveByLengthFast works by using actual lengths</remarks> /// <param name="tf">the current TF value</param> /// <param name="direction">the current direction, 1 or -1</param> /// <param name="distance">the distance in world units to move</param> /// <param name="clamping">clamping mode</param> /// <returns>the interpolated position</returns> public virtual Vector3 MoveByLengthFast(ref float tf, ref int direction, float distance, CurvyClamping clamping) { float dist = TFToDistance(tf); float delta = (clamping != CurvyClamping.Clamp) ? (distance % Length) * direction : distance * direction; float newDist = dist + delta; if (newDist > Length || newDist < 0) { switch (clamping) { case CurvyClamping.Clamp: tf = (delta < 0) ? 0 : 1; break; case CurvyClamping.PingPong: if (delta < 0) newDist *= -1; else newDist -= delta - Length; direction *= -1; tf = DistanceToTF(newDist); break; case CurvyClamping.Loop: if (newDist < 0) newDist += Length; else newDist -= Length; tf = DistanceToTF(newDist); break; } } else tf = DistanceToTF(newDist); return InterpolateFast(tf); }
/// <summary> /// Clamps absolute position and sets new direction /// </summary> public static float ClampDistance(float distance, ref int dir, CurvyClamping clamping, float length) { if (length == 0) return 0; switch (clamping) { case CurvyClamping.Loop: return Mathf.Repeat(distance, length); case CurvyClamping.PingPong: if (Mathf.FloorToInt(distance / length) % 2 != 0) dir *= -1; return Mathf.PingPong(distance, length); default: return Mathf.Clamp(distance, 0, length); } }
/// <summary> /// Alter TF to reflect a movement over a certain distance. Unlike MoveBy, a linear approximation will be used /// </summary> /// <param name="tf">the current TF value</param> /// <param name="direction">the current direction, 1 or -1</param> /// <param name="distance">the distance in world units to move</param> /// <param name="clamping">clamping mode</param> /// <param name="stepSize">stepSize defines the accuracy</param> /// <returns>the interpolated position</returns> public virtual Vector3 MoveByFast(ref float tf, ref int direction, float distance, CurvyClamping clamping, float stepSize) { return MoveFast(ref tf, ref direction, ExtrapolateDistanceToTFFast(tf, distance, stepSize), clamping); }
/// <summary> /// Converts a TF value to a distance /// </summary> /// <param name="tf">a TF value</param> /// <param name="clamping">Clamping to use</param> /// <returns>distance from the first segment's Control Point</returns> public virtual float TFToDistance(float tf, CurvyClamping clamping) { return(0); }
/// <summary> /// Advance the controller and return the new position /// </summary> /// <param name="tf">the current virtual position (either TF or World Units) </param> /// <param name="direction">the current direction</param> /// <param name="mode">movement mode</param> /// <param name="absSpeed">speed, always positive</param> /// <param name="clamping">clamping mode</param> protected virtual void Advance(ref float tf, ref int direction, MoveModeEnum mode, float absSpeed, CurvyClamping clamping) { }
/// <summary> /// Gets the segment and the local F for a certain TF /// </summary> /// <param name="tf">the TF value</param> /// <param name="localF">gets the remaining localF in the range 0..1</param> /// <param name="clamping">Clamping to use</param> /// <returns>the segment the given TF is inside</returns> public virtual CurvySplineSegment TFToSegment(float tf, out float localF, CurvyClamping clamping) { localF = 0; return(null); }
/// <summary> /// Alter TF to reflect a movement over a certain distance. /// </summary> /// <remarks>MoveByLengthFast is used internally, so stepSize is ignored</remarks> /// <param name="tf">the current TF value</param> /// <param name="direction">the current direction, 1 or -1</param> /// <param name="distance">the distance in world units to move</param> /// <param name="clamping">clamping mode</param> /// <param name="stepSize">stepSize defines the accuracy</param> /// <returns>the interpolated position</returns> public override Vector3 MoveByFast(ref float tf, ref int direction, float distance, CurvyClamping clamping, float stepSize) { return MoveByLengthFast(ref tf, ref direction, distance, clamping); }
/// <summary> /// Alter TF to reflect a movement over a certain portion of the spline/group /// </summary> /// <remarks>fDistance relates to the total spline, so longer splines will result in faster movement for constant fDistance</remarks> /// <param name="tf">the current TF value</param> /// <param name="direction">the current direction, 1 or -1</param> /// <param name="fDistance">the percentage of the spline/group to move</param> /// <param name="clamping">clamping mode</param> /// <returns>the interpolated position</returns> public virtual Vector3 Move(ref float tf, ref int direction, float fDistance, CurvyClamping clamping) { tf = CurvyUtility.ClampTF(tf + fDistance * direction, ref direction, clamping); return(Interpolate(tf)); }
/// <summary> /// Alter TF to reflect a movement over a certain distance using a default stepSize of 0.002, using connections if conditions match. /// Unlike MoveByConnection() a linear approximation will be used. /// </summary> /// <param name="spline">the current spline</param> /// <param name="tf">the current TF value</param> /// <param name="direction">the current direction, 1 or -1</param> /// <param name="distance">the distance in world units to move</param> /// <param name="clamping">clamping mode</param> /// <param name="minMatchesNeeded">minimum number of tags that must match to use a connection</param> /// <param name="tags">list of tags to match</param> /// <returns>the interpolated position</returns> public Vector3 MoveByConnectionFast(ref CurvySpline spline, ref float tf, ref int direction, float distance, CurvyClamping clamping, int minMatchesNeeded, params string[] tags) { return MoveByConnectionFast(ref spline, ref tf, ref direction, distance, clamping, minMatchesNeeded, 0.002f, tags); }
/// <summary> /// Advances the specified virtual position. /// </summary> /// <param name="virtualPosition">The virtual position.</param> /// <param name="direction">The direction.</param> /// <param name="mode">The mode.</param> /// <param name="absSpeed">The abs speed.</param> /// <param name="clamping">The clamping.</param> protected override void Advance(ref float virtualPosition, ref int direction, MoveModeEnum mode, float absSpeed, CurvyClamping clamping) { switch (mode) { case MoveModeEnum.Relative: PathData.Move(ref virtualPosition, ref direction, absSpeed, clamping); break; default: PathData.MoveBy(ref virtualPosition, ref direction, absSpeed, clamping); break; } }
/// <summary> /// Alter TF to reflect a movement over a certain distance, using connections if conditions match. Unlike MoveByConnection() a linear approximation will be used. /// </summary> /// <param name="spline">the current spline</param> /// <param name="tf">the current TF value</param> /// <param name="direction">the current direction, 1 or -1</param> /// <param name="distance">the distance in world units to move</param> /// <param name="clamping">clamping mode</param> /// <param name="minMatchesNeeded">minimum number of tags that must match to use a connection</param> /// <param name="stepSize">stepSize defines the accuracy</param> /// <param name="tags">list of tags to match</param> /// <returns>the interpolated position</returns> public Vector3 MoveByConnectionFast(ref CurvySpline spline, ref float tf, ref int direction, float distance, CurvyClamping clamping, int minMatchesNeeded, float stepSize, params string[] tags) { return MoveConnectionFast(ref spline, ref tf, ref direction, ExtrapolateDistanceToTFFast(tf, distance, stepSize), clamping, minMatchesNeeded, tags); }
/// <summary> /// Clamps absolute position and sets new direction /// </summary> public static float ClampDistance(float distance, ref int dir, CurvyClamping clamping, float length, float min, float max) { if (length == 0) return 0; min = Mathf.Clamp(min, 0, length); max = Mathf.Clamp(max, min, length); switch (clamping) { case CurvyClamping.Loop: return min + Mathf.Repeat(distance, max - min); case CurvyClamping.PingPong: if (Mathf.FloorToInt(distance / (max - min)) % 2 != 0) dir *= -1; return min + Mathf.PingPong(distance, max - min); default: return Mathf.Clamp(distance, min, max); } }
/// <summary> /// Alter TF to reflect a movement over a certain portion of the spline, using connections if conditions match. Unlike MoveConnection() a linear approximation will be used /// </summary> /// <param name="spline">the current spline</param> /// <param name="tf">the current TF value</param> /// <param name="direction">the current direction, 1 or -1</param> /// <param name="fDistance">the percentage of the spline to move</param> /// <param name="clamping">clamping mode</param> /// <param name="minMatchesNeeded">minimum number of tags that must match to use a connection</param> /// <param name="tags">list of tags to match</param> /// <returns>the interpolated position</returns> public Vector3 MoveConnectionFast(ref CurvySpline spline, ref float tf, ref int direction, float fDistance, CurvyClamping clamping, int minMatchesNeeded, params string[] tags) { List<CurvyConnection> cons = GetConnectionsWithin(tf, direction, fDistance, minMatchesNeeded,true, tags); if (cons.Count > 0) { CurvyConnection con; if (cons.Count == 1) con = cons[0]; else con = CurvyConnection.GetBestMatchingConnection(cons, tags); CurvySplineSegment cp = con.GetFromSpline(this); float cptf = SegmentToTF(cp); fDistance -= cptf - tf; CurvySplineSegment counterp = con.GetCounterpart(cp); tf = counterp.LocalFToTF(0); spline = counterp.Spline; return spline.MoveConnectionFast(ref spline, ref tf, ref direction, fDistance, clamping, minMatchesNeeded, tags); } else return MoveFast(ref tf, ref direction, fDistance, clamping); }
/// <summary> /// Alter TF to reflect a movement over a certain portion of the spline/group, respecting Clamping. Unlike Move() a linear approximation will be used /// </summary> /// <remarks>fDistance relates to the total spline, so longer splines will result in faster movement for constant fDistance</remarks> /// <param name="tf">the current TF value</param> /// <param name="direction">the current direction, 1 or -1</param> /// <param name="fDistance">the percentage of the spline/group to move</param> /// <param name="clamping">clamping mode</param> /// <returns>the interpolated position</returns> public virtual Vector3 MoveFast(ref float tf, ref int direction, float fDistance, CurvyClamping clamping) { tf += fDistance * direction; ClampTF(ref tf, ref direction, clamping); return(InterpolateFast(tf)); }
/// <summary> /// Alter TF to reflect a movement over a certain distance. /// </summary> /// <remarks>MoveByLengthFast is used internally, so stepSize is ignored</remarks> /// <param name="tf">the current TF value</param> /// <param name="direction">the current direction, 1 or -1</param> /// <param name="distance">the distance in world units to move</param> /// <param name="clamping">clamping mode</param> /// <param name="stepSize">stepSize defines the accuracy</param> /// <returns>the interpolated position</returns> public override Vector3 MoveByFast(ref float tf, ref int direction, float distance, CurvyClamping clamping, float stepSize) { return(MoveByLengthFast(ref tf, ref direction, distance, clamping)); }
/// <summary> /// Alter TF to reflect a movement over a certain distance. Unlike MoveBy, a linear approximation will be used /// </summary> /// <param name="tf">the current TF value</param> /// <param name="direction">the current direction, 1 or -1</param> /// <param name="distance">the distance in world units to move</param> /// <param name="clamping">clamping mode</param> /// <param name="stepSize">stepSize defines the accuracy</param> /// <returns>the interpolated position</returns> public virtual Vector3 MoveByFast(ref float tf, ref int direction, float distance, CurvyClamping clamping, float stepSize) { return(MoveFast(ref tf, ref direction, ExtrapolateDistanceToTFFast(tf, distance, stepSize), clamping)); }
/// <summary> /// Clamps absolute position /// </summary> public float ClampDistance(float distance, CurvyClamping clamping) { return(CurvyUtility.ClampDistance(distance, clamping, Length)); }
/// <summary> /// Alter TF to move until the curvation reached angle, using a default stepSize of 0.002f /// </summary> /// <param name="tf">the current TF value</param> /// <param name="direction">the current direction, 1 or -1</param> /// <param name="angle">the angle in degrees</param> /// <param name="clamping">the clamping mode. CurvyClamping.PingPong isn't supported!</param> /// <returns>the interpolated position</returns> public virtual Vector3 MoveByAngle(ref float tf, ref int direction, float angle, CurvyClamping clamping) { return(MoveByAngle(ref tf, ref direction, angle, clamping, 0.002f)); }
/// <summary> /// Clamps absolute position and sets new direction /// </summary> public float ClampDistance(float distance, ref int dir, CurvyClamping clamping, float min, float max) { return(CurvyUtility.ClampDistance(distance, ref dir, clamping, Length, min, max)); }
/// <summary> /// Alter TF to move until the curvation reached angle, using a default stepSize of 0.002f /// </summary> /// <param name="tf">the current TF value</param> /// <param name="direction">the current direction, 1 or -1</param> /// <param name="angle">the angle in degrees</param> /// <param name="clamping">the clamping mode. CurvyClamping.PingPong isn't supported!</param> /// <returns>the interpolated position</returns> public virtual Vector3 MoveByAngle(ref float tf, ref int direction, float angle, CurvyClamping clamping) { return MoveByAngle(ref tf, ref direction, angle, clamping, 0.002f); }
/*! \cond PRIVATE */ /*! @name Internal Public * Don't use them unless you know what you're doing! */ //@{ protected virtual bool ClampTF(ref float tf, ref int dir, CurvyClamping clamping) { switch (clamping) { case CurvyClamping.Loop: if (tf < 0) { tf = 1 - Mathf.Abs(tf % 1); return true; } else if (tf > 1) { tf = tf % 1; return true; } break; case CurvyClamping.PingPong: if (tf < 0) { tf = (tf % 1) * -1; dir *= -1; return true; } else if (tf > 1) { tf = 1 - tf % 1; dir *= -1; return true; } break; default: // Clamp tf = Mathf.Clamp01(tf); break; } return false; }