Custom Type can it be done from GH_Python?

Hi,

Can someone give me a simple example how can I create custom type to come out of GH_Python component and then another GH_Python which is accepting only that custom type?

Is this possible to implement from within grasshopper or do I have to do this by setting up a VisualStudio project?

Simple example could be just a box that passes itself and its volume as a single stream of data (a custom type) to another component.

Thanks in advance.

I can’t answer to python, but for C# only part of this is possible.

You can create a new type inside a script component which implements IGH_Goo or one of its derived types/interfaces. This type will be treated by Grasshopper the way it treats all data. Provided you wrote code for it, this type can be baked, previewed, converted into other types, formatted.
It will not be possible however to deserialize the data, as Grasshopper won’t know where to start looking for the class when it is asked to read one of these in from a file.

The problem is that a different script component won’t have access to the same type definition (because it was declared in an assembly it has no references to), and so it cannot convert it into something it can use. This part may work in Python what with the duck-typing, I don’t know.

If you wish to send data from one script component to another, you have the following options in C#:

  1. Use an existing type, for example string. A lot of data could be converted from and to strings, so this allows you to exchange data through regular channels. However it may not be possible in some cases, or may be so involved/expensive that it’s not worth the effort.

  2. Use a framework type which is accessible from both components, for example SortedDictionary<int, byte[]>. Both components have access to the type declaration so casting is no issue. To exchange an instance which does not implement IGH_Goo, you should wrap it up inside a GH_ObjectWrapper. That will prevent Grasshopper from trying to interpret your data and possibly changing it.

  3. Create a dll using Visual Studio which declares the type and reference this dll from both script components. But at this point why not do everything in VS?

  4. Write the data to a file on the disk and only share the file location. The other component then reads the data from the disk. This is a bit of a hack though and leads to potential conflicts or collisions.

You can pass anything you like (custom class instances, functions, nested lists, dictionaries etc) between GHPython components, by setting the input parameter type hint to No Type Hint. This is actually one of the things I really like/prefer about GHPython (as opposed to the other scripting components, if I understand how they work accurately). This can also aid in severely speeding things up by not casting/exposing large chunks of data to the GH canvas.

1 Like

Hi @ivelin.peychev

  1. you can store definitions of types in the sticky dictionary and use them from any GhPython component that resolves after that one.
    http://developer.rhino3d.com/guides/rhinopython/ghpython-global-sticky/

  2. Another option is to just use duck typing. In the example, as long as the class has a “welcome” method that accepts no parameters, it will work.

This example shows both ways:

pass-types.gh (4.9 KB)

Thanks,

Giulio


Giulio Piacentino
for Robert McNeel & Associates
giulio@mcneel.com

2 Likes

Thansk Giulio, Anders, David,

This is very helpful.

So in fact not passing the results as such (the class attributes and methods results) but rather passing the class itself to the output is the way to dealing with custom types.

Kind Regards,
Ivelin

You can both pass the class or the instance, using Python.

Thanks

Giulio

@piac, can I change the name displayed on a panel connected to the output?

2018-06-09%2018_46_41-Grasshopper%20-%20pass-types_

If you inherit from object, it will look better I think (I am away from keyboard, cannot check).

Otherwise, you can override the def ToString(self) method and provide the text you need.

Giulio

It’s ok, whenever you have time.

I’m attaching an example.
I have two problems:

  1. Displaying custom name (e.g. customCylinder)
  2. I got Goo coming out, but I have no visual representation coming out of the class. How can I do that?

Thanks in advance.

You should follow what @piac suggested and override ToString method. Also you should initiate the class and output an instance of the class and not the class itself.

Thanks Mostapha,

I tried but I didn’t quite understand what he meant by “override”. As I see it now, I just didn’t add the “return”.

Still doesn’t work with my example, don’t know why
EDIT:
my bad, it worked :slight_smile:

GH.TST.gh (11.7 KB)

How will CastTo override look in python?

def CastTo:
    return ?

Where can I find a list of all the functions that can be “overridden” inside a custom type?

