TheSwamp

Code Red => .NET => Topic started by: cannorth on October 07, 2013, 06:30:15 PM

Title: Setting attribute properly using ObjectARX
Post by: cannorth on October 07, 2013, 06:30:15 PM
Hello,

  This code won't let me set an attribute for a certain block.  I'd like to know if there's anything wrong with it.

Code: [Select]
            brID = modelspace.AppendEntity(blockRef)
            tr.AddNewlyCreatedDBObject(blockRef, True)

            For Each idAtt As ObjectId In btr
                Dim subent As Entity
                subent = CType(tr.GetObject(idAtt, Autodesk.AutoCAD.DatabaseServices.OpenMode.ForRead), Entity)
                If TypeOf subent Is AttributeDefinition Then
                    Dim str_text As String
                    Dim attDef As AttributeDefinition
                    attDef = CType(subent, AttributeDefinition)
                    Dim attRef As New AttributeReference()
                    attRef.SetAttributeFromBlock(attDef, blockRef.BlockTransform)

                    Dim ptBase As New Autodesk.AutoCAD.Geometry.Point3d(attRef.Position.X, attRef.Position.Y, attRef.Position.Z)
                    attRef.Position = ptBase
                    attRef.Tag = attDef.Tag
                    attRef.TextString = str_text

                  End If

                    Dim idTmp As ObjectId
                    idTmp = blockRef.AttributeCollection.AppendAttribute(attRef)
                    tr.AddNewlyCreatedDBObject(attRef, True)

Thanks,
cannorth
Title: Re: Setting attribute properly using ObjectARX
Post by: WILL HATCH on October 08, 2013, 12:02:31 AM
I can't remember exactly why the choice to call SetDatabaseDefaults first, I put this extension together quite awhile back and have never needed to think about it again.  It's use is for newly created blocks, only works when called from within a transaction.

Code: [Select]
            brID = modelspace.AppendEntity(blockRef)
            tr.AddNewlyCreatedDBObject(blockRef, True)

            For Each idAtt As ObjectId In btr
                Dim subent As Entity
                subent = CType(tr.GetObject(idAtt, Autodesk.AutoCAD.DatabaseServices.OpenMode.ForRead), Entity) <--opening objects unnecessarily
                If TypeOf subent Is AttributeDefinition Then
                    Dim str_text As String
                    Dim attDef As AttributeDefinition
                    attDef = CType(subent, AttributeDefinition)
                    Dim attRef As New AttributeReference()
                    attRef.SetAttributeFromBlock(attDef, blockRef.BlockTransform)<--should set database defaults first

                    Dim ptBase As New Autodesk.AutoCAD.Geometry.Point3d(attRef.Position.X, attRef.Position.Y, attRef.Position.Z)<--this is useless, the last step sets the position for you
                    attRef.Position = ptBase
                    attRef.Tag = attDef.Tag<--ditto to redundant
                    attRef.TextString = str_text

                  End If

                    Dim idTmp As ObjectId
                    idTmp = blockRef.AttributeCollection.AppendAttribute(attRef)
                    tr.AddNewlyCreatedDBObject(attRef, True)
Code - C#: [Select]
  1.         public static void GenerateAttibutes(this BlockReference br)
  2.         {
  3.             using (Transaction tr = br.Database.TransactionManager.StartTransaction())
  4.             {
  5.                 if (!br.IsWriteEnabled) br.UpgradeOpen();
  6.                 using (BlockTableRecord btr = (BlockTableRecord)br.BlockTableRecord.GetObject(OpenMode.ForRead))
  7.                 {
  8.                     foreach (ObjectId id in btr)
  9.                     {
  10.                         if (id.ObjectClass == RXClass.GetClass(typeof(AttributeDefinition)))
  11.                         {
  12.                             AttributeDefinition ad = (AttributeDefinition)id.GetObject(OpenMode.ForRead);
  13.                             AttributeReference ar = new AttributeReference();
  14.                             ar.SetDatabaseDefaults();
  15.                             ar.SetAttributeFromBlock(ad, br.BlockTransform);
  16.                             br.AttributeCollection.AppendAttribute(ar);
  17.                             tr.AddNewlyCreatedDBObject(ar, true);
  18.                         }
  19.                     }
  20.                 }
  21.                 br.DowngradeOpen();
  22.                 tr.Commit();
  23.             }
  24.         }
Title: Re: Setting attribute properly using ObjectARX
Post by: dgorsman on October 08, 2013, 09:58:10 AM
I can't remember exactly why the choice to call SetDatabaseDefaults first, I put this extension together quite awhile back and have never needed to think about it again...

One word: comments.  Highly useful for these types of situations where the code only documents the "how" and not the "why".