| name | orklev2-ezapp |
| description | Answer questions about orkid's EzApp framework, OrkEzApp creation, main loop, EzTopWidget, secondary windows, refresh policies, GPU/update thread lifecycle, and Python app patterns. Use when the user asks about creating apps, the main loop, windows, refresh, or the EzApp lifecycle. |
| user-invocable | false |
Orkid EzApp Framework Reference
When answering questions about EzApp or application creation in orkid, consult these files.
Key Files
| Component | Location |
|---|
| EzApp Header | ork.lev2/inc/ork/lev2/ezapp.h |
| EzApp Impl | ork.lev2/src/ezapp.cpp |
| EzTopWidget | ork.lev2/src/ezapp_topwidget.cpp |
| EzMainWin | ork.lev2/src/ezapp_mainwin.cpp |
| Secondary Windows | ork.lev2/src/ez_secondary_win.cpp |
| Python Bindings | ork.lev2/pyext/src/pyext_ezapp.cpp |
| CTXBASE (refresh) | ork.lev2/inc/ork/lev2/gfx/ctxbase.h |
| Tests | ork.lev2/pyext/tests/application/test_ezapp_creation.py |
Architecture Overview
OrkEzApp Creation (Python)
from orkengine import lev2
class MyApp:
def onGpuInit(self, ctx): ...
def onUpdate(self, updinfo): ...
def onDraw(self, draw_event): ...
app = MyApp()
ezapp = lev2.OrkEzApp.create(app,
width=1280, height=720,
fullscreen=False,
enable_audio=True,
use_subsystems=True,
target_ups=60.0,
target_fps=60.0)
ezapp.mainThreadLoop()
Creation kwargs
- Window:
name, left, top, width, height, fullscreen, fullscreen_monitor, offscreen
- Graphics:
enable_graphics, msaa, ssaa, disable_mouse_cursor, fsmouse
- Audio:
enable_audio, enable_audio_input/output, enable_audio_synth, audio_input/output_devname, audio_stream_sync
- Timing:
freerun, target_ups, target_fps, enable_freerun_ups/fps, enable_lockstep_ups/fps
- Advanced:
use_subsystems, drm_mode_id, movie_output_path, rcfd
Callback Detection (hasattr-based)
onAppInit()
onAppExit()
onGpuInit(ctx)
onGpuExit(ctx)
onGpuUpdate(ctx)
onGpuPreFrame(ctx)
onGpuPostFrame(ctx)
onUpdateInit()
onUpdateExit()
onUpdate(update_data)
onDraw(draw_event)
onUiEvent(event)
onAudioInit(audiodevice)
onAudioExit()
onSynthInit(synth)
onSynthExit()
Two Init Modes
- Legacy Ad-Hoc (
use_subsystems=False): direct inline GPU/audio init
- HFSM Subsystem (
use_subsystems=True): dependency-driven via subsystem graph
Main Loop Modes
- Freerun: wall-clock timing, adaptive wait, independent update/render rates
- Lockstep: fixed timestep, deterministic, frame-request sync between threads
EzTopWidget
- Root UI widget (
ui::Group subclass)
- Owns
_topLayoutGroup (layout root for UI)
enableUiDraw() — sets up compositing pipeline (call once in onGpuInit)
- Handles resize, draws UI context, manages movie capture
Properties
ezapp.topWidget
ezapp.topLayoutGroup
ezapp.uicontext
ezapp.mainwin
ezapp.audio_device
ezapp.audio_synth
ezapp.vars
ezapp.timescale
Refresh Policies
ezapp.setRefreshPolicy(lev2.EREFRESH_FASTEST, -1)
ezapp.setRefreshPolicy(lev2.EREFRESH_WHENDIRTY, -1)
ezapp.setRefreshPolicy(lev2.EREFRESH_FIXEDFPS, 60)
Secondary Windows
popup = ezapp.createSecondaryWindow(
width=800, height=600, x=200, y=150,
title="Tool Window", decorated=True, resizable=True, floating=True)
uic = popup.ui_context
root = lev2.ui.LayoutGroup.create("popup_lg")
root.setRect(0, 0, popup.width, popup.height)
uic.top = root
popup.onClosed = lambda: print("Window closed")
popup.requestClose()
Config options: width, height, x, y, title, decorated, resizable, floating, transparent, focusOnShow
Popup shortcut:
popup = ezapp.createPopupWindow(x, y, w, h, transparent=True)
Granular Loop Control
ezapp.mainThreadBegin()
while not done:
ezapp.mainThreadIter()
ezapp.mainThreadEnd()
Movie Recording
settings = lev2.MovieCaptureSettings()
settings.output_path = "/tmp/output.mp4"
ezapp.enableMovieRecording(settings)
ezapp.finishMovieRecording()
Thread Model
- Main Thread: GPU context, rendering, UI events
- Update Thread: simulation logic (
onUpdate)
- Audio Thread: audio processing (if enabled)
- GIL released during
mainThreadLoop(), acquired per-callback
Monitor Enumeration
monitors = lev2.enumerateGlfwMonitors()
for mon in monitors:
print(mon.name, mon.width, mon.height, mon.refresh_rate, mon.primary)
How to Answer
- For app creation: check
pyext_ezapp.cpp for kwargs handling
- For lifecycle order: trace callback registration in
pyext_ezapp.cpp
- For secondary windows: read
ez_secondary_win.cpp
- For refresh policies: check
ctxbase.h ERefreshPolicy enum
- For main loop internals: read
ezapp.cpp mainThreadLoop methods