AutoCAD like selection style

Here's the Eyeshot code to simulate the selection style of AutoCAD®. Clicking the mouse will set the pick state to "Pick". When moving the mouse to the right more than 10 pixels, the pick state changes to Enclosed and when moving to the left of the same amount the pick state becomes Crossing. A transparent rectangle is drawn in overlay according to the pick state and when releasing the mouse the selection is performed according to the pick state. Instead of the Design.SelectionChanged event, we raise a CustomSelectionChanged event with the added and removed entities computed in the OnMouseUp().

Animation.gif

  • WinForms code:
internal class MyDesign : devDept.Eyeshot.Control.Design
{

    private enum pickState
    {
        Pick,
        Enclosed,
        Crossing
    };

    private pickState currPickState;
    private bool buttonPressed;

    private System.Drawing.Point initialLocation;
    private System.Drawing.Point currentLocation;

    protected override void OnMouseDown(MouseEventArgs e)
    {
        if (e.Button == MouseButtons.Left && ActionMode == actionType.None)
        {
            if (!ActiveViewport.ViewCubeIcon.Contains(e.Location))
            {
                buttonPressed = true;
                initialLocation = currentLocation = e.Location;
                currPickState = pickState.Pick;
            }
        }

        base.OnMouseDown(e);
    }

    protected override void OnMouseMove(MouseEventArgs e)
    {
        if (buttonPressed)
        {
            int diffX = e.Location.X - initialLocation.X;

            if (diffX > 10)
                currPickState = pickState.Enclosed;
            else if (diffX < -10)
                currPickState = pickState.Crossing;
            else
                currPickState = pickState.Pick;

            currentLocation = e.Location;

            PaintBackBuffer();
            SwapBuffers();
        }

        base.OnMouseMove(e);
    }

    protected override void OnMouseUp(MouseEventArgs e)
    {
        List<int> added = new List<int>();
        List<int> removed = new List<int>();

        if (buttonPressed)
        {
            IList<Entity> myEnts = CurrentBlockReference != null
                ? Blocks[CurrentBlockReference.BlockName].Entities
                : (IList<Entity>)new List<Entity>(Entities);

            buttonPressed = false;
            int ent;
            int[] ents;

            if (ModifierKeys != Keys.Control)
            {
                for (int i = 0; i < myEnts.Count; i++)
                {
                    if (myEnts[i].Selected)
                        removed.Add(i);

                    myEnts[i].Selected = false;
                }
            }

            int dx = currentLocation.X - initialLocation.X;
            int dy = currentLocation.Y - initialLocation.Y;

            System.Drawing.Point p1 = initialLocation;
            System.Drawing.Point p2 = currentLocation;

            NormalizeBox(ref p1, ref p2);

            switch (currPickState)
            {
                case pickState.Pick:

                    ent = GetEntityUnderMouseCursor(currentLocation);

                    if (ent >= 0)
                    {
                        ManageSelection(ent, myEnts, added, removed);
                    }

                    break;

                case pickState.Crossing:

                    if (dx != 0 && dy != 0)
                    {
                        ents =
                            GetAllCrossingEntities(new System.Drawing.Rectangle(p1,
                                new System.Drawing.Size(Math.Abs(dx), Math.Abs(dy))));

                        for (int i = 0; i < ents.Length; i++)
                        {
                            ManageSelection(ents[i], myEnts, added, removed);
                        }
                    }

                    break;

                case pickState.Enclosed:

                    if (dx != 0 && dy != 0)
                    {
                        ents =
                            GetAllEnclosedEntities(new System.Drawing.Rectangle(p1,
                                new System.Drawing.Size(Math.Abs(dx), Math.Abs(dy))));

                        for (int i = 0; i < ents.Length; i++)
                        {
                            ManageSelection(ents[i], myEnts, added, removed);
                        }
                    }
                    break;

            }
            Invalidate();
        }

        if (CustomSelectionChanged != null)
            CustomSelectionChanged(this, new SelectionChangedEventArgs(added.ToArray(), removed.ToArray(), this));

        base.OnMouseUp(e);
    }

