private static void UpdateMouseOverPrimitives(Event current) { // Can't perform picking during repaint event. if (current == null || !(current.isMouse || current.isKey)) { return; } // Update mouse over before we reveal the VisualPrimitives. // NOTE: We're putting our "visual primitives" in the ignore list. if (current.isMouse) { List <GameObject> ignoreList = new List <GameObject>(); foreach (var primitive in m_visualPrimitives) { if (!primitive.Visible) { continue; } MeshFilter[] primitiveFilters = primitive.Node.GetComponentsInChildren <MeshFilter>(); ignoreList.AddRange(primitiveFilters.Select(pf => { return(pf.gameObject); })); } // If the mouse is hovering a scene view window - MouseOverObject should be null. if (SceneViewWindow.GetMouseOverWindow(current.mousePosition) != null) { MouseOverObject = null; } else { MouseOverObject = RouteObject(HandleUtility.PickGameObject(current.mousePosition, false, ignoreList.ToArray())) as GameObject; } } // Early exit if we haven't any active visual primitives. if (m_visualPrimitives.Count == 0) { return; } var primitiveHitList = new[] { new { Primitive = (Utils.VisualPrimitive)null, RaycastResult = Raycast.Hit.Invalid } }.ToList(); primitiveHitList.Clear(); Ray mouseRay = HandleUtility.GUIPointToWorldRay(current.mousePosition); foreach (var primitive in m_visualPrimitives) { primitive.MouseOver = false; if (!primitive.Pickable) { continue; } Raycast.Hit hit = Raycast.Test(primitive.Node, mouseRay, 500f, true); if (hit.Triangle.Valid) { primitiveHitList.Add(new { Primitive = primitive, RaycastResult = hit }); } } if (primitiveHitList.Count == 0) { return; } var bestResult = primitiveHitList[0]; for (int i = 1; i < primitiveHitList.Count; ++i) { if (primitiveHitList[i].RaycastResult.Triangle.Distance < bestResult.RaycastResult.Triangle.Distance) { bestResult = primitiveHitList[i]; } } bestResult.Primitive.MouseOver = true; if (HijackLeftMouseClick()) { bestResult.Primitive.OnMouseClick(bestResult.RaycastResult, bestResult.Primitive); } }
public override void OnSceneViewGUI(SceneView sceneView) { if (EdgeVisual.Visible && EdgeVisual.MouseOver) { return; } // 1. Find target game object. if (m_collectedData == null) { if (GetChild <SelectGameObjectTool>() == null) { SelectGameObjectTool selectGameObjectTool = new SelectGameObjectTool(); selectGameObjectTool.OnSelect = go => { m_collectedData = new CollectedData() { Target = go }; }; AddChild(selectGameObjectTool); } } // 2. Select edge on target game object. else if (!m_collectedData.SelectedEdge.Valid) { Raycast.Hit hit = Raycast.Test(m_collectedData.Target, HandleUtility.GUIPointToWorldRay(Event.current.mousePosition)); if (hit.ClosestEdge.Valid) { m_collectedData.CurrentEdge = hit.ClosestEdge; } } // 3. Find point on edge - hold ctrl for "no-snap" mode. else if (!m_collectedData.PointOnEdgeGiven) { Vector3 pointOnEdge = FindClosestPointOnEdge(m_collectedData.SelectedEdge.Edge); if (Event.current.control) { m_collectedData.PointOnEdge = pointOnEdge; } else { float snapValue = 0.5f * HandleUtility.GetHandleSize(pointOnEdge); float closestDistance = float.PositiveInfinity; Vector3 closestPoint = pointOnEdge; Vector3[] predefinedPoints = FindPredefinedEdgePoints(m_collectedData.SelectedEdge.Edge).ToArray(); // Given set of predefined points along the edge, finds the // closest to the mouse ray (i.e., the actual point on the edge). foreach (var point in predefinedPoints) { float distanceToPoint = Vector3.Distance(pointOnEdge, point); if (distanceToPoint < snapValue && distanceToPoint < closestDistance) { closestPoint = point; closestDistance = distanceToPoint; } } m_collectedData.PointOnEdge = closestPoint; } } // 4. Find direction. else if (!m_collectedData.DirectionGiven) { if (GetChild <DirectionTool>() == null) { DirectionTool directionTool = new DirectionTool(m_collectedData.PointOnEdge, m_collectedData.SelectedEdge.Edge.Direction, m_collectedData.SelectedEdge.Edge.Normal); directionTool.OnSelect += (position, rotation) => { m_collectedData.DirectionRotation = rotation; m_collectedData.DirectionGiven = true; }; AddChild(directionTool); } } // 5. Done, fire callback with result and remove us. else { MeshUtils.Edge orgEdge = m_collectedData.SelectedEdge.Edge; Result resultingData = new Result() { Target = m_collectedData.Target, Edge = new MeshUtils.Edge(m_collectedData.PointOnEdge + 0.5f * orgEdge.Length * (m_collectedData.DirectionRotation * Vector3.back), m_collectedData.PointOnEdge + 0.5f * orgEdge.Length * (m_collectedData.DirectionRotation * Vector3.forward), m_collectedData.DirectionRotation * Vector3.up, MeshUtils.Edge.EdgeType.Triangle), Position = m_collectedData.PointOnEdge, Rotation = m_collectedData.DirectionRotation }; OnEdgeFound(resultingData); PerformRemoveFromParent(); return; } EdgeVisual.Visible = m_collectedData != null && m_collectedData.CurrentEdge.Valid; if (EdgeVisual.Visible) { const float edgeRadius = 0.035f; const float defaultAlpha = 0.25f; const float mouseOverAlpha = 0.65f; EdgeVisual.SetTransform(m_collectedData.CurrentEdge.Edge.Start, m_collectedData.CurrentEdge.Edge.End, edgeRadius); if (m_collectedData.CurrentEdge.Edge.Type == MeshUtils.Edge.EdgeType.Triangle) { EdgeVisual.Color = new Color(Color.yellow.r, Color.yellow.g, Color.yellow.b, defaultAlpha); EdgeVisual.MouseOverColor = new Color(Color.yellow.r, Color.yellow.g, Color.yellow.b, mouseOverAlpha); } else if (m_collectedData.CurrentEdge.Edge.Type == MeshUtils.Edge.EdgeType.Principal) { EdgeVisual.Color = new Color(Color.red.r, Color.red.g, Color.red.b, defaultAlpha); EdgeVisual.MouseOverColor = new Color(Color.red.r, Color.red.g, Color.red.b, mouseOverAlpha); } } NodeVisual.Visible = EdgeVisual.Visible && m_collectedData.SelectedEdge.Valid; if (NodeVisual.Visible) { const float nodeRadius = 0.040f; NodeVisual.SetTransform(m_collectedData.PointOnEdge, Quaternion.identity, nodeRadius); // The user doesn't have to hit the node sphere. if (Manager.HijackLeftMouseClick()) { OnPointClick(null, NodeVisual); } } }
/// <summary> /// Callback when the edge has been picked. /// </summary> private void OnEdgeClick(Raycast.Hit hit, Utils.VisualPrimitive primitive) { m_collectedData.SelectedEdge = m_collectedData.CurrentEdge; EdgeVisual.Pickable = false; NodeVisual.Pickable = false; }
/// <summary> /// Callback when the node/position has been picked. /// </summary> private void OnPointClick(Raycast.Hit hit, Utils.VisualPrimitive primitive) { m_collectedData.PointOnEdgeGiven = true; }
private void OnPrimitiveClick(Raycast.Hit hit, Utils.VisualPrimitive primitive) { OnSelect(Position, GetRotation(Vector3.forward, GetDirection(primitive))); PerformRemoveFromParent(); }