Author Topic: Setting Dynamic Block Values with VB.NET  (Read 1915 times)

0 Members and 1 Guest are viewing this topic.

cmwade77

  • Swamp Rat
  • Posts: 1443
Setting Dynamic Block Values with VB.NET
« on: January 25, 2024, 12:37:12 PM »
Please bear with me here, I am very new to .NET and I am having an issue with setting Dynamic Block Properties, this is the code I have:

Code - vb.net: [Select]
  1.     Public Sub SetProperty(BlockRef As BlockReference, PropName As String, NewValue As Object)
  2.         ' Use a transaction when modifying block properties
  3.         Using trans As Transaction = db.TransactionManager.StartTransaction()
  4.             Dim Prop As DynamicBlockReferenceProperty = GetProperty(BlockRef, PropName)
  5.             If Not IsNothing(Prop) Then
  6.                 If Not Prop.Value.Equals(NewValue) Then ' Check if the values are different
  7.                     Try
  8.                         ' Use Convert.ChangeType to convert NewValue to the property's data type                        
  9.                         Prop.Value = Convert.ChangeType(NewValue, Prop.Value.GetType())
  10.                         ' Commit the transaction after setting the property
  11.                         trans.Commit()
  12.                         ed.WriteMessage(vbCrLf & NewValue.ToString & "  Property: " & Prop.PropertyName & " set successfully to value of: " & Prop.Value.ToString)
  13.                     Catch ex As System.Exception
  14.                         ' Handle conversion error or unsupported data type
  15.                         ' You can log an error or provide a custom error message
  16.                         Console.WriteLine("Error: " & ex.Message)
  17.                     End Try
  18.                 End If
  19.             End If
  20.         End Using
  21.     End Sub
  22.  
  23.     Public Function GetProperty(BlockRef As BlockReference, PropName As String) As DynamicBlockReferenceProperty
  24.         If BlockRef.IsDynamicBlock Then
  25.             For Each Prop As DynamicBlockReferenceProperty In BlockRef.DynamicBlockReferencePropertyCollection
  26.                 If Not Prop.ReadOnly Then
  27.                     If Prop.PropertyName.ToLower = PropName.ToLower Then
  28.                         Return Prop
  29.                     End If
  30.                 End If
  31.             Next
  32.         End If
  33.         Return Nothing
  34.     End Function

When this code sets the property, sometimes things will stretch, but as you can see on the command line message, it still thinks the property value is the original 40 and if you look at the image, even the grip is still showing at the original 40, this would be for the property DUCT_1 in the attached block.

I am sure I am missing something obvious here, but I just don't know what.
« Last Edit: January 25, 2024, 01:03:16 PM by cmwade77 »

gile

  • Gator
  • Posts: 2507
  • Marseille, France
Re: Setting Dynamic Block Values with VB.NET
« Reply #1 on: January 25, 2024, 02:56:37 PM »
I am very new to .NET
So don't go any further with VB and switch to C#. You'll find a lot more help and examples in C#, and the difference between the two languages should become even greater with the forthcoming move to .NET 8.0.
Speaking English as a French Frog

kdub_nz

  • Mesozoic keyThumper
  • SuperMod
  • Water Moccasin
  • Posts: 2141
  • class keyThumper<T>:ILazy<T>
Re: Setting Dynamic Block Values with VB.NET
« Reply #2 on: January 25, 2024, 02:58:37 PM »
I was thinking of a way to say the same thing, then your reply popped up.
Called Kerry in my other life
Retired; but they dragged me back in !

I live at UTC + 13.00

---
some people complain about loading the dishwasher.
Sometimes the question is more important than the answer.

cmwade77

  • Swamp Rat
  • Posts: 1443
Re: Setting Dynamic Block Values with VB.NET
« Reply #3 on: January 25, 2024, 02:59:36 PM »
I already know enough VB to make this workable, I know nothing with C#

Jeff H

  • Needs a day job
  • Posts: 6150
Re: Setting Dynamic Block Values with VB.NET
« Reply #4 on: January 25, 2024, 02:59:40 PM »
Try calling BlockTableRecord.UpdateAnonymousBlocks Method
Guessing the AnonymousBlockTableRecord for that BlockReference has not updated.

One way to test really quick in UI is to open it Block Editor and save it then see if it updates.

If you only have access to the Blockreference then make sure you use the BlockReference.DynamicBlockTableRecord Property to get its blocktable record

gile

  • Gator
  • Posts: 2507
  • Marseille, France
Re: Setting Dynamic Block Values with VB.NET
« Reply #5 on: January 25, 2024, 04:09:15 PM »
The dynamic property value does not change because you do not Commit the Transaction you start in the SetProperty method.
You should not have to start a transaction in this method as you you pass it a DBObject (BlockReference) which should be already opened with or added to a Transaction in the calling code.

PS: your knowledge of VB won't help you that much in learning .NET. Learning C# isn't much compared to learning .NET in general and AutoCAD's .NET API.
« Last Edit: January 25, 2024, 04:19:27 PM by gile »
Speaking English as a French Frog

cmwade77

  • Swamp Rat
  • Posts: 1443
Re: Setting Dynamic Block Values with VB.NET
« Reply #6 on: January 25, 2024, 04:38:44 PM »
I am confused, wouldn't trans.Commit() commit this?

kdub_nz

  • Mesozoic keyThumper
  • SuperMod
  • Water Moccasin
  • Posts: 2141
  • class keyThumper<T>:ILazy<T>
Re: Setting Dynamic Block Values with VB.NET
« Reply #7 on: January 25, 2024, 05:07:28 PM »
Hi Chris,
Not if an error occurs earlier in the try statement.

Move the statement either to just prior the End Using or incorporate it in a finally block.

. . . if I understand the question . .

but a Gilles mentions, the transaction ( and commit ) declaration should be in the calling method.

Regards,
« Last Edit: January 25, 2024, 05:11:02 PM by kdub_nz »
Called Kerry in my other life
Retired; but they dragged me back in !

I live at UTC + 13.00

---
some people complain about loading the dishwasher.
Sometimes the question is more important than the answer.

cmwade77

  • Swamp Rat
  • Posts: 1443
Re: Setting Dynamic Block Values with VB.NET
« Reply #8 on: January 25, 2024, 06:41:27 PM »
Hmm, it seems to update somewhat, but not always accurate still with the adjusted code below, more concerning is that I cannot use the grips afterwards. In this code, it tells me it cannot find the property DUCT_1 in the block, even though it is indeed there:

Code - vb.net: [Select]
  1. Imports System
  2. Imports System.Collections.Generic
  3. Imports System.Text
  4. Imports Autodesk.AutoCAD.DatabaseServices
  5. Imports Autodesk.AutoCAD.GraphicsInterface
  6. Imports Autodesk.AutoCAD.Runtime
  7. Imports Autodesk.AutoCAD.Geometry
  8. Imports Autodesk.AutoCAD.ApplicationServices
  9. Imports Autodesk.AutoCAD.ApplicationServices.Application
  10. Imports Autodesk.AutoCAD.EditorInput
  11. Imports System.IO
  12. Imports System.Security.Cryptography
  13. Imports Autodesk.AutoCAD.Windows
  14. Imports System.Windows.Interop
  15. Module AutoCADFunctions
  16.     Public Sub InsertBlock(BlkName As String)
  17.         Dim bRollup As Boolean = ps.AutoRollUp
  18.         If ps.Dock.Equals(DockSides.None) Then
  19.             If ps.Style.Equals(32) Then
  20.                 ps.Style = 0
  21.             End If
  22.             With ps
  23.                 .AutoRollUp = True
  24.                 .Visible = False
  25.                 .Visible = True
  26.             End With
  27.             ps.AutoRollUp = bRollup
  28.         End If
  29.         BlkName = Duct_Shape & "_" & BlkName
  30.         Dim FullPath As String = Directory.GetCurrentDirectory & "\Blocks\" & BlkName & ".dwg"
  31.         Using xDb As New Database(False, True)
  32.             xDb.ReadDwgFile(FullPath, FileShare.Read, True, Nothing)
  33.             Using DocLock As DocumentLock = doc.LockDocument
  34.                 Try
  35.                     Dim Id As ObjectId = db.Insert(BlkName, xDb, True)
  36.                     If Id.IsNull Then
  37.                         ed.WriteMessage(vbLf & "Failed to insert block")
  38.                         Return
  39.                     End If
  40.                     Using tr As Transaction = db.TransactionManager.StartTransaction()
  41.                         Try
  42.                             Dim bt As BlockTable =
  43.                     DirectCast(tr.GetObject(db.BlockTableId, OpenMode.ForRead), BlockTable)
  44.                             If Not bt.Has(BlkName) Then
  45.                                 ed.WriteMessage(vbLf & "Block '{0}' not found.", BlkName)
  46.                                 Return
  47.                             End If
  48.  
  49.                             Dim pr As PromptResult
  50.                             Using br As New BlockReference(Point3d.Origin, bt(BlkName))
  51.                                 br.TransformBy(ed.CurrentUserCoordinateSystem)
  52.  
  53.                                 ' Using InsertBlockJig class to insert the block
  54.                                 Dim insertJig As New InsertBlockJig(br)
  55.                                 pr = ed.Drag(insertJig)
  56.                                 If pr.Status <> PromptStatus.OK Then
  57.                                     Return
  58.                                 End If
  59.  
  60.                                 ' Using RotateBlockJig class to rotate the block
  61.                                 Dim rotateJig As New RotateBlockJig(br)
  62.                                 pr = ed.Drag(rotateJig)
  63.                                 If pr.Status <> PromptStatus.OK Then
  64.                                     Return
  65.                                 End If
  66.                                 rotateJig.UpdateRotation()
  67.  
  68.                                 Dim btr As BlockTableRecord =
  69.                                 DirectCast(tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite), BlockTableRecord)
  70.                                 btr.AppendEntity(br)
  71.                                 tr.AddNewlyCreatedDBObject(br, True)
  72.  
  73.                                 If Not IsNothing(btr) Then
  74.                                     btr.UpdateAnonymousBlocks()
  75.                                 End If
  76.                                 tr.Commit()
  77.                                 Dim Prop As DynamicBlockReferenceProperty = GetProperty(br, "DUCT_1")
  78.                                 If Not IsNothing(Prop) Then
  79.                                     ed.WriteMessage(vbCrLf & "Property: " & Prop.PropertyName & " set successfully to value of: " & Prop.Value.ToString)
  80.                                 Else
  81.                                     ed.WriteMessage(vbCrLf & "Could not find DUCT_1 property in block " & br.Name)
  82.                                 End If
  83.                             End Using
  84.  
  85.                         Catch Ex As System.AccessViolationException
  86.                         End Try
  87.                     End Using
  88.                 Catch Ex As System.AccessViolationException
  89.                 End Try
  90.             End Using
  91.  
  92.         End Using
  93.         Duct_Distance = 0
  94.  
  95.     End Sub
  96.     Public Sub SetProperty(BlockRef As BlockReference, PropName As String, NewValue As Object)
  97.  
  98.  
  99.         Dim Prop As DynamicBlockReferenceProperty = GetProperty(BlockRef, PropName)
  100.         If Not IsNothing(Prop) Then
  101.             If Not Prop.Value.Equals(NewValue) Then ' Check if the values are different
  102.                 Try
  103.                     ' Use Convert.ChangeType to convert NewValue to the property's data type                        
  104.                     Prop.Value = Convert.ChangeType(NewValue, Prop.Value.GetType())
  105.                 Catch ex As System.Exception
  106.                     ' Handle conversion error or unsupported data type
  107.                     ' You can log an error or provide a custom error message
  108.                     Console.WriteLine("Error: " & ex.Message)
  109.                 End Try
  110.             End If
  111.         End If
  112.     End Sub
  113.     Public Function GetProperty(BlockRef As BlockReference, PropName As String) As DynamicBlockReferenceProperty
  114.         If BlockRef.IsDynamicBlock Then
  115.             For Each Prop As DynamicBlockReferenceProperty In BlockRef.DynamicBlockReferencePropertyCollection
  116.                 If Not Prop.ReadOnly Then
  117.                     If Prop.PropertyName.ToLower = PropName.ToLower Then
  118.                         Return Prop
  119.                     End If
  120.                 End If
  121.             Next
  122.         End If
  123.         Return Nothing
  124.     End Function
  125.  
  126.     Public Sub SetDuct(br As BlockReference)
  127.         If Duct_Distance > 0 Then
  128.             SetProperty(br, "DUCT_1", Duct_Distance)
  129.         End If
  130.     End Sub
  131.     Sub forsafekeeping(br As BlockReference)
  132.         If Duct_Width > 0 Then
  133.             If Insulation_KeepClear Then
  134.                 SetProperty(br, "SIZE_1", Duct_Width + Insulation_Clear_Size)
  135.             Else
  136.                 SetProperty(br, "SIZE_1", Duct_Width)
  137.  
  138.             End If
  139.         End If
  140.         SetProperty(br, "INSULATION", Insulation_Type)
  141.         If Insulation_Type <> "NONE" Then
  142.             If Insulation_Internal_Size > 0 Then
  143.                 SetProperty(br, "INSULATION_INTERNAL", Insulation_Internal_Size)
  144.             End If
  145.             If Insulation_External_Size > 0 Then
  146.                 SetProperty(br, "INSULATION_EXTERNAL", Insulation_External_Size)
  147.             End If
  148.         End If
  149.     End Sub
  150. End Module
  151. Class InsertBlockJig
  152.     Inherits EntityJig
  153.  
  154.     ' Protected fields
  155.     Protected position As Point3d
  156.     Protected br As BlockReference
  157.  
  158.     ' Constructor (fields initialization)
  159.     Public Sub New(br As BlockReference)
  160.         MyBase.New(br)
  161.         Me.br = br
  162.         Me.position = br.Position
  163.  
  164.     End Sub
  165.  
  166.     ' Prompts the user to specify the insertion point (EntityJig implementation)
  167.     Protected Overrides Function Sampler(prompts As JigPrompts) As SamplerStatus
  168.         Dim msg As String = vbLf & "Specify the insertion point: "
  169.         Dim jppo As New JigPromptPointOptions(msg)
  170.         jppo.UserInputControls = (UserInputControls.Accept3dCoordinates Or
  171.                                       UserInputControls.NullResponseAccepted)
  172.         Dim ppr As PromptPointResult = prompts.AcquirePoint(jppo)
  173.         If Me.position.DistanceTo(ppr.Value) < Tolerance.[Global].EqualPoint Then
  174.             Return SamplerStatus.NoChange
  175.         Else
  176.             SetDuct(Me.br)
  177.             Me.position = ppr.Value
  178.         End If
  179.         Return SamplerStatus.OK
  180.     End Function
  181.  
  182.     ' Updates the bloc position (EntityJig implementation)
  183.     Protected Overrides Function Update() As Boolean
  184.         Me.br.Position = Me.position
  185.  
  186.         Return True
  187.     End Function
  188. End Class
  189.  
  190. Class RotateBlockJig
  191.     Inherits EntityJig
  192.  
  193.     ' Private fields
  194.     Protected br As BlockReference
  195.     Protected rot As Double, ucsRot As Double
  196.  
  197.     ' Constructor
  198.     Public Sub New(br As BlockReference)
  199.         MyBase.New(br)
  200.         Me.br = br
  201.         Me.ucsRot = br.Rotation
  202.  
  203.     End Sub
  204.  
  205.     ' Prompts the user to specify the rotation (EntityJig implementation)
  206.     Protected Overrides Function Sampler(prompts As JigPrompts) As SamplerStatus
  207.         Dim BasePoint As Point3d = Me.br.Position
  208.         Dim jpao As New JigPromptPointOptions(vbLf & "Specify Duct EndPoint: ")
  209.         'JigPromptAngleOptions(vbLf & "Specify the rotation: ")
  210.         jpao.DefaultValue = BasePoint
  211.         jpao.UseBasePoint = True
  212.         jpao.BasePoint = BasePoint
  213.         jpao.Cursor = CursorType.RubberBand
  214.         jpao.UserInputControls = (UserInputControls.Accept3dCoordinates Or
  215.                                       UserInputControls.UseBasePointElevation Or
  216.                                       UserInputControls.NullResponseAccepted)
  217.         Dim pt As PromptPointResult = prompts.AcquirePoint(jpao)
  218.         Dim NewPt As Point3d = pt.Value
  219.         Dim Pt1 As New Point2d(BasePoint.X, BasePoint.Y)
  220.         Dim Pt2 As New Point2d(NewPt.X, NewPt.Y)
  221.         Dim NewAngle As Double = Pt1.GetVectorTo(Pt2).Angle
  222.         Duct_Distance = Pt1.GetDistanceTo(Pt2)
  223.         SetDuct(Me.br)
  224.         If Me.rot = NewAngle Then
  225.             Return SamplerStatus.NoChange
  226.         Else
  227.             Me.rot = NewAngle
  228.             Return SamplerStatus.OK
  229.         End If
  230.     End Function
  231.  
  232.     ' Updates the bloc rotation (EntityJig implementation)
  233.     Protected Overrides Function Update() As Boolean
  234.         UpdateRotation()
  235.         Return True
  236.     End Function
  237.  
  238.     ' Updates the bloc rotation (mandatory for the 'default' option)
  239.     ' This method is called from the method where the jig is created
  240.     Friend Sub UpdateRotation()
  241.         Me.br.Rotation = Me.rot + Me.ucsRot
  242.         'SetDuct(Me.br)
  243.     End Sub
  244. End Class

