def pyobj_to_gdobj(pyobj, steal_gdobj=True): if pyobj is None: return ffi.NULL elif isinstance(pyobj, bool): return godot_bool_alloc(1 if pyobj else 0) elif isinstance(pyobj, int): return godot_int_alloc(pyobj) elif isinstance(pyobj, float): return godot_real_alloc(pyobj) elif isinstance(pyobj, str): gdobj = godot_string_alloc() lib.godot_string_new_unicode_data(gdobj, pyobj, -1) return gdobj elif isinstance(pyobj, BaseBuiltinWithGDObjOwnership): if steal_gdobj: return pyobj._gd_ptr else: return pyobj._copy_gdobj(pyobj._gd_ptr) elif isinstance(pyobj, BaseBuiltin): return pyobj._gd_ptr elif isinstance(pyobj, BaseObject): # TODO: copy ptr box ? return pyobj._gd_ptr else: raise TypeError( "Unknown Variant type `%s` (this should never happen !)" % gdtype)
def godot_string_from_pyobj(pystr): if isinstance(pystr, str): gdstr = godot_string_alloc() lib.godot_string_new_unicode_data(gdstr, pystr, len(pystr)) elif isinstance(pystr, bytes): gdstr = godot_string_alloc() lib.godot_string_new_data(gdstr, pystr, len(pystr)) else: raise TypeError('`pystr` must be `str` or `bytes`') return gdstr
def pybind_auto_indent_code(handle, code, from_line, to_line): try: import autopep8 except ImportError: print("[Pythonscript] Auto indent requires module `autopep8`, " "install it with `pip install autopep8`") pycode = godot_string_to_pyobj(code).splitlines() before = '\n'.join(pycode[:from_line]) to_fix = '\n'.join(pycode[from_line:to_line]) after = '\n'.join(pycode[to_line:]) fixed = autopep8.fix_code(to_fix) final_code = '\n'.join((before, fixed, after)) # TODO: modify code instead of replace it when binding on godot_string # operation is available lib.godot_string_destroy(code) lib.godot_string_new_unicode_data(code, final_code, len(final_code))
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 pybind_get_class_name(handle, r_name): cls_or_instance = ffi.from_handle(handle) cls = cls_or_instance if isinstance(cls_or_instance, type) else type(cls_or_instance) lib.godot_string_new_unicode_data(r_name, cls.__name__, -1)