def pybind_get_prop_type(handle, propname, prop_type): instance = ffi.from_handle(handle) prop = instance._exported.get(ffi.string(propname), None) if not prop: return False else: prop_type[0] = prop.gd_type return True
def pybind_set_prop(handle, propname, val): instance = ffi.from_handle(handle) try: pyval = variant_to_pyobj(val) setattr(instance, ffi.string(propname), pyval) return True except Exception: traceback.print_exc() return False
def pybind_get_prop_default_value(handle, propname, r_val): cls_or_instance = ffi.from_handle(handle) cls = cls_or_instance if isinstance(cls_or_instance, type) else type(cls_or_instance) prop = cls.__exported.get(ffi.string(propname), None) if not prop: return False pyobj_to_variant(prop.default, r_val) return True
def pybind_get_prop(handle, propname, ret): instance = ffi.from_handle(handle) try: pyret = getattr(instance, ffi.string(propname)) pyobj_to_variant(pyret, ret) return True except Exception: traceback.print_exc() return False
def pybind_init_sys_path_and_argv(pythonpath, res_path, data_path): pythonpath = ffi.string(pythonpath) res_path = ffi.string(res_path) data_path = ffi.string(data_path) import sys from godot.bindings import OS sys.argv = ["godot"] + OS.get_cmdline_args() for p in pythonpath.split(';'): if p.startswith("res://"): p = p.replace("res:/", res_path, 1) elif p.startswith("user://"): p = p.replace("user:/", data_path, 1) sys.path.append(p) print('PYTHON_PATH: %s' % sys.path) return True
def get_parent_class(cls, classname): ret = godot_string_alloc() lib.godot_string_new(ret) gd_classname = godot_string_from_pyobj(classname) args = ffi.new("godot_string**", gd_classname) lib.godot_method_bind_ptrcall(cls._meth_get_parent_class, cls._instance, ffi.cast("void**", args), ret) raw_str = lib.godot_string_wide_str(ret) return ffi.string(raw_str)
def pybind_get_meth_info(handle, methname, r_argcount): cls_or_instance = ffi.from_handle(handle) cls = cls_or_instance if isinstance(cls_or_instance, type) else type(cls_or_instance) meth = getattr(cls, ffi.string(methname), None) if not meth: return False spec = inspect.getfullargspec(meth) # Cannot pass keyword only arguments through godot r_argcount[0] = len(spec.args) return True
def pybind_get_prop_info(handle, propname, r_prop_info): cls_or_instance = ffi.from_handle(handle) cls = cls_or_instance if isinstance(cls_or_instance, type) else type(cls_or_instance) prop = cls.__exported.get(ffi.string(propname), None) if not prop: return False r_prop_info.type = prop.gd_type r_prop_info.hint = prop.gd_hint r_prop_info.name = prop.gd_name[0] r_prop_info.hint_string = prop.gd_hint_string[0] r_prop_info.usage = prop.gd_usage return True
def pybind_get_rpc_mode(handle, methname): cls_or_instance = ffi.from_handle(handle) cls = cls_or_instance if isinstance(cls_or_instance, type) else type(cls_or_instance) # TODO: it seems if gdstript find a method with RPC_MODE_DISABLED, it tries # to find a parent with rpc enabled... for parentcls in inspect.getmro(cls): try: mode = parentcls.__dict__[ffi.string(methname)].__rpc if mode != lib.GODOT_METHOD_RPC_MODE_DISABLED: return mode except (KeyError, AttributeError): pass return lib.GODOT_METHOD_RPC_MODE_DISABLED
def get_class_consts(cls, classname): consts = [] ret = godot_pool_string_array_alloc() lib.godot_pool_string_array_new(ret) gd_classname = godot_string_from_pyobj(classname) gd_true = godot_bool_alloc(True) args = ffi.new("void*[2]", [gd_classname, gd_true]) # 2nd arg should be false, which what we get by not initializing it lib.godot_method_bind_ptrcall(cls._meth_get_integer_constant_list, cls._instance, args, ret) for i in range(lib.godot_pool_string_array_size(ret)): godot_str = lib.godot_pool_string_array_get(ret, i) raw_str = lib.godot_string_wide_str(ffi.addressof(godot_str)) consts.append(ffi.string(raw_str)) return consts
def pybind_call_meth(handle, methname, args, argcount, ret, error): instance = ffi.from_handle(handle) try: meth = getattr(instance, ffi.string(methname)) except AttributeError: error[0] = CALL_METH_ERROR_INVALID_METHOD return # print('[GD->PY] Calling %s on %s ==> %s' % (ffi.string(methname), instance, meth)) pyargs = [variant_to_pyobj(args[i]) for i in range(argcount)] # error is an hacky int compressing Variant::CallError values try: pyret = meth(*pyargs) pyobj_to_variant(pyret, ret) error[0] = CALL_METH_OK except NotImplementedError: error[0] = CALL_METH_ERROR_INVALID_METHOD except TypeError: traceback.print_exc() error[0] = 1 | CALL_METH_ERROR_INVALID_ARGUMENT | CALL_METH_TYPE_NIL
def get_class_list(cls): ret = godot_pool_string_array_alloc() lib.godot_method_bind_ptrcall(cls._meth_get_class_list, cls._instance, ffi.NULL, ret) # Convert Godot return into Python civilized stuff unordered = [] for i in range(lib.godot_pool_string_array_size(ret)): godot_str = lib.godot_pool_string_array_get(ret, i) raw_str = lib.godot_string_wide_str(ffi.addressof(godot_str)) unordered.append(ffi.string(raw_str)) # Order class to have a parent defined before their children classes = [] while len(unordered) != len(classes): for classname in unordered: parentname = cls.get_parent_class(classname) if not parentname or parentname in classes: if classname not in classes: classes.append(classname) return classes
def pybind_load_exposed_class_per_module(modname): modname = ffi.string(modname) __import__(modname) # Force lazy loading of the module cls = get_exposed_class_per_module(modname) return connect_handle(cls)
def pybind_has_signal(handle, signalname): cls_or_instance = ffi.from_handle(handle) cls = cls_or_instance if isinstance(cls_or_instance, type) else type(cls_or_instance) return ffi.string(signalname) in cls.__signals
def pybind_has_meth(handle, methname): cls_or_instance = ffi.from_handle(handle) cls = cls_or_instance if isinstance(cls_or_instance, type) else type(cls_or_instance) meth = getattr(cls, ffi.string(methname), None) return callable(meth)
def path(self): gd_repr = lib.godot_node_path_as_string(self._gd_ptr) return ffi.string(lib.godot_string_wide_str(ffi.addressof(gd_repr)))
def __repr__(self): gd_repr = lib.godot_transform2d_as_string(self._gd_ptr) raw_str = lib.godot_string_wide_str(ffi.addressof(gd_repr)) return "<%s(%s)>" % (type(self).__name__, ffi.string(raw_str))
def godot_string_to_pyobj(p_gdstring): raw_str = lib.godot_string_unicode_str(p_gdstring) return ffi.string(raw_str)
def to_html(self, with_alpha=True): gdstr = lib.godot_color_to_html(self._gd_ptr, with_alpha) return ffi.string(lib.godot_string_wide_str(ffi.addressof(gdstr)))
def pybind_instanciate_from_classname(classname): cls = get_exposed_class_per_name(ffi.string(classname)) instance = cls() protect_from_gc.register(instance) return connect_handle(instance)