I save user data on PointGeometry.
there is no method to replace the point geometry.
help please…
I save user data on PointGeometry.
there is no method to replace the point geometry.
help please…
Hi @dale,
I am unable to get the sample to work successfully by using the userdata to store a list of guids
the undo does not revert the list in the userdata back to the previous list.
the string is reverted.
Kindly check and let me know how to handle this.
In the project, review these sample files:
SampleCsAddUserData.cs
SampleCsModifyUserData.cs
SampleCsRemoveUserData.cs
– Dale
Kindly identify what’s wrong.
SampleCsUserDataObject.cs (2.4 KB)
SampleCsAddUserData.cs (2.0 KB)
SampleCsModifyUserData.cs (2.0 KB)
Its the same files from the sample project but included a list.
steps:
the object still has 2 ids.
I have used the dictionary so that i can have multiple guid list.
Make sure your user data’s OnDuplicate
actucally copies the data, not just the reference to the data.
SampleCsUserDataObject.cs (2.1 KB)
– Dale
Hi @dale,
Your samples have helped a lot. Thank you.
You have used the UserData in the attributes and used the following line to override it,
doc.Objects.ModifyAttributes(obj, new_attributes, true);
If I intend to use the UserData in the geometry to save data, I assume it has to be
doc.Objects.Replace(obj.Id, new_geometry);
But this returns false.
How can the userdata in geometry be used successfully?
Also, I save user data on PointGeometry.
there is no method to replace the point geometry.
Hi @HepChan,
Can you provide the source code that is not working for you?
Yes, this is true. This has been resolved in the Rhino WIP.
– Dale
I figured that this line in the code before the replacement makes it to return false.
ObjectAttributes oa = new ObjectAttributes();
oa.Mode = ObjectMode.Hidden;
obj.Attributes = oa;
obj.CommitChanges();
SampleCsModifyUserData.cs (3.1 KB)
Why cant the geometry be replaced on a hidden object?
is there any other way to achieve the hiding before the replacement.
Hi @dale
Any help on this?
Hi @HepChan,
If I understand correctly, you want to attached a piece of user data to selected object and then hide the object. Is this correct?
Why do you need to attach user data to geometry and not to the object’s attributes?
– Dale
The real requirement is, I want to modify the user data of a hidden object (which fails).
is there specific criteria which user data to be used??
I chose geometry as i use the commands on the geometry of the objects.
In general, we try to encourage developers to attach user data to an object’s attributes, rather than it’s geometry, as it tends to survive “better”.
But if you want to attached user data and hide the object too, then replace the object’s geometry first and then modify the attributes to hide it (rather than the opposite order you are trying now).
– Dale
Hi @dale ,
Sorry to revive this old topic but I’m trying to figure out how to handle undo for user data and I’m stuck.
My original code works fine except for undos (with RBT_BeamDataClass Inheriting Custom.UserData):
Public Shared Function WriteToObject(ByRef BeamRHObject As RhinoObject, ByVal BeamData As RBT_BeamDataClass) As Boolean
If BeamRHObject Is Nothing OrElse BeamRHObject.ObjectType <> DocObjects.ObjectType.Curve Then Return False
Return BeamRHObject.Attributes.UserData.Add(BeamData) Or BeamRHObject.Geometry.UserData.Add(BeamData)
End Function
I am trying to use instead the ObjectTable functions as you suggested, but with no success:
Public Shared Function WriteToObject(ByRef BeamRHObject As RhinoObject, ByVal BeamData As RBT_BeamDataClass) As Boolean
If BeamRHObject Is Nothing OrElse BeamRHObject.ObjectType <> DocObjects.ObjectType.Curve Then Return False
'Alternative method to handle Rhino's undo feature
Dim Geom As Curve = DirectCast(BeamRHObject.Geometry.Duplicate, Curve)
If Not Geom.UserData.Add(BeamData) Then Return False
If Not BeamRHObject.Document.Objects.Replace(BeamRHObject.Id, Geom) Then Return False
Dim attr As ObjectAttributes = BeamRHObject.Attributes.Duplicate
If Not attr.UserData.Add(BeamData) Then Return False
If Not BeamRHObject.Document.Objects.ModifyAttributes(BeamRHObject.Id, attr, True) Then Return False
Return True
End Function
Any idea on what goes wrong? Could it be because my code is not always run from a command?
Hi @TOMKOD-Matthieu,
If your WriteToObject
function isn’t called by a command’s RunScript
method, then you need to handle undo recording yourself.
Public Shared Function TestUndoRecording(obj As RhinoObject) As Boolean
Dim rc As Boolean
If (obj IsNot Nothing) Then
Dim doc As RhinoDoc = obj.Document
If (doc IsNot Nothing) Then
Dim sn = doc.BeginUndoRecord("Setting user string")
Dim attrib As ObjectAttributes = obj.Attributes.Duplicate
attrib.SetUserString("Test", "Hello Rhino!")
rc = doc.Objects.ModifyAttributes(obj.Id, attrib, True)
If (sn > 0) Then
doc.EndUndoRecord(sn)
End If
End If
End If
Return rc
End Function
Does this help?
– Dale
Hi @dale, your sample works indeed for user strings, but for my class inheriting from Rhino.DocObjects.Custom.UserData
it fails: instead of restoring the previous data, undoing just clear the data.
EDIT: Ok I’ve managed to make it work. Two things were causing issues:
In my former code, I was just casting and editing my existing custom userdata before applying it back to the object. Apparently it is not possible if I want to manage the undos, I need to instanciate a new userdata instance.
attrib.UserData.Add(NodeData)
won’t work the the attributes already contains a UserData of the same type. I have to remove it beforehand, then it works:
If attrib.UserData.Contains(New Guid("MyUserDataGuid")) Then
attrib.UserData.Remove(attrib.UserData.Find(GetType(RBT_NodeDataClass)))
End If
If Not attrib.UserData.Add(NodeData) Then Return False
Hi @dale, This approach works for RhinoObject, but what would be the best approach if I am adding UserData to InstanceDefinition, and then I want to undo?
Currently, I am creating an entirely new InstanceDefinition, adding UserData to it, and deleting the old InstanceDefinition (and then renaming the new one with same name as old one).
Is there a better way? If not, would it be convenient to provide a method to do this in the future? Something like InstanceDefinitionTable.ModifyUserData() ?