I am sure it is something stupid and obvious.

Jeff H

  • Needs a day job
  • Posts: 6150
Re: Setting Dynamic Block Values with VB.NET
« Reply #9 on: January 25, 2024, 06:56:51 PM »
Your calling UpadteAnonymousBlocks on Model Space.
You need to call it on whatever "BlkName" is

kdub_nz

  • Mesozoic keyThumper
  • SuperMod
  • Water Moccasin
  • Posts: 2141
  • class keyThumper<T>:ILazy<T>
Re: Setting Dynamic Block Values with VB.NET
« Reply #10 on: January 25, 2024, 06:58:51 PM »
<scrapped>
Jeff beat me.

added:
My head hurts,
. . . there's a reason I haven't touched xVBx in 20 odd years.

Called Kerry in my other life
Retired; but they dragged me back in !

I live at UTC + 13.00

---
some people complain about loading the dishwasher.
Sometimes the question is more important than the answer.

cmwade77

  • Swamp Rat
  • Posts: 1443
Re: Setting Dynamic Block Values with VB.NET
« Reply #11 on: January 25, 2024, 07:01:36 PM »
Oki, makes sense, but how do I get the blocktablerecord for that? Blkname is just the string that represents the block name

br is the block reference itself.

kdub_nz

  • Mesozoic keyThumper
  • SuperMod
  • Water Moccasin
  • Posts: 2141
  • class keyThumper<T>:ILazy<T>
Re: Setting Dynamic Block Values with VB.NET
« Reply #12 on: January 25, 2024, 07:15:43 PM »
Just a note, because I see this a lot:
Though technically correct,
Code - vb.net: [Select]
  1.    Dim btr As BlockTableRecord =
  2.          DirectCast(tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite), BlockTableRecord)
  3.  

is better written:
Code - vb.net: [Select]
  1.    Dim currentSpace As BlockTableRecord =
  2.          DirectCast(tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite), BlockTableRecord)
  3.  
and make the refactors required.
This naming is more indicative of intent , and reduces misinterpretation.
« Last Edit: January 25, 2024, 07:18:44 PM by kdub_nz »
Called Kerry in my other life
Retired; but they dragged me back in !

I live at UTC + 13.00

---
some people complain about loading the dishwasher.
Sometimes the question is more important than the answer.

cmwade77

  • Swamp Rat
  • Posts: 1443
Re: Setting Dynamic Block Values with VB.NET
« Reply #13 on: January 25, 2024, 07:22:33 PM »
That certainly makes sense, I have tried adjusting the code to this and I am getting the same results:

Code - vb.net: [Select]
  1.     Public Sub InsertBlock(BlkName As String)
  2.         Dim bRollup As Boolean = ps.AutoRollUp
  3.         If ps.Dock.Equals(DockSides.None) Then
  4.             If ps.Style.Equals(32) Then
  5.                 ps.Style = 0
  6.             End If
  7.             With ps
  8.                 .AutoRollUp = True
  9.                 .Visible = False
  10.                 .Visible = True
  11.             End With
  12.             ps.AutoRollUp = bRollup
  13.         End If
  14.         BlkName = Duct_Shape & "_" & BlkName
  15.         Dim FullPath As String = Directory.GetCurrentDirectory & "\Blocks\" & BlkName & ".dwg"
  16.         Using xDb As New Database(False, True)
  17.             xDb.ReadDwgFile(FullPath, FileShare.Read, True, Nothing)
  18.             Using DocLock As DocumentLock = doc.LockDocument
  19.                 Try
  20.                     Dim Id As ObjectId = db.Insert(BlkName, xDb, True)
  21.                     If Id.IsNull Then
  22.                         ed.WriteMessage(vbLf & "Failed to insert block")
  23.                         Return
  24.                     End If
  25.                     Using tr As Transaction = db.TransactionManager.StartTransaction()
  26.                         Try
  27.                             Dim bt As BlockTable =
  28.                     DirectCast(tr.GetObject(db.BlockTableId, OpenMode.ForRead), BlockTable)
  29.                             If Not bt.Has(BlkName) Then
  30.                                 ed.WriteMessage(vbLf & "Block '{0}' not found.", BlkName)
  31.                                 Return
  32.                             End If
  33.  
  34.                             Dim pr As PromptResult
  35.                             Using br As New BlockReference(Point3d.Origin, bt(BlkName))
  36.                                 br.TransformBy(ed.CurrentUserCoordinateSystem)
  37.  
  38.                                 ' Using InsertBlockJig class to insert the block
  39.                                 Dim insertJig As New InsertBlockJig(br)
  40.                                 pr = ed.Drag(insertJig)
  41.                                 If pr.Status <> PromptStatus.OK Then
  42.                                     Return
  43.                                 End If
  44.  
  45.                                 ' Using RotateBlockJig class to rotate the block
  46.                                 Dim rotateJig As New RotateBlockJig(br)
  47.                                 pr = ed.Drag(rotateJig)
  48.                                 If pr.Status <> PromptStatus.OK Then
  49.                                     Return
  50.                                 End If
  51.                                 rotateJig.UpdateRotation()
  52.  
  53.                                 Dim currentSpace As BlockTableRecord =
  54.                                 DirectCast(tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite), BlockTableRecord)
  55.                                 currentSpace.AppendEntity(br)
  56.                                 tr.AddNewlyCreatedDBObject(br, True)
  57.  
  58.                                 Dim btr As BlockTableRecord = DirectCast(tr.GetObject(br.BlockTableRecord, OpenMode.ForWrite), BlockTableRecord)
  59.                                 If Not IsNothing(btr) Then
  60.                                     btr.UpdateAnonymousBlocks()
  61.                                 End If
  62.  
  63.                                 tr.Commit()
  64.                                 Dim Prop As DynamicBlockReferenceProperty = GetProperty(br, "DUCT_1")
  65.                                 If Not IsNothing(Prop) Then
  66.                                     ed.WriteMessage(vbCrLf & "Property: " & Prop.PropertyName & " set successfully to value of: " & Prop.Value.ToString)
  67.                                 Else
  68.                                     ed.WriteMessage(vbCrLf & "Could not find DUCT_1 property in block " & br.Name)
  69.                                 End If
  70.                             End Using
  71.  
  72.                         Catch Ex As System.AccessViolationException
  73.                         End Try
  74.                     End Using
  75.                 Catch Ex As System.AccessViolationException
  76.                 End Try
  77.             End Using
  78.         End Using
  79.         Duct_Distance = 0
  80.     End Sub

gile

  • Gator
  • Posts: 2507
  • Marseille, France
Re: Setting Dynamic Block Values with VB.NET
« Reply #14 on: January 26, 2024, 03:26:27 AM »
It seems that you want to do a lot of things at once in this method, which makes things confusing (even for you apparently).
  • You should test whether the block table doesn't already contain the block before inserting the file with (db.Insert ...).
  • As your method is called in the context of the application (from a non-modal UI), you should define a command (CommandMethod) that you call from the Palette with SendStringToExecute. This lets AutoCAD lock the document and allows you to call and test the method without the palette.
  • You should not mix hard coded names ("DUCT_1") and parameters (blockName) in the same method.
  • Duct_Distance should be a public property of the RotateBlockJig class.
  • You should report exception messages instead of hiding them.

The following code seems to work as expected. It uses the "hard-coding' way to insert a "ROUND_DUCT" block which we know has a dynamic property named "DUCT_1" whose value is of type double.
Code - C#: [Select]
  1.         [CommandMethod("INSERT_ROUND_DUCT")]
  2.         public static void InsertRoundDuctBlock()
  3.         {
  4.             var doc = Application.DocumentManager.MdiActiveDocument;
  5.             var db = doc.Database;
  6.             var ed = doc.Editor;
  7.             using (var tr = db.TransactionManager.StartTransaction())
  8.             {
  9.                 // Get the ObjectId of the "ROUND_DUCT" block definition
  10.                 var btrId = GetBlock("ROUND_DUCT", db);
  11.                 if (btrId.IsNull)
  12.                 {
  13.                     ed.WriteMessage("\nBlock 'ROUND_DUCT' not found.");
  14.                     return;
  15.                 }
  16.                 using (var br = new BlockReference(Point3d.Origin, btrId))
  17.                 {
  18.                     // Insert and rotate a new reference of "ROUND_DUCT"
  19.                     br.TransformBy(ed.CurrentUserCoordinateSystem);
  20.  
  21.                     var insertJig = new InsertBlockJig(br);
  22.                     var promptResult = ed.Drag(insertJig);
  23.                     if (promptResult.Status != PromptStatus.OK)
  24.                         return;
  25.  
  26.                     var rotateJig = new RotateBlockJig(br);
  27.                     promptResult = ed.Drag(rotateJig);
  28.                     if (promptResult.Status != PromptStatus.OK)
  29.                         return;
  30.  
  31.                     var currentSpace = (BlockTableRecord)tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite);
  32.                     currentSpace.AppendEntity(br);
  33.                     tr.AddNewlyCreatedDBObject(br, true);
  34.  
  35.                     // Resize the block reference using the "DUCT_1" dynamic property and the 'RotateJig.DuctDistance value
  36.                     foreach (DynamicBlockReferenceProperty property in br.DynamicBlockReferencePropertyCollection)
  37.                     {
  38.                         if (property.PropertyName == "DUCT_1")
  39.                         {
  40.                             property.Value = rotateJig.DuctDistance;
  41.                             break;
  42.                         }
  43.                     }
  44.                 }
  45.                 tr.Commit();
  46.             }
  47.         }
  48.  
  49.         private static ObjectId GetBlock(string blockName, Database db)
  50.         {
  51.             var blockTable = (BlockTable)db.BlockTableId.GetObject(OpenMode.ForRead);
  52.             if (blockTable.Has(blockName))
  53.             {
  54.                 return blockTable[blockName];
  55.             }
  56.             string fileName = Path.Combine(Directory.GetCurrentDirectory(), $@"Block\{blockName}.dwg");
  57.             {
  58.                 using (var xDb = new Database(false, true))
  59.                 {
  60.                     xDb.ReadDwgFile(fileName, FileOpenMode.OpenForReadAndAllShare, true, null);
  61.                     return db.Insert(fileName, xDb, true);
  62.                 }
  63.             }
  64.             return ObjectId.Null;
  65.         }

From your Palette, you can simply do:
Code - C#: [Select]
  1.         public static void FromPalette()
  2.         {
  3.             var doc = Application.DocumentManager.MdiActiveDocument;
  4.             doc.SendStringToExecute("INSERT_ROUND_DUCT\n", false, false, false);
  5.         }

Or, if I don't misunderstand what you're trying to do with the palette (set AutoRollUp to true during the Jig and reset its preious value after if completes), you have to call the InsertRoundDuct command synchronously:
Code - C#: [Select]
  1.         private void button3_Click(object sender, EventArgs e)
  2.         {
  3.             var ps = Commands.Palette;
  4.             bool rollup = ps.AutoRollUp;
  5.             if (ps.Dock == DockSides.None && ps.Style.HasFlag(PaletteSetStyles.Snappable))
  6.             {
  7.                 ps.Style &= ~PaletteSetStyles.Snappable;
  8.             }
  9.             ps.AutoRollUp = true;
  10.             var doc = AcAp.DocumentManager.MdiActiveDocument;
  11.             var ed = doc.Editor;
  12.             AcAp.DocumentManager.ExecuteInCommandContextAsync(
  13.                 (_) =>
  14.                 {
  15.                     ed.Command("INSERT_ROUND_DUCT");
  16.                     ps.AutoRollUp = rollup;
  17.                     return Task.CompletedTask;
  18.                 },
  19.                 null);
  20.         }


« Last Edit: January 29, 2024, 02:56:10 AM by gile »
Speaking English as a French Frog

gile

  • Gator
  • Posts: 2507
  • Marseille, France
