/// <summary> /// Handles the control logic for adding a point. This will draw a red line from the mouse position to the closest point along the /// curve /// </summary> /// <param name="spline">spline to handle control point logic for</param> protected void PointSelection(ISpline2DEditor spline) { float2 mouse = EditorInputAbstractions.MousePos2D(); int splineIndex; float2 createPoint = ClosestPointSelection(mouse, spline, out splineIndex); if (splineIndex != m_editNewPointIndex) { m_editNewPointIndex = splineIndex; Repaint(); // force refresh inspector } Handles.color = Color.red; Handles.DrawLine( new Vector3(createPoint.x, createPoint.y, 0f), new Vector3(mouse.x, mouse.y, 0f)); if (EditorInputAbstractions.LeftClick() && spline is Object objSpline) { Undo.RecordObject(objSpline, "Insert Spline Point"); EditorUtility.SetDirty(objSpline); float3 origin = m_sourceTrans.position; spline.InsertControlPoint(m_editNewPointIndex, mouse - origin.xy); SceneView.RepaintAll(); } }
private void OnSceneGUI() { if (!m_editing) { if (m_debugPointQty > 0) { RenderIntermediateSplinePoints(m_debugPointQty, pointSpline); } return; } if (m_editControlPoint.HasValue && EditorInputAbstractions.AddPointMode()) { m_editControlPoint = null; } CheckActiveCamera(); RenderControlPoints(pointSpline); if (EditorInputAbstractions.AddPointMode() && SceneView.currentDrawingSceneView == SceneView.lastActiveSceneView) { PointSelection(pointSpline); if (Event.current.type == EventType.MouseMove) { SceneView.RepaintAll(); } } }
private void OnSceneGUI() { if (!m_editing) { if (m_debugPointQty > 0) { RenderIntermediateSplinePoints(m_debugPointQty, cubic2DSpline); } return; } if (m_editControlPoint.HasValue && EditorInputAbstractions.AddPointMode()) { m_editControlPoint = null; } RenderControlPoints(cubic2DSpline); if (EditorInputAbstractions.AddPointMode()) { PointSelection(cubic2DSpline); if (Event.current.type == EventType.MouseMove) { SceneView.RepaintAll(); } } }
/// <summary> /// Handles the control logic for adding a point. This will draw a red line from the mouse position to the closest point along the /// curve /// </summary> /// <param name="spline">spline to handle control point logic for</param> protected void PointSelection(ISpline3DEditor spline) { int splineIndex; float3 splinePoint, splineMousePoint; ClosestPointSelection(Event.current.mousePosition, spline, out splineIndex, out splinePoint, out splineMousePoint); if (splineIndex != m_editNewPointIndex) { m_editNewPointIndex = splineIndex; Repaint(); // force refresh inspector } Handles.color = Color.red; Handles.DrawLine(splinePoint, splineMousePoint); if (EditorInputAbstractions.LeftClick() && spline is Object objSpline) { Undo.RecordObject(objSpline, "Insert Spline Point"); EditorUtility.SetDirty(objSpline); if ((m_editNewPointIndex == spline.ControlPointCount - 1 || spline.ControlPointCount == 1) && splinePoint.Equals(spline.GetControlPoint3DLocal(m_editNewPointIndex))) { spline.AddControlPoint(splineMousePoint); } else { spline.InsertControlPointWorldSpace(m_editNewPointIndex, splineMousePoint); } SceneView.RepaintAll(); } }
/// <summary> /// Find the closest point to the spline /// </summary> /// <param name="mouse">mouse position</param> /// <param name="spline">spline to check</param> /// <param name="index">spline index of the closest point</param> /// <param name="splinePoint">Point on spline that is closest</param> /// <param name="creationPoint">point that aligned to the mouse point relative to the camera</param> /// <returns>true is point could be found</returns> protected virtual bool ClosestPointSelection(float2 mouse, ISpline3DEditor spline, out int index, out float3 splinePoint, out float3 creationPoint) { index = 0; float2 mouseComparison = new float2(mouse.x, LastSceneCamera.pixelHeight - mouse.y); if (spline.ControlPointCount == 0) { splinePoint = EditorInputAbstractions.MousePos3D(); } if (spline.ControlPointCount == 1) { splinePoint = spline.GetControlPoint3DLocal(0); } else { splinePoint = float3.zero; float bestDistance = float.MaxValue; const int segmentSampleAmount = 64; const float segmentSampleAmountF = segmentSampleAmount; // this could potentially be cached as long as the spline doesn't change and the camera is at the same position for (int i = 1; i < spline.SegmentPointCount; i++) { for (int s = 0; s <= segmentSampleAmount; s++) { float progress = s / segmentSampleAmountF; float3 p = spline.Get3DPoint(progress, i - 1); Vector3 screenPosition = LastSceneCamera.WorldToScreenPoint(p); float dist = math.distance(mouseComparison, new float2(screenPosition.x, screenPosition.y)); if (bestDistance > dist) { splinePoint = p; index = i; bestDistance = dist; } } } if (!(spline is ILoopingSpline) || !((ILoopingSpline)spline).Looped) { if (math.distance(splinePoint, spline.GetControlPoint3DWorld(0)) <= 0.00001f) { index = 0; } else if (math.distance(splinePoint, spline.GetControlPoint3DWorld(spline.ControlPointCount - 1)) <= 0.00001f) { index = spline.ControlPointCount; } } } // convert the spline point and mouse position into the new point position if (!splinePoint.Equals(float3.zero)) { Vector3 camPosition = LastSceneCameraTrans.position; float worldDistance = math.distance(splinePoint, camPosition); Ray cameraRay = LastSceneCamera.ScreenPointToRay(new Vector3(mouseComparison.x, mouseComparison.y, 0f)); creationPoint = cameraRay.GetPoint(worldDistance); return(true); } creationPoint = default; return(false); }