Thanks BlackBox_.
I saw Kean's thread sometimes ago. I rewrote the code to publish it on a French web site: CADxp.
Two toggle commands are defined. Both can be called transparently.
LOKO to (de)activate osnaps on locked layers.
XROS to (de)activate osnaps on xrefs.
Here's the code:
using System;
using System.Collections.Generic;
using System.Linq;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.Runtime;
using AcAp = Autodesk.AutoCAD.ApplicationServices.Application;
[assembly: CommandClass(typeof(Gile.LockOsnap.CommandMethods))]
namespace Gile.LockOsnap
{
public class CommandMethods
{
private OSOverrule lokoOSOverrule, xrosOSOverrule;
private IntOverrule lokoIntOverrule, xrosIntOverrule;
[CommandMethod("LOKO", CommandFlags.Modal | CommandFlags.Transparent)]
public void LockOsnapCmd()
{
ToggleOsnaps(ref lokoOSOverrule, ref lokoIntOverrule, lokoPromptingForPoint, LockedUpdate, "calques verrouillés");
}
[CommandMethod("XROS", CommandFlags.Modal | CommandFlags.Transparent)]
public void XrefOsnapCmd()
{
ToggleOsnaps(ref xrosOSOverrule, ref xrosIntOverrule, xrosPromptingForPoint, XrefUpdate, "références externes");
}
void lokoPromptingForPoint(object sender, PromptPointOptionsEventArgs e)
{
LockedUpdate();
}
void xrosPromptingForPoint(object sender, PromptPointOptionsEventArgs e)
{
XrefUpdate();
}
private void ToggleOsnaps(
ref OSOverrule osOverrule,
ref IntOverrule intOverrule,
PromptPointOptionsEventHandler handler,
Action update,
string msg)
{
Editor ed = AcAp.DocumentManager.MdiActiveDocument.Editor;
RXClass entityClass = RXClass.GetClass(typeof(Entity));
if (osOverrule == null)
{
ed.PromptingForPoint += handler;
osOverrule = new OSOverrule();
Overrule.AddOverrule(entityClass, osOverrule, false);
intOverrule = new IntOverrule();
Overrule.AddOverrule(entityClass, intOverrule, false);
ed.WriteMessage(string.Format("\nAccrochages sur les {0} désactivés.", msg));
update();
Overrule.Overruling = true;
}
else
{
ed.PromptingForPoint -= xrosPromptingForPoint;
Overrule.RemoveOverrule(entityClass, osOverrule);
osOverrule = null;
Overrule.RemoveOverrule(entityClass, intOverrule);
intOverrule = null;
ed.WriteMessage(string.Format("\nAccrochages sur les {0} activés.", msg));
}
}
private void LockedUpdate()
{
if (lokoOSOverrule != null)
{
Database db = HostApplicationServices.WorkingDatabase;
using (Transaction tr = db.TransactionManager.StartOpenCloseTransaction())
{
HashSet<string> layers = new HashSet<string>(
((LayerTable)tr.GetObject(db.LayerTableId, OpenMode.ForRead))
.Cast<ObjectId>()
.Select(id => (LayerTableRecord)tr.GetObject(id, OpenMode.ForRead))
.Where(ltr => ltr.IsLocked)
.Select(ltr => ltr.Name));
ObjectId[] onLocked = ((BlockTableRecord)tr.GetObject(db.CurrentSpaceId, OpenMode.ForRead))
.Cast<ObjectId>()
.Where(id => layers.Contains(((Entity)tr.GetObject(id, OpenMode.ForRead)).Layer))
.ToArray();
lokoOSOverrule.SetIdFilter(onLocked);
lokoIntOverrule.SetIdFilter(onLocked);
tr.Commit();
}
}
}
private void XrefUpdate()
{
if (xrosOSOverrule != null)
{
Database db = HostApplicationServices.WorkingDatabase;
using (Transaction tr = db.TransactionManager.StartOpenCloseTransaction())
{
ObjectId[] xrIds = ((BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead))
.Cast<ObjectId>()
.Select(id => (BlockTableRecord)tr.GetObject(id, OpenMode.ForRead))
.Where(btr => btr.IsFromExternalReference)
.SelectMany(btr => btr.GetBlockReferenceIds(true, false).Cast<ObjectId>())
.ToArray();
xrosOSOverrule.SetIdFilter(xrIds);
xrosIntOverrule.SetIdFilter(xrIds);
tr.Commit();
}
}
}
class OSOverrule : OsnapOverrule
{
public override void GetObjectSnapPoints(
Entity ent,
ObjectSnapModes mode,
IntPtr gsm,
Point3d pick,
Point3d last,
Matrix3d view,
Point3dCollection snap,
IntegerCollection geomIds) { }
public override void GetObjectSnapPoints(
Entity ent,
ObjectSnapModes mode,
IntPtr gsm,
Point3d pick,
Point3d last,
Matrix3d view,
Point3dCollection snaps,
IntegerCollection geomIds,
Matrix3d insertion) { }
public override bool IsContentSnappable(Entity entity)
{
return false;
}
}
class IntOverrule : GeometryOverrule
{
public override void IntersectWith(
Entity ent1,
Entity ent2,
Intersect intType,
Plane proj,
Point3dCollection points,
IntPtr thisGsm,
IntPtr otherGsm) { }
public override void IntersectWith(
Entity ent1,
Entity ent2,
Intersect intType,
Point3dCollection points,
IntPtr thisGsm,
IntPtr otherGsm) { }
}
}
}