Add UserData to instancedefinition

I created a custom userdata class (Inherits Rhino.DocObjects.Custom.UserData), and I would like to .add it to an InstanceDefinition, but I can’t figure out how to do this. (I know how to do this for a classic RhinoObject because it has a geometry)
I need to store common data for my blocs.

Any Idea how to do this?
Best regards

Hi @Matthieu_from_NAVINN,

I don’t believe this is possible in Rhino 5. Have you tried in Rhino 6?

– Dale

Hi Dale,
I can’t use Rhino 6 for now because it is meant to interface with a Rhino5 script.
I tried a workaround by adding a point with the userdata in the InstanceDefinition. It works on the current session but curiously the data is lost when the session is closed. Is there a specific operation to do to save the Instance definition Objects data?
This is how I add the data:

            ' Gather all of the selected objects
            Dim geometry = New System.Collections.Generic.List(Of Rhino.Geometry.GeometryBase)()
            Dim attributes = New System.Collections.Generic.List(Of Rhino.DocObjects.ObjectAttributes)()
            For i As Integer = 0 To MyBlockInstDef.GetObjects.Length - 1
                Dim rhinoObject = MyBlockInstDef.GetObjects(i)
                If rhinoObject IsNot Nothing Then
                    If rhinoObject.Name <> "GPointDefinition" Then
                    End If
                End If
            Next i
            'Create the GPoint
            Dim MyGPoint As New Point(GBlockDefData.GLocationDefinition)
            Dim MyGPointXform As Rhino.Geometry.Transform = MyBlockInstGeometry.Xform
            Dim attr As New ObjectAttributes()
            attr.Name = "GPointDefinition"
            attr.ColorSource = ObjectColorSource.ColorFromObject
            attr.ObjectColor = Drawing.Color.Red
            attr.PlotWeight = -1
            doc.InstanceDefinitions.ModifyGeometry(MyBlockInstDef.Index, geometry, attributes)

And this is how I read it:

'Get Instance definition
        Dim MyBlockInstDef As DocObjects.InstanceDefinition = doc.InstanceDefinitions.Find(MyBlockInstGeometry.ParentIdefId, True)
        If MyBlockInstDef Is Nothing Then Return False

        'Get Properties
        For i As Integer = 0 To MyBlockInstDef.GetObjects.Length - 1
            Dim rhinoObject = MyBlockInstDef.GetObjects(i)
            If rhinoObject IsNot Nothing Then
                If rhinoObject.Name = "GPointDefinition" Then
                    Dim MyGBlockData As GBlockDefDataClass = TryCast(rhinoObject.Geometry.UserData.Find(GetType(GBlockDefDataClass)), GBlockDefDataClass)
                    If MyGBlockData Is Nothing Then
                        RhinoApp.WriteLine("Error while reading GBlock data")
                        Return False
                        Dim MyGPointDef As Point = TryCast(rhinoObject.Geometry, Point)
                        If MyGPointDef Is Nothing Then Return False
                        GBlockInstanceLocation = MyGPointDef.Location
                        data = MyGBlockData
                        Return True
                    End If
                End If
            End If
        Next i

Hi @Matthieu_from_NAVINN,

Rather than add some extra geometry to the instance definition, why don’t you just store the user data on the document and track the user data record by the ID of the instance definition?

– Dale

Hi @Dale,
Storing the data in the document would be inconvenient because it would be lost when the block is used on another doc.

Do you know why doc.InstanceDefinitions.ModifyGeometry() works but lose the data when closing the session? It would be weird not to be able to do something like that. (And there is not even a sync reference issue, the blocks where created in my test document)


For information I’ve figured out a way to write data to the Instance definition:

  'Save Data to BlockDescription
            Dim DataAsString As String = ""
            Dim x As New Xml.Serialization.XmlSerializer(GBlockDefData.GetType)
            Dim sw As New IO.StringWriter()
            x.Serialize(sw, GBlockDefData)
            DataAsString = sw.ToString()
            doc.InstanceDefinitions.Modify(MyBlockInstDef.Index, MyBlockInstDef.Name, DataAsString, True)

And to read it:

'Get Properties from Instance Ref xml
            Dim x As New Xml.Serialization.XmlSerializer(GetType(GCenterBlockDataClass))
            Dim sr As New IO.StringReader(MyBlockInstDef.Description)
            Dim Obj As GCenterBlockDataClass = CType(x.Deserialize(sr), GCenterBlockDataClass)
            'MsgBox("Deserialisation Result= " & vbCrLf & Obj.ToString)
            Return True
        Catch ex As Exception
            Return False
        End Try