Author Topic: AutoCAD - First Plug-in Training  (Read 35499 times)

0 Members and 1 Guest are viewing this topic.

Matt__W

  • Seagull
  • Posts: 12955
  • I like my water diluted.
Re: AutoCAD - First Plug-in Training
« Reply #15 on: December 22, 2011, 11:15:53 AM »
If you can code in VB or C#, you can learn the other in a weekend.
My mind automatically translated that to: "If you can dodge a wrench, you can dodge a ball."   :-D
Autodesk Expert Elite
Revit Subject Matter Expert (SME)
Owner/FAA sUAS Pilot @ http://skyviz.io

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: AutoCAD - First Plug-in Training
« Reply #16 on: December 25, 2011, 10:17:15 PM »
For anyone manually translating the first lesson :

The C# language is strongly typed.
ie
a Swan is a bird           : can't be converted to Ingredients
a Pidgeon is a bird        : can be converted to Ingredients


you can't do this
Code: [Select]
    Ingredients pieStuff = bird;
because a bird can't be implicitly converted into Ingredients

If you want a  pie you'll need to keep the compiler happy by being explicit about what you want.

Code: [Select]
   Ingredients pieStuff = (Ingredients )bird;
This will only work IF your bird can be converted into Ingredients.
no guarantees that it will taste great, but at least the compiler won't bitch about your language.

If the VB code is marked
Code: [Select]
Option Explicit Off Option Strict Off
the compiler will assume your requirements and this code will be accepted
Code: [Select]
    Dim attRef As AttributeReference = entity
If
Code: [Select]
Option Explicit On Option Strict On
you'll need to write the asignment like this, with an explicit conversion (which I prefer)
Code: [Select]
    Dim attRef As AttributeReference = CType(entity, AttributeReference)

A mind in neutral translation of
Code: [Select]
    Dim attRef As AttributeReference = entityis
Code: [Select]
    AttributeReference attRef = entity;
In C#,  the compiler requires that your code is explicit  ie written like this at the outset:-
Code: [Select]
    AttributeReference attRef = (AttributeReference)entity;

Note 1:
I took some artistic licence with the Swan pie example. :)
Note 2:
This difference in requirements is not necessarily a shortcoming in either language ... it's just the way it is :) 

« Last Edit: December 29, 2011, 06:12:23 AM by Kerry »
kdub, kdub_nz in other timelines.
Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.

Jeff H

  • Needs a day job
  • Posts: 6144
Re: AutoCAD - First Plug-in Training
« Reply #17 on: December 26, 2011, 09:02:14 PM »
My computer crashed when I was almost done so I got mad and typed this quickly and went from memory which is a very very bad thing. Someone might want to double check it.
First Example Converted
 
In VB you 'Import' the namespace and in C# you 'use' the namespace.
So
Code: [Select]
Imports Autodesk.AutoCAD.Runtime
Imports Autodesk.AutoCAD.DatabaseServices
Imports Autodesk.AutoCAD.Geometry
becomes
Code: [Select]
using Autodesk.AutoCAD.Runtime;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.Geometry;
Here is the KeepStraightOverrule class
Code: [Select]
    Public Class KeepStraightOverrule
        Inherits TransformOverrule
        'We want to change how an AttributeReference responds to being
        ' transformed (moved, rotated, etc.), so we override its
        ' standard TransformBy function.
        Public Overrides Sub TransformBy(ByVal entity As Entity,
                                         ByVal transform As Matrix3d)
            'Call the normal TransformBy function for the attribute
            ' reference we're overruling.
            MyBase.TransformBy(entity, transform)
            'We know entity must be an AttributeReference because
            ' that is the only entity we registered the overrule for.
            Dim attRef As AttributeReference = entity
            'Set rotation of attribute reference to 0 (horizontal)
            attRef.Rotation = 0.0
        End Sub
    End Class

In VB when a class inherits from another the first line in the class is 'Inherits' then the the name of the class.
In C# you use ':'
In the TransformOverrule class it has a method TransformBy marked as
Code: [Select]
Public Overridable Sub TransformBy(ByVal entity As Entity, ByVal transform As Matrix3d)
or in C#
Code: [Select]
public virtual void TransformBy(Entity entity, Matrix3d transform)
Overridable = virtual
 
Quote
The virtual keyword is used to modify a method, property, indexer, or event declaration and allow for it to be overridden in a derived class. For example, this method can be overridden by any class that inherits it:
Quote
The Overidable keyword specifies that a property or procedure can be overridden by an identically named property or procedure in a derived class.
A derived class is one that inherits another class.
 
Also a Sub is method that 'does something' and does not return anything so in C# a 'void' method.
 
