IEnumerator <object> DragTangent(SplinePoint3D point, int tangentIndex) { var input = SceneView.Instance.Input; Document.Current.History.BeginTransaction(); Vector3?posCorrection = null; try { var spline = (Spline3D)Document.Current.Container; var viewport = spline.Viewport; var plane = CalcPlane(spline, point.Position + GetTangent(point, tangentIndex)); var tangentsAreEqual = (point.TangentA + point.TangentB).Length < 0.1f; while (input.IsMousePressed()) { Document.Current.History.RevertActiveTransaction(); Utils.ChangeCursorIfDefault(MouseCursor.Hand); var ray = viewport.ScreenPointToRay(input.MousePosition); var distance = ray.Intersects(plane); if (distance.HasValue) { var pos = (ray.Position + ray.Direction * distance.Value) * spline.GlobalTransform.CalcInverted() - point.Position; posCorrection = posCorrection ?? GetTangent(point, tangentIndex) - pos; Core.Operations.SetAnimableProperty.Perform(point, GetTangentPropertyName(tangentIndex), pos + posCorrection.Value); if (input.IsKeyPressed(Key.Shift) ^ tangentsAreEqual) { Core.Operations.SetAnimableProperty.Perform(point, GetTangentPropertyName(1 - tangentIndex), -(pos + posCorrection.Value)); } } yield return(null); } } finally { Document.Current.History.EndTransaction(); } }
void DrawSplinePoint(SplinePoint3D point, Viewport3D viewport, Matrix44 splineWorldMatrix, bool selected) { var color = selected ? Color4.Green : Color4.Red; var viewportToSceneFrame = viewport.CalcTransitionToSpaceOf(SceneView.Instance.Frame); var a = (Vector2)viewport.WorldToViewportPoint(point.Position * splineWorldMatrix) * viewportToSceneFrame; Renderer.DrawRect(a - Vector2.One * 3, a + Vector2.One * 3, color); for (int i = 0; i < 2; i++) { var t = i == 0 ? point.TangentA : point.TangentB; var b = (Vector2)viewport.WorldToViewportPoint((point.Position + t) * splineWorldMatrix) * viewportToSceneFrame; Renderer.DrawLine(a, b, color, 1); Renderer.DrawRect(b - Vector2.One * 1.5f, b + Vector2.One * 1.5f, color); } }
Vector3 GetTangent(SplinePoint3D point, int index) => index == 0 ? point.TangentA : point.TangentB;