def getter(self): ret = godot_variant_alloc() lib.godot_variant_new_nil(ret) args = ffi.new("void*[]", [self._gd_ptr, gd_propname]) lib.godot_method_bind_ptrcall(cls._meth_get_property, cls._instance, args, ret) return variant_to_pyobj(ret)
def pybind_script_init(handle, path, source, r_error): path = godot_string_to_pyobj(path) if verbose: print("Loading python script from %s" % path) if not path.startswith("res://") or not path.rsplit( ".", 1)[-1] in ("py", "pyc", "pyo", "pyd"): print( "Bad python script path `%s`, must starts by `res://` and ends with `.py/pyc/pyo/pyd`" % path) r_error[0] = lib.GODOT_ERR_FILE_BAD_PATH return ffi.NULL # TODO: possible bug if res:// is not part of PYTHONPATH # Remove `res://`, `.py` and replace / by . modname = path[6:].rsplit(".", 1)[0].replace("/", ".") try: __import__(modname) # Force lazy loading of the module # TODO: make sure script reloading works cls = get_exposed_class_per_module(modname) except Exception: # If we are here it could be because the file doesn't exists # or (more possibly) the file content is not a valid python (or # miss an exposed class) print("Got exception loading %s (%s): %s" % (path, modname, traceback.format_exc())) r_error[0] = lib.GODOT_ERR_PARSE_ERROR # Obliged to return the structure, but no need in init it return ffi.new("godot_pluginscript_script_manifest*")[0] r_error[0] = lib.GODOT_OK return _build_script_manifest(cls)[0]
def setter(self, value): gd_value = pyobj_to_variant(value) args = ffi.new("void*[]", [self._gd_ptr, gd_propname, gd_value]) ret = godot_variant_alloc() lib.godot_variant_new_nil(ret) lib.godot_method_bind_ptrcall(cls._meth_set_property, cls._instance, args, ret) return variant_to_pyobj(ret)
def get_integer_constant(cls, classname, constname): ret = godot_int_alloc() gd_classname = godot_string_from_pyobj(classname) gd_constname = godot_string_from_pyobj(constname) args = ffi.new("void*[2]", [gd_classname, gd_constname]) # 2nd arg should be false, which what we get by not initializing it lib.godot_method_bind_ptrcall(cls._meth_get_integer_constant, cls._instance, args, ret) return int(ret[0])
def bind(self, *args): # TODO: allow **kwargs # check number of args n_args, nm_args, nmd_args = ( len(args), len(meth["args"]), len(meth["default_args"]), ) nr_args = nm_args - nmd_args # number of required arguments if n_args < nr_args: # not enough args, raise error if nr_args - n_args == 1: raise TypeError( "%s() missing 1 required positional argument: '%s'" % (methname, meth["args"][nr_args - 1]["name"]) ) else: raise TypeError( "%s() missing %i required positional arguments: " % (methname, nr_args - n_args) + ", ".join( "'%s'" % (arg["name"]) for arg in meth["args"][n_args : nr_args - 1] ) + " and '%s'" % (meth["args"][nr_args - 1]["name"]) ) if n_args > nm_args: # too many args, raise error if nmd_args == 0: raise TypeError( "%s() takes %i positional argument%s but %i were given" % (methname, nm_args, "s" if nm_args > 1 else "", n_args) ) else: raise TypeError( "%s() takes from %i to %i positional arguments but %i were given" % (methname, nr_args, nm_args, n_args) ) # complete missing optional args with default values diff = len(args) - len(meth["args"]) args = args + tuple(meth["default_args"][diff:]) # TODO: check args type here (ptrcall means segfault on bad args...) # print('[PY->GD] Ptrcall %s.%s (%s) on %s with %s' % (classname, methname, meth, self, args)) raw_args = [ convert_arg(meth_arg["type"], meth_arg["name"], arg) for arg, meth_arg in zip(args, meth["args"]) ] gdargs = ffi.new("void*[]", raw_args) if raw_args else ffi.NULL ret = new_uninitialized_gdobj(rettype) lib.godot_method_bind_ptrcall(methbind, self._gd_ptr, gdargs, ret) ret = gdobj_to_pyobj(rettype, ret) # print('[PY->GD] returned:', ret) return ret
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 constructor(self): gd_classname = godot_string_from_pyobj(classname) # TODO: alloc this on the stack (using _malloca ?) args = ffi.new("void*[]", [gd_classname]) ret = godot_variant_alloc() lib.godot_method_bind_ptrcall(cls._meth_instance, cls._instance, args, ret) objret = lib.godot_variant_as_object(ret) # Quick'n dirty fix to prevent Ressource objects from beeing automatically # freed when the variant is destroyed given it holds the only ref on it self._gd_var = ret return objret
def godot_string_from_pyobj_for_ffi_return(pystr): """ /!\ Don't use me unless you have good reason /!\ Resulting godot_string object will not call godot_string_destroy when garbage collected. This is useful when a copy of this object is passed as a return value to Godot (which will be then responsible to actually call the destructor). """ gdstr = ffi.new("godot_string*") lib.godot_string_new_with_wide_string(gdstr, pystr, len(pystr)) return gdstr
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 get_class_properties(cls, classname): properties = [] ret = godot_array_alloc() lib.godot_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_property_list, cls._instance, args, ret) for i in range(lib.godot_array_size(ret)): var = lib.godot_array_get(ret, i) gddict = lib.godot_variant_as_dictionary(ffi.addressof(var)) propdict = Dictionary.build_from_gdobj(gddict) properties.append(propdict) return properties
def bind(self, *args): # print('[PY->GD] Varargs call %s.%s (%s) on %s with %s' % (classname, methname, meth, self, args)) vaargs = [ convert_arg(meth_arg["type"], meth_arg["name"], arg, to_variant=True) for arg, meth_arg in zip(args, meth["args"]) ] vaargs += [pyobj_to_variant(arg) for arg in args[fixargs_count:]] vavaargs = ffi.new("godot_variant*[]", vaargs) if vaargs else ffi.NULL # TODO: use `godot_variant_call_error` to raise exceptions varret = lib.godot_method_bind_call( methbind, self._gd_ptr, vavaargs, len(args), ffi.NULL ) ret = variant_to_pyobj(ffi.addressof(varret)) lib.godot_variant_destroy(ffi.addressof(varret)) # print('[PY->GD] returned:', ret) return ret
def bind(self, *args): if len(args) != len(meth['args']): raise TypeError( '%s() takes %s positional argument but %s were given' % (methname, len(meth['args']), len(args))) # TODO: check args number and type here (ptrcall means segfault on bad args...) # print('[PY->GD] Ptrcall %s.%s (%s) on %s with %s' % (classname, methname, meth, self, args)) raw_args = [ convert_arg(meth_arg['type'], meth_arg['name'], arg) for arg, meth_arg in zip(args, meth['args']) ] gdargs = ffi.new("void*[]", raw_args) if raw_args else ffi.NULL ret = new_uninitialized_gdobj(rettype) lib.godot_method_bind_ptrcall(methbind, self._gd_ptr, gdargs, ret) ret = gdobj_to_pyobj(rettype, ret) # print('[PY->GD] returned:', ret) return ret
def pybind_get_signal_list(handle): # Lazily generate the list of exported properties' names cls_or_instance = ffi.from_handle(handle) cls = cls_or_instance if isinstance(cls_or_instance, type) else type(cls_or_instance) # Need to store the cached list with a per-class name to avoid shadowing # from a parent class field = '_%s__signal_raw_list' % cls.__name__ raw_list = getattr(cls, field, None) if not raw_list: # Build the list of signals, ready to be access by godot raw_list = ffi.new('godot_string[]', len(cls.__signals) + 1) for i, name in enumerate(cls.__signals.keys()): lib.godot_string_new_unicode_data(ffi.addressof(raw_list[i]), name, -1) # Last entry is an empty string lib.godot_string_new(ffi.addressof(raw_list[len(cls.__signals)])) setattr(cls, field, raw_list) return raw_list
def pybind_get_meth_list(handle): # Lazily generate the list of methods' names cls_or_instance = ffi.from_handle(handle) cls = cls_or_instance if isinstance(cls_or_instance, type) else type(cls_or_instance) # Need to store the cached list with a per-class name to avoid shadowing # from a parent class field = '_%s__meth_raw_list' % cls.__name__ raw_list = getattr(cls, field, None) if not raw_list: meths = [ k for k in dir(cls) if not k.startswith('__') and callable(getattr(cls, k)) ] raw_list = ffi.new('godot_string[]', len(meths) + 1) for i, name in enumerate(meths): lib.godot_string_new_unicode_data(ffi.addressof(raw_list[i]), name, -1) # Last entry is an empty string lib.godot_string_new(ffi.addressof(raw_list[len(meths)])) setattr(cls, field, raw_list) return raw_list
def _build_script_manifest(cls): from godot.bindings import Dictionary, Array def _build_signal_info(signal): methinfo = Dictionary() methinfo['name'] = signal.name # Dummy data, only name is important here methinfo['args'] = Array() methinfo['default_args'] = Array() methinfo['return'] = None methinfo['flags'] = lib.METHOD_FLAG_FROM_SCRIPT return methinfo def _build_method_info(meth, methname): spec = inspect.getfullargspec(meth) methinfo = Dictionary() methinfo['name'] = methname # TODO: Handle classmethod/staticmethod methinfo['args'] = Array(spec.args) methinfo['default_args'] = Array() # TODO # TODO: use annotation to determine return type ? methinfo['return'] = None methinfo['flags'] = lib.METHOD_FLAG_FROM_SCRIPT methinfo['rpc_mode'] = getattr(meth, '__rpc', lib.GODOT_METHOD_RPC_MODE_DISABLED) return methinfo def _build_property_info(prop): propinfo = Dictionary() propinfo['name'] = prop.name propinfo['type'] = py_to_gd_type(prop.type) propinfo['hint'] = prop.hint propinfo['hint_string'] = prop.hint_string propinfo['usage'] = prop.usage propinfo['default_value'] = prop.default propinfo['rset_mode'] = prop.rpc return propinfo manifest = ffi.new('godot_pluginscript_script_manifest*') manifest.data = connect_handle(cls) gdname = godot_string_from_pyobj(cls.__name__) lib.godot_string_name_new(ffi.addressof(manifest.name), gdname) if cls.__bases__ and issubclass(cls.__bases__[0], BaseObject): gdbase = godot_string_from_pyobj(cls.__bases__[0].__name__) lib.godot_string_name_new(ffi.addressof(manifest.base), gdbase) manifest.is_tool = cls.__tool lib.godot_dictionary_new(ffi.addressof(manifest.member_lines)) lib.godot_array_new(ffi.addressof(manifest.methods)) methods = Array() # TODO: include inherited in exposed methods ? Expose Godot base class' ones ? # for methname in vars(cls): for methname in dir(cls): meth = getattr(cls, methname) if not inspect.isfunction(meth) or meth.__name__.startswith('__'): continue methinfo = _build_method_info(meth, methname) methods.append(methinfo) signals = Array() for signal in cls.__signals.values(): signalinfo = _build_signal_info(signal) signals.append(signalinfo) properties = Array() for prop in cls.__exported.values(): property_info = _build_property_info(prop) properties.append(property_info) lib.godot_array_new_copy(ffi.addressof(manifest.methods), methods._gd_ptr) lib.godot_array_new_copy(ffi.addressof(manifest.signals), signals._gd_ptr) lib.godot_array_new_copy(ffi.addressof(manifest.properties), properties._gd_ptr) return manifest
def _build_script_manifest(cls): def _build_signal_info(signal): methinfo = Dictionary() methinfo["name"] = signal.name # Dummy data, only name is important here methinfo["args"] = Array() methinfo["default_args"] = Array() methinfo["return"] = None methinfo["flags"] = lib.METHOD_FLAG_FROM_SCRIPT return methinfo def _build_method_info(meth, methname): spec = inspect.getfullargspec(meth) methinfo = Dictionary() methinfo["name"] = methname # TODO: Handle classmethod/staticmethod methinfo["args"] = Array(spec.args) methinfo["default_args"] = Array() # TODO # TODO: use annotation to determine return type ? methinfo["return"] = None methinfo["flags"] = lib.METHOD_FLAG_FROM_SCRIPT methinfo["rpc_mode"] = getattr(meth, "__rpc", lib.GODOT_METHOD_RPC_MODE_DISABLED) return methinfo def _build_property_info(prop): propinfo = Dictionary() propinfo["name"] = prop.name propinfo["type"] = py_to_gd_type(prop.type) propinfo["hint"] = prop.hint propinfo["hint_string"] = prop.hint_string propinfo["usage"] = prop.usage propinfo["default_value"] = prop.default propinfo["rset_mode"] = prop.rpc return propinfo manifest = ffi.new("godot_pluginscript_script_manifest*") manifest.data = connect_handle(cls) # TODO: should be able to use lib.godot_string_new_with_wide_string directly gdname = godot_string_from_pyobj(cls.__name__) lib.godot_string_name_new(ffi.addressof(manifest.name), gdname) if cls.__bases__: # Only one Godot parent class (checked at class definition time) godot_parent_class = next( (b for b in cls.__bases__ if issubclass(b, BaseObject))) if godot_parent_class.__dict__.get("__is_godot_native_class"): path = godot_parent_class.__name__ else: # Pluginscript wants us to return the parent as a path path = "res://%s.py" % "/".join( cls.__bases__[0].__module__.split(".")) gdbase = godot_string_from_pyobj(path) lib.godot_string_name_new(ffi.addressof(manifest.base), gdbase) manifest.is_tool = cls.__tool lib.godot_dictionary_new(ffi.addressof(manifest.member_lines)) lib.godot_array_new(ffi.addressof(manifest.methods)) methods = Array() # TODO: include inherited in exposed methods ? Expose Godot base class' ones ? # for methname in vars(cls): for methname in dir(cls): meth = getattr(cls, methname) if not inspect.isfunction(meth) or meth.__name__.startswith("__"): continue methinfo = _build_method_info(meth, methname) methods.append(methinfo) signals = Array() for signal in cls.__signals.values(): signalinfo = _build_signal_info(signal) signals.append(signalinfo) properties = Array() for prop in cls.__exported.values(): property_info = _build_property_info(prop) properties.append(property_info) lib.godot_array_new_copy(ffi.addressof(manifest.methods), methods._gd_ptr) lib.godot_array_new_copy(ffi.addressof(manifest.signals), signals._gd_ptr) lib.godot_array_new_copy(ffi.addressof(manifest.properties), properties._gd_ptr) return manifest
def pyobj_to_variant(pyobj, p_gdvar=None, for_ffi_return=False): """ `initialized=False` means we MUST manually init this by hand no matter what `for_ffi_return=True` means the returned variant won't have it destructor called once it is garbage collected by python. This is typically what we want when we pass the variant object by copy as a return value to Godot (which is then in charge of calling the destructor itself). """ if not p_gdvar: if for_ffi_return: p_gdvar = ffi.new("godot_variant*") else: p_gdvar = godot_variant_alloc(initialized=False) try: if pyobj is None: lib.godot_variant_new_nil(p_gdvar) elif (isinstance(pyobj, bool)): lib.godot_variant_new_bool(p_gdvar, pyobj) elif (isinstance(pyobj, int)): lib.godot_variant_new_int(p_gdvar, pyobj) elif (isinstance(pyobj, float)): lib.godot_variant_new_real(p_gdvar, pyobj) elif (isinstance(pyobj, str)): gdstr = godot_string_alloc(initialized=False) lib.godot_string_new_with_wide_string(gdstr, pyobj, len(pyobj)) lib.godot_variant_new_string(p_gdvar, gdstr) elif isinstance(pyobj, BaseBuiltin): if pyobj.GD_TYPE == lib.GODOT_VARIANT_TYPE_VECTOR2: lib.godot_variant_new_vector2(p_gdvar, pyobj._gd_ptr) elif pyobj.GD_TYPE == lib.GODOT_VARIANT_TYPE_RECT2: lib.godot_variant_new_rect2(p_gdvar, pyobj._gd_ptr) elif pyobj.GD_TYPE == lib.GODOT_VARIANT_TYPE_VECTOR3: lib.godot_variant_new_vector3(p_gdvar, pyobj._gd_ptr) elif pyobj.GD_TYPE == lib.GODOT_VARIANT_TYPE_TRANSFORM2D: lib.godot_variant_new_transform2d(p_gdvar, pyobj._gd_ptr) elif pyobj.GD_TYPE == lib.GODOT_VARIANT_TYPE_PLANE: lib.godot_variant_new_plane(p_gdvar, pyobj._gd_ptr) elif pyobj.GD_TYPE == lib.GODOT_VARIANT_TYPE_QUAT: lib.godot_variant_new_quat(p_gdvar, pyobj._gd_ptr) elif pyobj.GD_TYPE == lib.GODOT_VARIANT_TYPE_AABB: lib.godot_variant_new_aabb(p_gdvar, pyobj._gd_ptr) elif pyobj.GD_TYPE == lib.GODOT_VARIANT_TYPE_BASIS: lib.godot_variant_new_basis(p_gdvar, pyobj._gd_ptr) elif pyobj.GD_TYPE == lib.GODOT_VARIANT_TYPE_TRANSFORM: lib.godot_variant_new_transform(p_gdvar, pyobj._gd_ptr) elif pyobj.GD_TYPE == lib.GODOT_VARIANT_TYPE_COLOR: lib.godot_variant_new_color(p_gdvar, pyobj._gd_ptr) elif pyobj.GD_TYPE == lib.GODOT_VARIANT_TYPE_NODE_PATH: lib.godot_variant_new_node_path(p_gdvar, pyobj._gd_ptr) elif pyobj.GD_TYPE == lib.GODOT_VARIANT_TYPE_RID: lib.godot_variant_new_rid(p_gdvar, pyobj._gd_ptr) elif pyobj.GD_TYPE == lib.GODOT_VARIANT_TYPE_OBJECT: lib.godot_variant_new_object(p_gdvar, pyobj._gd_ptr) elif pyobj.GD_TYPE == lib.GODOT_VARIANT_TYPE_DICTIONARY: lib.godot_variant_new_dictionary(p_gdvar, pyobj._gd_ptr) elif pyobj.GD_TYPE == lib.GODOT_VARIANT_TYPE_ARRAY: lib.godot_variant_new_array(p_gdvar, pyobj._gd_ptr) elif pyobj.GD_TYPE == lib.GODOT_VARIANT_TYPE_POOL_BYTE_ARRAY: lib.godot_variant_new_pool_byte_array(p_gdvar, pyobj._gd_ptr) elif pyobj.GD_TYPE == lib.GODOT_VARIANT_TYPE_POOL_INT_ARRAY: lib.godot_variant_new_pool_int_array(p_gdvar, pyobj._gd_ptr) elif pyobj.GD_TYPE == lib.GODOT_VARIANT_TYPE_POOL_REAL_ARRAY: lib.godot_variant_new_pool_real_array(p_gdvar, pyobj._gd_ptr) elif pyobj.GD_TYPE == lib.GODOT_VARIANT_TYPE_POOL_STRING_ARRAY: lib.godot_variant_new_pool_string_array(p_gdvar, pyobj._gd_ptr) elif pyobj.GD_TYPE == lib.GODOT_VARIANT_TYPE_POOL_VECTOR2_ARRAY: lib.godot_variant_new_pool_vector2_array(p_gdvar, pyobj._gd_ptr) elif pyobj.GD_TYPE == lib.GODOT_VARIANT_TYPE_POOL_VECTOR3_ARRAY: lib.godot_variant_new_pool_vector3_array(p_gdvar, pyobj._gd_ptr) elif pyobj.GD_TYPE == lib.GODOT_VARIANT_TYPE_POOL_COLOR_ARRAY: lib.godot_variant_new_pool_color_array(p_gdvar, pyobj._gd_ptr) elif isinstance(pyobj, BaseObject): lib.godot_variant_new_object(p_gdvar, pyobj._gd_ptr) else: raise TypeError("Cannot convert `%s` to Godot's Variant" % pyobj) except BaseException: # Must init the variant anyway to avoid segfault in it destructor lib.godot_variant_new_nil(p_gdvar) raise return p_gdvar
def pyobj_to_variant(pyobj, p_gdvar=None): # `initialized=False` means we MUST manually init this by hand no matter what p_gdvar = p_gdvar if p_gdvar else godot_variant_alloc(initialized=False) try: if pyobj is None: lib.godot_variant_new_nil(p_gdvar) elif (isinstance(pyobj, bool)): lib.godot_variant_new_bool(p_gdvar, pyobj) elif (isinstance(pyobj, int)): lib.godot_variant_new_int(p_gdvar, pyobj) elif (isinstance(pyobj, float)): lib.godot_variant_new_real(p_gdvar, pyobj) elif (isinstance(pyobj, str)): gdstr = ffi.new("godot_string*") pyobj_as_bytes = pyobj.encode() lib.godot_string_new_data(gdstr, pyobj_as_bytes, len(pyobj_as_bytes)) lib.godot_variant_new_string(p_gdvar, gdstr) elif (isinstance(pyobj, bytes)): gdstr = ffi.new("godot_string*") lib.godot_string_new_data(gdstr, pyobj, len(pyobj)) lib.godot_variant_new_string(p_gdvar, gdstr) elif isinstance(pyobj, BaseBuiltin): if pyobj.GD_TYPE == lib.GODOT_VARIANT_TYPE_VECTOR2: lib.godot_variant_new_vector2(p_gdvar, pyobj._gd_ptr) elif pyobj.GD_TYPE == lib.GODOT_VARIANT_TYPE_RECT2: lib.godot_variant_new_rect2(p_gdvar, pyobj._gd_ptr) elif pyobj.GD_TYPE == lib.GODOT_VARIANT_TYPE_VECTOR3: lib.godot_variant_new_vector3(p_gdvar, pyobj._gd_ptr) elif pyobj.GD_TYPE == lib.GODOT_VARIANT_TYPE_TRANSFORM2D: lib.godot_variant_new_transform2d(p_gdvar, pyobj._gd_ptr) elif pyobj.GD_TYPE == lib.GODOT_VARIANT_TYPE_PLANE: lib.godot_variant_new_plane(p_gdvar, pyobj._gd_ptr) elif pyobj.GD_TYPE == lib.GODOT_VARIANT_TYPE_QUAT: lib.godot_variant_new_quat(p_gdvar, pyobj._gd_ptr) elif pyobj.GD_TYPE == lib.GODOT_VARIANT_TYPE_AABB: lib.godot_variant_new_aabb(p_gdvar, pyobj._gd_ptr) elif pyobj.GD_TYPE == lib.GODOT_VARIANT_TYPE_BASIS: lib.godot_variant_new_basis(p_gdvar, pyobj._gd_ptr) elif pyobj.GD_TYPE == lib.GODOT_VARIANT_TYPE_TRANSFORM: lib.godot_variant_new_transform(p_gdvar, pyobj._gd_ptr) elif pyobj.GD_TYPE == lib.GODOT_VARIANT_TYPE_COLOR: lib.godot_variant_new_color(p_gdvar, pyobj._gd_ptr) elif pyobj.GD_TYPE == lib.GODOT_VARIANT_TYPE_NODE_PATH: lib.godot_variant_new_nodepath(p_gdvar, pyobj._gd_ptr) elif pyobj.GD_TYPE == lib.GODOT_VARIANT_TYPE_RID: lib.godot_variant_new_rid(p_gdvar, pyobj._gd_ptr) elif pyobj.GD_TYPE == lib.GODOT_VARIANT_TYPE_OBJECT: lib.godot_variant_new_object(p_gdvar, pyobj._gd_ptr) elif pyobj.GD_TYPE == lib.GODOT_VARIANT_TYPE_DICTIONARY: lib.godot_variant_new_dictionary(p_gdvar, pyobj._gd_ptr) elif pyobj.GD_TYPE == lib.GODOT_VARIANT_TYPE_ARRAY: lib.godot_variant_new_array(p_gdvar, pyobj._gd_ptr) elif pyobj.GD_TYPE == lib.GODOT_VARIANT_TYPE_POOLBYTEARRAY: lib.godot_variant_new_poolbytearray(p_gdvar, pyobj._gd_ptr) elif pyobj.GD_TYPE == lib.GODOT_VARIANT_TYPE_POOLINTARRAY: lib.godot_variant_new_poolintarray(p_gdvar, pyobj._gd_ptr) elif pyobj.GD_TYPE == lib.GODOT_VARIANT_TYPE_POOLREALARRAY: lib.godot_variant_new_poolrealarray(p_gdvar, pyobj._gd_ptr) elif pyobj.GD_TYPE == lib.GODOT_VARIANT_TYPE_POOLSTRINGARRAY: lib.godot_variant_new_poolstringarray(p_gdvar, pyobj._gd_ptr) elif pyobj.GD_TYPE == lib.GODOT_VARIANT_TYPE_POOLVECTOR2ARRAY: lib.godot_variant_new_poolvector2array(p_gdvar, pyobj._gd_ptr) elif pyobj.GD_TYPE == lib.GODOT_VARIANT_TYPE_POOLVECTOR3ARRAY: lib.godot_variant_new_poolvector3array(p_gdvar, pyobj._gd_ptr) elif pyobj.GD_TYPE == lib.GODOT_VARIANT_TYPE_POOLCOLORARRAY: lib.godot_variant_new_poolcolorarray(p_gdvar, pyobj._gd_ptr) elif isinstance(pyobj, BaseObject): lib.godot_variant_new_object(p_gdvar, pyobj._gd_ptr) else: raise TypeError("Cannot convert `%s` to Godot's Variant" % pyobj) except: # Must init the variant anyway to avoid segfault in it destructor lib.godot_variant_new_nil(p_gdvar) raise return p_gdvar