internal class BlockJig : EntityJig
{
private Database _database; // Add a field to store the database
private Point3d mPosition = Point3d.Origin;
private ObjectId mObjectIdToAlignWith = ObjectId.Null;
private DynamicBlockReferenceProperty mLengthProperty = null;
private static ObjectId pickObjId = ObjectId.Null;
private static ObjectId pickBlockRefId = ObjectId.Null;
private double mAngleOffset = 0.0;
private bool mFlipAlignment = false; // Field to store the flip state
private double mAlignmentAngle = 0.0;
private bool mLastTabState = false;
private DateTime mLastTabToggleTime = DateTime.MinValue;
private TimeSpan mDebounceInterval = TimeSpan.FromMilliseconds(200);
public BlockJig(BlockReference blockRef, Database database) : base(blockRef)
{
// Check if the block has an alignment parameter
if (blockRef.IsDynamicBlock)
{
mLengthProperty = AutoCADFunctions.GetProperty(blockRef, "DUCT_1") ?? AutoCADFunctions.GetProperty(blockRef, "LENGTH");
}
mAngleOffset = blockRef.Rotation;
_database = database;
}
protected static Editor CurEditor
{
get
{
return Application.DocumentManager.MdiActiveDocument.Editor;
}
}
protected static Matrix3d UCS
{
get
{
return CurEditor.CurrentUserCoordinateSystem;
}
}
protected new BlockReference Entity
{
get
{
return (BlockReference)base.Entity;
}
}
protected override SamplerStatus Sampler(JigPrompts prompts)
{
JigPromptPointOptions options;
options
= new JigPromptPointOptions
("\nBlock insertion point [<Tab> to Flip alignment]:");
options.UserInputControls = UserInputControls.Accept3dCoordinates
| UserInputControls.UseBasePointElevation
| UserInputControls.GovernedByOrthoMode
| UserInputControls.NoDwgLimitsChecking
| UserInputControls.NoNegativeResponseAccepted
| UserInputControls.NoZeroResponseAccepted;
PromptPointResult result = prompts.AcquirePoint(options);
if (mPosition.IsEqualTo(result.Value))
{
return SamplerStatus.NoChange;
}
else
{
if (result.Status == PromptStatus.Cancel)
{
return SamplerStatus.Cancel;
}
}
mPosition = result.Value.TransformBy(UCS.Inverse());
mObjectIdToAlignWith = pickObjId;
return SamplerStatus.OK;
}
protected override bool Update()
{
Entity.Position = mPosition;
if (!mObjectIdToAlignWith.IsNull)
{
bool currentTabState = Keyboard.IsKeyDown(Key.Tab);
DateTime currentTime = DateTime.Now;
if (currentTabState != mLastTabState && // Check if the Tab key state has changed
currentTime - mLastTabToggleTime > mDebounceInterval) // Check if the debounce interval has passed
{
mFlipAlignment = !mFlipAlignment;
mLastTabToggleTime = currentTime;
}
mLastTabState = currentTabState;
using (Transaction tr = _database.TransactionManager.StartTransaction())
{
using (DBObject obj = tr.GetObject(mObjectIdToAlignWith, OpenMode.ForRead))
{
{
Matrix3d transform = Matrix3d.Identity;
if (!pickBlockRefId.IsNull) // Check if the subentity is part of a block
{
using (BlockReference blockRef = tr.GetObject(pickBlockRefId, OpenMode.ForRead) as BlockReference)
{
if (blockRef != null)
{
transform = blockRef.BlockTransform;
}
}
}
using (curve = (Curve)curve.GetTransformedCopy(transform))
{
Point3d closestPoint = curve.GetClosestPointTo(Entity.Position, false);
Vector3d dir = curve.GetFirstDerivative(closestPoint).TransformBy(UCS.Inverse());
mAlignmentAngle = Vector3d.XAxis.GetAngleTo(dir, Vector3d.ZAxis);
}
// Apply the flip based on the mFlipAlignment flag
if (mFlipAlignment)
{
mAlignmentAngle += Math.PI; // Add 180 degrees
}
Entity.Rotation = mAlignmentAngle + mAngleOffset;
}
else
{
mObjectIdToAlignWith = ObjectId.Null;
}
}
tr.Commit();
}
}
else
{
Entity.Rotation = 0.0;
}
AutoCADFunctions.SetDynamicProperties(Entity, 40.0);
return true;
}
public static void Editor_PointMonitor(object sender, PointMonitorEventArgs e)
{
Document doc = Application.DocumentManager.MdiActiveDocument;
Database db = doc.Database;
Editor ed = doc.Editor;
if (e.Context == null)
{
return;
}
FullSubentityPath[] fullEntPath = e.Context.GetPickedEntities();
if (fullEntPath.Length > 0)
{
try
{
using (Transaction tr = db.TransactionManager.StartTransaction())
{
using (Entity topLevelEntity = tr.GetObject(fullEntPath.First().GetObjectIds().First(), OpenMode.ForRead) as Entity)
{
Point3d cursorPosition = e.Context.ComputedPoint;
if (topLevelEntity
is BlockReference
) {
using (BlockReference blockRef = (BlockReference)topLevelEntity)
{
using (BlockTableRecord blockDef = tr.GetObject(blockRef.BlockTableRecord, OpenMode.ForRead) as BlockTableRecord)
{
foreach (ObjectId entId in blockDef)
{
using (Entity subEntity = tr.GetObject(entId, OpenMode.ForRead) as Entity)
{
if (IsCursorOnEntity(subEntity, cursorPosition, blockRef, tr))
{
pickObjId = subEntity.ObjectId;
pickBlockRefId = blockRef.ObjectId; // Store the block reference ObjectId
break;
}
}
}
}
}
}
else
{
pickObjId = topLevelEntity.ObjectId;
pickBlockRefId = ObjectId.Null; // Reset the block reference ObjectId
}
}
tr.Commit();
}
}
catch (System.Exception ex)
{
if (!string.Equals(ex.Message, "enullextents", StringComparison.OrdinalIgnoreCase))
{
ed.WriteMessage("\nError: " + ex.Message);
pickObjId = ObjectId.Null;
pickBlockRefId = ObjectId.Null;
}
}
}
else
{
pickObjId = ObjectId.Null;
pickBlockRefId = ObjectId.Null;
}
}
private static bool IsCursorOnEntity(Entity entity, Point3d cursorPosition, BlockReference blockRef, Transaction tr)
{
// Adjust tolerance as needed
double tolerance = 0.01;
// Transform the cursor position from WCS to the block reference's ECS
Matrix3d transform = blockRef.BlockTransform.Inverse();
Point3d transformedCursorPosition = cursorPosition.TransformBy(transform);
// Check if the entity's linetype is ByLayer and the layer is plottable
if (string.Equals(entity.Linetype, "BYLAYER", StringComparison.OrdinalIgnoreCase))
{
LayerTableRecord layer = tr.GetObject(entity.LayerId, OpenMode.ForRead) as LayerTableRecord;
if (layer != null && layer.IsPlottable)
{
if (entity
is Curve curve
) {
// Get the closest point on the curve to the transformed cursor position
Point3d closestPoint = curve.GetClosestPointTo(transformedCursorPosition, false);
// Check if the distance between the closest point and the transformed cursor position is within the tolerance
return transformedCursorPosition.DistanceTo(closestPoint) <= tolerance;
}
else
{
// For non-curve entities, check if the transformed cursor position is within the entity's geometric extents
Extents3d extents = entity.GeometricExtents;
return transformedCursorPosition.X >= extents.MinPoint.X - tolerance &&
transformedCursorPosition.X <= extents.MaxPoint.X + tolerance &&
transformedCursorPosition.Y >= extents.MinPoint.Y - tolerance &&
transformedCursorPosition.Y <= extents.MaxPoint.Y + tolerance &&
transformedCursorPosition.Z >= extents.MinPoint.Z - tolerance &&
transformedCursorPosition.Z <= extents.MaxPoint.Z + tolerance;
}
}
}
return false;
}
}