feat(rhino): adds user dictionary to object props (#1046)

* adds user dicts to rhino

* defaults to string value

---------

Co-authored-by: Björn <steinhagen.bjoern@gmail.com>
This commit is contained in:
Claire Kuang
2025-09-02 15:56:56 +01:00
committed by GitHub
parent ff5cdf47df
commit fe3d4e5544
@@ -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<string, object?> GetProperties(RhinoObject rhObject)
{
Dictionary<string, object?> properties = new();
Dictionary<string, object?> properties = GetUserStrings(rhObject);
Dictionary<string, object?> userDict = GetUserDict(rhObject);
if (userDict.Count > 0)
{
properties["User Dictionary"] = userDict;
}
return properties;
}
private Dictionary<string, object?> GetUserDict(RhinoObject rhObject)
{
Dictionary<string, object?> userDict = new();
if (rhObject.Attributes.UserDictionary != null && rhObject.Attributes.UserDictionary.Count > 0)
{
ParseArchivableToDictionary(userDict, rhObject.Attributes.UserDictionary);
}
return userDict;
}
/// <summary>
/// Copies an ArchivableDictionary to a Dictionary
/// </summary>
/// <param name="target"></param>
/// <param name="dict"></param>
private void ParseArchivableToDictionary(Dictionary<string, object?> target, ArchivableDictionary dict)
{
foreach (var key in dict.Keys)
{
var obj = dict[key];
switch (obj)
{
case ArchivableDictionary o:
Dictionary<string, object?> nested = new();
ParseArchivableToDictionary(nested, o);
target[key] = nested;
continue;
case double:
case bool:
case int:
case string:
case IEnumerable<double>:
case IEnumerable<bool>:
case IEnumerable<int>:
case IEnumerable<string>:
target[key] = obj;
continue;
default:
target[key] = obj.ToString();
continue;
}
}
}
private Dictionary<string, object?> GetUserStrings(RhinoObject rhObject)
{
Dictionary<string, object?> 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;
}
}