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

0 Members and 1 Guest are viewing this topic.

cmwade77

  • Swamp Rat
  • Posts: 1430
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

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