예제 #1
0
        void ClickEnd([NotNull] object sender, [NotNull] KeyEventArgs e)
        {
            if (!Selected)
            {
                return;
            }

            BlockPosition pos;

            if (!Camera.TryGetBlockAtMousePosition(out pos))
            {
                return;
            }

            switch (SelectionState)
            {
            case SelectionState.NotSet:
                NewSelection(pos, pos, SelectionState.HalfSet);
                break;

            case SelectionState.HalfSet:
            case SelectionState.DragMove:
                NewSelection(_cornerOne, pos, SelectionState.Set);
                break;

            case SelectionState.Set:
                NewSelection(pos, pos, SelectionState.HalfSet);
                break;

            default:
                Debug.Fail("SelectionState out of range");
                break;
            }
        }
예제 #2
0
        void DragMove([NotNull] object sender, [NotNull] KeyEventArgs e)
        {
            // update face drag
            if (!Selected)
            {
                return;
            }

            var selection = Selection;

            var faceDragRay = _faceDragRay;

            if (faceDragRay == default(Ray))
            {
                return;
            }

            var pos = Camera.Position;

            // dragPlane is used to hit-test the unprojected mouse position
            // we need to calculate the dragPlane every DragMove, as Camera.Position can change
            var dragPlane = faceDragRay.ToPlane(pos);
            var mouseRay  = Camera.ScreenPointToRay(e.Position);

            // find where the mouse intersects the drag plane
            Vector3 mouseHit;

            if (!dragPlane.Intersects(ref mouseRay, out mouseHit))
            {
                return;
            }

            // use pythagorean (C^2-B^2=A^2) to calculate distance from faceDragRay
            var diff     = mouseHit - faceDragRay.Position;
            var cSquared = diff.LengthSquared();
            var b        = faceDragRay.Distance(mouseHit);
            var a        = (float)Math.Sqrt(cSquared - b * b);

            // Determine if the drag is moving the face away or towards its center
            // We need this because direction information is always positive
            var draggingFromCenter = Vector3.Dot(faceDragRay.Direction, diff) < 0;

            if (draggingFromCenter)
            {
                a = -a;
            }

            var dragPosWorldSpace = faceDragRay.Position + faceDragRay.Direction * a;
            var alignedDragDir    = faceDragRay.Direction.GetFace();
            var lesser            = selection.Lesser;
            var greater           = selection.Greater;

            switch (alignedDragDir)
            {
            case Faces.Left:
                NewSelection(new BlockPosition((int)dragPosWorldSpace.X, lesser.Y, lesser.Z), greater,
                             SelectionState.DragMove);
                break;

            case Faces.Right:
                NewSelection(lesser, new BlockPosition((int)dragPosWorldSpace.X, greater.Y, greater.Z),
                             SelectionState.DragMove);
                break;

            case Faces.Bottom:
                NewSelection(new BlockPosition(lesser.X, (int)dragPosWorldSpace.Y, lesser.Z), greater,
                             SelectionState.DragMove);
                break;

            case Faces.Top:
                NewSelection(lesser, new BlockPosition(greater.X, (int)dragPosWorldSpace.Y, greater.Z),
                             SelectionState.DragMove);
                break;

            case Faces.Forward:
                NewSelection(new BlockPosition(lesser.X, lesser.Y, (int)dragPosWorldSpace.Z), greater,
                             SelectionState.DragMove);
                break;

            case Faces.Backward:
                NewSelection(lesser, new BlockPosition(greater.X, greater.Y, (int)dragPosWorldSpace.Z),
                             SelectionState.DragMove);
                break;

            default:
                Debug.Fail("Vector3Extensions.GetFace didn't return a valid face");
                break;
            }
        }
예제 #3
0
 void DragEnd([NotNull] object sender, [NotNull] KeyEventArgs e)
 {
     _faceDragRay = default(Ray);
     NewSelection(_cornerOne, _cornerTwo, SelectionState.Set);
 }
예제 #4
0
        void DragStart([NotNull] object sender, [NotNull] KeyEventArgs e)
        {
            // Drag the face of the selection along its axis
            if (SelectionState != SelectionState.Set)
            {
                return;
            }
            var selection = Selection;

            var cuboid      = selection.GetCuboid();
            var lesser      = new Vector3(selection.Lesser.X, selection.Lesser.Y, selection.Lesser.Z);
            var greaterTemp = cuboid.Position + cuboid.Dimensions;
            var greater     = new Vector3(greaterTemp.X, greaterTemp.Y, greaterTemp.Z);
            var pos         = Camera.Position;

            // Calculate if the mouse is over the selection
            var     selectionBox = new BoundingBox(lesser, greater);
            var     ray          = Camera.ScreenPointToRay(e.Position);
            Vector3 hit;

            if (!selectionBox.Intersects(ref ray, out hit))
            {
                return;
            }
            var roundedHit = hit.Round(); // BoundingBox.Intersects can return a value + epsilon, so round it

            // enumerate faces
            // left
            if (pos.X < roundedHit.X && Math.Abs(hit.X - lesser.X) < .01 &&
                new Plane(lesser, Vector3.Left).Intersects(ref roundedHit) == PlaneIntersectionType.Intersecting)
            {
                _faceDragRay = new Ray(roundedHit, Vector3.Left);
            }
            // right
            else if (pos.X > roundedHit.X && Math.Abs(hit.X - greater.X) < .01 &&
                     new Plane(greater, Vector3.Right).Intersects(ref roundedHit) == PlaneIntersectionType.Intersecting)
            {
                _faceDragRay = new Ray(roundedHit, Vector3.Right);
            }
            // down
            else if (pos.Y < roundedHit.Y && Math.Abs(hit.Y - lesser.Y) < .01 &&
                     new Plane(lesser, Vector3.Down).Intersects(ref roundedHit) == PlaneIntersectionType.Intersecting)
            {
                _faceDragRay = new Ray(roundedHit, Vector3.Down);
            }
            // up
            else if (pos.Y > roundedHit.Y && Math.Abs(hit.Y - greater.Y) < .01 &&
                     new Plane(greater, Vector3.Up).Intersects(ref roundedHit) ==
                     PlaneIntersectionType.Intersecting)
            {
                _faceDragRay = new Ray(roundedHit, Vector3.Up);
            }
            // forward
            else if (pos.Z < roundedHit.Z && Math.Abs(hit.Z - lesser.Z) < .01 &&
                     new Plane(lesser, Vector3.ForwardRH).Intersects(ref roundedHit) ==
                     PlaneIntersectionType.Intersecting)
            {
                _faceDragRay = new Ray(roundedHit, Vector3.ForwardRH);
            }
            // back
            else if (pos.Z > roundedHit.Z && Math.Abs(hit.Z - greater.Z) < .01 &&
                     new Plane(greater, Vector3.BackwardRH).Intersects(ref roundedHit) ==
                     PlaneIntersectionType.Intersecting)
            {
                _faceDragRay = new Ray(roundedHit, Vector3.BackwardRH);
            }
        }