Re: Setting Dynamic Block Values with VB.NET
« Reply #15 on: January 29, 2024, 02:55:09 AM »
If you want a more 'generic' function to be used with different dynamic blocks which all have a Distance dynamic parameter.
Note: I add to the GetBlock method the ability to search in the Support File Search Paths.
Code - C#: [Select]
  1.         [CommandMethod("INSERT_ROUND_DUCT")]
  2.         public static void InsertRoundDuctBlock()
  3.         {
  4.             InsertRotateResizeBlock("ROUND_DUCT", "DUCT_1");
  5.         }
  6.  
  7.         public static void InsertRotateResizeBlock(string blockName, string propertyName)
  8.         {
  9.             var doc = Application.DocumentManager.MdiActiveDocument;
  10.             var db = doc.Database;
  11.             var ed = doc.Editor;
  12.             using (var tr = db.TransactionManager.StartTransaction())
  13.             {
  14.                 // Get the ObjectId of the block definition
  15.                 var btrId = GetBlock(blockName, db);
  16.                 if (btrId.IsNull)
  17.                 {
  18.                     ed.WriteMessage($"\nBlock '{blockName}' not found.");
  19.                     return;
  20.                 }
  21.                 using (var br = new BlockReference(Point3d.Origin, btrId))
  22.                 {
  23.                     // Insert and rotate a new 'blockName' reference
  24.                     br.TransformBy(ed.CurrentUserCoordinateSystem);
  25.  
  26.                     var insertJig = new InsertBlockJig(br);
  27.                     var promptResult = ed.Drag(insertJig);
  28.                     if (promptResult.Status != PromptStatus.OK)
  29.                         return;
  30.  
  31.                     var rotateJig = new RotateBlockJig(br);
  32.                     promptResult = ed.Drag(rotateJig);
  33.                     if (promptResult.Status != PromptStatus.OK)
  34.                         return;
  35.  
  36.                     var currentSpace = (BlockTableRecord)tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite);
  37.                     currentSpace.AppendEntity(br);
  38.                     tr.AddNewlyCreatedDBObject(br, true);
  39.  
  40.                     // Resize the block reference using the 'propertyName' dynamic property and the 'RotateJig.DuctDistance value
  41.                     var property = GetProperty(br, propertyName);
  42.                     if (property == null)
  43.                     {
  44.                         ed.WriteMessage($"\nDynamic property '{propertyName}' not found.");
  45.                         return;
  46.                     }
  47.                     try
  48.                     {
  49.                         property.Value = rotateJig.DuctDistance;
  50.                     }
  51.                     catch
  52.                     {
  53.                         ed.WriteMessage($"\n Unable to set '{propertyName}' value with: {rotateJig.DuctDistance}");
  54.                     }
  55.                 }
  56.                 tr.Commit();
  57.             }
  58.         }
  59.  
  60.         private static ObjectId GetBlock(string blockName, Database db)
  61.         {
  62.             // Search in the drawing BlockTable
  63.             var blockTable = (BlockTable)db.BlockTableId.GetObject(OpenMode.ForRead);
  64.             if (blockTable.Has(blockName))
  65.             {
  66.                 return blockTable[blockName];
  67.             }
  68.  
  69.             // Search in the current directory
  70.             string fileName = Path.Combine(Directory.GetCurrentDirectory(), $@"Block\{blockName}.dwg");
  71.             if (File.Exists(fileName))
  72.             {
  73.                 using (var xDb = new Database(false, true))
  74.                 {
  75.                     xDb.ReadDwgFile(fileName, FileOpenMode.OpenForReadAndAllShare, true, null);
  76.                     return db.Insert(fileName, xDb, true);
  77.                 }
  78.             }
  79.  
  80.             // Search in the Support File Search Paths
  81.             try
  82.             {
  83.                 fileName = HostApplicationServices.Current.FindFile($@"{blockName}.dwg", db, FindFileHint.Default);
  84.                 using (var xDb = new Database(false, true))
  85.                 {
  86.                     xDb.ReadDwgFile(fileName, FileOpenMode.OpenForReadAndAllShare, true, null);
  87.                     return db.Insert(blockName, xDb, true);
  88.                 }
  89.             }
  90.             catch { return ObjectId.Null; }
  91.         }
  92.  
  93.         private static DynamicBlockReferenceProperty GetProperty(BlockReference br, string propertyName)
  94.         {
  95.             foreach (DynamicBlockReferenceProperty property in br.DynamicBlockReferencePropertyCollection)
  96.             {
  97.                 if (propertyName.Equals(property.PropertyName, StringComparison.CurrentCultureIgnoreCase))
  98.                 {
  99.                     return property;
  100.                 }
  101.             }
  102.             return null;
  103.         }
Speaking English as a French Frog

cmwade77

  • Swamp Rat
  • Posts: 1443
Re: Setting Dynamic Block Values with VB.NET
« Reply #16 on: February 02, 2024, 12:08:35 PM »
I found the issue, but I am unsure if this is a bug or as designed with AutoCAD, but if you modify the dynamic block properties before appending the entity to the space, then you get the malformed block, now the problem is in order for the jig to work properly as a full preview, you have to modify the block before adding it to the space in the drawing, so the work around I have found is:

  • Create a temporary block insertion.
  • Modify it with the Jig and save the applicable settings in the jig
  • Create a second block
  • Set the position and rotation of the new block
  • Copy over the dynamic properties
  • Commit the transaction without having added the first block to the drawing


Here is the code I now have:
Code - C#: [Select]
  1. using System;
  2. using System.IO;
  3. using System.Reflection;
  4. using Autodesk.AutoCAD.DatabaseServices;
  5. using Autodesk.AutoCAD.EditorInput;
  6. using Autodesk.AutoCAD.Geometry;
  7. using BDuct_Global;
  8.  
  9. namespace BDuct
  10. {
  11.     static class AutoCADFunctions
  12.     {
  13.         public static void InsertBlock(string BlkName)
  14.         {
  15.             Editor ed = GlobalVariables.ed;
  16.             Database db = GlobalVariables.db;
  17.             using (var DocLock = GlobalVariables.doc.LockDocument())
  18.             {
  19.                 // First transaction: To add the block definition
  20.                 using (Transaction tr = db.TransactionManager.StartTransaction())
  21.                 {
  22.                     BlockTable bt = (BlockTable)tr.GetObject(db.BlockTableId, Autodesk.AutoCAD.DatabaseServices.OpenMode.ForRead);
  23.  
  24.                     if (!bt.Has(BlkName))
  25.                     {
  26.                         // Path to the block file
  27.                         string assemblyPath = Assembly.GetExecutingAssembly().Location;
  28.                         string directoryPath = Path.GetDirectoryName(assemblyPath);
  29.                         string blockFilePath = Path.Combine(directoryPath, "Blocks", BlkName + ".dwg");
  30.  
  31.                         if (!File.Exists(blockFilePath))
  32.                         {
  33.                             ed.WriteMessage("\nBlock file does not exist: " + blockFilePath);
  34.                             return; // Exit if file does not exist
  35.                         }
  36.  
  37.                         bt.UpgradeOpen();
  38.                         using (Database tempDb = new Database(false, true))
  39.                         {
  40.                             tempDb.ReadDwgFile(blockFilePath, FileShare.Read, true, null);
  41.                             ObjectIdCollection blockIds = new ObjectIdCollection();
  42.                             // blockIds.Add(tempDb.BlockTableId);
  43.                             var Id = db.Insert(BlkName, tempDb, true);
  44.                             db.WblockCloneObjects(blockIds, bt.Id, new IdMapping(), DuplicateRecordCloning.Replace, false);
  45.                         }
  46.                         bt.DowngradeOpen();
  47.                         tr.Commit();
  48.                     }
  49.                 }
  50.                 using (Transaction tr = db.TransactionManager.StartTransaction())
  51.                 {
  52.                     BlockTable bt = (BlockTable)tr.GetObject(db.BlockTableId, Autodesk.AutoCAD.DatabaseServices.OpenMode.ForRead);
  53.  
  54.                     if (bt.Has(BlkName))
  55.                     {
  56.                         bt.UpgradeOpen();
  57.                         BlockTableRecord btr = (BlockTableRecord)tr.GetObject(bt[BlkName], Autodesk.AutoCAD.DatabaseServices.OpenMode.ForRead);
  58.                         BlockReference temp_ent = new BlockReference(new Point3d(0, 0, 0), btr.ObjectId);
  59.                         BlockIns Jigger_Ins = new BlockIns(temp_ent);
  60.                         PromptResult pr_Ins = ed.Drag(Jigger_Ins);
  61.                         if (pr_Ins.Status == PromptStatus.OK)
  62.                         {
  63.                             BlockRot Jigger_Rot = new BlockRot(temp_ent);
  64.                             PromptResult pr_Rot = ed.Drag(Jigger_Rot);
  65.                             if (pr_Rot.Status == PromptStatus.OK)
  66.                             {                                
  67.                                 BlockReference ent = new BlockReference(new Point3d(0, 0, 0), btr.ObjectId);
  68.                                 BlockTableRecord currentSpace = (BlockTableRecord)tr.GetObject(db.CurrentSpaceId, Autodesk.AutoCAD.DatabaseServices.OpenMode.ForWrite);
  69.                                 currentSpace.AppendEntity(ent);
  70.                                 tr.AddNewlyCreatedDBObject(ent, true);
  71.                                 ent.Position = Jigger_Ins.position;
  72.                                 ent.Rotation = Jigger_Rot.rotation;
  73.                                 if (ent.IsDynamicBlock)
  74.                                 {
  75.                                     DynamicBlockReferencePropertyCollection props = ent.DynamicBlockReferencePropertyCollection;
  76.                                     foreach (DynamicBlockReferenceProperty prop in props)
  77.                                     {
  78.                                         DynamicBlockReferencePropertyCollection temp_props = temp_ent.DynamicBlockReferencePropertyCollection;
  79.                                         foreach (DynamicBlockReferenceProperty temp_prop in props)
  80.                                         {
  81.                                             if (prop.PropertyName == temp_prop.PropertyName && !prop.ReadOnly) // Replace "YourDynamicProperty"
  82.                                             {
  83.                                                 ed.WriteMessage("\n" + prop.PropertyName.ToString() + "\n");
  84.                                                 prop.Value = temp_prop.Value;
  85.                                                 break;
  86.                                             }
  87.                                         }                                        
  88.                                     }
  89.                                 }
  90.                                 currentSpace.AppendEntity(temp_ent);
  91.                                 tr.AddNewlyCreatedDBObject(temp_ent, true);
  92.                                 temp_ent.Erase();
  93.                                 bt.DowngradeOpen(); tr.Commit();                                
  94.                             }
  95.                             else
  96.                             {
  97.                                 bt.DowngradeOpen(); tr.Abort();
  98.                             }                            
  99.                         }
  100.                         else
  101.                         {
  102.                             bt.DowngradeOpen(); tr.Abort();
  103.                         }
  104.                     }
  105.                 }
  106.             }
  107.         }
  108.     }
  109.  
  110.     public class BlockRot : EntityJig
  111.     {
  112.         #region Fields
  113.         private double mRotation;
  114.         private double mDistance;        
  115.         #endregion
  116.         public BlockRot(Entity ent) : base(ent)
  117.         {
  118.         }
  119.  
  120.         // Add a property to access mPosition
  121.         public double rotation
  122.         {
  123.             get { return mRotation; }
  124.             set { mRotation = value; }
  125.         }
  126.  
  127.         public double distance
  128.         {
  129.             get { return mDistance; }
  130.             set { mDistance = value; }
  131.         }
  132.  
  133.         protected override SamplerStatus Sampler(JigPrompts prompts)
  134.         {
  135.             Point3d basePoint = (Entity as BlockReference).Position;
  136.             JigPromptPointOptions prOptionsPoint = new JigPromptPointOptions("\rSelect next point: ");
  137.             prOptionsPoint.BasePoint = basePoint;
  138.             prOptionsPoint.UseBasePoint = true;
  139.             prOptionsPoint.Cursor = CursorType.RubberBand;
  140.             PromptPointResult promptPointResult = prompts.AcquirePoint(prOptionsPoint);
  141.  
  142.             if (promptPointResult.Status == PromptStatus.Cancel)
  143.             {
  144.                 return SamplerStatus.Cancel;
  145.             }
  146.             else
  147.             {
  148.                 Point3d newPosition = promptPointResult.Value;
  149.                 double newRotation = CalculateRotation(basePoint, newPosition);
  150.                 double newDistance = basePoint.DistanceTo(newPosition);
  151.                 if (!newDistance.Equals(mDistance) || !newRotation.Equals(mRotation))
  152.                 {
  153.                     mDistance = newDistance;
  154.                     mRotation = newRotation;
  155.                     (Entity as BlockReference).Rotation = mRotation;
  156.                     UpdateDynamicBlockProperty(mDistance); // Update distance dynamically
  157.                     return SamplerStatus.OK;
  158.                 }                
  159.             }
  160.             return SamplerStatus.NoChange;
  161.         }
  162.  
  163.         protected override bool Update()
  164.         {
  165.             (Entity as BlockReference).Rotation = mRotation;
  166.             return true;
  167.         }
  168.  
  169.         #region Methods
  170.         private double CalculateRotation(Point3d basePoint, Point3d newPosition)
  171.         {
  172.             Vector3d vector = newPosition - basePoint;
  173.             // Assuming the X-axis as the reference, adjust as needed
  174.             double angle = Math.Atan2(vector.Y, vector.X);
  175.             return angle;
  176.         }
  177.  
  178.         private void UpdateDynamicBlockProperty(double distance)
  179.         {
  180.             // Assuming the block reference and its dynamic properties are accessible
  181.             // Similar to the previous example, directly set the dynamic block property here
  182.             DynamicBlockReferencePropertyCollection props = (Entity as BlockReference).DynamicBlockReferencePropertyCollection;
  183.             foreach (DynamicBlockReferenceProperty prop in props)
  184.             {
  185.                 if (prop.PropertyName == "DUCT_1" && !prop.ReadOnly) // Replace "YourDynamicProperty"
  186.                 {
  187.                     prop.Value = distance;
  188.                     break; // Exit after setting the relevant property
  189.                 }
  190.             }
  191.         }
  192.         #endregion
  193.  
  194.     }
  195.  
  196.  
  197.  
  198.     public class BlockIns : EntityJig
  199.     {
  200.         #region Fields
  201.         private Point3d mPosition;        
  202.         #endregion
  203.  
  204.         public BlockIns(BlockReference ent) : base(ent)
  205.         {
  206.         }
  207.  
  208.         // Add a property to access mPosition
  209.         public Point3d position
  210.         {
  211.             get { return mPosition; }
  212.             set { mPosition = value; }
  213.         }
  214.  
  215.         protected override SamplerStatus Sampler(JigPrompts prompts)
  216.         {
  217.             JigPromptPointOptions prOptions1 = new JigPromptPointOptions("\rSelect start point:");
  218.             PromptPointResult prResult1 = prompts.AcquirePoint(prOptions1);
  219.             if (prResult1.Status == PromptStatus.Cancel) return SamplerStatus.Cancel;
  220.  
  221.             if (prResult1.Value.Equals(mPosition))
  222.             {
  223.                 return SamplerStatus.NoChange;
  224.             }
  225.             else
  226.             {
  227.                 mPosition = prResult1.Value;
  228.                 return SamplerStatus.OK;
  229.             }
  230.         }
  231.  
  232.         protected override bool Update()
  233.         {
  234.             (Entity as BlockReference).Position = mPosition;
  235.             return true;
  236.         }
  237.     }
  238. }
  239.  