Some of you might wonder how is entity passed with ByVal(Meaning By Value) and in the body of the method the entity is changed and the original entity is changed. When a custom class is used in an argument it is always passed ByRef(By Reference) meaning its memory address not a copy of the value is passed and any changes made in the method will change the original object.
 
As Kerry mentioned if Option Strict is on then one of the things that will cause a compile error is
Implicit narrowing conversions
Since AttributeReference is derived from Entity and Entity does not contain all the methods as AttributeReference it is considered a narrowing conversion(A conversion with Data loss)
Another example would be
Code: [Select]
            Dim d As Double = 45.25
            Dim i As Integer = d
With option strict On it will throw a error with it off the compiler will do the conversion.
As Kerry mentioned you must explicitly do the conversion in C#
Code: [Select]
AttributeReference attRef = entity as AttributeReference;
MyBase(VB) and base(C#) call the 'base'(The class you are inherting from) class method.
Last couple things as my computer crashed and I am lazy and do not feel like retyping but in VB to make a null check you check if 'Is Nothing', and static = Shared.
Code: [Select]
using Autodesk.AutoCAD.Runtime;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.Geometry;
namespace HorizontalAttributesCSharp
{
    public class Commands
    {
        private static KeepStraightOverrule myOverrule;
        [CommandMethod("KeepStraight")]
        public static void ImplementOverrule()
        {
            if (myOverrule == null)
            {
       
                myOverrule = new KeepStraightOverrule();
               
                Overrule.AddOverrule(RXClass.GetClass(typeof(AttributeReference)), myOverrule, false);
            }
           
            Overrule.Overruling = true;
        }
    }
    public class KeepStraightOverrule : TransformOverrule
 {
  public override void TransformBy(Entity entity, Matrix3d transform)
  {
            base.TransformBy(entity, transform);
   AttributeReference attRef = entity as AttributeReference; 
   attRef.Rotation = 0.0;
  }
 }
}

**********************Edit************************************
Also AddOverule first arguement is a System.Type to read more for VB GetType
and for C# typeof
 
 
« Last Edit: December 26, 2011, 09:22:16 PM by Jeff H »

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: AutoCAD - First Plug-in Training
« Reply #18 on: December 26, 2011, 09:41:41 PM »
< .. >
Someone might want to double check it.
< .. >
I have the same translation.
Either we're both correct or both miserably wrong

:)
kdub, kdub_nz in other timelines.
Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.

Jeff H

  • Needs a day job
  • Posts: 6144
Re: AutoCAD - First Plug-in Training
« Reply #19 on: December 26, 2011, 09:51:45 PM »
< .. >
Someone might want to double check it.
< .. >
I have the same translation.
Either we're both correct or both miserably wrong

 :)

If Kerry has the same then looks like I got it correct or what little I cleaned up from here

Kerry or Stephen do you a know way to make the Attribute horizontal on 'Insert' using a overrule, maybe with ObjectOverule.
I see the SetAttributes in  DrawableOverrule but I do not think that is what I need.

If you like Overrules and the example is really good reason why to use them then you need to check out Stephen's class
AutoCADŽ .NET: Practical Examples of Customizing AutoCAD Entity Behavior

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: AutoCAD - First Plug-in Training
« Reply #20 on: December 26, 2011, 10:01:51 PM »

Sorry, haven't played with Overrules at all Jeff.
Recall a couple of mentions on Kean's blog ...
kdub, kdub_nz in other timelines.
Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.

Jeff H

  • Needs a day job
  • Posts: 6144
Re: AutoCAD - First Plug-in Training
« Reply #21 on: December 26, 2011, 10:45:48 PM »
I tried this and it makes the Attribute appear horizontal during the Jig of the Insert but crashes with a eOpenforWrite error after the rotation is selected
Code: [Select]
using Autodesk.AutoCAD.Runtime;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.GraphicsInterface;
namespace HorizontalAttributesCSharp
{
    public class Commands
    {
        private static KeepStraightOverrule myOverrule;
        private static KeepStraightOverruleOnInsert myOverruleInsert;
        [CommandMethod("KeepStraight")]
        public static void ImplementOverrule()
        {
            if (myOverrule == null)
            {
                myOverrule = new KeepStraightOverrule();
                myOverruleInsert = new KeepStraightOverruleOnInsert();
                Overrule.AddOverrule(RXClass.GetClass(typeof(AttributeReference)), myOverrule, false);
                Overrule.AddOverrule(RXClass.GetClass(typeof(AttributeReference)), myOverruleInsert, false);
            }
            Overrule.Overruling = true;
        }
    }
    public class KeepStraightOverrule : TransformOverrule
    {
        public override void TransformBy(Entity entity, Matrix3d transform)
        {
            base.TransformBy(entity, transform);
            AttributeReference attRef = entity as AttributeReference;
            attRef.Rotation = 0.0;
        }
    }

