from cffi import FFI ffi = FFI() ffi.cdef(""" typedef struct { float x, y; } V2; typedef struct { float x, y; float w, h; } Rect; typedef struct { float a, r, g, b; } Color; typedef void* Image; typedef bool(*const InitFn)(); typedef bool(*const LoopFn)(float dt); typedef void(*const DeinitFn)(); void run ( InitFn const init_fn, LoopFn const loop_fn, DeinitFn const deinit_fn ); typedef void* Context; Context context_init(void); void context_deinit(Context ctx); typedef struct { Color color; Image image; bool* hover; bool consume_hover; bool ignore_hover_if_consumed; bool begin_drag_if_hover_and; bool end_drag_if; V2** drag; } RectangleOptions_; bool rectangle_(Context ctx, Rect rect, RectangleOptions_ o); """) lib = ffi.dlopen("../zig-out/lib/libminimgui.so") class Context: def __init__(self): self.ctx = lib.context_init() def deinit(self): lib.context_deinit(self.ctx) def rectangle(self, *args, color = {"a": 1.0, "r": 1.0, "g": 1.0, "b": 1.0}): if len(args) == 4: x, y, w, h = args rect = { "x": x, "y": y, "w": w, "h": h } elif len(args) == 1: rect = args[0] lib.rectangle_(self.ctx, rect, { "color": to_color(color) }) # bgra def color_hex(x): a = (x >> 24) & 0xFF r = (x >> 16) & 0xFF g = (x >> 8) & 0xFF b = x & 0xFF return (a / 255.0, r / 255.0, g / 255.0, b / 255.0) def to_color(color): if isinstance(color, int): return color_hex(color) else: return color def run(*args): if len(args) == 3: init_fn = args[0] loop_fn = args[1] deinit_fn = args[2] elif len(args) <= 1: def init_fn(): global global_context global_context = Context() def deinit_fn(): global_context.deinit() if len(args) == 1: loop_fn = args[0] else: import sys main = sys.modules["__main__"] loop_fn = getattr(main, "loop", None) @ffi.callback("InitFn") def _init(): res = init_fn() if res is None or res is True: return True elif res is False: return False else: raise ValueError("minimgui.init() must return None or True") @ffi.callback("LoopFn") def _loop(dt): res = loop_fn(dt) if res is None or res is True: return True elif res is False: return False else: raise ValueError("minimgui.loop() must return None or True") @ffi.callback("DeinitFn") def _deinit(): deinit_fn() lib.run(_init, _loop, _deinit) def __getattr__(name): return getattr(global_context, name)