    private void ManageSelection(int ent, IList<Entity> myEnts, List<int> added, List<int> removed)
    {
        if (ModifierKeys == Keys.Control)
        {
            myEnts[ent].Selected = !myEnts[ent].Selected;
            if (myEnts[ent].Selected)
                added.Add(ent);
            else
                removed.Add(ent);
        }
        else
        {
            myEnts[ent].Selected = true;
            added.Add(ent);
        }
    }

    public event SelectionChangedEventHandler CustomSelectionChanged;

    protected override void DrawOverlay(DrawSceneParams data)
    {
        if (buttonPressed)
        {
            if (currPickState == pickState.Crossing)
                DrawSelectionBox(initialLocation, currentLocation, Color.DarkBlue, true, true);
            else if (currPickState == pickState.Enclosed)
                DrawSelectionBox(initialLocation, currentLocation, Color.DarkRed, true, false);
        }
    }

    void DrawSelectionBox(System.Drawing.Point p1, System.Drawing.Point p2, Color transparentColor, bool drawBorder,
        bool dottedBorder)
    {
        p1.Y = (int)(Height - p1.Y);
        p2.Y = (int)(Height - p2.Y);

        NormalizeBox(ref p1, ref p2);

        // Adjust the bounds so that it doesn't exit from the current viewport frame
        int[] viewFrame = ActiveViewport.GetViewFrame();
        int left = viewFrame[0];
        int top = viewFrame[1] + viewFrame[3];
        int right = left + viewFrame[2];
        int bottom = viewFrame[1];

        if (p2.X > right - 1)
            p2.X = right - 1;

        if (p2.Y > top - 1)
            p2.Y = top - 1;

        if (p1.X < left + 1)
            p1.X = left + 1;

        if (p1.Y < bottom + 1)
            p1.Y = bottom + 1;

        RenderContext.SetState(blendStateType.Blend);
        RenderContext.SetColorWireframe(System.Drawing.Color.FromArgb(40, transparentColor.R, transparentColor.G,
            transparentColor.B));
        RenderContext.SetState(rasterizerStateType.CCW_PolygonFill_CullFaceBack_NoPolygonOffset);

        int w = p2.X - p1.X;
        int h = p2.Y - p1.Y;

        RenderContext.DrawQuad(new System.Drawing.RectangleF(p1.X + 1, p1.Y + 1, w - 1, h - 1));
        RenderContext.SetState(blendStateType.NoBlend);

        if (drawBorder)
        {
            RenderContext.SetColorWireframe(System.Drawing.Color.FromArgb(255, transparentColor.R,
                transparentColor.G, transparentColor.B));

            List<Point3D> pts = null;

            if (dottedBorder)
            {
                RenderContext.SetLineStipple(1, 0x0F0F, Viewports[0].Camera);
                RenderContext.EnableLineStipple(true);
            }

            int l = p1.X;
            int r = p2.X;
            if (RenderContext.IsDirect3D) // In Eyeshot 9 use RenderContext.IsDirect3D
            {
                l += 1;
                r += 1;
            }

            pts = new List<Point3D>(new Point3D[]
            {
            new Point3D(l, p1.Y), new Point3D(p2.X, p1.Y),
            new Point3D(r, p1.Y), new Point3D(r, p2.Y),
            new Point3D(r, p2.Y), new Point3D(l, p2.Y),
            new Point3D(l, p2.Y), new Point3D(l, p1.Y),
            });


            RenderContext.DrawLines(pts.ToArray());

            if (dottedBorder)
                RenderContext.EnableLineStipple(false);
        }
    }

    internal static void NormalizeBox(ref System.Drawing.Point p1, ref System.Drawing.Point p2)
    {

        int firstX = Math.Min(p1.X, p2.X);
        int firstY = Math.Min(p1.Y, p2.Y);
        int secondX = Math.Max(p1.X, p2.X);
        int secondY = Math.Max(p1.Y, p2.Y);

        p1.X = firstX;
        p1.Y = firstY;
        p2.X = secondX;
        p2.Y = secondY;
    }

}
  • WPF code:
internal class MyDesign : devDept.Eyeshot.Control.Design
{
    private enum pickState
    {
        Pick,
        Enclosed,
        Crossing
    };

