/// <summary> /// When the mouse is pressed in the 3D view, we want to select the clicked object. /// </summary> /// <param name="viewport">The viewport that was clicked</param> /// <param name="e">The click event</param> protected override void MouseDown3D(Viewport3D viewport, ViewportEvent e) { // Do not perform selection if space is down if (Sledge.Settings.View.Camera3DPanRequiresMouseClick && KeyboardState.IsKeyDown(Keys.Space)) { return; } // First, get the ray that is cast from the clicked point along the viewport frustrum var ray = viewport.CastRayFromScreen(e.X, e.Y); // Grab all the elements that intersect with the ray var hits = Document.Map.WorldSpawn.GetAllNodesIntersectingWith(ray); // Sort the list of intersecting elements by distance from ray origin IntersectingObjectsFor3DSelection = hits .Select(x => new { Item = x, Intersection = GetIntersectionPoint(x, ray) }) .Where(x => x.Intersection != null) .OrderBy(x => (x.Intersection - ray.Start).VectorMagnitude()) .Select(x => x.Item) .ToList(); // By default, select the closest object ChosenItemFor3DSelection = IntersectingObjectsFor3DSelection.FirstOrDefault(); // If Ctrl is down and the object is already selected, we should deselect it instead. var list = new[] { ChosenItemFor3DSelection }; var desel = ChosenItemFor3DSelection != null && KeyboardState.Ctrl && ChosenItemFor3DSelection.IsSelected; SetSelected(desel ? list : null, desel ? null : list, !KeyboardState.Ctrl, IgnoreGrouping()); State.ActiveViewport = null; }
/// <summary> /// The select tool captures the mouse wheel when the mouse is down in the 3D viewport /// </summary> /// <returns>True if the select tool is capturing wheel events</returns> public override bool IsCapturingMouseWheel() { return(IntersectingObjectsFor3DSelection != null && IntersectingObjectsFor3DSelection.Any() && ChosenItemFor3DSelection != null); }
/// <summary> /// When the mouse wheel is scrolled while the mouse is down in the 3D view, cycle through the candidate elements. /// </summary> /// <param name="viewport">The viewport that was scrolled</param> /// <param name="e">The scroll event</param> public override void MouseWheel(ViewportBase viewport, ViewportEvent e) { if (WidgetAction((w, vp, ev) => w.MouseWheel(vp, ev), viewport, e)) { return; } // If we're not in 3D cycle mode, carry on if (!(viewport is Viewport3D) || IntersectingObjectsFor3DSelection == null || ChosenItemFor3DSelection == null) { return; } var desel = new List <MapObject>(); var sel = new List <MapObject>(); // Select (or deselect) the current element if (ChosenItemFor3DSelection.IsSelected) { desel.Add(ChosenItemFor3DSelection); } else { sel.Add(ChosenItemFor3DSelection); } // Get the index of the current element var index = IntersectingObjectsFor3DSelection.IndexOf(ChosenItemFor3DSelection); if (index < 0) { return; } // Move the index in the mouse wheel direction, cycling if needed var dir = e.Delta / Math.Abs(e.Delta); index = (index + dir) % IntersectingObjectsFor3DSelection.Count; if (index < 0) { index += IntersectingObjectsFor3DSelection.Count; } ChosenItemFor3DSelection = IntersectingObjectsFor3DSelection[index]; // Select (or deselect) the new current element if (ChosenItemFor3DSelection.IsSelected) { desel.Add(ChosenItemFor3DSelection); } else { sel.Add(ChosenItemFor3DSelection); } SetSelected(desel, sel, false, IgnoreGrouping()); State.ActiveViewport = null; }