Not sure what your goals are but it looks like you’re trying to cast a method. Could you hold an instance of the cylinder you’re creating and return it?

    def CastTo(self):
        return self.__cylinder

This is not working for any custom type. This will only work for types that implement the interface.
You can see an example of a custom-bakeable entity here:

Please kindly read IronPython in Action, as gently mentioned last week. We unfortunately do not have the resources to distill a whole book, one question at a time.

A .Net interface (such as IGH_GeometricGoo) contains all methods and properties that can be overriden. For methods of a .Net class, methods and properties marked with virtual or override or abstract can be overriden. Python can mask all function names.

2 Likes

Thanks for the help, but what does this had to do with what I’m asking? I’m asking RhinoCommon / GH specific types. I doubt I can find GOO inside “IronPython in action”
I assume some objects can return GeometricGoo some don’t.
When I was “swimming” through the Grasshopper api i found RefObject, with no explanation whatsoever where can I get it. I assume it’s coming from RhinoCommon or RhinoPythonScript but… since there’s no example how can I figure that out. I’m not a programmer and never will become one. I use “IronPython in Action” as a reference this is how I got this far. (I got the goo). I’ll try what @Alain said when I got back home.

EDIT:
If there was a template for creating “custom GH Brep type”, “custom GH Geometry type”, “custom GH tree type”, “custom GH vector type”, etc. and more python examples in the API I wouldn’t have to ask so many stupid (for you) questions.

Thanks @Alain.

This page from the _GrasshopperSDKDocumentation command probably answers the question you ask from the Grasshopper-SDK perspective. Also available online.

But there is no need to (and we actually hope that you do not) create a ‘custom Brep type’ unless you actually create a new geometry type.

So, for custom ‘Brep’ type, there is no guide. Custom DataTree is not possible in any language because Grasshopper expects its own trees. There is an example with a new data type ‘tristate’, in the Grasshopper SDK documentation, that I linked above. Also, there is an example in Python with a bakable data type in the link I sent before.


Alain’s answer is generic (because your question was generic), but it won’t mean something for the Grasshopper UI. It may mean something for your (future) components.

In reality, your questions regarding custom types can be entirely Grasshopper-SDK-free. You can just add the types you need, and as long as your components understand each other, they will work perfectly fine with one another.

If you want to program such an operation, you need to learn first. And inevitably you’ll be a developer.

Arguably you are now one already. Just a novice one.

EDIT: see also this page:

Did that, I probably went through everything related to goo on developer.rhino3d.com

I was getting errors when I try to use CastTo

Or Grashopper/something/something/Convert.ToGeometricGoo (or whaever else)

All I saw was C# and VB examples, and not examples but rather syntax, not explaining anything.

here’s the latest version of my test script GH.TST.customType.py.gh (12.8 KB)

I was printing a lot of things trying to understand what does RefObject require in order to do the Convert or the CastTo

EDIT:
I do not understand why this:

2018-06-11%2016_59_43-Grasshopper%20SDK

returns Bool instead of Brep?
Logic implies a ConvertTo should result in the product of the conversion and not True or False. If Convert coins ToBankNotes and the result = 0 or 1. The World will bankrupt.

It means that the operation failed, or succeeded.

The explanation is

True = Succeeded
False = Failed.

If the result was “False”, then don’t try to use the rc Brep, because it’s value can be rubbish. Only if the function returns True you can use rc and expect it to be meaningful.

Please.

// Rolf

I’ve never used the GH_Convert class before, but notice the “ref” keyword in the function signature, that means to pass in a Brep object by reference, which the method will then modify in-place. Something like this in C#:

Brep my_brep = null;
bool result = GH_Convert.ToBrep(data, ref my_brep, GH_Conversion.Primary);
if (result){
  do_stuff_with( my_brep );
}

IronPython doesn’t support this syntax directly and has some other mechanism of doing so, you’ll have to search around for the specifics.

1st result on Google:

Yes, instead of returning a single item, in these cases IronPython returns a tuple with (bool, my_brep).

If you need to override a method that takes a by-reference parameter, the input variable will be like the result of clr.Reference(), which is an instance of the type System.StrongBox.