diff --git a/Connectors/Revit/Speckle.Connectors.RevitShared/Bindings/BasicConnectorBindingRevit.cs b/Connectors/Revit/Speckle.Connectors.RevitShared/Bindings/BasicConnectorBindingRevit.cs index 98b5ab4d8..3b2c095fb 100644 --- a/Connectors/Revit/Speckle.Connectors.RevitShared/Bindings/BasicConnectorBindingRevit.cs +++ b/Connectors/Revit/Speckle.Connectors.RevitShared/Bindings/BasicConnectorBindingRevit.cs @@ -105,6 +105,8 @@ public async Task HighlightModel(string modelCardId) .SendFilter.NotNull() .GetObjectIds() .Select(uid => ElementIdHelper.GetElementIdFromUniqueId(activeUIDoc.Document, uid)) + .Where(el => el is not null) + .Cast() .ToList(); } @@ -113,6 +115,8 @@ public async Task HighlightModel(string modelCardId) elementIds = receiverModelCard .BakedObjectIds.NotNull() .Select(uid => ElementIdHelper.GetElementIdFromUniqueId(activeUIDoc.Document, uid)) + .Where(el => el is not null) + .Cast() .ToList(); } @@ -138,7 +142,11 @@ public async Task HighlightObjects(IReadOnlyList objectIds) ?? throw new SpeckleException("Unable to retrieve active UI document"); await HighlightObjectsOnView( - objectIds.Select(uid => ElementIdHelper.GetElementIdFromUniqueId(activeUIDoc.Document, uid)).ToList() + objectIds + .Select(uid => ElementIdHelper.GetElementIdFromUniqueId(activeUIDoc.Document, uid)) + .Where(el => el is not null) + .Cast() + .ToList() ) .ConfigureAwait(false); ; diff --git a/Connectors/Revit/Speckle.Connectors.RevitShared/Bindings/RevitSendBinding.cs b/Connectors/Revit/Speckle.Connectors.RevitShared/Bindings/RevitSendBinding.cs index df3d88257..62cde7438 100644 --- a/Connectors/Revit/Speckle.Connectors.RevitShared/Bindings/RevitSendBinding.cs +++ b/Connectors/Revit/Speckle.Connectors.RevitShared/Bindings/RevitSendBinding.cs @@ -132,7 +132,9 @@ public async Task Send(string modelCardId) List revitObjects = modelCard .SendFilter.NotNull() .GetObjectIds() - .Select(uid => activeUIDoc.Document.GetElement(uid).Id) + .Select(uid => activeUIDoc.Document.GetElement(uid)) + .Where(el => el is not null) // NOTE: elements can get deleted from the host app. + .Select(el => el.Id) .ToList(); if (revitObjects.Count == 0) @@ -249,6 +251,9 @@ private async Task RunExpirationChecks() } // Note: We're using unique ids as application ids in revit, so cache eviction must happen by those. + // NOTE: this is currently broken when deleting freestanding elements (e.g. unhosted elements) + // To reproduce, draw two unconnected walls, send, delete one wall -> no expiration notice + // I do not yet know the solution besides going back to element ids, but it would mean revisiting why we switched to unique ids (conflicting ids) var objUniqueIds = objectIdsList .Select(id => new ElementId(Convert.ToInt32(id))) .Select(doc.GetElement) diff --git a/Connectors/Revit/Speckle.Connectors.RevitShared/ElementIdHelper.cs b/Connectors/Revit/Speckle.Connectors.RevitShared/ElementIdHelper.cs index e49b6885e..f19938e0f 100644 --- a/Connectors/Revit/Speckle.Connectors.RevitShared/ElementIdHelper.cs +++ b/Connectors/Revit/Speckle.Connectors.RevitShared/ElementIdHelper.cs @@ -1,18 +1,12 @@ using Autodesk.Revit.DB; -using Speckle.Sdk; namespace Speckle.Connectors.RevitShared; public static class ElementIdHelper { - public static ElementId GetElementIdFromUniqueId(Document doc, string uniqueId) + public static ElementId? GetElementIdFromUniqueId(Document doc, string uniqueId) { Element element = doc.GetElement(uniqueId); - if (element == null) - { - throw new SpeckleException($"Cannot find element with UniqueId: {uniqueId}"); - } - - return element.Id; + return element?.Id; } } diff --git a/Connectors/Revit/Speckle.Connectors.RevitShared/HostApp/ElementUnpacker.cs b/Connectors/Revit/Speckle.Connectors.RevitShared/HostApp/ElementUnpacker.cs index 235aba240..bc3304998 100644 --- a/Connectors/Revit/Speckle.Connectors.RevitShared/HostApp/ElementUnpacker.cs +++ b/Connectors/Revit/Speckle.Connectors.RevitShared/HostApp/ElementUnpacker.cs @@ -93,8 +93,15 @@ private List UnpackElements(IEnumerable elements) private List PackCurtainWallElements(List elements) { var ids = elements.Select(el => el.Id).ToArray(); + var doc = _revitContext.UIApplication?.ActiveUIDocument.Document!; elements.RemoveAll(element => - (element is Mullion m && ids.Contains(m.Host.Id)) || (element is Panel p && ids.Contains(p.Host.Id)) + (element is Mullion m && ids.Contains(m.Host.Id)) + || (element is Panel p && ids.Contains(p.Host.Id)) + || ( + element is FamilyInstance { Host: not null } f + && doc.GetElement(f.Host.Id) is Wall { CurtainGrid: not null } + && ids.Contains(f.Host.Id) + ) ); return elements; }