|
| 1 | +import sys |
| 2 | + |
| 3 | +if sys.platform != "cli": |
| 4 | + raise(RuntimeError, "This module is only intended to be run in Rhino Python") |
| 5 | + |
| 6 | +import clr |
| 7 | + |
| 8 | +clr.AddReference('Grasshopper, Culture=neutral, PublicKeyToken=dda4f5ec2cd80803') |
| 9 | + |
| 10 | +import System |
| 11 | +import Rhino |
| 12 | +import Grasshopper as gh |
| 13 | +import sys |
| 14 | +import re |
| 15 | + |
| 16 | +from System.Collections import IEnumerable, IEnumerator |
| 17 | + |
| 18 | + |
| 19 | +class namespace_object(object): |
| 20 | + pass |
| 21 | + |
| 22 | + |
| 23 | +def __make_function_uo__(helper): |
| 24 | + def component_function(*args, **kwargs): |
| 25 | + comp = helper.proxy.CreateInstance() |
| 26 | + comp.ClearData() |
| 27 | + if args: |
| 28 | + for i, arg in enumerate(args): |
| 29 | + if arg is None: continue |
| 30 | + param = comp.Params.Input[i] |
| 31 | + param.PersistentData.Clear() |
| 32 | + if hasattr(arg, '__iter__'): # TODO deal with polyline, str |
| 33 | + [param.AddPersistentData(a) for a in arg] |
| 34 | + else: |
| 35 | + param.AddPersistentData(arg) |
| 36 | + if kwargs: |
| 37 | + for param in comp.Params.Input: |
| 38 | + name = param.Name.lower() |
| 39 | + if name in kwargs: |
| 40 | + param.PersistentData.Clear() |
| 41 | + arg = kwargs[name] |
| 42 | + if hasattr(arg, '__iter__'): # TODO deal with polyline, str |
| 43 | + [param.AddPersistentData(a) for a in arg] |
| 44 | + else: |
| 45 | + param.AddPersistentData(arg) |
| 46 | + doc = gh.Kernel.GH_Document() |
| 47 | + doc.AddObject(comp, False, 0) |
| 48 | + comp.CollectData() |
| 49 | + comp.ComputeData() |
| 50 | + output = helper.create_output(comp.Params) |
| 51 | + comp.ClearData() |
| 52 | + doc.Dispose() |
| 53 | + return output |
| 54 | + |
| 55 | + return component_function |
| 56 | + |
| 57 | + |
| 58 | +class function_helper(object): |
| 59 | + def __init__(self, proxy, name): |
| 60 | + self.proxy = proxy |
| 61 | + self.return_type = None |
| 62 | + |
| 63 | + def create_output(self, params, output_values=None): |
| 64 | + if not output_values: |
| 65 | + output_values = [] |
| 66 | + for output in params.Output: |
| 67 | + data = output.VolatileData.AllData(True) |
| 68 | + # We could call Value, but ScriptVariable seems to do a better job |
| 69 | + v = [x.ScriptVariable() for x in data] |
| 70 | + if len(v) < 1: |
| 71 | + output_values.append(None) |
| 72 | + elif len(v) == 1: |
| 73 | + output_values.append(v[0]) |
| 74 | + else: |
| 75 | + output_values.append(v) |
| 76 | + if len(output_values) == 1: return output_values[0] |
| 77 | + if self.return_type is None: |
| 78 | + names = [output.Name.lower() for output in params.Output] |
| 79 | + try: |
| 80 | + self.return_type = namedtuple('Output', names, rename=True) |
| 81 | + except: |
| 82 | + self.return_type = False |
| 83 | + if not self.return_type: return output_values |
| 84 | + return self.return_type(*output_values) |
| 85 | + |
| 86 | + def runfast(self, args, kwargs): |
| 87 | + return False, None |
| 88 | + |
| 89 | + |
| 90 | +def __build_module_uo(): |
| 91 | + core_module = sys.modules[__name__] |
| 92 | + translate_from = u"|+-*\u2070\u00B9\u00B2\u00B3\u2074\u2075\u2076\u2077\u2078\u2079" |
| 93 | + translate_to = "X__x0123456789" |
| 94 | + transl = dict(zip(translate_from, translate_to)) |
| 95 | + |
| 96 | + def regex_helper(match): |
| 97 | + if match.group() in transl: |
| 98 | + return transl[match.group()] |
| 99 | + return '' |
| 100 | + |
| 101 | + def function_description(description, params): |
| 102 | + rc = ['', description, "Input:"] |
| 103 | + for param in params.Input: |
| 104 | + s = "\t{0} [{1}] - {2}" |
| 105 | + if param.Optional: |
| 106 | + s = "\t{0} (in, optional) [{1}] - {2}" |
| 107 | + rc.append(s.format(param.Name.lower(), param.TypeName, param.Description)) |
| 108 | + if params.Output.Count == 1: |
| 109 | + param = params.Output[0] |
| 110 | + rc.append("Returns: [{0}] - {1}".format(param.TypeName, param.Description)) |
| 111 | + elif params.Output.Count > 1: |
| 112 | + rc.append("Returns:") |
| 113 | + for out in params.Output: |
| 114 | + s = "\t{0} [{1}] - {2}" |
| 115 | + rc.append(s.format(out.Name.lower(), out.TypeName, out.Description)) |
| 116 | + return '\n'.join(rc) |
| 117 | + |
| 118 | + for obj in gh.Instances.ComponentServer.ObjectProxies: |
| 119 | + if obj.Exposure == gh.Kernel.GH_Exposure.hidden or obj.Obsolete: |
| 120 | + continue |
| 121 | + |
| 122 | + t = clr.GetClrType(gh.Kernel.IGH_Component) |
| 123 | + library_id = obj.LibraryGuid |
| 124 | + assembly = gh.Instances.ComponentServer.FindAssembly(library_id) |
| 125 | + name = obj.Desc.Name |
| 126 | + |
| 127 | + if "LEGACY" in name or "#" in name: |
| 128 | + continue |
| 129 | + name = re.sub("[^a-zA-Z0-9]", regex_helper, name) |
| 130 | + if not name[0].isalpha(): |
| 131 | + name = 'x' + name |
| 132 | + |
| 133 | + m = core_module |
| 134 | + if assembly is None: |
| 135 | + # UserObjects |
| 136 | + pass |
| 137 | + elif not (t.IsAssignableFrom(obj.Type)): |
| 138 | + # Specialized inputs/outputs and misconfigured components |
| 139 | + # Discard |
| 140 | + continue |
| 141 | + elif not assembly.IsCoreLibrary: |
| 142 | + # Compiled components, leave them to ghpythonlib |
| 143 | + continue |
| 144 | + |
| 145 | + function = __make_function_uo__(function_helper(obj, name)) |
| 146 | + try: |
| 147 | + setattr(m, name, function) |
| 148 | + a = m.__dict__[name] |
| 149 | + a.__name__ = name |
| 150 | + comp = obj.CreateInstance() |
| 151 | + a.__doc__ = function_description(obj.Desc.Description, comp.Params) |
| 152 | + except Exception as err: |
| 153 | + Rhino.RhinoApp.WriteLine(str(err)) |
| 154 | + Rhino.Runtime.HostUtils.ExceptionReport("ghpythonlib.components.py|" + name, |
| 155 | + err.clsException) |
| 156 | + |
| 157 | + |
| 158 | +__build_module_uo() |
0 commit comments