    private pickState currPickState;
    private bool buttonPressed;

    private System.Drawing.Point initialLocation;
    private System.Drawing.Point currentLocation;

    protected override void OnMouseDown(MouseButtonEventArgs e)
    {
        if (e.ChangedButton == System.Windows.Input.MouseButton.Left && ActionMode == actionType.None)
        {
            if (!ActiveViewport.ViewCubeIcon.Contains(RenderContextUtility.ConvertPoint(GetMousePosition(e))))
            {
                buttonPressed = true;
                initialLocation = currentLocation = RenderContextUtility.ConvertPoint(GetMousePosition(e));
                currPickState = pickState.Pick;
            }
        }

        base.OnMouseDown(e);
    }

    protected override void OnMouseMove(MouseEventArgs e)
    {
        if (buttonPressed)
        {
            System.Drawing.Point location = RenderContextUtility.ConvertPoint(GetMousePosition(e));

            int diffX = location.X - initialLocation.X;

            if (diffX > 10)
                currPickState = pickState.Enclosed;
            else if (diffX < -10)
                currPickState = pickState.Crossing;
            else
                currPickState = pickState.Pick;

            currentLocation = location;

            PaintBackBuffer();
            SwapBuffers();
        }

        base.OnMouseMove(e);
    }

    protected override void OnMouseUp(MouseButtonEventArgs e)
    {
        List<int> added = new List<int>();
        List<int> removed = new List<int>();

        if (buttonPressed)
        {
            IList<Entity> myEnts = CurrentBlockReference != null
                ? Blocks[CurrentBlockReference.BlockName].Entities
                : (IList<Entity>)new List<Entity>(Entities);

            buttonPressed = false;
            int ent;
            int[] ents;

            if (Keyboard.Modifiers != ModifierKeys.Control)
            {
                for (int i = 0; i < myEnts.Count; i++)
                {
                    if (myEnts[i].Selected)
                        removed.Add(i);

                    myEnts[i].Selected = false;
                }
            }

            int dx = currentLocation.X - initialLocation.X;
            int dy = currentLocation.Y - initialLocation.Y;

            System.Drawing.Point p1 = initialLocation;
            System.Drawing.Point p2 = currentLocation;

            NormalizeBox(ref p1, ref p2);

            switch (currPickState)
            {
                case pickState.Pick:

                    ent = GetEntityUnderMouseCursor(currentLocation);

                    if (ent >= 0)
                    {
                        ManageSelection(ent, myEnts, added, removed);
                    }

                    break;

                case pickState.Crossing:

                    if (dx != 0 && dy != 0)
                    {
                        ents =
                            GetAllCrossingEntities(new System.Drawing.Rectangle(p1,
                                new System.Drawing.Size(Math.Abs(dx), Math.Abs(dy))));

                        for (int i = 0; i < ents.Length; i++)
                        {
                            ManageSelection(ents[i], myEnts, added, removed);
                        }
                    }

                    break;

                case pickState.Enclosed:

                    if (dx != 0 && dy != 0)
                    {
                        ents =
                            GetAllEnclosedEntities(new System.Drawing.Rectangle(p1,
                                new System.Drawing.Size(Math.Abs(dx), Math.Abs(dy))));

                        for (int i = 0; i < ents.Length; i++)
                        {
                            ManageSelection(ents[i], myEnts, added, removed);
                        }
                    }
                    break;

            }
            Invalidate();
        }

        if (CustomSelectionChanged != null)
            CustomSelectionChanged(this, new SelectionChangedEventArgs(added.ToArray(), removed.ToArray(), this));

        base.OnMouseUp(e);
    }

    private void ManageSelection(int ent, IList<Entity> myEnts, List<int> added, List<int> removed)
    {
        if (Keyboard.Modifiers == ModifierKeys.Control)
        {
            myEnts[ent].Selected = !myEnts[ent].Selected;
            if (myEnts[ent].Selected)
                added.Add(ent);
            else
                removed.Add(ent);
        }
        else
        {
            myEnts[ent].Selected = true;
            added.Add(ent);
        }
    }

    public event SelectionChangedEventHandler CustomSelectionChanged;

