public override void OnSceneViewGUI(SceneView sceneView) { if (m_collectedData == null) { if (GetChild <SelectGameObjectTool>() == null) { SelectGameObjectTool selectGameObjectTool = new SelectGameObjectTool(); selectGameObjectTool.OnSelect = go => { m_collectedData = new CollectedData() { Target = go }; }; AddChild(selectGameObjectTool); } } else if (!m_collectedData.TriangleGiven) { // TODO: Handle world point? if (m_collectedData.Target == null) { PerformRemoveFromParent(); return; } HighlightObject = m_collectedData.Target; m_collectedData.RaycastResult = Utils.Raycast.Intersect(HandleUtility.GUIPointToWorldRay(Event.current.mousePosition), m_collectedData.Target, m_collectedData.Target.GetComponent <AGXUnity.RigidBody>() != null); // Done (next state) when the user left click and we've a valid triangle. m_collectedData.TriangleGiven = m_collectedData.RaycastResult && Manager.HijackLeftMouseClick(); } else if (!m_collectedData.RotationGiven) { if (GetChild <DirectionTool>() == null) { DirectionTool directionTool = new DirectionTool(m_collectedData.RaycastResult.Point, m_collectedData.RaycastResult.Triangle.Normal, m_collectedData.RaycastResult.ClosestEdge.Direction); directionTool.OnSelect += (position, rotation) => { m_collectedData.Rotation = rotation; m_collectedData.RotationGiven = true; }; AddChild(directionTool); } } else { Result resultingData = new Result() { Target = m_collectedData.Target, RaycastResult = m_collectedData.RaycastResult, Rotation = m_collectedData.Rotation }; OnPointFound(resultingData); PerformRemoveFromParent(); } PointVisual.Visible = m_collectedData != null && m_collectedData.RaycastResult && !m_collectedData.TriangleGiven; if (PointVisual.Visible) { PointVisual.SetTransform(m_collectedData.RaycastResult.Point, Quaternion.identity, 0.05f); } }
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) { HighlightObject = m_collectedData.Target; // Similar behavior as FindPointTool - remove ourself if // the users choice is World. if (m_collectedData.Target == null) { PerformRemoveFromParent(); return; } var ray = HandleUtility.GUIPointToWorldRay(Event.current.mousePosition); var result = Utils.Raycast.Intersect(ray, m_collectedData.Target); m_collectedData.CurrentEdge = FindClosestEdgeIncludingTargetPrincipalAxes(ray, result.ClosestEdge); } // 3. Find point on edge - hold ctrl for "no-snap" mode. else if (!m_collectedData.PointOnEdgeGiven) { Vector3 pointOnEdge = FindClosestPointOnEdge(m_collectedData.SelectedEdge); 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).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.Direction, m_collectedData.SelectedEdge.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 { var orgEdge = m_collectedData.SelectedEdge; var resultingData = new Result() { Target = m_collectedData.Target, Edge = new AGXUnity.Edge() { Start = m_collectedData.PointOnEdge + 0.5f * orgEdge.Length * (m_collectedData.DirectionRotation * Vector3.back), End = m_collectedData.PointOnEdge + 0.5f * orgEdge.Length * (m_collectedData.DirectionRotation * Vector3.forward), Normal = m_collectedData.DirectionRotation * Vector3.up, Type = AGXUnity.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.Start, m_collectedData.CurrentEdge.End, edgeRadius); if (m_collectedData.CurrentEdge.Type == AGXUnity.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.Type == AGXUnity.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(new Utils.Raycast.Result() { Hit = false }, NodeVisual); } } }