public static void OnDocumentChanged(
            object InSender,
            DocumentChangedEventArgs InArgs)
        {
            FDirectLink DirectLink = FDirectLink.Get();

            Debug.Assert(DirectLink != null);

            // Handle modified elements
            foreach (ElementId ElemId in InArgs.GetModifiedElementIds())
            {
                Element ModifiedElement = DirectLink.RootCache.SourceDocument.GetElement(ElemId);

                if (ModifiedElement.GetType() == typeof(RevitLinkInstance))
                {
                    DirectLink.ModifiedLinkedDocuments.Add((ModifiedElement as RevitLinkInstance).GetLinkDocument());
                }

                DirectLink.RootCache.ModifiedElements.Add(ElemId);
            }
        }
        public override Result OnExecute(ExternalCommandData InCommandData, ref string OutCommandMessage, ElementSet OutElements)
        {
            UIDocument UIDoc      = InCommandData.Application.ActiveUIDocument;
            Document   Doc        = UIDoc.Document;
            View3D     ActiveView = Doc.ActiveView as View3D;

            if (ActiveView == null)
            {
                string Message = "You must be in a 3D view to export.";
                MessageBox.Show(Message, DIALOG_CAPTION, MessageBoxButtons.OK, MessageBoxIcon.Warning);
                return(Result.Cancelled);
            }

            if (ActiveView.IsTemplate || !ActiveView.CanBePrinted)
            {
                string Message = "The active 3D view cannot be exported.";
                MessageBox.Show(Message, DIALOG_CAPTION, MessageBoxButtons.OK, MessageBoxIcon.Warning);
                return(Result.Cancelled);
            }

            Debug.Assert(FDirectLink.Get() != null);

            // Holding ctrl will force full sync.
            if (FDirectLink.Get().SyncCount > 0 && (System.Windows.Forms.Control.ModifierKeys & Keys.Control) == Keys.Control)
            {
                FDirectLink.DestroyInstance(FDirectLink.Get(), InCommandData.Application.Application);
                FDirectLink.ActivateInstance(Doc);
            }

            FDatasmithRevitExportContext ExportContext = new FDatasmithRevitExportContext(
                InCommandData.Application.Application,
                Doc,
                null,
                new DatasmithRevitExportOptions(Doc),
                FDirectLink.Get());

            // Export the active 3D View to the given Unreal Datasmith file.
            using (CustomExporter Exporter = new CustomExporter(Doc, ExportContext))
            {
                try
                {
                    // The export process will exclude output of geometric objects such as faces and curves,
                    // but the context needs to receive the calls related to Faces or Curves to gather data.
                    // The context always receive their tessellated geometry in form of polymeshes or lines.
                    Exporter.IncludeGeometricObjects = true;

                    // The export process should stop in case an error occurs during any of the exporting methods.
                    Exporter.ShouldStopOnError = true;

#if REVIT_API_2020
                    Exporter.Export(ActiveView as Autodesk.Revit.DB.View);
#else
                    Exporter.Export(ActiveView);
#endif
                }
                catch (System.Exception exception)
                {
                    OutCommandMessage = string.Format("Cannot export the 3D view:\n\n{0}\n\n{1}", exception.Message, exception.StackTrace);
                    MessageBox.Show(OutCommandMessage, DIALOG_CAPTION, MessageBoxButtons.OK, MessageBoxIcon.Error);
                    return(Result.Failed);
                }
                finally
                {
                    if (ExportContext.GetMessages().Count > 0)
                    {
                        string Messages = string.Join($"{System.Environment.NewLine}", ExportContext.GetMessages());
                        DatasmithRevitApplication.SetExportMessages(Messages);
                    }
                }
            }

            return(Result.Succeeded);
        }