Today we have a special guest post from my colleague and friend Fraser Greenroyd. Fraser is the team’s resident computer scientist, and as such he is subject to the daily brunt of my programming woes. Here he recounts one of the many challenges we face in another day of beating Grasshopper into submission…
How often do you think “this won’t take more than a few minutes to figure out” and then spend far longer solving the problem? For me, that happens on an almost daily basis in my work with James, and today was no exception. Starting with a simple “before you sit down” question, James and I spent an hour traversing the inheritance of Grasshopper to solve one problem – accessing the DataMapping property of any plugged in component.
To begin with, James had created a C# component that read the component plugged into the inputs and checked if it was a ‘Num’ component. From there, he was able to output the DataMapping type, but the code doing this limited the functionality to only the ‘Num’ component. Useless for any other type.
It was recognised that, as multiple components shared similar data members, the chances of them inheriting from a single class were high, but knowing which class was, to begin with, tricky. This was compounded by the fact that I am a Computer Scientist, I’ve been programming for years and am used to reading and digesting well written SDKs but it appears the Grasshopper SDK is not well written. But never-the-less, James took me to the beginning steps and from there we began a journey up and down the inheritance tree until we stumbled upon GH_Param – a class housing such members as the Description, DataMapping and VolatileData. Â Further up the tree, this inherited from the GH_DocumentObject class which meant access to this generic class should be possible from the bottom level of a component.
Our goal – seems simple, no?
The majority of the hour we spent on this was looking at the SDK and figuring out where we needed to be on the inheritance tree. The minority was the actual nice bit – coding. Our initial development, which was based on James’ first piece of code for the ‘Num’ component gave us a bit of a headache when the GH_Param<T> didn’t like the type we supplied. Unfortunately, the not so well written documentation did not reveal what type we needed but through some trial and error we found it to be the IGH_Goo type.
If you’re a developer, you’ll know only too well the scent of victory drawing ever closer as you change lines here and there, and the sheer frustration when it won’t compile, or doesn’t provide the output you expect. For James and I, we reached this point when the code compiled but the output wasn’t the correct DataMapping for the component plugged in. Thankfully, this did not last long as, not being a Grasshopper developer, it transpired I had forgotten to make use of the ‘sources’ of the inputs.
The final code, included in this post does not do credit to the journey we went on. From an original 30 lines of code, James was able to condense what we needed into two lines (I would have condensed it into one but that’s another story). The source code supplied here allows you to access the DataMapping variable for the first component plugged into the input side of a component, but can be easily extended using lists to include all components plugged in OR, with some clever use of the GH_DocumentObject any component on the canvas (but whether that would be useful is up for debate).
However, if you take just one thing away from this post let it be this – if you ever have to write SDK documentation, for the sanity of those using it write it properly and write it well!
Grasshopper.Kernel.IGH_Param param = Component.Params.Input[0].Sources[0]; A = param.DataMapping; or A = ((Grasshopper.Kernal.IGH_Param)Component.Params.Input[0].Sources[0]).DataMapping;