Get Elefront Attributes fom C# sdk Plugin

Hi There,

I am currently trying to develop a plugin using rhinocommon in c#. To get the functionality i want i need to be able to read the data in the attributes that i assigned from Grasshopper with Elefront. The data is attached to a group and shown in Rhino:

But in my plugin it only shows an empty SharedUserDictionary:

I also tried adding some User Data manually in the Rhino interface, but it doesnt show. Same happens the other way around, the user data or dictionaries i add to the objects get added and i can access them in my code but they dont reflect in the User data shown in Rhino itself.

Here is my code for reading and adding the data:

internal void Dtgrd_LoadWeld(int index)
{

  //AddUserDataTEMP();

  dt_WeldTable.Rows.Clear();
  List<int> _GroupInts = new List<int>();

  var _weldObjects = rhinoDoc.Objects.FindByLayer(rhinoDoc.Layers.FindIndex(index));
  foreach (var target in _weldObjects)
  {
    if (!_GroupInts.Contains(target.Attributes.GetGroupList().First()))
      _GroupInts.Add(target.Attributes.GetGroupList().First());


    //dt_WeldTable.Rows.Add(target.Id, target.Name, target.Attributes.GetUserString("Target Index"));
  }
  foreach (var groupInt in _GroupInts)
  {
    var _group = rhinoDoc.Groups.FindIndex(groupInt);
    dt_WeldTable.Rows.Add(_group.Id, _group.Name, _group.GetUserString("1"));
    var GroupDict = _group.UserDictionary;
    System.Object sad = "";
    var Value = GroupDict.TryGetValue("1", out sad);
    var GroupUserData = _group.UserData;
    var GroupUserStrings = _group.GetUserStrings();
    

    var objectIds = rhinoDoc.Groups.GroupMembers(_group.Index);
    if (objectIds == null || objectIds.Length == 0)
    {
      RhinoApp.WriteLine("Group is empty or does not exist.");
    }

    // Retrieve the objects from the document using the object IDs
    List<RhinoObject> groupObjects = new List<RhinoObject>();
    foreach (var id in objectIds)
    {
      var item = rhinoDoc.Objects.Find(id.Id);
      var userData = new Rhino.Collections.ArchivableDictionary();
      userData.Set("FKey", "FValue");
      var succ = item.Attributes.UserDictionary.Set("DirectKey", "DirectValue");
      if (item.HasUserData)
      {
        var sdf = item.Geometry.UserDictionary.Count;
        var sdsfsd = item.UserData.First();
        if (sdf > 0)
        {
          var sdfa = item.UserDictionary;
        }
      }
      item.CommitChanges();
    }
  }
}

Any help is much appreciated and Thanks in advance,
Tobias

Alternatively i could do with a C# Component that sets the User Data from Grasshopper. I tried that, but again i can not read the data from my plugin, it just gives me a null dictionary. Is it even possible to do that or does the information from Grasshopper and Rhino live in seperate spaces and can’t be accessed from both?

Here is a sample of code that we use to serialize our data objects onto rhino geometry, a rhino object named rhinoObject saved like this:

var objectToSerialize = new SerializeThisObject();
string key = "dataKey";
string val = JsonConvert.SerializeObject(objectToSerialize, Formatting.None);
rhinoObject.Attributes.UserDictionary.Set(key, val);

You can then simply check the rhinoObject for the key to see if the data is there:

if(rhinoObject.Attributes.UserDictionary.ContainsKey(key))
{
    rhinoObject.Attributes.TryGetString(key, out string serializedDataObject);
    // Deserialize Your Object
    // ...
}

I don’t think you need to mess with the ArchivableDictionary unless you are overidding the WriteDocument logic to embed data into the file.

image

The values you see in the Rhino panel are UserStrings, stored in the UserStrings field, in the object’s Attributes.

It can be confusing, since there is also UserData (which is generally for serializing custom plugin information - where you would need your custom plugin installed to deserialize the data), and UserDictionary, which allows you to store data in a Dictionary that gets archived in the 3dm file (so you don’t need your plugin installed, but you are limited to the datatypes provided).

But at least specifically for UserStrings, it looks something like this:

        var rhinoObject = RhinoDoc.ActiveDoc.Objects.FindId(id);
        var attributes = rhinoObject.Attributes;
        var allUserStrings = rhinoObject.Attributes.GetUserStrings(); // this is a collection of Key/Value pairs
        var keyValueDictionary = new Dictionary<string, string>();

        foreach(var key in allUserStrings.AllKeys){
            keyValueDictionary.Add(key, attributes.GetUserString(key));
        }