Grasshopper

algorithmic modeling for Rhino

Using Custom Classes as Input Parameters to a GH Component

Hi

 

has anyone managed to use thir own custom class as an output parameter to a GH component?

 

I cant seem to do it and GH hangs after the pManage.Regsiter.Param method is called. Im running

0.6.0059.

 

Some psuedo code to get the ball rolling;

 

Namespace MyLibrary

Class MyClass

Inherits Grasshopper.Kernel.Types.GH_Goo

End Class

End Namespace

 

Now in the RegisterOutputParams sub.......................

 

Protected Overrides Sub RegisterOutputParams(ByVal pManager As GH_OutputParamManager)

Dim ghMyClassParameter As Grasshopper.Kernel.GH_Param(Of MyLibrary.MyClass)

pManager.RegisterParam(ghMyClassParameter, "MyClasses", "MC_P", "MyClass Output Parameters")

End Sub

 

It fails after execution of the regsiterparam method, i note that ghMyClassParameter has a value of null and have unsuccessfully tried casting from a new instance, say:

 

Dim myClass As New MyLibrary.MyClass

myClass.CastTo(ghMyClassParameter)

 

I still get a null instance for ghMyClassParameter

 

Cheers

 

 

 

 

 

 

 

 

Views: 2623

Replies to This Discussion

I've thought about doing this, but haven't tried at all.

My first two reactions, does your class implement the interface IGH_Param as required for the type provided to GH_OutputParamManager method to register an output? Even more likely to be sucessful would be to derive from an appropriate implemented class, else you may need to (and this may not be possible) implement your own method that the overloaded function calls.

I'm sure David will comment if this is even possible yet.

Cheers,

Jon
Hey jon, I'm trying the generic param option. I'm able to get
my custom data out as a list that way. I haven't checked yet to see if the output makes sense but at least something is now showing up in the output param of the component.
Adding your own types can be pretty daunting, a lot needs to be done, plus, this has changed somewhat in 0.7 (I tried making it a little bit easier).

Here's what you should do:

1) Create a new class that either implements IGH_Goo or which inherits from GH_Goo (in 0.7, GH_Goo will be a generic type so it will be GH_Goo(Of T)). Be sure to fill out all required fields.

2) Create a new class that either implements IGH_Param or which inherits from GH_Param(Of T), where T is the class you created under (1). Be sure to fill out all required fields.

You'll have to define both these classes in a component library, as they need to be available throughout Grasshopper. If you define them inside a Script component, nobody will know about them.

I'll add information to the SDK docs that deals with this, although probably not right away.

In the meantime, using a Generic Parameter (as you already found out) allows you to transfer data types that do not implement IGH_Goo. However, that is a last resort, since Grasshopper won't really know how to deal with that data, it'll try to ferry it around as best it can but the data will lack all the functions that will make it 'understandable'.

--
David Rutten
david@mcneel.com
Poprad, Slovakia
Hi Guys,

thanks for the replies. I managed to get what I wanted to do to work. I didnt use item 2 as suggested. Not sure why it is needed, can you explain?

So, my class was defined in an external VB class project and compiled as an external DLL. Within that class I made reference to

Inherits Grasshopper.Kernel.Types.GH_Goo

Now the pain here is that as i undersstand it multiple inheritance is not possible in VB.NET. So, i wasnt able to also inherit properites of my base class as I was forced to inherit the GH_Goo. Why isnt multiple inheritance possible?.

Within my GH Component class I then referenced teh external DLL and
Parameters do a little bit more than just wrap a tree of data items. Granted, there may be cases where you can get away without writing a dedicated parameter, but this will be a subset.

Multiple inheritance is evil. When you allow multiple inheritance you get into cases where the two (or more) base classes collide. It is confusing and ultimately does more harm than good.

GH_Goo is not meant to act as a data type (like Integer, String or On3dPoint). It is meant to wrap a Data type and provide formatting, conversion, preview display, baking and file IO functionality for that underlying type.

In 0.7 I've enforced this standard harder than before, and all native IGH_Goo derived types now have a Value property that gets or sets the 'internal' data.