cmwade77

  • Swamp Rat
  • Posts: 1443
Re: Setting Dynamic Block Values with VB.NET
« Reply #17 on: February 02, 2024, 01:37:42 PM »
Now what I don't get is why it isn't copying the values over, so I decided to try to set everything individually, the problem is I have to put what is essentially the same code in three spaces, I am sure there is a way to make a class that works for this, but everything I tried doesn't work.

Code - C#: [Select]
  1. using System;
  2. using System.IO;
  3. using System.Reflection;
  4. using Autodesk.AutoCAD.DatabaseServices;
  5. using Autodesk.AutoCAD.EditorInput;
  6. using Autodesk.AutoCAD.Geometry;
  7. using BDuct_Global;
  8.  
  9. namespace BDuct
  10. {
  11.     public class AutoCADFunctions
  12.     {
  13.        
  14.         public static void InsertBlock(string BlkName)
  15.         {
  16.             Editor ed = GlobalVariables.ed;
  17.             Database db = GlobalVariables.db;
  18.             using (var DocLock = GlobalVariables.doc.LockDocument())
  19.             {
  20.                 // First transaction: To add the block definition
  21.                 using (Transaction tr = db.TransactionManager.StartTransaction())
  22.                 {
  23.                     BlockTable bt = (BlockTable)tr.GetObject(db.BlockTableId, Autodesk.AutoCAD.DatabaseServices.OpenMode.ForRead);
  24.  
  25.                     if (!bt.Has(BlkName))
  26.                     {
  27.                         // Path to the block file
  28.                         string assemblyPath = Assembly.GetExecutingAssembly().Location;
  29.                         string directoryPath = Path.GetDirectoryName(assemblyPath);
  30.                         string blockFilePath = Path.Combine(directoryPath, "Blocks", BlkName + ".dwg");
  31.  
  32.                         if (!File.Exists(blockFilePath))
  33.                         {
  34.                             ed.WriteMessage("\nBlock file does not exist: " + blockFilePath);
  35.                             return; // Exit if file does not exist
  36.                         }
  37.  
  38.                         bt.UpgradeOpen();
  39.                         using (Database tempDb = new Database(false, true))
  40.                         {
  41.                             tempDb.ReadDwgFile(blockFilePath, FileShare.Read, true, null);
  42.                             ObjectIdCollection blockIds = new ObjectIdCollection();
  43.                             // blockIds.Add(tempDb.BlockTableId);
  44.                             var Id = db.Insert(BlkName, tempDb, true);
  45.                             db.WblockCloneObjects(blockIds, bt.Id, new IdMapping(), DuplicateRecordCloning.Replace, false);
  46.                         }
  47.                         bt.DowngradeOpen();
  48.                         tr.Commit();
  49.                     }
  50.                 }
  51.                 using (Transaction tr = db.TransactionManager.StartTransaction())
  52.                 {
  53.                     BlockTable bt = (BlockTable)tr.GetObject(db.BlockTableId, Autodesk.AutoCAD.DatabaseServices.OpenMode.ForRead);
  54.  
  55.                     if (bt.Has(BlkName))
  56.                     {
  57.                         bt.UpgradeOpen();
  58.                         BlockTableRecord btr = (BlockTableRecord)tr.GetObject(bt[BlkName], Autodesk.AutoCAD.DatabaseServices.OpenMode.ForRead);
  59.                         BlockReference temp_ent = new BlockReference(new Point3d(0, 0, 0), btr.ObjectId);
  60.                         BlockIns Jigger_Ins = new BlockIns(temp_ent);
  61.                         PromptResult pr_Ins = ed.Drag(Jigger_Ins);
  62.                         if (pr_Ins.Status == PromptStatus.OK)
  63.                         {
  64.                             BlockRot Jigger_Rot = new BlockRot(temp_ent);
  65.                             PromptResult pr_Rot = ed.Drag(Jigger_Rot);
  66.                             if (pr_Rot.Status == PromptStatus.OK)
  67.                             {
  68.                                 BlockTableRecord currentSpace = (BlockTableRecord)tr.GetObject(db.CurrentSpaceId, Autodesk.AutoCAD.DatabaseServices.OpenMode.ForWrite);
  69.                                 currentSpace.AppendEntity(temp_ent);
  70.                                 tr.AddNewlyCreatedDBObject(temp_ent, true);
  71.                                 temp_ent.Erase();
  72.                                 BlockReference ent = new BlockReference(new Point3d(0, 0, 0), btr.ObjectId);                                
  73.                                 currentSpace.AppendEntity(ent);
  74.                                 tr.AddNewlyCreatedDBObject(ent, true);
  75.                                 ent.Position = Jigger_Ins.position;
  76.                                 ent.Rotation = Jigger_Rot.rotation;
  77.                                 DynamicBlockReferencePropertyCollection props = ent.DynamicBlockReferencePropertyCollection;
  78.                                 foreach (DynamicBlockReferenceProperty prop in props)
  79.                                 {
  80.                                     if (!prop.ReadOnly) // Replace "YourDynamicProperty"
  81.                                     {
  82.  
  83.                                         switch (prop.PropertyName)
  84.                                         {
  85.                                             case "DUCT_1":
  86.                                                 prop.Value = Jigger_Rot.distance;
  87.                                                 break;
  88.                                             case "DUCT_WIDTH":
  89.                                                 prop.Value = GlobalVariables.Duct_Width;
  90.                                                 break;
  91.                                             case "DUCT_HEIGHT":
  92.                                                 //prop.Value = GlobalVariables.Duct_Hee
  93.                                                 break;
  94.                                             case "INSULATION":
  95.                                                 prop.Value = GlobalVariables.Insulation_Type;
  96.                                                 break;
  97.                                             case "INSULATION_INTERNAL":
  98.                                                 prop.Value = GlobalVariables.Insulation_Internal_Size;
  99.                                                 break;
  100.                                             case "INSULATION_EXTERNAL":
  101.                                                 prop.Value = GlobalVariables.Insulation_External_Size;
  102.                                                 break;
  103.                                             default:
  104.                                                 break;
  105.  
  106.                                         }
  107.  
  108.                                     }
  109.                                 }                                
  110.                                 bt.DowngradeOpen(); tr.Commit();                                
  111.                             }
  112.                             else
  113.                             {
  114.                                 bt.DowngradeOpen(); tr.Abort();
  115.                             }                            
  116.                         }
  117.                         else
  118.                         {
  119.                             bt.DowngradeOpen(); tr.Abort();
  120.                         }
  121.                     }
  122.                 }
  123.             }
  124.         }
  125.     }
  126.  
  127.     public class BlockRot : EntityJig
  128.     {
  129.         #region Fields
  130.         private double mRotation;
  131.         private double mDistance;        
  132.         #endregion
  133.         public BlockRot(Entity ent) : base(ent)
  134.         {
  135.         }
  136.  
  137.         // Add a property to access mPosition
  138.         public double rotation
  139.         {
  140.             get { return mRotation; }
  141.             set { mRotation = value; }
  142.         }
  143.  
  144.         public double distance
  145.         {
  146.             get { return mDistance; }
  147.             set { mDistance = value; }
  148.         }
  149.  
  150.         protected override SamplerStatus Sampler(JigPrompts prompts)
  151.         {
  152.             Point3d basePoint = (Entity as BlockReference).Position;
  153.             JigPromptPointOptions prOptionsPoint = new JigPromptPointOptions("\rSelect next point: ");
  154.             prOptionsPoint.BasePoint = basePoint;
  155.             prOptionsPoint.UseBasePoint = true;
  156.             prOptionsPoint.Cursor = CursorType.RubberBand;
  157.             PromptPointResult promptPointResult = prompts.AcquirePoint(prOptionsPoint);
  158.  
  159.             if (promptPointResult.Status == PromptStatus.Cancel)
  160.             {
  161.                 return SamplerStatus.Cancel;
  162.             }
  163.             else
  164.             {
  165.                 Point3d newPosition = promptPointResult.Value;
  166.                 double newRotation = CalculateRotation(basePoint, newPosition);
  167.                 double newDistance = basePoint.DistanceTo(newPosition);
  168.                 if (!newDistance.Equals(mDistance) || !newRotation.Equals(mRotation))
  169.                 {
  170.                     mDistance = newDistance;
  171.                     mRotation = newRotation;
  172.                     (Entity as BlockReference).Rotation = mRotation;
  173.                     UpdateDynamicBlockProperty(mDistance); // Update distance dynamically
  174.                     return SamplerStatus.OK;
  175.                 }                
  176.             }
  177.             return SamplerStatus.NoChange;
  178.         }
  179.  
  180.         protected override bool Update()
  181.         {
  182.             (Entity as BlockReference).Rotation = mRotation;
  183.             return true;
  184.         }
  185.  
  186.         #region Methods
  187.         private double CalculateRotation(Point3d basePoint, Point3d newPosition)
  188.         {
  189.             Vector3d vector = newPosition - basePoint;
  190.             // Assuming the X-axis as the reference, adjust as needed
  191.             double angle = Math.Atan2(vector.Y, vector.X);
  192.             return angle;
  193.         }
  194.  
  195.         private void UpdateDynamicBlockProperty(double distance)
  196.         {
  197.             // Assuming the block reference and its dynamic properties are accessible
  198.             // Similar to the previous example, directly set the dynamic block property here
  199.             DynamicBlockReferencePropertyCollection props = (Entity as BlockReference).DynamicBlockReferencePropertyCollection;
  200.             foreach (DynamicBlockReferenceProperty prop in props)
  201.             {
  202.                 if (!prop.ReadOnly) // Replace "YourDynamicProperty"
  203.                 {  
  204.  
  205.                     switch (prop.PropertyName)
  206.                     {
  207.                         case "DUCT_1":
  208.                             prop.Value = distance;
  209.                             break;
  210.                         case "DUCT_WIDTH":
  211.                             prop.Value = GlobalVariables.Duct_Width;
  212.                             break;
  213.                         case "DUCT_HEIGHT":
  214.                             //prop.Value = GlobalVariables.Duct_Hee
  215.                             break;
  216.                         case "INSULATION":
  217.                             prop.Value = GlobalVariables.Insulation_Type;
  218.                             break;
  219.                         case "INSULATION_INTERNAL":
  220.                             prop.Value = GlobalVariables.Insulation_Internal_Size;
  221.                             break;
  222.                         case "INSULATION_EXTERNAL":
  223.                             prop.Value = GlobalVariables.Insulation_External_Size;
  224.                             break;
  225.                         default:
  226.                             break;
  227.  
  228.                     }
  229.                                    
  230.                 }
  231.             }
  232.         }
  233.         #endregion
  234.  
  235.     }
  236.        
  237.  
  238.     public class BlockIns : EntityJig
  239.     {
  240.         #region Fields
  241.         private Point3d mPosition;        
  242.         #endregion
  243.  
  244.         public BlockIns(BlockReference ent) : base(ent)
  245.         {
  246.         }
  247.  
  248.         // Add a property to access mPosition
  249.         public Point3d position
  250.         {
  251.             get { return mPosition; }
  252.             set { mPosition = value; }
  253.         }
  254.  
  255.         protected override SamplerStatus Sampler(JigPrompts prompts)
  256.         {
  257.             JigPromptPointOptions prOptions1 = new JigPromptPointOptions("\rSelect start point:");
  258.             PromptPointResult prResult1 = prompts.AcquirePoint(prOptions1);
  259.             if (prResult1.Status == PromptStatus.Cancel) return SamplerStatus.Cancel;
  260.  
  261.             if (prResult1.Value.Equals(mPosition))
  262.             {
  263.                 return SamplerStatus.NoChange;
  264.             }
  265.             else
  266.             {
  267.                 mPosition = prResult1.Value;
  268.                 UpdateDynamicBlockProperty(15); // Update distance dynamically
  269.                 return SamplerStatus.OK;
  270.             }
  271.         }
  272.  
  273.         protected override bool Update()
  274.         {
  275.             (Entity as BlockReference).Position = mPosition;
  276.             return true;
  277.         }
  278.  
  279.         private void UpdateDynamicBlockProperty(double distance)
  280.         {
  281.             // Assuming the block reference and its dynamic properties are accessible
  282.             // Similar to the previous example, directly set the dynamic block property here
  283.             DynamicBlockReferencePropertyCollection props = (Entity as BlockReference).DynamicBlockReferencePropertyCollection;
  284.             foreach (DynamicBlockReferenceProperty prop in props)
  285.             {
  286.                 if (!prop.ReadOnly) // Replace "YourDynamicProperty"
  287.                 {
  288.  
  289.                     switch (prop.PropertyName)
  290.                     {
  291.                         case "DUCT_1":
  292.                             prop.Value = distance;
  293.                             break;
  294.                         case "DUCT_WIDTH":
  295.                             prop.Value = GlobalVariables.Duct_Width;
  296.                             break;
  297.                         case "DUCT_HEIGHT":
  298.                             //prop.Value = GlobalVariables.Duct_Hee
  299.                             break;
  300.                         case "INSULATION":
  301.                             prop.Value = GlobalVariables.Insulation_Type;
  302.                             break;
  303.                         case "INSULATION_INTERNAL":
  304.                             prop.Value = GlobalVariables.Insulation_Internal_Size;
  305.                             break;
  306.                         case "INSULATION_EXTERNAL":
  307.                             prop.Value = GlobalVariables.Insulation_External_Size;
  308.                             break;
  309.                         default:
  310.                             break;
  311.  
  312.                     }
  313.  
  314.                 }
  315.             }
  316.         }
  317.     }
  318. }
  319.  
  320.  

Does anyone have any ideas? There are going to be a lot more properties and I don't want to have to update them in three locations.
« Last Edit: February 02, 2024, 02:09:46 PM by cmwade77 »

gile

  • Gator
  • Posts: 2507
  • Marseille, France
