// // (C) Copyright 2003-2019 by Autodesk, Inc. All rights reserved. // // Permission to use, copy, modify, and distribute this software in // object code form for any purpose and without fee is hereby granted // provided that the above copyright notice appears in all copies and // that both that copyright notice and the limited warranty and // restricted rights notice below appear in all supporting // documentation. // // AUTODESK PROVIDES THIS PROGRAM 'AS IS' AND WITH ALL ITS FAULTS. // AUTODESK SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTY OF // MERCHANTABILITY OR FITNESS FOR A PARTICULAR USE. AUTODESK, INC. // DOES NOT WARRANT THAT THE OPERATION OF THE PROGRAM WILL BE // UNINTERRUPTED OR ERROR FREE. // // Use, duplication, or disclosure by the U.S. Government is subject to // restrictions set forth in FAR 52.227-19 (Commercial Computer // Software - Restricted Rights) and DFAR 252.227-7013(c)(1)(ii) // (Rights in Technical Data and Computer Software), as applicable. /* * This sample demonstrates how to use DirectContext3D to draw graphics. The graphics primitives that * are needed for DirectContext3D are taken from the contents of existing Revit elements. The result of * the macro is to duplicate the graphics of existing Revit elements by using DirectContext3D. No new * elements are created to contain the graphics produced with DirectContext3D. * * The following are the main steps for using DirectContext3D: * 1) create a DirectContext3D server (derived from Autodesk.Revit.DB.DirectContext3D.IDirectContext3DServer) * a. register the server with the DirectContext3D service * 2) use the server to submit geometry for drawing * a. represent geometry primitives using pairs of vertex and index buffers * b. determine when to submit opaque/transparent geometry * c. flush the buffers * d. update the buffers when necessary */ using Autodesk.Revit.UI; using Autodesk.Revit.DB; using Autodesk.Revit.DB.ExternalService; using Autodesk.Revit.DB.Events; using Autodesk.Revit.UI.Selection; using System; using System.Collections.Generic; namespace Revit.SDK.Samples.DuplicateGraphics.CS { /// /// Implements the Revit add-in interface IExternalApplication /// [Autodesk.Revit.Attributes.Transaction(Autodesk.Revit.Attributes.TransactionMode.Manual)] [Autodesk.Revit.Attributes.Regeneration(Autodesk.Revit.Attributes.RegenerationOption.Manual)] public class Application : IExternalApplication { #region IExternalApplication Members /// /// Implements the OnStartup event /// /// /// Result that indicates whether the external application has completed its work successfully. public Result OnStartup(UIControlledApplication application) { try { // Register events. application.ControlledApplication.DocumentClosing += new EventHandler (OnDocumentClosing); m_servers = new List(); m_documents = new HashSet(); s_applicationInstance = this; } catch (Exception) { return Result.Failed; } return Result.Succeeded; } /// /// Implements the OnShutdown event /// /// /// Result that indicates whether the external application has completed its work successfully. public Result OnShutdown(UIControlledApplication application) { // remove the event. application.ControlledApplication.DocumentClosing -= OnDocumentClosing; return Result.Succeeded; } /// /// Implements the OnDocumentClosing event /// /// /// /// public void OnDocumentClosing(object sender, DocumentClosingEventArgs args) { unregisterServers(args.Document, false); } #endregion /// /// Responds to the external command CommandDuplicateGraphics. /// /// public static void ProcessCommandDuplicateGraphics(Document document) { if (s_applicationInstance != null) { s_applicationInstance.AddMultipleRevitElementServers(new UIDocument(document)); } } /// /// Responds to the external command CommandClearExternalGraphics. /// /// public static void ProcessCommandClearExternalGraphics(Document document) { if (s_applicationInstance != null) { s_applicationInstance.unregisterServers(null, true); } } /// /// Picks a Revit element and creates a corresponding DirectContext3D server that will draw the element's graphics at a fixed offset from the original location. /// /// public void AddRevitElementServer(UIDocument uidoc) { Reference reference = uidoc.Selection.PickObject(ObjectType.Element, "Select an element to duplicate with DirectContext3D"); Element elem = uidoc.Document.GetElement(reference); // Create the server and register it with the DirectContext3D service. ExternalService directContext3DService = ExternalServiceRegistry.GetService(ExternalServices.BuiltInExternalServices.DirectContext3DService); RevitElementDrawingServer revitServer = new RevitElementDrawingServer(uidoc, elem, m_offset); directContext3DService.AddServer(revitServer); m_servers.Add(revitServer); MultiServerService msDirectContext3DService = directContext3DService as MultiServerService; IList serverIds = msDirectContext3DService.GetActiveServerIds(); serverIds.Add(revitServer.GetServerId()); // Add the new server to the list of active servers. msDirectContext3DService.SetActiveServers(serverIds); m_documents.Add(uidoc.Document); uidoc.UpdateAllOpenViews(); } /// /// Same as AddRevitElementServer(), but for multiple elements. /// /// public void AddMultipleRevitElementServers(UIDocument uidoc) { IList references = uidoc.Selection.PickObjects(ObjectType.Element, "Select elements to duplicate with DirectContext3D"); ExternalService directContext3DService = ExternalServiceRegistry.GetService(ExternalServices.BuiltInExternalServices.DirectContext3DService); MultiServerService msDirectContext3DService = directContext3DService as MultiServerService; IList serverIds = msDirectContext3DService.GetActiveServerIds(); // Create one server per element. foreach (Reference reference in references) { Element elem = uidoc.Document.GetElement(reference); RevitElementDrawingServer revitServer = new RevitElementDrawingServer(uidoc, elem, m_offset); directContext3DService.AddServer(revitServer); m_servers.Add(revitServer); serverIds.Add(revitServer.GetServerId()); } msDirectContext3DService.SetActiveServers(serverIds); m_documents.Add(uidoc.Document); uidoc.UpdateAllOpenViews(); } /// /// Cleans up by unregistering the servers corresponding to the specified document, or all servers if the document is not provided. /// /// The document whose servers should be removed, or null. /// Update views of the affected document(s). public void unregisterServers(Document document, bool updateViews) { ExternalServiceId externalDrawerServiceId = ExternalServices.BuiltInExternalServices.DirectContext3DService; var externalDrawerService = ExternalServiceRegistry.GetService(externalDrawerServiceId) as MultiServerService; if (externalDrawerService == null) return; foreach (var registeredServerId in externalDrawerService.GetRegisteredServerIds()) { var externalDrawServer = externalDrawerService.GetServer(registeredServerId) as RevitElementDrawingServer; if (externalDrawServer == null) continue; if (document != null && !document.Equals(externalDrawServer.Document)) continue; externalDrawerService.RemoveServer(registeredServerId); } if (document != null) { m_servers.RemoveAll(server => document.Equals(server.Document)); if (updateViews) { UIDocument uidoc = new UIDocument(document); uidoc.UpdateAllOpenViews(); } m_documents.Remove(document); } else { m_servers.Clear(); if (updateViews) foreach (var doc in m_documents) { UIDocument uidoc = new UIDocument(doc); uidoc.UpdateAllOpenViews(); } m_documents.Clear(); } } List m_servers; XYZ m_offset = new XYZ(0, 0, 45); HashSet m_documents; static Application s_applicationInstance; } }