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 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 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): 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 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