    public class KeepStraightOverruleOnInsert : DrawableOverrule
    {
        public override int SetAttributes(Drawable drawable, DrawableTraits traits)
        {
            AttributeReference attRef = drawable as AttributeReference;
            attRef.Rotation = 0.0;
            return base.SetAttributes(drawable, traits);
        }

    }
}
When I tried placing it in a OpenClose transaction
I got this error
 
« Last Edit: December 26, 2011, 10:59:45 PM by Jeff H »

Jeff H

  • Needs a day job
  • Posts: 6144
Re: AutoCAD - First Plug-in Training
« Reply #22 on: December 27, 2011, 12:03:24 AM »
Using code from Stephen's last example
Code: [Select]
public class KeepStraightOverruleOnInsert : DrawableOverrule
    {
        public override bool WorldDraw(Drawable drawable, WorldDraw wd)
        {
            return false;
        }
       
        // Called for each viewport so entity can draw itself differently
        //  depending on the view.
        public override void ViewportDraw(Drawable drawable, ViewportDraw vd)
        {
            // Cast drawable to type AttributeReference (we know it's an
            //  AttributeReference because that's the only class we register our
            //  overrule for).
            AttributeReference attRef = drawable as AttributeReference;
            // First calculate the transformation matrix to rotate from the
            //  BlockReference's current orientation to the view.
            Point3d org = attRef.Position;
            Vector3d zVec = vd.Viewport.ViewDirection;
            Vector3d yVec = vd.Viewport.CameraUpVector;
            Vector3d xVec = yVec.CrossProduct(zVec).GetNormal();
            Matrix3d viewmat = Matrix3d.AlignCoordinateSystem(org, Vector3d.XAxis, Vector3d.YAxis, Vector3d.ZAxis, org, xVec, yVec, zVec);
            // Then calculate the additional rotation required to compensate for
            //  the AttributeReference having a rotation.
            Matrix3d rotMat = Matrix3d.Rotation(-attRef.Rotation, attRef.Normal, org);
            // Apply the two transformations
            vd.Geometry.PushModelTransform(viewmat);
            vd.Geometry.PushModelTransform(rotMat);
            //Draw the 'per viewport geometry
            base.ViewportDraw(drawable, vd);
            // Remove the transformation - we don't want any other objects
            //  to draw themselves in the view plane.
            vd.Geometry.PopModelTransform();
            vd.Geometry.PopModelTransform();
        }
 
    }
 
This works using a Insert, but is not persisent and need to somehow make it persistent.
And the other problem I have noticed is that it does not keep AttributeReference in the same location when rotated.
For a pic example the block is a dynamic block and the top BlockReference was rotated with a RotationParameter and the overriden TransformBy method places it correctly, but the bottom reference is done during the Insert which the overriden ViewportDraw handles.
 

Jeff H

  • Needs a day job
  • Posts: 6144
Re: AutoCAD - First Plug-in Training
« Reply #23 on: December 27, 2011, 02:43:56 AM »
Overriding the Open Method seems to work but does not show during the Insertion Jig.
Also it only worked when applied to BlockReference's then grabbing the AttributeReferences
 
Code: [Select]
Overrule.AddOverrule(RXClass.GetClass(typeof(BlockReference)), myOverruleInsert, false);

Code: [Select]

 public class KeepStraightOverruleOnInsert : ObjectOverrule
    {
        public override void Open(DBObject dbObject, OpenMode mode)
        {
            if (mode == OpenMode.ForWrite)
            {
                BlockReference blkRef = dbObject as BlockReference;
           
                if (blkRef.AttributeCollection.Count != 0)
                {
                    using (Transaction trx = dbObject.Database.TransactionManager.StartOpenCloseTransaction())
                    {
                        foreach (ObjectId attRefId in blkRef.AttributeCollection)
                        {
                            AttributeReference attRef = trx.GetObject(attRefId, OpenMode.ForWrite) as AttributeReference;
                            attRef.Rotation = 0.0;
                        }
                        trx.Commit();
                    }
                }
            }
            base.Open(dbObject, mode);
        }

    }
 

Arizona

  • Guest
Re: AutoCAD - First Plug-in Training
« Reply #24 on: December 28, 2011, 11:12:21 AM »
Sigh! You C# guys and your semi-colon addictions  8-).

C# versions of the projects will be added eventually (after I've received enough feedback to be confident I don't have to edit too much of the VB.NET code)...
Yes please!
And thank you for the great resource!

David Hall

  • Automatic Duh Generator
  • King Gator
  • Posts: 4073
