Author Topic: overrule, read attributes from blockreference  (Read 26127 times)

0 Members and 1 Guest are viewing this topic.

nekitip

  • Guest
overrule, read attributes from blockreference
« on: May 12, 2013, 08:34:13 AM »
I am trying hard to learn Overrules, the things I've been avoiding all this years.
Here is the first thing that I do not understand.

When overruling DrawableOverrule for blockreference, overrule will execute when user is changing attribute reference in properties (i did not expect that).
Object will be presented open (in this case blockreference) to read its properties, but to access its attributereferences from .net, one needs transaction, and none is active. How to read them?
The way around is to create another overrule for attribute reference. What is the best practice?
Code - vb.net: [Select]
  1. Public Class test2overrule
  2.     Inherits DrawableOverrule
  3.     Const regappname As String = "testap1"
  4.     Public Shared test2overrulevas As New test2overrule
  5.     Public Sub New()
  6.         ' Tell AutoCAD to filter on our application name
  7.         ' (this means our overrule will only be called
  8.         ' on objects possessing XData with this name)
  9.         SetXDataFilter(regAppName)
  10.     End Sub
  11.  
  12.     Public Overrides Function WorldDraw(ByVal drawable As Autodesk.AutoCAD.GraphicsInterface.Drawable, ByVal wd As Autodesk.AutoCAD.GraphicsInterface.WorldDraw) As Boolean
  13.         Dim m As BlockReference = TryCast(drawable, Entity)
  14.         Return MyBase.WorldDraw(drawable, wd)
  15.     End Function
  16.  
  17.     Public Overrides Function SetAttributes(ByVal drawable As Autodesk.AutoCAD.GraphicsInterface.Drawable, ByVal traits As Autodesk.AutoCAD.GraphicsInterface.DrawableTraits) As Integer
  18.         Dim m As BlockReference = TryCast(drawable, Entity)
  19.  
  20.         Return MyBase.SetAttributes(drawable, traits)
  21.     End Function
  22. End Class

TheMaster

  • Guest
Re: overrule, read attributes from blockreference
« Reply #1 on: May 12, 2013, 03:43:10 PM »
I am trying hard to learn Overrules, the things I've been avoiding all this years.
Here is the first thing that I do not understand.

When overruling DrawableOverrule for blockreference, overrule will execute when user is changing attribute reference in properties (i did not expect that).
Object will be presented open (in this case blockreference) to read its properties, but to access its attributereferences from .net, one needs transaction, and none is active. How to read them?
The way around is to create another overrule for attribute reference. What is the best practice?
Code - vb.net: [Select]
  1. Public Class test2overrule
  2.     Inherits DrawableOverrule
  3.     Const regappname As String = "testap1"
  4.     Public Shared test2overrulevas As New test2overrule
  5.     Public Sub New()
  6.         ' Tell AutoCAD to filter on our application name
  7.         ' (this means our overrule will only be called
  8.         ' on objects possessing XData with this name)
  9.         SetXDataFilter(regAppName)
  10.     End Sub
  11.  
  12.     Public Overrides Function WorldDraw(ByVal drawable As Autodesk.AutoCAD.GraphicsInterface.Drawable, ByVal wd As Autodesk.AutoCAD.GraphicsInterface.WorldDraw) As Boolean
  13.         Dim m As BlockReference = TryCast(drawable, Entity)
  14.         Return MyBase.WorldDraw(drawable, wd)
  15.     End Function
  16.  
  17.     Public Overrides Function SetAttributes(ByVal drawable As Autodesk.AutoCAD.GraphicsInterface.Drawable, ByVal traits As Autodesk.AutoCAD.GraphicsInterface.DrawableTraits) As Integer
  18.         Dim m As BlockReference = TryCast(drawable, Entity)
  19.  
  20.         Return MyBase.SetAttributes(drawable, traits)
  21.     End Function
  22. End Class

Why do you need to open attributes from your overrule's WorldDraw() ?

nekitip

  • Guest
Re: overrule, read attributes from blockreference
« Reply #2 on: May 13, 2013, 02:59:31 AM »
What I really want is:
When user modifies Entity (lets say - move Blockreference), then read (lets say position.y) and update my .net object with new values.
-and I also want to know if the user has changed attributereference.text in blockreference, and read that.
-and if he has modified dynamic block property, read that.
Not sure which overrule to use, but in case of "move", i would like to see it in real-time.
I can put some code here if it is needed.

Up untill now, I've been doing this like this: I hooked to objectmodified event of each of objectid of my interest, and when events fired, turn on .net objects flag, and then, when possible, open single transaction and bulk read all of the flaged objects.

nekitip

  • Guest
Re: overrule, read attributes from blockreference
« Reply #3 on: May 13, 2013, 03:30:19 AM »
So I'm planing something like this in this code.
This is overrule for move, it will update .NET objects, but I want to know, like I said earlier: if dynprop has changed, if attref is chaged (and what value is it now). I believe the way to go is DrawableOverrule, but not sure.

