Files
prosperon/core.cm
2026-01-07 14:25:11 -06:00

209 lines
4.6 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 = 60
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()
for (var ev of evts) {
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)
}
}
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) {
render_result.commands.push({
cmd: 'imgui',
draw: function(ui) {
if (_config.imgui) _config.imgui(ui)
if (_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
}
}
}
// Measure actual frame work time (excluding delay)
var frame_end = time_mod.number()
var actual_frame_time = frame_end - frame_start
// Track FPS based on actual work time
_frame_time_ms = actual_frame_time * 1000
_fps_samples.push(actual_frame_time)
if (_fps_samples.length > _fps_sample_count) {
_fps_samples.shift()
}
var avg_frame_time = 0
for (var i = 0; i < _fps_samples.length; i++) {
avg_frame_time += _fps_samples[i]
}
avg_frame_time = avg_frame_time / _fps_samples.length
_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