Thanks to your report, I just discovered a bug, or maybe a missing feature, that would allow to directly handle GH_Structure<specializedtype>
from GhPython compiled components (GHPYs
).
To be able to immediately consume this type of object (as you noticed, the only working one is the GH_Goo
type, which handles the most generic no-hint case), I wrote an additional static method that you can add to your class: structure_to_list
. Here is a fully sample that works with GH_Structure (the equivalent of DataTree outside of scripting components. This converts the structure to a list of lists, much easier to use in Python.
from ghpythonlib.componentbase import dotnetcompiledcomponent as component
import Grasshopper, GhPython
import System
import Rhino
import rhinoscriptsyntax as rs
import scriptcontext as sc
import ghpythonlib.treehelpers as tree
class Load(component):
def __new__(cls):
instance = Grasshopper.Kernel.GH_Component.__new__(cls,
"Load2", "Load2", """analyze objects""", "Params", "Util")
return instance
def get_ComponentGuid(self):
return System.Guid("7b7be4ce-e0ec-4f87-bf95-879ec3a98757")
def SetUpParam(self, p, name, nickname, description):
p.Name = name
p.NickName = nickname
p.Description = description
p.Optional = True
def RegisterInputParams(self, pManager):
p = Grasshopper.Kernel.Parameters.Param_Geometry()
self.SetUpParam(p, "O", "O", "all objects")
p.Access = Grasshopper.Kernel.GH_ParamAccess.tree
self.Params.Input.Add(p)
p = Grasshopper.Kernel.Parameters.Param_String()
self.SetUpParam(p, "T", "T", """option tag""")
p.Access = Grasshopper.Kernel.GH_ParamAccess.item
self.Params.Input.Add(p)
p = Grasshopper.Kernel.Parameters.Param_Boolean()
self.SetUpParam(p, "b", "b", "boolean")
p.Access = Grasshopper.Kernel.GH_ParamAccess.item
self.Params.Input.Add(p)
def RegisterOutputParams(self, pManager):
p = Grasshopper.Kernel.Parameters.Param_GenericObject()
self.SetUpParam(p, "a", "a", "Script output a.")
self.Params.Output.Add(p)
def SolveInstance(self, DA):
val, p0 = DA.GetDataTree[Grasshopper.Kernel.Types.IGH_GeometricGoo](0) #change to GH_String, GH_Brep,...
if p0: p0 = Load.structure_to_list(p0)
p1 = self.marshal.GetInput(DA, 1)
p2 = self.marshal.GetInput(DA, 2)
result = self.RunScript(p0, p1, p2)
if result is not None:
self.marshal.SetOutput(result, DA, 0, True)
# written by Giulio Piacentino, giulio@mcneel.com
@staticmethod
def structure_to_list(input, retrieve_base = lambda x: x[0]):
"""Returns a list representation of a Grasshopper DataTree"""
def extend_at(path, index, simple_input, rest_list):
target = path[index]
if len(rest_list) <= target: rest_list.extend([None]*(target-len(rest_list)+1))
if index == path.Length - 1:
rest_list[target] = list(simple_input)
else:
if rest_list[target] is None: rest_list[target] = []
extend_at(path, index+1, simple_input, rest_list[target])
all = []
for i in range(input.PathCount):
path = input.Path[i]
extend_at(path, 0, input.Branch[path], all)
return retrieve_base(all)
def RunScript(self, O, T, b):
# return outputs if you have them; here I try it for you:
return O
import GhPython
import System
class AssemblyInfo(GhPython.Assemblies.PythonAssemblyInfo):
def get_AssemblyName(self):
return "PyN"
def get_AssemblyDescription(self):
return """"""
def get_AssemblyVersion(self):
return "0.1"
def get_AuthorName(self):
return ""
def get_Id(self):
return System.Guid("d0adc7c0-d053-4da6-8cdf-f002c013a959")
Additionally, I am adding a bugfix that will permit to directly consume GH_Structures as datatrees from GHPYs in a new Service Release of Rhino 6.
You can track it here: RH-48754.
Thanks,
Giulio
–
Giulio Piacentino
for Robert McNeel & Associates
giulio@mcneel.com