generative modeling for Rhino
Hi all, I'm learning about deep copy, but I dont know if that is what I need to do:
I'm using only the custom VB.net components in GH. I would open up the script editor and type my own stuff. I realized that when an object is passed outside that component, the object is pass as reference.
The object's variable is not behaving what I would expect.
For example, I created a class in one VB component:
Public Class NumberObj
Public X As Integer
Public Sub New()
X = 0
I then created that object and passed it out from the component:
I modified that object in another component, changing X to something else.
In the code shown below (just as example). I slide the slider around, and every time I move the slider, the value keep adding up. Obviously the programme keeps all objects in memory. It is not until I press recompute that everything reset.
What should the proper way of handling this? Should I do a deep copy every time I take an object into an VB component before making changes. I don't know how to do that yet.
In my normal use, my object are actually in a List (of myObjects), I'm assuming to make a deep copy of that is more difficult.
Thanks in adv.
typical .NET classes do not have a standard mechanism for creating duplicates. This is one of the reasons why all data in Grasshopper needs to implement the IGH_Goo interface, because IGH_Goo specifically declares a Duplicate function that allows me to pass safe instances of data to different components in the knowledge that changes to one instance will not 'contaminate' other instances elsewhere, i.e. exactly what you are seeing.
The reason you're seeing it is because your class NumberObj does not implement IGH_Goo and therefore must be wrapped at the last possible moment into a class that does (one of my own, used only as a last resort). This wrapper class however does not know how to duplicate your NumberObj instance, so you end up with the same instance being shared amongst all components and all iterations.
Sharing classes between VB components is actually quite a fragile approach anyway because Script #2 doesn't actually 'know' about the class as it wasn't defined within scope. The only reason it works is because VB is trying to be helpful and interpret your code as best it can.
If you want your own data type, I highly recommend one of two approaches:
Hi David, thank you for the explanation, I have never written a GHA library, but now I decide to learn. My objects are far more complex then that example, so serialization is a bit difficult. I noticed the GHA assembly wizard, and I'll give it a try. I have some experience writing VB.net stuff in Visual Studio Express.
Is there any description of the interface IGH_Goo or GH_Goo<T>, I'm downloading the GrasshopperSDK.chm
By the way, is it true that if I write my GHA library, when I update a new component, changed the code, I have a way to use the tool "Upgrade Legacy Component" to upgrade components that are old? I'm now having to change them one by one if I made changes.
Yes, the SDK helpfile has a help topic on "Simple Data Types" which deals with IGH_Goo and GH_Goo<T>.
Yes, it is possible to write an automatic upgrader, but it's still quite difficult. I'm looking for ways to make it easier to use as a developer.
Hi David and all,
I have tried both option you suggested, I have two concerns.
1. I tried writing a custom class definition in VisualStudio and compiling it to a GHA library, however I realized that I wont be able to use that class in the custom VB component in GH. Since I find the VB component much quicker to be modified and I need to work with other people. I want other to access that class without touching the GHA Library. Is it possible to access those classes inside GH, within those custom VB component?
What I did is:
Public Class MyCustomClass
Inherits Grasshopper.Kernel.Types.GH_Goo(Of MyCustomClass)
Public Overrides Function Duplicate() As Grasshopper.Kernel.Types.IGH_Goo
Public Overrides ReadOnly Property IsValid As Boolean
Public Overrides Function ToString() As String
Public Overrides ReadOnly Property TypeDescription As String
Public Overrides ReadOnly Property TypeName As String
2. I also tried the XMLSerializer method,. I wrote my class definition inside GH custom VB component. I can serialize them into xml streams and deserialize them in another custom VB component. However, I will have to paste my class definition everywhere in all the custom VB components, and that cause a maintenance issue when I have to change them. Any suggestion?
Thanks a lot.
An update of this :
I have find a work around that worked for me, creating a custom class and duplicating it. In case anyone whats to do something similar this might be helpful.
The workaround is simple, you need to write your own duplicate function inside your class, to handle the deep copy.
Public Class car
Public Name As String
Public Year As Integer
Public Sub New()
Public ReadOnly Property Age As Integer
Return datetime.Now.Year - Year
Public Function Duplicate() As car
Dim duplicatedCar As New car
duplicatedCar.Name = Name
duplicatedCar.Year = Year
Then, whenever you use the object in another VB component, do the duplicate first.
Attached is an example file.