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

0 Members and 1 Guest are viewing this topic.

gile

  • Water Moccasin
  • Posts: 2493
  • 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: 1430
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: 1430
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

  • Water Moccasin
  • Posts: 2493
  • 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: 1430
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

  • Water Moccasin
  • Posts: 2493
  • 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: 1430
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: 1430
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

  • Water Moccasin
  • Posts: 2493
  • 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: 1430
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: 1430
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: 1430
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

  • Water Moccasin
  • Posts: 2493
  • 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: 1430
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: 1430
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 »