Re: Setting Dynamic Block Values with VB.NET
« Reply #18 on: February 02, 2024, 02:47:09 PM »
You can make things much more simple.
No need to use two transactions
No need to create two block references
No need to UpgradeOpen/DowngradeOpen the BlockTable.
Code - C#: [Select]
  1.         public static void InsertRotateResizeBlock(string blockName, string propertyName)
  2.         {
  3.             var doc = Application.DocumentManager.MdiActiveDocument;
  4.             var db = doc.Database;
  5.             var ed = doc.Editor;
  6.             using (var tr = db.TransactionManager.StartTransaction())
  7.             {
  8.                 // Get the ObjectId of the block definition
  9.                 var btrId = GetBlock(blockName, db);
  10.                 if (btrId.IsNull)
  11.                 {
  12.                     ed.WriteMessage($"\nBlock '{blockName}' not found.");
  13.                     return;
  14.                 }
  15.  
  16.                 // Create a block reference
  17.                 using (var ghost = new BlockReference(Point3d.Origin, btrId))
  18.                 {
  19.                     // Check if 'propertyName' exists in the dynamic properties of the block reference
  20.                     var property = GetProperty(ghost, propertyName);
  21.                     if (property == null)
  22.                     {
  23.                         ed.WriteMessage($"\nDynamic property '{propertyName}' not found.");
  24.                         return;
  25.                     }
  26.  
  27.                     ghost.TransformBy(ed.CurrentUserCoordinateSystem);
  28.  
  29.                     // Set dynamic properties (except "DUCT_1")
  30.                     SetDynamicProperties(ghost, 40.0);
  31.  
  32.                     // Insert and rotate a new 'blockName' reference
  33.                     var insertJig = new InsertBlockJig(ghost);
  34.                     var promptResult = ed.Drag(insertJig);
  35.                     if (promptResult.Status == PromptStatus.OK)
  36.                     {
  37.                         var rotateJig = new RotateResizeBlockJig(ghost, property);
  38.                         promptResult = ed.Drag(rotateJig);
  39.                         if (promptResult.Status == PromptStatus.OK)
  40.                         {
  41.                             var currentSpace = (BlockTableRecord)tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite);
  42.                             var br = new BlockReference(ghost.Position, btrId) { Rotation = ghost.Rotation };
  43.                             currentSpace.AppendEntity(br);
  44.                             tr.AddNewlyCreatedDBObject(br, true);
  45.                             SetDynamicProperties(br, rotateJig.Distance);
  46.                         }
  47.                     }
  48.                     tr.Commit();
  49.                 }
  50.             }
  51.         }
  52.  
  53.         private static void SetDynamicProperties(BlockReference br, double distance)
  54.         {
  55.             foreach (DynamicBlockReferenceProperty prop in br.DynamicBlockReferencePropertyCollection)
  56.             {
  57.                 if (!prop.ReadOnly) // Replace "YourDynamicProperty"
  58.                 {
  59.                     switch (prop.PropertyName)
  60.                     {
  61.                         case "DUCT_1":
  62.                             prop.Value = distance;
  63.                             break;
  64.                         case "DUCT_WIDTH":
  65.                             prop.Value = GlobalVariables.Duct_Width;
  66.                             break;
  67.                         case "DUCT_HEIGHT":
  68.                             //prop.Value = GlobalVariables.Duct_Hee
  69.                             break;
  70.                         case "INSULATION":
  71.                             prop.Value = GlobalVariables.Insulation_Type;
  72.                             break;
  73.                         case "INSULATION_INTERNAL":
  74.                             prop.Value = GlobalVariables.Insulation_Internal_Size;
  75.                             break;
  76.                         case "INSULATION_EXTERNAL":
  77.                             prop.Value = GlobalVariables.Insulation_External_Size;
  78.                             break;
  79.                         default:
  80.                             break;
  81.                     }
  82.                 }
  83.             }
  84.         }
  85.  
  86.         private static ObjectId GetBlock(string blockName, Database db)
  87.         {
  88.             // Search in the drawing BlockTable
  89.             var blockTable = (BlockTable)db.BlockTableId.GetObject(OpenMode.ForRead);
  90.             if (blockTable.Has(blockName))
  91.             {
  92.                 return blockTable[blockName];
  93.             }
  94.  
  95.             // Search in the current directory
  96.             string fileName = Path.Combine(Directory.GetCurrentDirectory(), $@"Block\{blockName}.dwg");
  97.             if (File.Exists(fileName))
  98.             {
  99.                 using (var xDb = new Database(false, true))
  100.                 {
  101.                     xDb.ReadDwgFile(fileName, FileOpenMode.OpenForReadAndAllShare, true, null);
  102.                     return db.Insert(fileName, xDb, true);
  103.                 }
  104.             }
  105.  
  106.             // Search in the Support File Search Paths
  107.             try
  108.             {
  109.                 fileName = HostApplicationServices.Current.FindFile($@"{blockName}.dwg", db, FindFileHint.Default);
  110.                 using (var xDb = new Database(false, true))
  111.                 {
  112.                     xDb.ReadDwgFile(fileName, FileOpenMode.OpenForReadAndAllShare, true, null);
  113.                     return db.Insert(blockName, xDb, true);
  114.                 }
  115.             }
  116.             catch { return ObjectId.Null; }
  117.         }
  118.  
  119.         private static DynamicBlockReferenceProperty GetProperty(BlockReference br, string propertyName)
  120.         {
  121.             foreach (DynamicBlockReferenceProperty property in br.DynamicBlockReferencePropertyCollection)
  122.             {
  123.                 if (propertyName.Equals(property.PropertyName, StringComparison.CurrentCultureIgnoreCase))
  124.                 {
  125.                     return property;
  126.                 }
  127.             }
  128.             return null;
  129.         }
Jigs
Code - C#: [Select]
  1. internal class InsertBlockJig : EntityJig
  2. {
  3.     protected Point3d dragPoint;
  4.     protected BlockReference br;
  5.  
  6.     public InsertBlockJig(BlockReference br)
  7.         : base(br)
  8.     {
  9.         this.br = br;
  10.     }
  11.  
  12.     protected override SamplerStatus Sampler(JigPrompts prompts)
  13.     {
  14.         var options = new JigPromptPointOptions("\nSpecify insertion point: ");
  15.         options.UserInputControls =
  16.             UserInputControls.Accept3dCoordinates |
  17.             UserInputControls.GovernedByOrthoMode;
  18.         var result = prompts.AcquirePoint(options);
  19.         if (dragPoint.IsEqualTo(result.Value))
  20.             return SamplerStatus.NoChange;
  21.         dragPoint = result.Value;
  22.         return SamplerStatus.OK;
  23.     }
  24.  
  25.     protected override bool Update()
  26.     {
  27.         br.Position = dragPoint;
  28.         return true;
  29.     }
  30. }
  31.  
  32. internal class RotateResizeBlockJig : EntityJig
  33. {
  34.     protected BlockReference br;
  35.     protected Point3d dragPoint;
  36.     protected Plane plane;
  37.     protected DynamicBlockReferenceProperty property;
  38.  
  39.     public double Distance => br.Position.DistanceTo(dragPoint);
  40.  
  41.     public RotateResizeBlockJig(BlockReference br, DynamicBlockReferenceProperty property)
  42.         : base(br)
  43.     {
  44.         this.br = br;
  45.         this.property = property;
  46.         plane = new Plane(Point3d.Origin, br.Normal);
  47.     }
  48.  
  49.     protected override SamplerStatus Sampler(JigPrompts prompts)
  50.     {
  51.         var options = new JigPromptPointOptions("\nSpecify End Point: ");
  52.         options.UseBasePoint = true;
  53.         options.BasePoint = br.Position;
  54.         options.Cursor = CursorType.RubberBand;
  55.         options.UserInputControls =
  56.             UserInputControls.Accept3dCoordinates |
  57.             UserInputControls.UseBasePointElevation;
  58.         var result = prompts.AcquirePoint(options);
  59.  
  60.         if (dragPoint.IsEqualTo(result.Value))
  61.             return SamplerStatus.NoChange;
  62.         dragPoint = result.Value;
  63.         property.Value = Distance;
  64.         return SamplerStatus.OK;
  65.     }
  66.  
  67.     protected override bool Update()
  68.     {
  69.         br.Rotation = br.Position.GetVectorTo(dragPoint).AngleOnPlane(plane);
  70.         return true;
  71.     }
  72. }
« Last Edit: February 02, 2024, 06:08:52 PM by gile »
Speaking English as a French Frog

cmwade77

  • Swamp Rat
  • Posts: 1443
Re: Setting Dynamic Block Values with VB.NET
« Reply #19 on: February 02, 2024, 04:54:01 PM »
I will have to try your code on Monday, but I had tried something similar and it left the dynamic block unusable after the command was completed.

gile

  • Gator
  • Posts: 2507
  • Marseille, France
Re: Setting Dynamic Block Values with VB.NET
« Reply #20 on: February 02, 2024, 06:09:42 PM »
I updated the upper code. It seems to work as expected.
Speaking English as a French Frog

cmwade77

  • Swamp Rat
  • Posts: 1443
Re: Setting Dynamic Block Values with VB.NET
« Reply #21 on: February 02, 2024, 09:06:27 PM »
Thank you, I will take a look, it is such a strange quirk.

cmwade77

  • Swamp Rat
  • Posts: 1443
Re: Setting Dynamic Block Values with VB.NET
« Reply #22 on: February 05, 2024, 02:29:27 PM »
I looked at your code, but it only dynamically sets the one property of length in real time, ultimately I want all properties set in real time, but I think I can pick up some things from your code too that will simplify things and your method also doesn't insert the block from a file if not already in the drawing, that was the reason for my second transaction.
« Last Edit: February 05, 2024, 02:35:32 PM by cmwade77 »

gile

  • Gator
  • Posts: 2507
  • Marseille, France
Re: Setting Dynamic Block Values with VB.NET
« Reply #23 on: February 05, 2024, 03:49:24 PM »
your method also doesn't insert the block from a file if not already in the drawing, that was the reason for my second transaction.
Yes it does. Look at the GetBlock method.
Speaking English as a French Frog

cmwade77

  • Swamp Rat
  • Posts: 1443
Re: Setting Dynamic Block Values with VB.NET
« Reply #24 on: February 05, 2024, 04:42:57 PM »
Strange, it didn't do it on my end.

cmwade77

  • Swamp Rat
  • Posts: 1443
Re: Setting Dynamic Block Values with VB.NET
« Reply #25 on: February 05, 2024, 07:27:36 PM »
I think I figured out most of the issues, the one item I am now struggling with is during the rotation jig, if I move the mouse before the last redraw finishes, the length of the block "DUCT_1" property doesn't update until the next time I move the mouse. And also, if the rotation doesn't change, but the distance does, the length of the block won't update until the rotation changes.

Code - C#: [Select]
  1. using System;
  2. using System.IO;
  3. using System.Reflection;
  4. using Autodesk.AutoCAD.DatabaseServices;
  5. using Autodesk.AutoCAD.EditorInput;
  6. using Autodesk.AutoCAD.Geometry;
  7. using BDuct_Global;
  8.  
  9. namespace BDuct
  10. {
  11.     public class AutoCADFunctions
  12.     {
  13.         public static void InsertBlock(string blockName)
  14.         {
  15.             var doc = GlobalVariables.doc;
  16.             var db = doc.Database;
  17.             var ed = doc.Editor;
  18.             using (var tr = db.TransactionManager.StartTransaction())
  19.             {
  20.                 // Get the ObjectId of the block definition
  21.                 var btrId = GetBlock(blockName, db);
  22.                 if (btrId.IsNull)
  23.                 {
  24.                     ed.WriteMessage($"\nBlock '{blockName}' not found.");
  25.                     return;
  26.                 }
  27.  
  28.                 // Create a block reference
  29.                 using (var ghost = new BlockReference(Point3d.Origin, btrId))
  30.                 {
  31.                     ghost.TransformBy(ed.CurrentUserCoordinateSystem);
  32.                     // Set dynamic properties (except "DUCT_1")
  33.                     SetDynamicProperties(ghost, 40.0);
  34.  
  35.                     // Insert and rotate a new 'blockName' reference
  36.                     var insertJig = new InsertBlockJig(ghost);
  37.                     var promptResult = ed.Drag(insertJig);
  38.                     if (promptResult.Status == PromptStatus.OK)
  39.                     {
  40.                         DynamicBlockReferenceProperty property = GetProperty(ghost, "DUCT_1");
  41.                         var rotateJig = new RotateResizeBlockJig(ghost, property);
  42.                         promptResult = ed.Drag(rotateJig);
  43.                         if (promptResult.Status == PromptStatus.OK)
  44.                         {
  45.                             var currentSpace = (BlockTableRecord)tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite);
  46.                             var br = new BlockReference(ghost.Position, btrId) { Rotation = ghost.Rotation };
  47.                             currentSpace.AppendEntity(br);
  48.                             tr.AddNewlyCreatedDBObject(br, true);
  49.                             SetDynamicProperties(br, rotateJig.Distance);
  50.                         }
  51.                     }
  52.                     tr.Commit();
  53.                 }
  54.             }
  55.         }
  56.  
  57.         public static void SetDynamicProperties(BlockReference br, double distance)
  58.         {
  59.             foreach (DynamicBlockReferenceProperty prop in br.DynamicBlockReferencePropertyCollection)
  60.             {
  61.                 if (!prop.ReadOnly) // Replace "YourDynamicProperty"
  62.                 {
  63.                     switch (prop.PropertyName)
  64.                     {
  65.                         case "DUCT_1":
  66.                             if (distance > 0)
  67.                             {
  68.                                 prop.Value = distance;
  69.                                 double temp = (double)prop.Value;
  70.                                 string tempstring = temp.ToString();
  71.                                 GlobalVariables.ed.WriteMessage("\n" + tempstring + "\n");
  72.                             }
  73.                             break;
  74.                         case "SIZE_1":
  75.                             prop.Value = GlobalVariables.Duct_Width;                          
  76.                             break;
  77.                         case "DUCT_HEIGHT":
  78.                             //prop.Value = GlobalVariables.Duct_Hee
  79.                             break;
  80.                         case "INSULATION":
  81.                             prop.Value = GlobalVariables.Insulation_Type;
  82.                             break;
  83.                         case "INSULATION_INTERNAL":
  84.                             prop.Value = GlobalVariables.Insulation_Internal_Size;
  85.                             break;
  86.                         case "INSULATION_EXTERNAL":
  87.                             prop.Value = GlobalVariables.Insulation_External_Size;
  88.                             break;
  89.                         default:
  90.                             break;
  91.                     }
  92.                 }
  93.             }
  94.         }
  95.  
  96.         private static ObjectId GetBlock(string blockName, Database db)
  97.         {
  98.             // Search in the drawing BlockTable
  99.             var blockTable = (BlockTable)db.BlockTableId.GetObject(OpenMode.ForRead);
  100.             if (blockTable.Has(blockName))
  101.             {
  102.                 return blockTable[blockName];
  103.             }
  104.  
  105.             // Search in the current directory
  106.             string fileName = Path.Combine(Directory.GetCurrentDirectory(), $@"Blocks\{blockName}.dwg");
  107.             if (File.Exists(fileName))
  108.             {
  109.                 using (var xDb = new Database(false, true))
  110.                 {
  111.                     xDb.ReadDwgFile(fileName, FileOpenMode.OpenForReadAndAllShare, true, null);
  112.                     return db.Insert(fileName, xDb, true);
  113.                 }
  114.             }
  115.  
  116.             // Search in the Support File Search Paths
  117.             try
  118.             {
  119.                 fileName = HostApplicationServices.Current.FindFile($@"{blockName}.dwg", db, FindFileHint.Default);
  120.                 using (var xDb = new Database(false, true))
  121.                 {
  122.                     xDb.ReadDwgFile(fileName, FileOpenMode.OpenForReadAndAllShare, true, null);
  123.                     return db.Insert(blockName, xDb, true);
  124.                 }
  125.             }
  126.             catch { return ObjectId.Null; }
  127.         }
  128.  
  129.         private static DynamicBlockReferenceProperty GetProperty(BlockReference br, string propertyName)
  130.         {
  131.             foreach (DynamicBlockReferenceProperty property in br.DynamicBlockReferencePropertyCollection)
  132.             {
  133.                 if (propertyName.Equals(property.PropertyName, StringComparison.CurrentCultureIgnoreCase))
  134.                 {
  135.                     return property;
  136.                 }
  137.             }
  138.             return null;
  139.         }
  140.     }
  141.  
  142.     internal class InsertBlockJig : EntityJig
  143.     {
  144.         protected Point3d dragPoint;
  145.         protected BlockReference br;
  146.  
  147.         public InsertBlockJig(BlockReference br)
  148.             : base(br)
  149.         {
  150.             this.br = br;
  151.         }
  152.  
  153.         protected override SamplerStatus Sampler(JigPrompts prompts)
  154.         {
  155.             var options = new JigPromptPointOptions("\nSpecify insertion point: ");
  156.             AutoCADFunctions.SetDynamicProperties(br, -1);
  157.             options.UserInputControls =
  158.                 UserInputControls.Accept3dCoordinates |
  159.                 UserInputControls.GovernedByOrthoMode;
  160.             var result = prompts.AcquirePoint(options);
  161.             if (dragPoint.IsEqualTo(result.Value))
  162.                 return SamplerStatus.NoChange;
  163.             dragPoint = result.Value;
  164.             return SamplerStatus.OK;
  165.         }
  166.  
  167.         protected override bool Update()
  168.         {            
  169.             br.Position = dragPoint;
  170.             AutoCADFunctions.SetDynamicProperties(br, 40.0);
  171.             return true;
  172.         }
  173.     }
  174.  
  175.     internal class RotateResizeBlockJig : EntityJig
  176.     {
  177.         protected BlockReference br;
  178.         protected Point3d dragPoint;
  179.         protected Plane plane;
  180.         protected DynamicBlockReferenceProperty property;
  181.  
  182.         public double Distance;
  183.         private double Distance_Old;
  184.  
  185.         public RotateResizeBlockJig(BlockReference br, DynamicBlockReferenceProperty property)
  186.             : base(br)
  187.         {
  188.             this.br = br;
  189.             this.property = property;
  190.             plane = new Plane(Point3d.Origin, br.Normal);
  191.             this.property = property;
  192.         }
  193.  
  194.         protected override SamplerStatus Sampler(JigPrompts prompts)
  195.         {
  196.             var options = new JigPromptPointOptions("\nSpecify End Point: ");
  197.             options.UseBasePoint = true;
  198.             options.BasePoint = br.Position;
  199.             options.Cursor = CursorType.RubberBand;
  200.             options.UserInputControls =
  201.                 UserInputControls.Accept3dCoordinates |
  202.                 UserInputControls.UseBasePointElevation;
  203.             var result = prompts.AcquirePoint(options);
  204.            
  205.             Distance = br.Position.DistanceTo(dragPoint);
  206.             property.Value = Distance;
  207.  
  208.             if (dragPoint.IsEqualTo(result.Value))
  209.             {
  210.                 if (Distance == Distance_Old)
  211.                 {
  212.                     return SamplerStatus.NoChange;
  213.                 }
  214.             }
  215.             Distance_Old = Distance;
  216.             dragPoint = result.Value;            
  217.             return SamplerStatus.OK;
  218.         }
  219.  
  220.         protected override bool Update()
  221.         {
  222.             br.Rotation = br.Position.GetVectorTo(dragPoint).AngleOnPlane(plane);
  223.             AutoCADFunctions.SetDynamicProperties(br, -1);
  224.             return true;
  225.         }
  226.     }
  227.  
  228.  
  229. }
  230.  
  231.  