    protected override void DrawOverlay(DrawSceneParams data)
    {
        if (buttonPressed)
        {
            if (currPickState == pickState.Crossing)
                DrawSelectionBox(initialLocation, currentLocation, Colors.DarkBlue, true, true);
            else if (currPickState == pickState.Enclosed)
                DrawSelectionBox(initialLocation, currentLocation, Colors.DarkRed, true, false);
        }
    }

    void DrawSelectionBox(System.Drawing.Point p1, System.Drawing.Point p2, Color transparentColor, bool drawBorder, bool dottedBorder)
    {
        p1.Y = (int)(ActualHeight - p1.Y);
        p2.Y = (int)(ActualHeight - p2.Y);

        NormalizeBox(ref p1, ref p2);

        // Adjust the bounds so that it doesn't exit from the current viewport frame
        int[] viewFrame = ActiveViewport.GetViewFrame();
        int left = viewFrame[0];
        int top = viewFrame[1] + viewFrame[3];
        int right = left + viewFrame[2];
        int bottom = viewFrame[1];

        if (p2.X > right - 1)
            p2.X = right - 1;

        if (p2.Y > top - 1)
            p2.Y = top - 1;

        if (p1.X < left + 1)
            p1.X = left + 1;
        if (p1.Y < bottom + 1)
            p1.Y = bottom + 1;

        RenderContext.SetState(blendStateType.Blend);
        RenderContext.SetColorWireframe(System.Drawing.Color.FromArgb(40, transparentColor.R, transparentColor.G, transparentColor.B));
        RenderContext.SetState(rasterizerStateType.CCW_PolygonFill_CullFaceBack_NoPolygonOffset);

        int w = p2.X - p1.X;
        int h = p2.Y - p1.Y;

        RenderContext.DrawQuad(new System.Drawing.RectangleF(p1.X + 1, p1.Y + 1, w - 1, h - 1));
        RenderContext.SetState(blendStateType.NoBlend);

        if (drawBorder)
        {
            RenderContext.SetColorWireframe(System.Drawing.Color.FromArgb(255, transparentColor.R, transparentColor.G, transparentColor.B));
            List<Point3D> pts = null;

            if (dottedBorder)
            {
                RenderContext.SetLineStipple(1, 0x0F0F, Viewports[0].Camera);
                RenderContext.EnableLineStipple(true);
            }

            int l = p1.X;
            int r = p2.X;
            if (RenderContext.IsDirect3D)
            {
                l += 1;
                r += 1;
            }

            pts = new List<Point3D>(new Point3D[]
                {
                new Point3D(l, p1.Y), new Point3D(p2.X, p1.Y),
                new Point3D(r, p1.Y), new Point3D(r, p2.Y),
                new Point3D(r, p2.Y), new Point3D(l, p2.Y),
                new Point3D(l, p2.Y), new Point3D(l, p1.Y),
                });


            RenderContext.DrawLines(pts.ToArray());

            if (dottedBorder)
                RenderContext.EnableLineStipple(false);
        }
    }

    internal static void NormalizeBox(ref System.Drawing.Point p1, ref System.Drawing.Point p2)
    {

        int firstX = Math.Min(p1.X, p2.X);
        int firstY = Math.Min(p1.Y, p2.Y);
        int secondX = Math.Max(p1.X, p2.X);
        int secondY = Math.Max(p1.Y, p2.Y);

        p1.X = firstX;
        p1.Y = firstY;
        p2.X = secondX;
        p2.Y = secondY;
    }
}

 

Was this article helpful?
1 out of 1 found this helpful

Comments

3 comments
Date Votes
  • I follow this help, but i have and problem, can you help me.

    0
  • Hello, can you help me how to use this one in eyeshot 2020, i think that code is error.

     

    //IList<Entity> myEnts = Entities.CurrentBlockReference != null
                    //    ? Blocks[Entities.CurrentBlockReference.BlockName].Entities
                    //    : new List<Entity>(Entities);
    0
  • You can replace the code snippet with the following:

    EntityList myEnts = CurrentBlockReference != null
    ? Blocks[CurrentBlockReference.BlockName].Entities
    : Entities;

     

    0

Please sign in to leave a comment.

Articles in this section