From fe3d4e554440d38015d3c510e28fb4e2dd708bb9 Mon Sep 17 00:00:00 2001 From: Claire Kuang Date: Tue, 2 Sep 2025 15:56:56 +0100 Subject: [PATCH] feat(rhino): adds user dictionary to object props (#1046) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * adds user dicts to rhino * defaults to string value --------- Co-authored-by: Björn --- .../HostApp/Properties/PropertiesExtractor.cs | 73 +++++++++++++++++-- 1 file changed, 67 insertions(+), 6 deletions(-) diff --git a/Connectors/Rhino/Speckle.Connectors.RhinoShared/HostApp/Properties/PropertiesExtractor.cs b/Connectors/Rhino/Speckle.Connectors.RhinoShared/HostApp/Properties/PropertiesExtractor.cs index e5d07080a..9d86dc161 100644 --- a/Connectors/Rhino/Speckle.Connectors.RhinoShared/HostApp/Properties/PropertiesExtractor.cs +++ b/Connectors/Rhino/Speckle.Connectors.RhinoShared/HostApp/Properties/PropertiesExtractor.cs @@ -1,4 +1,5 @@ using Rhino; +using Rhino.Collections; using Rhino.DocObjects; using Speckle.Connectors.Rhino.Mapper.Revit; using Speckle.Sdk; @@ -19,7 +20,67 @@ public class PropertiesExtractor public Dictionary GetProperties(RhinoObject rhObject) { - Dictionary properties = new(); + Dictionary properties = GetUserStrings(rhObject); + + Dictionary userDict = GetUserDict(rhObject); + if (userDict.Count > 0) + { + properties["User Dictionary"] = userDict; + } + + return properties; + } + + private Dictionary GetUserDict(RhinoObject rhObject) + { + Dictionary userDict = new(); + if (rhObject.Attributes.UserDictionary != null && rhObject.Attributes.UserDictionary.Count > 0) + { + ParseArchivableToDictionary(userDict, rhObject.Attributes.UserDictionary); + } + + return userDict; + } + + /// + /// Copies an ArchivableDictionary to a Dictionary + /// + /// + /// + private void ParseArchivableToDictionary(Dictionary target, ArchivableDictionary dict) + { + foreach (var key in dict.Keys) + { + var obj = dict[key]; + switch (obj) + { + case ArchivableDictionary o: + Dictionary nested = new(); + ParseArchivableToDictionary(nested, o); + target[key] = nested; + continue; + + case double: + case bool: + case int: + case string: + case IEnumerable: + case IEnumerable: + case IEnumerable: + case IEnumerable: + target[key] = obj; + continue; + + default: + target[key] = obj.ToString(); + continue; + } + } + } + + private Dictionary GetUserStrings(RhinoObject rhObject) + { + Dictionary userStringDict = new(); var userStrings = rhObject.Attributes.GetUserStrings(); foreach (string? key in userStrings.AllKeys) { @@ -38,7 +99,7 @@ public class PropertiesExtractor if (userStrings[key]?.StartsWith("%<") ?? false) { var value = RhinoApp.ParseTextField(userStrings[key], rhObject, null); - properties[key] = value; + userStringDict[key] = value; continue; } } @@ -47,19 +108,19 @@ public class PropertiesExtractor // Shh. We can fail silently here - it's not even worth logging. I expect users will complain properties are missing. } - properties[key] = userStrings[key]; + userStringDict[key] = userStrings[key]; } // NOTE: if no mapping was found on the object, check layer(s) recursively - if (!properties.ContainsKey(RevitMappingConstants.CATEGORY_USER_STRING_KEY)) + if (!userStringDict.ContainsKey(RevitMappingConstants.CATEGORY_USER_STRING_KEY)) { var layerMapping = _revitMappingResolver.SearchLayerHierarchyForMapping(rhObject); if (!string.IsNullOrEmpty(layerMapping)) { - properties[RevitMappingConstants.CATEGORY_USER_STRING_KEY] = layerMapping; + userStringDict[RevitMappingConstants.CATEGORY_USER_STRING_KEY] = layerMapping; } } - return properties; + return userStringDict; } }