Hi,
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.
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:
'SetProperties
' 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
geometry.Add(rhinoObject.Geometry)
attributes.Add(rhinoObject.Attributes)
End If
End If
Next i
'Create the GPoint
Dim MyGPoint As New Point(GBlockDefData.GLocationDefinition)
Dim MyGPointXform As Rhino.Geometry.Transform = MyBlockInstGeometry.Xform
MyGPointXform.TryGetInverse(MyGPointXform)
MyGPoint.Transform(MyGPointXform)
Dim attr As New ObjectAttributes()
attr.Name = "GPointDefinition"
attr.ColorSource = ObjectColorSource.ColorFromObject
attr.ObjectColor = Drawing.Color.Red
attr.PlotWeight = -1
MyGPoint.UserData.Add(GBlockDefData)
geometry.Add(MyGPoint)
attributes.Add(attr)
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
Else
Dim MyGPointDef As Point = TryCast(rhinoObject.Geometry, Point)
If MyGPointDef Is Nothing Then Return False
MyGPointDef.Transform(MyBlockInstGeometry.Xform)
GBlockInstanceLocation = MyGPointDef.Location
data = MyGBlockData
Return True
End If
End If
End If
Next i
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?
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)
Hi,
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
Try
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