Files
prosperon/core.cm
2026-01-24 09:56:07 -06:00

232 lines
5.1 KiB
Plaintext

// core.cm - Minimal entry point for prosperon rendering
//
// Usage:
// var core = use('prosperon/core')
// core.start({
// width: 1280,
// height: 720,
// title: "My Game",
// update: function(dt) { ... },
// render: function() { return graph }
// })
var video = use('sdl3/video')
var events = use('sdl3/input')
var time_mod = use('time')
var debug_imgui = use('debug_imgui')
var core = {}
// Private state
var _running = false
var _config = null
var _backend = null
var _window = null
var _last_time = 0
var _framerate = 60
var imgui = use('imgui')
// Start the application
core.start = function(config) {
_config = config
_framerate = config.framerate || 60
// Initialize SDL GPU backend
var sdl_gpu = use('sdl_gpu')
_backend = sdl_gpu
var init_result = _backend.init({
width: config.width || 1280,
height: config.height || 720,
title: config.title || "Prosperon"
})
if (!init_result) {
log.console("core: Failed to initialize backend")
return false
}
_window = _backend.get_window()
if ((config.imgui || config.editor) && imgui.init) {
imgui.init(_window, _backend.get_device())
}
_running = true
_last_time = time_mod.number()
// Start main loop
_main_loop()
return true
}
// Stop the application
core.stop = function() {
_running = false
}
// Get window size
core.window_size = function() {
return _backend.get_window_size()
}
// Get backend for direct access
core.backend = function() {
return _backend
}
// FPS tracking
var _fps_samples = []
var _fps_sample_count = 120
var _fps_sample_sum = 0
var _fps_sample_pos = 0
function fps_add_sample(sample) {
var n = length(_fps_samples)
if (n < _fps_sample_count) {
push(_fps_samples, sample)
_fps_sample_sum += sample
} else {
var old = _fps_samples[_fps_sample_pos]
_fps_samples[_fps_sample_pos] = sample
_fps_sample_sum += sample - old
_fps_sample_pos++
if (_fps_sample_pos >= _fps_sample_count) _fps_sample_pos = 0
}
}
function fps_get_avg() {
var n = length(_fps_samples)
return n ? _fps_sample_sum / n : 0
}
var _current_fps = 0
var _frame_time_ms = 0
// Main loop
function _main_loop() {
var frame_start = time_mod.number()
if (!_running) return
var now = frame_start
var dt = now - _last_time
_last_time = now
// Process events
var evts = events.get_events()
var win_size = _backend.get_window_size()
// Get input module for auto-ingestion
var input_mod = use('input')
arrfor(evts, function(ev) {
if (_config.imgui || _config.editor) {
imgui.process_event(ev)
}
var ev_obj = events.objectify(ev)
if (ev_obj.type == 'quit') {
_running = false
$stop()
return
}
if (ev_obj.type == 'window_pixel_size_changed') {
win_size.width = ev_obj.width
win_size.height = ev_obj.height
if (_backend.set_window_size) {
_backend.set_window_size(ev_obj.width, ev_obj.height)
}
}
// Auto-ingest through input system
input_mod.ingest(ev_obj)
// Optional raw hook for debugging
if (_config.input) {
_config.input(ev_obj)
}
})
// Update
if (_config.update) {
_config.update(dt)
}
var imgui_mod = use('imgui')
var debug_imgui = use('debug_imgui')
// ImGui Frame
if (_config.imgui || _config.editor) {
imgui_mod.newframe()
}
// Render
if (_config.render) {
var render_result = _config.render()
if (render_result) {
if (_config.debug == 'graph') {
log.console(render_result)
$stop()
return
}
var dbg = _config.debug == 'cmd'
// Build stats for debug_imgui
var stats = {
fps: _current_fps,
frame_time_ms: _frame_time_ms
}
// Handle both compositor result ({commands: [...]}) and fx_graph (graph object)
if (render_result.commands) {
if (_config.imgui || _config.editor) {
push(render_result.commands, {
cmd: 'imgui',
draw: function(ui) {
if (_config.imgui) _config.imgui(ui)
if (is_function(_config.editor)) {
debug_imgui.render(ui, null, render_result.plan, stats)
_config.editor(ui)
}
},
target: 'screen'
})
}
// Compositor result - execute commands directly
_backend.execute_commands(render_result.commands, win_size, dbg)
} else {
// fx_graph result - execute graph
_backend.execute_graph(render_result, win_size, dbg)
}
if (dbg) {
$stop()
return
}
}
}
var frame_end = time_mod.number()
var actual_frame_time = frame_end - frame_start
_frame_time_ms = actual_frame_time * 1000
fps_add_sample(actual_frame_time)
var avg_frame_time = fps_get_avg()
_current_fps = avg_frame_time > 0 ? 1 / avg_frame_time : 0
// Schedule next frame
var frame_time = 1 / _framerate
var elapsed = frame_end - frame_start
var delay = frame_time - elapsed
if (delay < 0) delay = 0
$delay(_main_loop, delay)
}
return core