cmwade77

  • Swamp Rat
  • Posts: 1443
Re: Setting Dynamic Block Values with VB.NET
« Reply #26 on: February 07, 2024, 06:18:33 PM »
I have worked through most of the issues, but what I am not understanding is why if say I set the width to be 24, then sometimes the preview briefly goes back to 6", then comes back to what it should be set to again when rotating and changing the length. Once set, shouldn't it stay set for that instance of the block or the jig doing something else I am not aware of? My current code is below.

Code - C#: [Select]
  1. using System;
  2. using System.Diagnostics.Eventing.Reader;
  3. using System.IO;
  4. using System.Reflection;
  5. using Autodesk.AutoCAD.ApplicationServices;
  6. using Autodesk.AutoCAD.DatabaseServices;
  7. using Autodesk.AutoCAD.EditorInput;
  8. using Autodesk.AutoCAD.Geometry;
  9. using Autodesk.AutoCAD.Runtime;
  10. using BDuct_Global;
  11.  
  12. namespace BDuct
  13. {
  14.     public class AutoCADFunctions
  15.     {
  16.         public static void InsertBlock(string blockName)
  17.         {
  18.             var doc = GlobalVariables.doc;
  19.             var db = doc.Database;
  20.             var ed = doc.Editor;            
  21.             using (var tr = db.TransactionManager.StartTransaction())
  22.             {
  23.                 // Get the ObjectId of the block definition
  24.                 var btrId = GetBlock(blockName, db);
  25.                 if (btrId.IsNull)
  26.                 {
  27.                     ed.WriteMessage($"\nBlock '{blockName}' not found.");
  28.                     return;
  29.                 }
  30.                
  31.                 // Create a block reference
  32.                 using (var ghost = new BlockReference(Point3d.Origin, btrId))
  33.                 {
  34.                     var cLtScale = db.Ltscale;                    
  35.                     ghost.TransformBy(ed.CurrentUserCoordinateSystem);
  36.                     // Set dynamic properties (except "DUCT_1")
  37.                     SetDynamicProperties(ghost, 40.0);
  38.  
  39.                     // Insert and rotate a new 'blockName' reference
  40.                     var insertJig = new InsertBlockJig(ghost);
  41.                     var promptResult = ed.Drag(insertJig);
  42.                     if (promptResult.Status == PromptStatus.OK)
  43.                     {
  44.                         DynamicBlockReferenceProperty property = GetProperty(ghost, "DUCT_1");
  45.                         if (property == null)
  46.                         {
  47.                             property = GetProperty(ghost, "LENGTH");
  48.                         }
  49.                         db.Ltscale = 10000;                        
  50.                         var rotateJig = new RotateResizeBlockJig(ghost, property);
  51.                         SetDynamicProperties(ghost, rotateJig.Distance);
  52.                         promptResult = ed.Drag(rotateJig);
  53.                         if (promptResult.Status == PromptStatus.OK)
  54.                         {
  55.                             var currentSpace = (BlockTableRecord)tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite);                            
  56.                             var br = new BlockReference(ghost.Position, btrId) { Rotation = ghost.Rotation };
  57.                             currentSpace.AppendEntity(br);
  58.                             tr.AddNewlyCreatedDBObject(br, true);
  59.                             SetDynamicProperties(br, rotateJig.Distance);                        
  60.                         }
  61.                     }
  62.                     db.Ltscale = cLtScale;
  63.                     tr.Commit();
  64.                 }
  65.             }
  66.         }
  67.  
  68.         public static void SetDynamicProperties(BlockReference br, double distance)
  69.         {
  70.             Main main = GlobalVariables.MainWindow;
  71.             double NewValue = 6;
  72.             foreach (DynamicBlockReferenceProperty prop in br.DynamicBlockReferencePropertyCollection)
  73.             {
  74.                 if (!prop.ReadOnly) // Replace "YourDynamicProperty"
  75.                 {
  76.                     switch (prop.PropertyName)
  77.                     {
  78.                         case "DUCT_1" or "LENGTH":
  79.                             if (distance > 0)
  80.                             {                                
  81.                                 if ((double)prop.Value != distance)
  82.                                 {
  83.                                     prop.Value = distance;
  84.                                 }
  85.                             }
  86.                             break;
  87.                         case "SIZE_1" or "SIZE_1_WIDTH":                                                        
  88.                             if (main.Insulation_Clear.Checked == true && main.Insulation_Internal.Checked == true)
  89.                             {
  90.                                 NewValue = Convert.ToDouble((double)main.Dim_Width.Value % double.MaxValue) + (Convert.ToDouble((double)main.Insulation_Internal_SetSize.Value % double.MaxValue) * 2);
  91.                             }
  92.                             else
  93.                             {
  94.                                 NewValue = Convert.ToDouble((double)main.Dim_Width.Value % double.MaxValue);
  95.                             }
  96.  
  97.                             if ((double)prop.Value != NewValue)
  98.                             {
  99.                                 prop.Value = NewValue;
  100.                             }                      
  101.                             break;
  102.                         case "SIZE_1_HEIGHT":
  103.                             if (main.Insulation_Clear.Checked == true && main.Insulation_Internal.Checked == true)
  104.                             {
  105.                                 NewValue = Convert.ToDouble((double)main.Dim_Height.Value % double.MaxValue) + (Convert.ToDouble((double)main.Insulation_Internal_SetSize.Value % double.MaxValue) * 2);
  106.                             }
  107.                             else
  108.                             {
  109.                                 NewValue = Convert.ToDouble((double)main.Dim_Height.Value % double.MaxValue);
  110.                             }
  111.  
  112.                             if ((double)prop.Value != NewValue)
  113.                             {
  114.                                 prop.Value = NewValue;
  115.                             }
  116.                             break;
  117.                         case "INSULATION":
  118.                             string NewValue_Ins = "EXTERNAL";
  119.                             if (main.Insulation_External.Checked ==  true && main.Insulation_Internal.Checked == true)
  120.                             {
  121.                                 NewValue_Ins = "BOTH";
  122.                             }
  123.                             else
  124.                             {
  125.                                 if(main.Insulation_External.Checked == true)
  126.                                 {
  127.                                     NewValue_Ins = "EXTERNAL";                                    
  128.                                 }
  129.                                 else
  130.                                 {
  131.                                     if(main.Insulation_Internal.Checked == true)
  132.                                     {
  133.                                         NewValue_Ins = "INTERNAL";
  134.                                     }
  135.                                     else
  136.                                     {
  137.                                         NewValue_Ins = "NONE";
  138.                                     }
  139.                                 }
  140.                             }
  141.  
  142.                             if ((string)prop.Value != NewValue_Ins)
  143.                             {
  144.                                 prop.Value = NewValue_Ins;
  145.                             }
  146.                             break;
  147.                         case "INSULATION_INTERNAL":
  148.                             NewValue = Convert.ToDouble((double)main.Insulation_Internal_SetSize.Value % double.MaxValue);
  149.                             if ((double)prop.Value != NewValue)
  150.                             {
  151.                                 prop.Value = NewValue;
  152.                             }
  153.                             break;
  154.                         case "INSULATION_EXTERNAL":
  155.                             NewValue = Convert.ToDouble((double)main.Insulation_External_SetSize.Value % double.MaxValue);
  156.                             if ((double)prop.Value != NewValue)
  157.                             {
  158.                                 prop.Value = NewValue;
  159.                             }
  160.                             break;
  161.                         default:
  162.                             break;
  163.                     }
  164.                 }
  165.             }            
  166.         }
  167.  
  168.         private static ObjectId GetBlock(string blockName, Database db)
  169.         {
  170.             // Search in the drawing BlockTable
  171.             var blockTable = (BlockTable)db.BlockTableId.GetObject(OpenMode.ForRead);
  172.             if (blockTable.Has(blockName))
  173.             {
  174.                 return blockTable[blockName];
  175.             }
  176.  
  177.             // Search in the current directory
  178.             string fileName = Path.Combine(Directory.GetCurrentDirectory(), $@"Blocks\{blockName}.dwg");
  179.             if (File.Exists(fileName))
  180.             {
  181.                 using (var xDb = new Database(false, true))
  182.                 {
  183.                     xDb.ReadDwgFile(fileName, FileOpenMode.OpenForReadAndAllShare, true, null);
  184.                     return db.Insert(fileName, xDb, true);
  185.                 }
  186.             }
  187.  
  188.             // Search in the Support File Search Paths
  189.             try
  190.             {
  191.                 fileName = HostApplicationServices.Current.FindFile($@"{blockName}.dwg", db, FindFileHint.Default);
  192.                 using (var xDb = new Database(false, true))
  193.                 {
  194.                     xDb.ReadDwgFile(fileName, FileOpenMode.OpenForReadAndAllShare, true, null);
  195.                     return db.Insert(blockName, xDb, true);
  196.                 }
  197.             }
  198.             catch { return ObjectId.Null; }
  199.         }
  200.  
  201.         private static DynamicBlockReferenceProperty GetProperty(BlockReference br, string propertyName)
  202.         {
  203.             foreach (DynamicBlockReferenceProperty property in br.DynamicBlockReferencePropertyCollection)
  204.             {
  205.                 if (propertyName.Equals(property.PropertyName, StringComparison.CurrentCultureIgnoreCase))
  206.                 {
  207.                     return property;
  208.                 }
  209.             }
  210.             return null;
  211.         }
  212.     }
  213.  
  214.     internal class InsertBlockJig : EntityJig
  215.     {
  216.         protected Point3d dragPoint;
  217.         protected BlockReference br;
  218.  
  219.         public InsertBlockJig(BlockReference br)
  220.             : base(br)
  221.         {
  222.             this.br = br;
  223.         }
  224.  
  225.         protected override SamplerStatus Sampler(JigPrompts prompts)
  226.         {
  227.             var options = new JigPromptPointOptions("\nSpecify insertion point: ");
  228.             AutoCADFunctions.SetDynamicProperties(br, -1);
  229.             options.UserInputControls =
  230.                 UserInputControls.Accept3dCoordinates |
  231.                 UserInputControls.GovernedByOrthoMode;
  232.             var result = prompts.AcquirePoint(options);
  233.             if (dragPoint.IsEqualTo(result.Value))
  234.                 return SamplerStatus.NoChange;
  235.             dragPoint = result.Value;
  236.             return SamplerStatus.OK;
  237.         }
  238.  
  239.         protected override bool Update()
  240.         {            
  241.             br.Position = dragPoint;
  242.             AutoCADFunctions.SetDynamicProperties(br, 40.0);
  243.             return true;
  244.         }
  245.     }
  246.  
  247.     internal class RotateResizeBlockJig : EntityJig
  248.     {
  249.         protected BlockReference br;
  250.         protected Point3d dragPoint;
  251.         protected Plane plane;
  252.         protected DynamicBlockReferenceProperty property;
  253.  
  254.         public double Distance;
  255.         private double Distance_Old;
  256.        
  257.  
  258.         public RotateResizeBlockJig(BlockReference br, DynamicBlockReferenceProperty property)
  259.             : base(br)
  260.         {
  261.             this.br = br;
  262.             this.property = property;
  263.             plane = new Plane(Point3d.Origin, br.Normal);
  264.             this.property = property;
  265.         }
  266.  
  267.         protected override SamplerStatus Sampler(JigPrompts prompts)
  268.         {            
  269.             var options = new JigPromptPointOptions("\nSpecify End Point: ");
  270.             options.UseBasePoint = true;
  271.             options.BasePoint = br.Position;
  272.             options.Cursor = CursorType.RubberBand;
  273.             options.UserInputControls =
  274.                 UserInputControls.Accept3dCoordinates |
  275.                 UserInputControls.UseBasePointElevation;
  276.             var result = prompts.AcquirePoint(options);          
  277.             Distance = br.Position.DistanceTo(dragPoint);
  278.             if (property != null)
  279.             {
  280.                 property.Value = Distance;
  281.             }
  282.            
  283.             var blockTable = (BlockTable)GlobalVariables.db.BlockTableId.GetObject(OpenMode.ForRead);            
  284.             if (dragPoint.IsEqualTo(result.Value) && Distance == Distance_Old)
  285.             {                
  286.                 return SamplerStatus.NoChange;                
  287.             }            
  288.             Distance_Old = Distance;
  289.             dragPoint = result.Value;        
  290.             return SamplerStatus.OK;
  291.         }
  292.  
  293.         protected override bool Update()
  294.         {            
  295.             br.Rotation = br.Position.GetVectorTo(dragPoint).AngleOnPlane(plane);
  296.             AutoCADFunctions.SetDynamicProperties(br, -1);
  297.             return true;
  298.         }
  299.     }
  300. }
  301.  
  302.  