--
David Rutten
david@mcneel.com
Poprad, Slovakia
You can only derive from one base class in dotNET, but you can implement multiple interfaces which may be a means to achieve something akin to multiple inheritence. (Convention is for interface types to start with I).

You might already have known this, thought I would throw it in there in case.
Hi David,

If you have a minute, can you advise on the best way to overload on inputs? Not overloading as in interpreting curves as a number according to length, but instead recognizing whether a curve, point or number is being fed into an input.

Here's my (perhaps ignorant) attempt:
pManager.Register_GenericParam("Node/CL", "NCL", "First Node or Curve CL", false);
............................................

if (DA.GetData(1, out cl) || DA.GetData(1, out np1) || DA.GetData(1, out n1))

It works fine, but the component goes red with a runtime error about an Invalid Cast (if the first attempt to extract a curve is not valid, or two errors if it is an integer).

Maybe I have to live with Red for this version of Grasshopper, but like everything else I've asked, you've probably already encountered this. Is there either a means to suppress or catch this run time message? Or a better way to overload the input?

Cheers Jon
Dear Jon,

I know that the Scripting components allow the user to specify a typehint, which may serve your purposes. This is how these components deal with checking the typehint and access level of an input:

For j as Integer = 0 to Me.Params.Input.Count - 1
If (Me.Params.Input(j).Access = GH_ParamAccess.list) Then...
...

Dim typeHint As IGH_TypeHint = DirectCast(Me.Params.Input.Item(i),_ Param_ScriptVariable).TypeHint
Dim newValue As String = "System.Object"
If (Not typeHint Is Nothing) Then
newValue = typeHint.TypeName
End If

I hope that helps, and surely David will be able to tell us whether one can check the type directly/overload the input.

Best regards,
Ben
Silly quesiton perhaps, but can any one shed light on what the GH_ParamAccess type is, and where you'd typically use it? The same applies to the Access method of "Me.Params.Input(j).Access,

cheers
Parameter access describes whether a parameter acts as a single item parameter, a list parameter or a tree parameter. It affects how the component handles input data, so it's important you set it up correctly.

For example, the Polyline component requires a list of points to work, so it must set the P input parameter access to List. Then, inside SolveInstance(), you must call DA.GetDataList() instead of DA.GetData (you'll get an exception if you don't).

You'll almost never need Tree access, but List is quite common.

--
David Rutten
david@mcneel.com
London, UK
Hi Everyone,

I'm trying to create my own data type that can be passed between components. If I were doing this within a single custom component, I would set up a new structure above the sub like this:

Structure construction
surface As Surface
number As Integer
description As String
...
End Structure

Of course, I'd like to register this structure as an input/output parameter so it can be passed between components, and I'm trying to follow this thread on the topic, but I'm a bit confused. Does the multiple-inheritance issue mean I can't create a parameter that wraps more than one GH type?

Thanks,

Jon
Hi Jon,

I've been writing an SDK Helpfile topic about creating your own data-types and wrapper parameters. I won't release the new Docs until the next Grasshopper hits the scene (sometime this week I hope).

There's quite a lot of stuff you need to do to add a Data type to Grasshopper. First of all, your data type must implement IGH_Goo. Or you could derive from GH_Goo(Of T), where T is your Structure. Then implements all the required methods and properties.

Once you have a class that implements IGH_Goo and that contains all your fields, you'll need to make a parameter for it. This is as easy as deriving a class from GH_Param(Of T) where T is your new IGH_Goo type. This will give you the most basic data exposure.

But, as I said, there's a lot to writing a good Data Type, and you'll have to wait until the next SDK chm is released.

Another solution (in the meantime) would be to serialize your data to a string and then use String parameters for inter-component communication. But I can see that's not really an option if you're using Surfaces.

--
David Rutten
david@mcneel.com
Poprad, Slovakia

RSS

About

Translate

Search

Videos

  • Add Videos
  • View All

© 2024   Created by Scott Davidson.   Powered by

Badges  |  Report an Issue  |  Terms of Service