예제 #1
0
        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);
            }
        }
예제 #2
0
        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);
                }
            }
        }
예제 #3
0
 /// <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;
 }
예제 #4
0
 /// <summary>
 /// Callback when the node/position has been picked.
 /// </summary>
 private void OnPointClick(Raycast.Hit hit, Utils.VisualPrimitive primitive)
 {
     m_collectedData.PointOnEdgeGiven = true;
 }
예제 #5
0
        private void OnPrimitiveClick(Raycast.Hit hit, Utils.VisualPrimitive primitive)
        {
            OnSelect(Position, GetRotation(Vector3.forward, GetDirection(primitive)));

            PerformRemoveFromParent();
        }