/// <summary> /// Calculates the intersection of this line with the given line. /// </summary> /// <param name="other">Other.</param> /// <param name="finiteThis">If set to <c>true</c> this line is finite.</param> /// <param name="finiteOther">If set to <c>true</c> the other line is finite.</param> /// <param name="intersection">Intersection.</param> public bool Intersects(Line2d other, bool finiteThis, bool finiteOther, out Vector2 intersection) { intersection = Vector2.zero; Vector2 b = m_PointB - m_PointA; Vector2 d = other.pointB - other.pointA; float bDotDPerp = b.x * d.y - b.y * d.x; // If bDotDPerp is 0 it means the lines are parallel. if (HydraMathUtils.Approximately(bDotDPerp, 0.0f)) { return(false); } Vector2 c = other.pointA - m_PointA; float t = (c.x * d.y - c.y * d.x) / bDotDPerp; if (finiteThis && (t < 0.0f || t > 1.0f)) { return(false); } float u = (c.x * b.y - c.y * b.x) / bDotDPerp; if (finiteOther && (u < 0.0f || u > 1.0f)) { return(false); } intersection = m_PointA + t * b; return(true); }
/// <summary> /// Gets the color from gradient at time. /// </summary> /// <returns>The color from gradient at time.</returns> /// <param name="gradient">Gradient.</param> /// <param name="time">Time.</param> private Color GetColorFromGradientAtTime(Gradient gradient, float time) { if (!HydraMathUtils.Approximately(m_GradientLength, 0.0f)) { time /= m_GradientLength; } return(gradient.Evaluate(time, m_GradientWrapMode)); }
/// <summary> /// Draws the curve swatch. /// </summary> /// <param name="position">Position.</param> /// <param name="property">Property.</param> /// <param name="color">Color.</param> /// <param name="curveRanges">Curve ranges.</param> private void DrawCurveSwatch(Rect position, SerializedProperty property, Color color, Rect curveRanges) { Rect curvePosition = new Rect(position); // Special case - The curve is a flat line. if (HydraMathUtils.Approximately(curveRanges.height, 0.0f)) { curveRanges.y = -0.5f + curveRanges.y; curveRanges.height = 1.0f; } EditorGUIUtility.DrawCurveSwatch(curvePosition, property.animationCurveValue, property, color, s_CurveBackgroundColor, curveRanges); }
/// <summary> /// Gets the gradient at the given time. /// </summary> /// <returns>The gradient.</returns> /// <param name="extends">Extends.</param> /// <param name="time">Time.</param> public static float GetGradient(this AnimationCurve extends, float time) { float end = extends.GetEndTime(); bool isEnd = HydraMathUtils.Approximately(end, time); float firstTime = isEnd ? time - CURVE_DELTA_FUDGE : time; float secondTime = isEnd ? time : time + CURVE_DELTA_FUDGE; // Cheat and check the value at time + some small amount float first = extends.Evaluate(firstTime); float second = extends.Evaluate(secondTime); return((second - first) / CURVE_DELTA_FUDGE); }
/// <summary> /// Shows the curve editor window for the given curve. /// </summary> /// <param name="curve">Curve.</param> /// <param name="title">Title.</param> /// <param name="color">Color.</param> private void EditCurve(AnimationCurve curve, string title, Color color) { CurveEditorWindowWrapper.ShowCurveEditorWindow(title); CurveEditorWindowWrapper.curve = curve; CurveEditorWindowWrapper.color = color; Rect bounds = NormalCurveRendererWrapper.GetBounds(curve); if (HydraMathUtils.Approximately(bounds.height, 0.0f)) { bounds.height = bounds.width; bounds.y -= bounds.height / 2.0f; } CurveEditorWindowWrapper.Frame(bounds); }
/// <summary> /// Processes the time increment. /// </summary> /// <param name="offset">Offset.</param> private void ProcessTimeIncrement(float offset) { offset *= m_TimeScale; // Timer isn't playing if (!m_IsPlaying) { return; } // No change if (HydraMathUtils.Approximately(offset, 0.0f)) { return; } m_Time += offset; OnTimeAliveChanged(offset); }
/// <summary> /// Draws a dot cap handle that returns the distance it was dragged along its normal. /// </summary> /// <returns>The distance the cap was dragged.</returns> /// <param name="position">Position.</param> /// <param name="rotation">Rotation.</param> /// <param name="normal">Normal.</param> public static float NormalMoveHandle(Vector3 position, Quaternion rotation, Vector3 normal) { Color oldColor = Handles.color; // Check if the face is facing the other direction if (Vector3.Dot(normal, ToCamera(position)) < 0.0f) { Handles.color *= new Color(1.0f, 1.0f, 1.0f, 0.5f); } Vector3 newPosition = Handles.FreeMoveHandle(position, rotation, GetDotSize(position), Vector3.zero, Handles.DotCap); Handles.color = oldColor; if (newPosition == position) { return(0.0f); } Vector3 newVector = newPosition - position; if (HydraMathUtils.Approximately(Vector3.Dot(newVector, normal), 0.0f)) { return(0.0f); } // Calculate how far the point was dragged along the normal float angle = Vector3.Angle(normal, newVector); bool positive = (angle < 90.0f); if (angle > 90.0f) { angle = 180.0f - angle; } float adjacent = Mathf.Cos(Mathf.Deg2Rad * angle) * newVector.magnitude; return((positive) ? adjacent * 1.0f : adjacent * -1.0f); }
/// <summary> /// Performs a 2D raycast without discarding the Z component. /// /// This method also ignores any collision at the start of the ray. This is consistent /// with the 3D raycast behaviour. /// </summary> /// <returns>The collision data.</returns> /// <param name="origin">Origin.</param> /// <param name="direction">Direction.</param> /// <param name="distance">Distance.</param> /// <param name="layerMask">Layer mask.</param> /// <param name="minDepth">Minimum depth.</param> /// <param name="maxDepth">Max depth.</param> public static Hit2DWrapper Raycast2D(Vector3 origin, Vector3 direction, float distance, int layerMask, float minDepth, float maxDepth) { if (layerMask == LayerMaskUtils.EMPTY) { return(default(Hit2DWrapper)); } RaycastHit2D[] collisions = Physics2D.RaycastAll(origin, direction, distance, layerMask, minDepth, maxDepth); for (int index = 0; index < collisions.Length; index++) { RaycastHit2D hit2D = collisions[index]; if (HydraMathUtils.Approximately(hit2D.fraction, 0.0f)) { continue; } return(new Hit2DWrapper(hit2D, origin, 0.0f, direction, distance)); } return(default(Hit2DWrapper)); }
/// <summary> /// Draws a cone size handle. /// </summary> /// <returns>The radius, angle and length in a Vector3 tuple.</returns> /// <param name="rotation">Rotation.</param> /// <param name="position">Position.</param> /// <param name="radius">Radius.</param> /// <param name="angle">Angle.</param> /// <param name="length">Length.</param> public static Vector3 ConeSizeHandle(Quaternion rotation, Vector3 position, float radius, float angle, float length) { // Base circle radius = CircleRadiusHandle(rotation, position, radius); // Now we need to do some maths to get the radius of the secondary circle float secondaryRadius = radius + Mathf.Tan(Mathf.Deg2Rad * angle) * length; // Draw the struts Vector3 secondaryCirclePosition = position + rotation * Vector3.forward * length; Handles.DrawLine(position + rotation * Vector3.up * radius, secondaryCirclePosition + rotation * Vector3.up * secondaryRadius); Handles.DrawLine(position + rotation * Vector3.down * radius, secondaryCirclePosition + rotation * Vector3.down * secondaryRadius); Handles.DrawLine(position + rotation * Vector3.left * radius, secondaryCirclePosition + rotation * Vector3.left * secondaryRadius); Handles.DrawLine(position + rotation * Vector3.right * radius, secondaryCirclePosition + rotation * Vector3.right * secondaryRadius); // Draw the secondary circle float newSecondaryRadius = CircleRadiusHandle(rotation, secondaryCirclePosition, secondaryRadius); newSecondaryRadius = HydraMathUtils.Max(newSecondaryRadius, radius); if (!HydraMathUtils.Approximately(newSecondaryRadius, secondaryRadius)) { float delta = newSecondaryRadius - radius; angle = Mathf.Rad2Deg * Mathf.Atan(delta / length); } // Draw the dot in the middle of the secondary circle length += NormalMoveHandle(secondaryCirclePosition, rotation, rotation * Vector3.forward); return(new Vector3(radius, angle, length)); }