using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.Colors;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.Internal;
using Autodesk.AutoCAD.Runtime;
using Autodesk.Civil.DatabaseServices;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Win32 = Microsoft.Win32;
namespace C3dTest
{
public class TestCustomObjectViewerCmdSwitch : IExtensionApplication
{
static RXClass _pipeClass = RXClass.GetClass(typeof(Pipe));
List<ObjectId> _pipeTmpObjIds = new List<ObjectId>();
public void Initialize()
{
// Preloading AecUtilities.arx
if (!Utils.IsCommandDefined("AecObjectViewer"))
SystemObjects.DynamicLinker.LoadModule("AecUtilities.arx", false, false);
Utils.AddCommand("ACAD_MAIN", "AecObjectViewer",
"ObjectViewer", CommandFlags.UsePickSet | CommandFlags.Redraw,
MyObjectViewerHandler);
}
public void Terminate()
{
}
public void MyObjectViewerHandler()
{
List<ObjectId> _allSelObjIds;
if (!(Application.DocumentManager.MdiActiveDocument is Document adoc)) return;
PromptSelectionResult implSelRes = adoc.Editor.SelectImplied();
if (implSelRes.Status == PromptStatus.OK)
{
_allSelObjIds = implSelRes.Value.GetObjectIds().ToList();
}
else
{
// Если Просмотр объектов запущен без предварительного выбора
PromptSelectionOptions selOpts = new PromptSelectionOptions
{
AllowDuplicates = false,
AllowSubSelections = false,
RejectObjectsFromNonCurrentSpace = true,
RejectPaperspaceViewport = true
};
// Предлагаем выбрать объекты
PromptSelectionResult selRes = adoc.Editor.GetSelection(selOpts);
// Если объекты выбраны
if (selRes.Status == PromptStatus.OK)
{
// Запоминаем их для обработки
_allSelObjIds = selRes.Value.GetObjectIds().ToList();
}
else
{
// Если не выбраны - прерываем запуск команды
return;
}
}
// Ищем все трубы
ObjectId[] selPipesIds = _allSelObjIds.Where
(id => id.ObjectClass.Equals(_pipeClass)).ToArray();
// Если нашли
if (selPipesIds.Count() > 0)
{
// Удаляем трубы из списка
_allSelObjIds.RemoveAll
(item => selPipesIds.Contains(item));
// Создаём объекты для подмены
ObjectId[] curTmpObjs = selPipesIds
.Select(pipeId => GetPipeTmpObject(pipeId))
.ToArray();
_pipeTmpObjIds.AddRange(curTmpObjs);
// Добавляем объекты подмены в список
_allSelObjIds.AddRange(curTmpObjs);
}
// Назначаем предвыбор
adoc.Editor.SetImpliedSelection(_allSelObjIds.ToArray());
Application.Idle += Application_Idle;
string groupName = GetCmdGroupName();
if (groupName != null)
{
adoc.SendStringToExecute
($"_{groupName}.AecObjectViewer ", true, false, false);
}
}
void Application_Idle(object sender, EventArgs e)
{
Application.Idle -= Application_Idle;
Document adoc = Application.DocumentManager.MdiActiveDocument;
if (adoc == null) return;
using (DocumentLock docLock = adoc.LockDocument())
{
// Если есть временные объекты (завершена команда "Просмотр объектов")
if (_pipeTmpObjIds.Count > 0)
{
// Удаляем их
foreach (ObjectId id in _pipeTmpObjIds)
{
#pragma warning disable CS0618 // Type or member is obsolete
using (var ent = id.Open(OpenMode.ForWrite))
#pragma warning restore CS0618 // Type or member is obsolete
{
ent.Erase(true);
}
}
_pipeTmpObjIds.Clear();
}
}
}
/// <summary>
/// Получение названия группы команд для AecUtilites
/// </summary>
/// <example>
/// Например, для Civil 3D 2016. Раздел реестра:
/// HKEY_CURRENT_USER\Software\Autodesk\AutoCAD\R20.1\ACAD-F000:419
/// \AEC\7.8\General\Tools\{E04B3676-CBB7-454c-9CDB-A55ACA81C41F}
/// Название параметра: AppName
/// Значение параметра: AecUtilities70
/// Метод вернёт строку: "AecUtilities70"
/// </example>
/// <returns></returns>
static string GetCmdGroupName()
{
// Открываем раздел
// HKEY_CURRENT_USER\Software\Autodesk\AutoCAD\RXX.X\ACAD-XXXX:419\AEC
Win32.RegistryKey aecRoot = Win32.Registry.CurrentUser.OpenSubKey
(Path.Combine(HostApplicationServices.Current.UserRegistryProductRootKey, "AEC"));
if (aecRoot != null)
{
// В этом разделе внутри разделы с названиями в виде номера версии,
// в одном из них есть вложенный раздел General. Ищем его.
string[] aecSubKeyNames = aecRoot.GetSubKeyNames();
foreach (string aecSubKeyName in aecSubKeyNames)
{
Win32.RegistryKey aecSubKey = aecRoot.OpenSubKey(aecSubKeyName);
// Если нашли
if (aecSubKey.GetSubKeyNames().Contains("General"))
{
// Получаем раздел
// HKEY_CURRENT_USER\Software\Autodesk\AutoCAD\
// RXX.X\ACAD-XXXX:419\AEC\X.X\General\Tools
Win32.RegistryKey tools
= aecSubKey.OpenSubKey(Path.Combine("General", "Tools"));
// В нём - только один раздел с названием в виде GUID.
// Получаем его
string guidKeyName = tools.GetSubKeyNames()[0];
Win32.RegistryKey guidKey = tools.OpenSubKey(guidKeyName);
// Читаем значение AppName
return guidKey.GetValue("AppName").ToString();
}
}
}
return null;
}
static ObjectId GetPipeTmpObject(ObjectId pipeId)
{
Point3d start, end;
double innerRad;
#pragma warning disable CS0618 // Type or member is obsolete
using (Pipe pipe = pipeId.Open(OpenMode.ForRead) as Pipe)
#pragma warning restore CS0618 // Type or member is obsolete
{
start = pipe.StartPoint;
end = pipe.EndPoint;
innerRad = pipe.InnerDiameterOrWidth * 4;
}
Vector3d normal = start.GetVectorTo(end).GetNormal();
SweepOptionsBuilder optBuild = new SweepOptionsBuilder();
optBuild.TwistAngle = Math.PI;
SweepOptions opts = optBuild.ToSweepOptions();
using (SweptSurface surf = new SweptSurface())
{
using (Polyline pline = new Polyline(4))
using (Line line = new Line(start, end))
{
pline.AddVertexAt(0, new Point2d(-innerRad, -innerRad), 0, 0, 0);
pline.AddVertexAt(1, new Point2d(innerRad, -innerRad), 0, 0, 0);
pline.AddVertexAt(2, new Point2d(innerRad, innerRad), 0, 0, 0);
pline.AddVertexAt(3, new Point2d(-innerRad, innerRad), 0, 0, 0);
pline.Closed = true;
pline.Normal = normal;
pline.TransformBy(Matrix3d.Displacement(start.GetAsVector()));
surf.CreateSweptSurface(pline, line, opts);
}
// Сделаем трубы фиолетовыми
surf.Color = Color.FromColorIndex(ColorMethod.ByAci, 6);
#pragma warning disable CS0618 // Type or member is obsolete
using (BlockTableRecord bRec
= pipeId.Database.CurrentSpaceId.Open(OpenMode.ForWrite) as BlockTableRecord)
#pragma warning restore CS0618 // Type or member is obsolete
{
return bRec.AppendEntity(surf);
}
}
}
}
}