Re: AutoCAD - First Plug-in Training
« Reply #25 on: December 28, 2011, 01:09:32 PM »
Sigh! You C# guys and your semi-colon addictions  8-).

C# versions of the projects will be added eventually (after I've received enough feedback to be confident.
Add me to that!!
Everyone has a photographic memory, Some just don't have film.
They say money can't buy happiness, but it can buy Bacon and that's a close second.
Sometimes the question is more important than the answer. (Thanks Kerry for reminding me)

gile

  • Gator
  • Posts: 2505
  • Marseille, France
Re: AutoCAD - First Plug-in Training
« Reply #26 on: December 28, 2011, 02:13:52 PM »
Quote
I continue to hold the opinion that VB.NET is more suited to someone learning programming for the first time by working through tutorials like this - the code is that much more readable for mere mortals.

Why !?...
Aren't non English 'mere mortals' ?
Is it more difficult to learn the meaning of a semi-colon than the meaning of "End" ?
Does really implicit casts make easier coding in a strongly typed environment ?
IMO, in the .NET learning curve, the langauge syntax is 'peanuts' comparing to the programmation environment (Framework and API libraries, OOP, and so on...)

Anyway,
Quote
If necessary I (or  someone here) can convert the code for members here
I can give a hand this way too (these days I work on the migration of 20 000 VBA code lines to C#, hope I won't become 'Dim' addict).

I can try a F# translation too. F# isn't so 'unreadable' for those comming from LISP (neither 'Dim' nor semi-colon)...
Speaking English as a French Frog

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: AutoCAD - First Plug-in Training
« Reply #27 on: December 29, 2011, 03:57:38 AM »
< .. >
I can give a hand this way too (these days I work on the migration of 20 000 VBA code lines to C#, hope I won't become 'Dim' addict).

I can try a F# translation too. F# isn't so 'unreadable' for those comming from LISP (neither 'Dim' nor semi-colon)...

I'll be jumped upon if I laugh about the 'Dim' addict quote ,,, so I'll just have a quiet smile to myself. :)

I think F# is a GREAT idea. We probably won't get many new dotNet AutoCAD customisers usinf F#, but it may help them to become familiar with reading it ... thus helping with understanding some of the samples floatong around.
kdub, kdub_nz in other timelines.
Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.

Jeff H

  • Needs a day job
  • Posts: 6144
Re: AutoCAD - First Plug-in Training
« Reply #28 on: December 29, 2011, 05:03:32 AM »
hope I won't become 'Dim' addict
Be careful what you ask for
I'll be jumped upon if I laugh about the 'Dim' addict quote ,,, so I'll just have a quiet smile to myself.
Get ready for that smile to change to a cringe.
 
In VB you can always  turn Option Strict & and Explicit OFF and get rid of the Dims
so you can end up with this
Code: [Select]
attRef = entity
&
Code: [Select]
  Private Shared myOverrule

This runs but how much fun do you think it would be to deal with and find bugs with code on a much larger scale but written like this
Code: [Select]
Module Module1
    Sub Main()
        i = 10
        s = "word"
        d = 5.567
        ''answer = i * s ''-----This will compile but CRASH at runtime.
        answer = i * d   ''-----This will compile and work just fine.
        Console.WriteLine(answer)
        Console.ReadKey()
    End Sub
End Module

 
 
The code below compiles just fine
Code: [Select]
Imports Autodesk.AutoCAD.Runtime
Imports Autodesk.AutoCAD.DatabaseServices
Imports Autodesk.AutoCAD.Geometry
Namespace HorizontalAttributes
    Public Class Commands

        Private Shared myOverrule
        <CommandMethod("KeepStraight")>
        Public Shared Sub ImplementOverrule()
            If myOverrule Is Nothing Then
                myOverrule = New KeepStraightOverrule
                Overrule.AddOverrule(
                  RXClass.GetClass(GetType(AttributeReference)),
                  myOverrule, False)
            End If
            Overrule.Overruling = True
        End Sub
    End Class

    Public Class KeepStraightOverrule
        Inherits TransformOverrule
        Public Overrides Sub TransformBy(ByVal entity As Entity,
                                         ByVal transform As Matrix3d)
            MyBase.TransformBy(entity, transform)
            attRef = entity
            attRef.Rotation = 0.0
        End Sub
    End Class
End Namespace

Arizona

  • Guest
Re: AutoCAD - First Plug-in Training
« Reply #29 on: December 29, 2011, 05:55:24 AM »
Get ready for that smile to change to a cringe.
 
In VB you can always  turn Option Strict & and Explicit OFF and get rid of the Dims
so you can end up with this
Code: [Select]
attRef = entity

I even cringed at that one :-)