Code - vb.net: [Select]
  1. 'assume appname is already registered in database
  2. 'assume each entity has ent.XData = New ResultBuffer(New TypedValue(DxfCode.ExtendedDataRegAppName, "test"), New TypedValue(DxfCode.ExtendedDataAsciiString, ent.ObjectId.ToString), New TypedValue(DxfCode.ExtendedDataAsciiString, "good"))
  3. 'assume overruling is active for blockreference
  4.  
  5. Public Class app1
  6.     Public Shared mylist1 As New List(Of myobject1)
  7. End Class
  8.  
  9. Public Class myobject1
  10.     Private _positiony As Double
  11.     Private _oid As ObjectId
  12.  
  13.     Public Property positiony As Double
  14.         Get
  15.             Return _positiony
  16.         End Get
  17.         Set(ByVal value As Double)
  18.             _positiony = value
  19.         End Set
  20.     End Property
  21.  
  22.     Public Property oid As ObjectId
  23.         Get
  24.             Return _oid
  25.         End Get
  26.         Set(ByVal value As ObjectId)
  27.             _oid = value
  28.         End Set
  29.     End Property
  30.  
  31.     Public Sub readEnt(ByVal ent As Entity)
  32.         Dim blokref As BlockReference = DirectCast(ent, BlockReference)
  33.         positiony = blokref.Position.Y
  34.     End Sub
  35.  
  36. End Class
  37.  
  38.  
  39. Public Class test1Overrule1
  40.     Inherits TransformOverrule
  41.     Public Shared test1overrulevar As New test1Overrule1
  42.     Public regappname As String = "test"
  43.     Private storedid As String
  44.  
  45.     Public Sub New()
  46.         ' Tell AutoCAD to filter on our application name
  47.         ' (this means our overrule will only be called
  48.         ' on objects possessing XData with this name)
  49.         SetXDataFilter(regappname)
  50.     End Sub
  51.    
  52.     Public Overrides Sub TransformBy(ByVal entity As Entity,
  53.                                      ByVal transform As Matrix3d)
  54.  
  55.         MyBase.TransformBy(entity, transform)
  56.         If checkxdata(entity) Then
  57.             findmyobjectinlist(entity)
  58.         End If
  59.     End Sub
  60.  
  61.     Public Function checkxdata(ByVal ent As Entity) As Boolean
  62.         Dim retval As Boolean = False
  63.         Dim xdata As ResultBuffer = ent.GetXDataForApplication(regappname)
  64.         Select Case xdata.AsArray(2).Value.ToString
  65.             Case "good"
  66.                 storedid = xdata.AsArray(1).Value.ToString
  67.                 retval = True
  68.         End Select
  69.         Return retval
  70.     End Function
  71.  
  72.     Public Sub findmyobjectinlist(ByVal ent As Entity)
  73.         Dim myobj = From obj1 In app1.mylist1
  74.                     Where obj1.oid.ToString = storedid
  75.                     Select obj1
  76.  
  77.         If myobj.Count > 0 Then
  78.             myobj.First.readEnt(ent)
  79.         End If
  80.     End Sub
  81. End Class

TheMaster

  • Guest
Re: overrule, read attributes from blockreference
« Reply #4 on: May 13, 2013, 11:36:39 PM »
Sorry, your code doesn't convey your intent (what are you doing in 'ReadEnt()' for example?).

I won't comment on ideas on, or pseudo-code for solving a problem without your revealing the problem itself.

VVeli

  • Newt
  • Posts: 27
Re: overrule, read attributes from blockreference
« Reply #5 on: August 25, 2015, 08:08:23 AM »
Hi,
you can read blockreference attributes easily with transaction. The WorldDraw function Overrides all BlockRefereces only. Example reads blocks attribute value and display that with wd.Geometry.Text function. You have to create Autodesk.AutoCAD.GraphicsInterface.TextStyle for that.

Cheers
Veli V.

Code: [Select]
Public Overrides Function WorldDraw(drawable As Autodesk.AutoCAD.GraphicsInterface.Drawable, wd As Autodesk.AutoCAD.GraphicsInterface.WorldDraw) As Boolean
            Dim oAttrib As AttributeReference = Nothing
            Dim blk As BlockReference = DirectCast(drawable, BlockReference)
            If Not blk Is Nothing Then
                Dim attCol As AttributeCollection = blk.AttributeCollection
                Dim attTextPosYDiff As Double = 0.0
                Dim sAttribTexts As New List(Of String)
                ed.WriteMessage("BlockReference: " + blk.Name + vbCrLf)
                If blk.Name.Trim.ToLower = "kltaite" Then
                    Try
                        Using tr As Transaction = HostApplicationServices.WorkingDatabase.TransactionManager.StartOpenCloseTransaction
                            For Each attObjId As ObjectId In attCol
                                oAttrib = DirectCast(tr.GetObject(attObjId, OpenMode.ForRead), AttributeReference)
                                'ed.WriteMessage("BlockAttribute: " + oAttrib.Tag + vbCrLf)
                                sAttribTexts.Add(oAttrib.Tag + " = " + oAttrib.TextString)
                            Next attObjId
                            tr.Commit()
                        End Using
                    Catch ex As Exception
                        Debug.WriteLine("Error while reading block " + blk.Name + " attribute. " + ex.Message)
                        ed.WriteMessage("Error while reading block " + blk.Name + " attribute. " + ex.Message + vbCrLf)
                    End Try
                    If Not sAttribTexts Is Nothing Then
                        For Each sVal As String In sAttribTexts
                            wd.Geometry.Text(New Autodesk.AutoCAD.Geometry.Point3d(blk.Position.X, blk.Position.Y - attTextPosYDiff, blk.Position.Z), _TextNormal, _TextDirect, sVal, True, _style)
                            attTextPosYDiff += 0.5
                        Next sVal
                    End If
                    wd.Geometry.Circle(blk.Position, 1, New Autodesk.AutoCAD.Geometry.Vector3d(0, 0, 1))
                    Using sol3d As New Solid3d()
                        sol3d.CreateSphere(0.2)
                        sol3d.TransformBy(Autodesk.AutoCAD.Geometry.Matrix3d.Displacement(blk.Position - Autodesk.AutoCAD.Geometry.Point3d.Origin))
                        sol3d.WorldDraw(wd)
                    End Using
                End If
                sAttribTexts.Clear() : sAttribTexts = Nothing
            End If
            Return MyBase.WorldDraw(drawable, wd)
        End Function