gile

  • Gator
  • Posts: 2507
  • Marseille, France
Re: Setting Dynamic Block Values with VB.NET
« Reply #27 on: February 08, 2024, 02:29:42 AM »
What if you call SetDynamicProperties only once before jigging and pass the "DUCT_1" or "LENGTH" property as parameter of the RotateResizeBlockJig constructor (as in reply #18) ?
Speaking English as a French Frog

cmwade77

  • Swamp Rat
  • Posts: 1443
Re: Setting Dynamic Block Values with VB.NET
« Reply #28 on: February 08, 2024, 12:10:30 PM »
Then if the user changes the properties during the jig, it doesn't show a live preview of those changes, but thinking that through, I might be able to do the following:
  • Set the properties before jigging (aside from distance)
  • Monitor for changes
  • Stop the jig (returning the current position)
  • Set the properties again
  • Restart the jig at the same position

Just writing this out to see if there are issues with this approach, but this could also improve performance I would imagine as well.

cmwade77

  • Swamp Rat
  • Posts: 1443
Re: Setting Dynamic Block Values with VB.NET
« Reply #29 on: February 08, 2024, 02:51:51 PM »
Well this is odd, if I use the code from number 18 and set it only once, then it sets correctly for the insert jig, but not the rotate one.


ETA: Actually, the insert jig doesn't work correctly either, but it has other properties that aren't correct.
« Last Edit: February 08, 2024, 03:06:05 PM by cmwade77 »

cmwade77

  • Swamp Rat
  • Posts: 1443
Re: Setting Dynamic Block Values with VB.NET
« Reply #30 on: February 08, 2024, 07:08:03 PM »
I found the problem, it is when the distance gets set, it sets some, but not all parameters back to default values, now the question is how to fix it.

gile

  • Gator
  • Posts: 2507
  • Marseille, France
Re: Setting Dynamic Block Values with VB.NET
« Reply #31 on: February 09, 2024, 07:35:33 AM »
It looks like the issue is due to your block (jigs don't seems to like parametric constraints).
Try with the attached block.
See this screencast.
Edit: attached the solution (you'll need to change the paths to AutoCAD libraries and acad.exe).
« Last Edit: February 09, 2024, 11:03:17 AM by gile »
Speaking English as a French Frog

cmwade77

  • Swamp Rat
  • Posts: 1443
Re: Setting Dynamic Block Values with VB.NET
« Reply #32 on: February 09, 2024, 11:26:04 AM »
Yeah, it appears that you are right, but I think I found another solution and I have no idea why this works, it seems that it works if if I set UserInputControls to:
Code - C#: [Select]
  1. options.UserInputControls =
  2.     UserInputControls.Accept3dCoordinates
  3.     | UserInputControls.UseBasePointElevation
  4.     | UserInputControls.GovernedByOrthoMode
  5.     | UserInputControls.NoDwgLimitsChecking
  6.     | UserInputControls.NoNegativeResponseAccepted
  7.     | UserInputControls.NoZeroResponseAccepted;

I can't puzzle out why this would work thought, so just in case that isn't what corrected it, the overall code is:
Code - C#: [Select]
  1. using System;
  2. using System.Diagnostics.Eventing.Reader;
  3. using System.IO;
  4.  
  5. using System.Reflection;
  6. using Autodesk.AutoCAD.ApplicationServices;
  7. using Autodesk.AutoCAD.DatabaseServices;
  8. using Autodesk.AutoCAD.EditorInput;
  9. using Autodesk.AutoCAD.Geometry;
  10. using Autodesk.AutoCAD.Runtime;
  11. using BDuct_Global;
  12.  
  13. namespace BDuct
  14. {
  15.     public class AutoCADFunctions
  16.     {
  17.         public static void InsertBlock(string blockName)
  18.         {
  19.             Document doc = Autodesk.AutoCAD.ApplicationServices.Core.Application.DocumentManager.MdiActiveDocument;
  20.             Database db = doc.Database;
  21.             Editor ed = doc.Editor;            
  22.             using (var tr = db.TransactionManager.StartTransaction())
  23.             {
  24.                 // Get the ObjectId of the block definition
  25.                 var btrId = GetBlock(blockName, db);
  26.                 if (btrId.IsNull)
  27.                 {
  28.                     ed.WriteMessage($"\nBlock '{blockName}' not found.");
  29.                     return;
  30.                 }
  31.                
  32.                 // Create a block reference
  33.                 using (var ghost = new BlockReference(Point3d.Origin, btrId))
  34.                 {
  35.                     Main main = GlobalVariables.MainWindow;                    
  36.                     //string ObjLayer = main.Duct_Type.SelectedNode.Tag.ToString();
  37.                     //ghost.Layer = ObjLayer;
  38.  
  39.                     var cLtScale = db.Ltscale;                    
  40.                     ghost.TransformBy(ed.CurrentUserCoordinateSystem);
  41.                     SetDynamicProperties(ghost, 40.0);
  42.                     // Insert and rotate a new 'blockName' reference
  43.                     var insertJig = new InsertBlockJig(ghost);
  44.                     // Set dynamic properties (except "DUCT_1")                    
  45.                     var promptResult = ed.Drag(insertJig);
  46.                     if (promptResult.Status == PromptStatus.OK)
  47.                     {
  48.                         DynamicBlockReferenceProperty property = GetProperty(ghost, "DUCT_1");
  49.                         if (property == null)
  50.                         {
  51.                             property = GetProperty(ghost, "LENGTH");
  52.                         }
  53.                         db.Ltscale = 10000;
  54.                         SetDynamicProperties(ghost, -1);
  55.                         var rotateJig = new RotateResizeBlockJig(ghost, property);                        
  56.                         promptResult = ed.Drag(rotateJig);
  57.                         if (promptResult.Status == PromptStatus.OK)
  58.                         {
  59.                             var currentSpace = (BlockTableRecord)tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite);                            
  60.                             var br = new BlockReference(ghost.Position, btrId) { Rotation = ghost.Rotation };
  61.                             currentSpace.AppendEntity(br);
  62.                             tr.AddNewlyCreatedDBObject(br, true);
  63.                             SetDynamicProperties(br, rotateJig.Distance);
  64.                             //br.Layer = ObjLayer;
  65.                         }
  66.                     }
  67.                     db.Ltscale = cLtScale;
  68.                     tr.Commit();
  69.                 }
  70.             }
  71.         }
  72.  
  73.         public static void SetDynamicProperties(BlockReference br, double distance)
  74.         {
  75.             Main main = GlobalVariables.MainWindow;
  76.             double NewValue = 6;
  77.             foreach (DynamicBlockReferenceProperty prop in br.DynamicBlockReferencePropertyCollection)
  78.             {
  79.                 if (!prop.ReadOnly) // Replace "YourDynamicProperty"
  80.                 {
  81.                     switch (prop.PropertyName)
  82.                     {
  83.                         case "DUCT_1" or "LENGTH":
  84.                             if (distance > 0)
  85.                             {                                
  86.                                 if ((double)prop.Value != distance)
  87.                                 {
  88.                                     prop.Value = distance;
  89.                                 }
  90.                             }
  91.                             break;
  92.                         case "SIZE_1" or "SIZE_1_WIDTH":                                                        
  93.                             if (main.Insulation_Clear.Checked == true && main.Insulation_Internal.Checked == true)
  94.                             {
  95.                                 NewValue = Convert.ToDouble((double)main.Dim_Width.Value % double.MaxValue) + (Convert.ToDouble((double)main.Insulation_Internal_SetSize.Value % double.MaxValue) * 2);
  96.                             }
  97.                             else
  98.                             {
  99.                                 NewValue = Convert.ToDouble((double)main.Dim_Width.Value % double.MaxValue);
  100.                             }
  101.  
  102.                             if ((double)prop.Value != NewValue)
  103.                             {
  104.                                 prop.Value = NewValue;
  105.                             }                      
  106.                             break;
  107.                         case "SIZE_1_HEIGHT":
  108.                             if (main.Insulation_Clear.Checked == true && main.Insulation_Internal.Checked == true)
  109.                             {
  110.                                 NewValue = Convert.ToDouble((double)main.Dim_Height.Value % double.MaxValue) + (Convert.ToDouble((double)main.Insulation_Internal_SetSize.Value % double.MaxValue) * 2);
  111.                             }
  112.                             else
  113.                             {
  114.                                 NewValue = Convert.ToDouble((double)main.Dim_Height.Value % double.MaxValue);
  115.                             }
  116.  
  117.                             if ((double)prop.Value != NewValue)
  118.                             {
  119.                                 prop.Value = NewValue;
  120.                             }
  121.                             break;
  122.                         case "INSULATION":
  123.                             string NewValue_Ins = "EXTERNAL";
  124.                             if (main.Insulation_External.Checked ==  true && main.Insulation_Internal.Checked == true)
  125.                             {
  126.                                 NewValue_Ins = "BOTH";
  127.                             }
  128.                             else
  129.                             {
  130.                                 if(main.Insulation_External.Checked == true)
  131.                                 {
  132.                                     NewValue_Ins = "EXTERNAL";                                    
  133.                                 }
  134.                                 else
  135.                                 {
  136.                                     if(main.Insulation_Internal.Checked == true)
  137.                                     {
  138.                                         NewValue_Ins = "INTERNAL";
  139.                                     }
  140.                                     else
  141.                                     {
  142.                                         NewValue_Ins = "NONE";
  143.                                     }
  144.                                 }
  145.                             }
  146.  
  147.                             if ((string)prop.Value != NewValue_Ins)
  148.                             {
  149.                                 prop.Value = NewValue_Ins;
  150.                             }
  151.                             break;
  152.                         case "INSULATION_INTERNAL":
  153.                             NewValue = Convert.ToDouble((double)main.Insulation_Internal_SetSize.Value % double.MaxValue);
  154.                             if ((double)prop.Value != NewValue)
  155.                             {
  156.                                 prop.Value = NewValue;
  157.                             }
  158.                             break;
  159.                         case "INSULATION_EXTERNAL":
  160.                             NewValue = Convert.ToDouble((double)main.Insulation_External_SetSize.Value % double.MaxValue);
  161.                             if ((double)prop.Value != NewValue)
  162.                             {
  163.                                 prop.Value = NewValue;
  164.                             }
  165.                             break;
  166.                         default:
  167.                             break;
  168.                     }
  169.                 }
  170.             }            
  171.         }
  172.  
  173.         private static ObjectId GetBlock(string blockName, Database db)
  174.         {
  175.             // Search in the drawing BlockTable
  176.             var blockTable = (BlockTable)db.BlockTableId.GetObject(OpenMode.ForRead);
  177.             if (blockTable.Has(blockName))
  178.             {
  179.                 return blockTable[blockName];
  180.             }
  181.  
  182.             // Search in the current directory
  183.             string fileName = Path.Combine(Directory.GetCurrentDirectory(), $@"Blocks\{blockName}.dwg");
  184.             if (File.Exists(fileName))
  185.             {
  186.                 using (var xDb = new Database(false, true))
  187.                 {
  188.                     xDb.ReadDwgFile(fileName, FileOpenMode.OpenForReadAndAllShare, true, null);
  189.                     return db.Insert(fileName, xDb, true);
  190.                 }
  191.             }
  192.  
  193.             // Search in the Support File Search Paths
  194.             try
  195.             {
  196.                 fileName = HostApplicationServices.Current.FindFile($@"{blockName}.dwg", db, FindFileHint.Default);
  197.                 using (var xDb = new Database(false, true))
  198.                 {
  199.                     xDb.ReadDwgFile(fileName, FileOpenMode.OpenForReadAndAllShare, true, null);
  200.                     return db.Insert(blockName, xDb, true);
  201.                 }
  202.             }
  203.             catch { return ObjectId.Null; }
  204.         }
  205.  
  206.         private static DynamicBlockReferenceProperty GetProperty(BlockReference br, string propertyName)
  207.         {
  208.             foreach (DynamicBlockReferenceProperty property in br.DynamicBlockReferencePropertyCollection)
  209.             {
  210.                 if (propertyName.Equals(property.PropertyName, StringComparison.CurrentCultureIgnoreCase))
  211.                 {
  212.                     return property;
  213.                 }
  214.             }
  215.             return null;
  216.         }
  217.     }
  218.  
  219.     internal class InsertBlockJig : EntityJig
  220.     {
  221.         protected Point3d dragPoint;
  222.         protected BlockReference br;
  223.  
  224.         public InsertBlockJig(BlockReference br)
  225.             : base(br)
  226.         {
  227.             this.br = br;
  228.         }
  229.  
  230.         protected override SamplerStatus Sampler(JigPrompts prompts)
  231.         {
  232.             var options = new JigPromptPointOptions("\nSpecify insertion point: ");            
  233.             options.UserInputControls =
  234.                 UserInputControls.Accept3dCoordinates
  235.                 | UserInputControls.UseBasePointElevation
  236.                 | UserInputControls.GovernedByOrthoMode
  237.                 | UserInputControls.NoDwgLimitsChecking
  238.                 | UserInputControls.NoNegativeResponseAccepted
  239.                 | UserInputControls.NoZeroResponseAccepted;
  240.             var result = prompts.AcquirePoint(options);
  241.             if (dragPoint.IsEqualTo(result.Value))
  242.                 return SamplerStatus.NoChange;
  243.             dragPoint = result.Value;
  244.             return SamplerStatus.OK;
  245.         }
  246.  
  247.         protected override bool Update()
  248.         {            
  249.             br.Position = dragPoint;
  250.             AutoCADFunctions.SetDynamicProperties(br, -1);
  251.             return true;
  252.         }
  253.     }
  254.  
  255.  
  256.     internal class RotateResizeBlockJig : EntityJig
  257.     {
  258.         protected BlockReference br;
  259.         protected Point3d dragPoint;
  260.         protected Plane plane;
  261.         protected DynamicBlockReferenceProperty property;
  262.  
  263.         public double Distance => br.Position.DistanceTo(dragPoint);
  264.  
  265.         public RotateResizeBlockJig(BlockReference br, DynamicBlockReferenceProperty property)
  266.             : base(br)
  267.         {
  268.             this.br = br;
  269.             this.property = property;
  270.             plane = new Plane(Point3d.Origin, br.Normal);
  271.         }
  272.  
  273.         protected override SamplerStatus Sampler(JigPrompts prompts)
  274.         {
  275.             var options = new JigPromptPointOptions("\nSpecify End Point: ");
  276.             options.UseBasePoint = true;
  277.             options.BasePoint = br.Position;
  278.             options.Cursor = CursorType.RubberBand;
  279.             options.UserInputControls =
  280.                 UserInputControls.Accept3dCoordinates
  281.                 | UserInputControls.UseBasePointElevation
  282.                 | UserInputControls.GovernedByOrthoMode
  283.                 | UserInputControls.NoDwgLimitsChecking
  284.                 | UserInputControls.NoNegativeResponseAccepted
  285.                 | UserInputControls.NoZeroResponseAccepted;
  286.             var result = prompts.AcquirePoint(options);
  287.  
  288.             if (dragPoint.IsEqualTo(result.Value))
  289.             {
  290.                 return SamplerStatus.NoChange;
  291.             }
  292.             else
  293.             {
  294.                 dragPoint = result.Value;                
  295.             }            
  296.             property.Value = Distance;            
  297.             return SamplerStatus.OK;
  298.         }
  299.  
  300.         protected override bool Update()
  301.         {
  302.             AutoCADFunctions.SetDynamicProperties(br, -1);
  303.             br.Rotation = br.Position.GetVectorTo(dragPoint).AngleOnPlane(plane);
  304.             return true;
  305.         }
  306.     }
  307. }
  308.  
  309.  

cmwade77

  • Swamp Rat
  • Posts: 1443
Re: Setting Dynamic Block Values with VB.NET
« Reply #33 on: February 23, 2024, 01:51:27 PM »
I did finally figure out what I did to accomplish this, it has to do with the LTSCALE, I set it to 1000, then back again, here is a more streamlined version of the code and I would love to get some feedback on it:

Code - C#: [Select]
  1. using Autodesk.AutoCAD.ApplicationServices;
  2. using Autodesk.AutoCAD.DatabaseServices;
  3. using Autodesk.AutoCAD.EditorInput;
  4. using Autodesk.AutoCAD.Geometry;
  5. using Autodesk.AutoCAD.Runtime;
  6. using BDuct_Global;
  7. using System;
  8. using System.IO;
  9. using System.Linq;
  10. using System.Windows.Input;
  11.  
  12. namespace BDuct
  13. {
  14.     public static class AutoCADFunctions
  15.     {
  16.         private static bool mHasAlignment = false;
  17.  
  18.         private static bool HasAlignmentParameter(BlockReference blockRef)
  19.         {
  20.             if (blockRef.IsDynamicBlock)
  21.             {
  22.                 foreach (DynamicBlockReferenceProperty prop in blockRef.DynamicBlockReferencePropertyCollection)
  23.                 {
  24.                     if (prop.PropertyName.Equals("Alignment", StringComparison.OrdinalIgnoreCase))
  25.                     {
  26.                         return true;
  27.                     }
  28.                 }
  29.             }
  30.             return false;
  31.         }
  32.  
  33.         public static void InsertBlock(string blockName)
  34.         {
  35.             Document doc = Application.DocumentManager.MdiActiveDocument;
  36.             Database db = doc.Database;
  37.             Editor ed = doc.Editor;
  38.  
  39.             using (Transaction tr = db.TransactionManager.StartTransaction())
  40.             {
  41.                 ObjectId btrId = GetBlock(blockName, db);
  42.                 if (btrId.IsNull)
  43.                 {
  44.                     ed.WriteMessage($"\nBlock '{blockName}' not found.");
  45.                     return;
  46.                 }
  47.  
  48.                 using (BlockReference ghost = new BlockReference(Point3d.Origin, btrId))
  49.                 {
  50.                     mHasAlignment = HasAlignmentParameter(ghost);
  51.                     LayerTable lt = tr.GetObject(db.LayerTableId, OpenMode.ForRead) as LayerTable;
  52.                     Main main = GlobalVariables.MainWindow;
  53.                     string objLayer = main.Layer.Text;
  54.  
  55.                     if (lt.Has(objLayer))
  56.                     {
  57.                         ghost.Layer = objLayer;
  58.                     }
  59.  
  60.                     ghost.TransformBy(ed.CurrentUserCoordinateSystem);
  61.                     SetDynamicProperties(ghost, 40.0);
  62.  
  63.                     InsertBlockJig insertJig = new InsertBlockJig(ghost);
  64.                     PromptResult promptResult = ed.Drag(insertJig);
  65.  
  66.                     if (promptResult.Status == PromptStatus.OK)
  67.                     {
  68.                         DynamicBlockReferenceProperty property = GetProperty(ghost, "DUCT_1") ?? GetProperty(ghost, "LENGTH");
  69.  
  70.                         SetDynamicProperties(ghost, -1);
  71.  
  72.                         double originalLTScale = db.Ltscale;
  73.                         try
  74.                         {
  75.                             db.Ltscale = 1000;
  76.                             RotateResizeBlockJig rotateJig = new RotateResizeBlockJig(ghost, property);
  77.                             promptResult = ed.Drag(rotateJig);
  78.  
  79.                             if (promptResult.Status == PromptStatus.OK)
  80.                             {
  81.                                 BlockTableRecord currentSpace = tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite) as BlockTableRecord;
  82.                                 BlockReference br = new BlockReference(ghost.Position, btrId)
  83.                                 {
  84.                                     Rotation = ghost.Rotation
  85.                                 };
  86.  
  87.                                 currentSpace.AppendEntity(br);
  88.                                 tr.AddNewlyCreatedDBObject(br, true);
  89.                                 SetDynamicProperties(br, rotateJig.Distance);
  90.  
  91.                                 if (lt.Has(objLayer))
  92.                                 {
  93.                                     br.Layer = objLayer;
  94.                                 }
  95.                             }
  96.                         }
  97.                         finally
  98.                         {
  99.                             db.Ltscale = originalLTScale;
  100.                         }
  101.                     }
  102.  
  103.                     tr.Commit();
  104.                 }
  105.             }
  106.         }
  107.  
  108.         public static void SetDynamicProperties(BlockReference br, double distance)
  109.         {
  110.             Main main = GlobalVariables.MainWindow;
  111.  
  112.             void UpdateProperty(DynamicBlockReferenceProperty prop, object newValue)
  113.             {
  114.                 if (!prop.ReadOnly && !Equals(prop.Value, newValue))
  115.                 {
  116.                     prop.Value = newValue;
  117.                 }
  118.             }
  119.  
  120.             foreach (DynamicBlockReferenceProperty prop in br.DynamicBlockReferencePropertyCollection)
  121.             {
  122.                 switch (prop.PropertyName)
  123.                 {
  124.                     case "DUCT_1" or "LENGTH":
  125.                         if (distance > 0)
  126.                         {
  127.                             UpdateProperty(prop, distance);
  128.                         }
  129.                         break;
  130.  
  131.                     case "SIZE_1" or "SIZE_1_WIDTH":
  132.                         double width = Convert.ToDouble((double)main.Dim_Width.Value % double.MaxValue);
  133.                         if (main.Insulation_Clear.Checked && main.Insulation_Internal.Checked)
  134.                         {
  135.                             width += Convert.ToDouble((double)main.Insulation_Internal_SetSize.Value % double.MaxValue) * 2;
  136.                         }
  137.                         UpdateProperty(prop, width);
  138.                         break;
  139.  
  140.                     case "SIZE_1_HEIGHT":
  141.                         double height = Convert.ToDouble((double)main.Dim_Height.Value % double.MaxValue);
  142.                         if (main.Insulation_Clear.Checked && main.Insulation_Internal.Checked)
  143.                         {
  144.                             height += Convert.ToDouble((double)main.Insulation_Internal_SetSize.Value % double.MaxValue) * 2;
  145.                         }
  146.                         UpdateProperty(prop, height);
  147.                         break;
  148.  
  149.                     case "INSULATION":
  150.                         string insulation = main.Insulation_External.Checked && main.Insulation_Internal.Checked ? "BOTH" :
  151.                                             main.Insulation_External.Checked ? "EXTERNAL" :
  152.                                             main.Insulation_Internal.Checked ? "INTERNAL" : "NONE";
  153.                         UpdateProperty(prop, insulation);
  154.                         break;
  155.  
  156.                     case "INSULATION_INTERNAL":
  157.                         UpdateProperty(prop, Convert.ToDouble((double)main.Insulation_Internal_SetSize.Value % double.MaxValue));
  158.                         break;
  159.  
  160.                     case "INSULATION_EXTERNAL":
  161.                         UpdateProperty(prop, Convert.ToDouble((double)main.Insulation_External_SetSize.Value % double.MaxValue));
  162.                         break;
  163.                 }
  164.             }
  165.         }
  166.  
  167.         private static ObjectId GetBlock(string blockName, Database db)
  168.         {
  169.             BlockTable blockTable = db.BlockTableId.GetObject(OpenMode.ForRead) as BlockTable;
  170.  
  171.             if (blockTable.Has(blockName))
  172.             {
  173.                 return blockTable[blockName];
  174.             }
  175.  
  176.             string fileName = Path.Combine(Directory.GetCurrentDirectory(), $"Blocks\\{blockName}.dwg");
  177.             if (File.Exists(fileName))
  178.             {
  179.                 using (Database xDb = new Database(false, true))
  180.                 {
  181.                     xDb.ReadDwgFile(fileName, FileOpenMode.OpenForReadAndAllShare, true, null);
  182.                     return db.Insert(blockName, xDb, true);
  183.                 }
  184.             }
  185.  
  186.             try
  187.             {
  188.                 fileName = HostApplicationServices.Current.FindFile($"{blockName}.dwg", db, FindFileHint.Default);
  189.                 using (Database xDb = new Database(false, true))
  190.                 {
  191.                     xDb.ReadDwgFile(fileName, FileOpenMode.OpenForReadAndAllShare, true, null);
  192.                     return db.Insert(blockName, xDb, true);
  193.                 }
  194.             }
  195.             catch
  196.             {
  197.                 return ObjectId.Null;
  198.             }
  199.         }
  200.  
  201.         private static DynamicBlockReferenceProperty GetProperty(BlockReference br, string propertyName)
  202.         {
  203.             foreach (DynamicBlockReferenceProperty property in br.DynamicBlockReferencePropertyCollection)
  204.             {
  205.                 if (property.PropertyName.Equals(propertyName, StringComparison.OrdinalIgnoreCase))
  206.                 {
  207.                     return property;
  208.                 }
  209.             }
  210.             return null;
  211.         }
  212.     }
  213.  
  214.     internal class InsertBlockJig : EntityJig
  215.     {
  216.         protected Point3d dragPoint;
  217.         protected BlockReference br;
  218.  
  219.         public InsertBlockJig(BlockReference br) : base(br)
  220.         {
  221.             this.br = br;
  222.         }
  223.  
  224.         protected override SamplerStatus Sampler(JigPrompts prompts)
  225.         {
  226.             JigPromptPointOptions options = new JigPromptPointOptions("\nSpecify insertion point: ")
  227.             {
  228.                 UserInputControls = UserInputControls.Accept3dCoordinates
  229.                                     | UserInputControls.UseBasePointElevation
  230.                                     | UserInputControls.GovernedByOrthoMode
  231.                                     | UserInputControls.NoDwgLimitsChecking
  232.                                     | UserInputControls.NoNegativeResponseAccepted
  233.                                     | UserInputControls.NoZeroResponseAccepted
  234.             };
  235.  
  236.             PromptPointResult result = prompts.AcquirePoint(options);
  237.             if (dragPoint.IsEqualTo(result.Value))
  238.                 return SamplerStatus.NoChange;
  239.  
  240.             dragPoint = result.Value;
  241.             return SamplerStatus.OK;
  242.         }
  243.  
  244.         protected override bool Update()
  245.         {
  246.             br.Position = dragPoint;
  247.             AutoCADFunctions.SetDynamicProperties(br, -1);
  248.             return true;
  249.         }
  250.     }
  251.  
  252.     internal class RotateResizeBlockJig : EntityJig
  253.     {
  254.         protected BlockReference br;
  255.         protected Point3d dragPoint;
  256.         protected Plane plane;
  257.         protected DynamicBlockReferenceProperty property;
  258.  
  259.         public double Distance => br.Position.DistanceTo(dragPoint);
  260.  
  261.         public RotateResizeBlockJig(BlockReference br, DynamicBlockReferenceProperty property) : base(br)
  262.         {
  263.             this.br = br;
  264.             this.property = property;
  265.             plane = new Plane(Point3d.Origin, br.Normal);
  266.         }
  267.  
  268.         protected override SamplerStatus Sampler(JigPrompts prompts)
  269.         {
  270.             JigPromptPointOptions options = new JigPromptPointOptions("\nSpecify end point: ")
  271.             {
  272.                 UseBasePoint = true,
  273.                 BasePoint = br.Position,
  274.                 Cursor = Autodesk.AutoCAD.EditorInput.CursorType.RubberBand,
  275.                 UserInputControls = UserInputControls.Accept3dCoordinates
  276.                                     | UserInputControls.UseBasePointElevation
  277.                                     | UserInputControls.GovernedByOrthoMode
  278.                                     | UserInputControls.NoDwgLimitsChecking
  279.                                     | UserInputControls.NoNegativeResponseAccepted
  280.                                     | UserInputControls.NoZeroResponseAccepted
  281.             };
  282.  
  283.             PromptPointResult result = prompts.AcquirePoint(options);
  284.             if (dragPoint.IsEqualTo(result.Value))
  285.             {
  286.                 return SamplerStatus.NoChange;
  287.             }
  288.             else
  289.             {
  290.                 dragPoint = result.Value;
  291.             }
  292.  
  293.             property.Value = Distance;
  294.             return SamplerStatus.OK;
  295.         }
  296.  
  297.         protected override bool Update()
  298.         {
  299.             AutoCADFunctions.SetDynamicProperties(br, -1);
  300.             br.Rotation = br.Position.GetVectorTo(dragPoint).AngleOnPlane(plane);
  301.             return true;
  302.         }
  303.     }
  304. }

Do note that this is a work in progress, as I am needing to do some stuff with alignment as well in here.