fix camera ortho set to true; fix module loading; remove loop function to loop.js

This commit is contained in:
2025-02-03 17:08:07 -06:00
parent 68ccd63ddc
commit ede899e9a3
11 changed files with 203 additions and 152 deletions

View File

@@ -1,13 +1,15 @@
![alt text](doc/prosperon_orb_horizontal.gif) git![alt text](doc/prosperon_orb_horizontal.gif)
The easily moddable, programming minded, 2D-first game engine. The aim is to make the fastest way to make games. The easily moddable, programming minded, 2D-first game engine. The aim is to make the fastest way to make games.
Using ... It implements a good amount of ES6, but is NOT terribly compatible with the larger javascript ecosystem. Instead, the goal is to make it trivial to use C libraries in your programs, and to even write C code directly in your javascript.
* Sokol for rendering
* Chipmunk2D for physics
* imgui for easy editor UI
* Clay for game UI
Includes an implementation for Nota, and Kim. Everything is text based, which makes integrating with AI trivial.
*Prosperon is useful, but is a work in progress. Breaking changes are frequent.* ## What's different from ES6?
Prosperon does not use the module system. Instead, there is a 'use' statement. Modules return a single javascript object. It can be a number, a function, or an object with a list of them. Modules are ran once, cached, and frozen before returned. It is wise to keep scripts short and generously import modules.
Programs are separated into modules and scripts. Modules end in a return statement; scripts do not.
Javascript promises do not work. await does not work. async does not work. It's all handled via callbacks, and parseq wrapper functions. This is a lot more intuitive for computer game AI.

View File

@@ -1,5 +1,6 @@
var io = use('io') var io = use('io')
var util = use('util') var util = use('util')
var loop = use('loop')
var dumpfolder = ".prosperon"; var dumpfolder = ".prosperon";
@@ -86,7 +87,7 @@ Cmdline.register_order(
var ren = use('render') var ren = use('render')
while(1) ren.process(); while(1) loop.step();
}, },
"Play the game present in this folder.", "Play the game present in this folder.",
); );

View File

@@ -54,6 +54,7 @@ Object.defineProperty(Function.prototype, "hashify", {
}); });
var io = use_embed('io') var io = use_embed('io')
var tracy = use_embed('tracy')
var canonical = io.realdir('scripts/resources.js') + 'resources.js' var canonical = io.realdir('scripts/resources.js') + 'resources.js'
var content = io.slurp('scripts/resources.js') var content = io.slurp('scripts/resources.js')
@@ -424,7 +425,6 @@ Register.add_cb("hud");
Register.add_cb("draw"); Register.add_cb("draw");
Register.add_cb("imgui"); Register.add_cb("imgui");
Register.add_cb("app"); Register.add_cb("app");
Register.add_cb("prerender");
function cant_kill() function cant_kill()
{ {
@@ -551,3 +551,4 @@ actor[UNDERLINGS] = new Set()
globalThis.mixin("color"); globalThis.mixin("color");
use('cmd')(prosperon.argv) use('cmd')(prosperon.argv)

61
scripts/loop.js Normal file
View File

@@ -0,0 +1,61 @@
// loop.js
var render = use('render') // The refactored file above
var layout = use('clay')
var input = use('input')
var emitter = use('emitter')
var os = use('os')
var event = use('event')
var imgui = use('imgui')
var waittime = 1/240
var last_frame_time = 0
var frame_t = 0
var fpses = []
var timescale = 1
// This was originally your 'imgui_fn' in render.js
function imgui_fn() {
imgui.newframe()
// ... your debug menus, etc. ...
prosperon.imgui()
}
// Pull your old 'render.process' logic here:
function step() {
var now = os.now()
var dt = now - last_frame_time
if (dt < waittime) os.sleep(waittime - dt)
last_frame_time = os.now()
dt = last_frame_time - frame_t
frame_t = last_frame_time
// Input & events
event.engine_input(e => prosperon.dispatch(e.type, e))
layout.newframe()
// Game logic
prosperon.appupdate(dt)
input.procdown()
emitter.update(dt * timescale)
os.update_timers(dt * timescale)
prosperon.update(dt * timescale)
// Scenes or “draw” hooks
// We point to whichever queue we want
render.setup_draw()
render.setup_hud()
// Show your UI or debug
imgui_fn()
// Now do the GPU present (calls gpupresent in render.js)
render._main.present()
tracy.end_frame()
}
// Return or export them so you can call from a main script
return {
step
}

View File

@@ -89,12 +89,14 @@ cam.make = function()
{ {
var c = Object.create(basecam) var c = Object.create(basecam)
c.transform = os.make_transform() c.transform = os.make_transform()
c.transform.unit()
c.zoom = 1 c.zoom = 1
c.size = [640,360] c.size = [640,360]
c.mode = 'keep' c.mode = 'keep'
c.viewport = {x:0,y:0,width:1,height:1} c.viewport = {x:0,y:0,width:1,height:1}
c.fov = 45 c.fov = 45
c.type = 'ortho' c.type = 'ortho'
c.ortho = true
c.aspect = 16/9 c.aspect = 16/9
return c return c
} }

View File

@@ -1,6 +1,7 @@
// Layout code // Layout code
// Contain is for how it will treat its children. If they should be laid out as a row, or column, or in a flex style, etc. // Contain is for how it will treat its children. If they should be laid out as a row, or column, or in a flex style, etc.
var layout = use('layout')
var geometry = use('geometry') var geometry = use('geometry')
var draw = use('draw2d') var draw = use('draw2d')
var graphics = use('graphics') var graphics = use('graphics')
@@ -28,7 +29,10 @@ var root_config;
var boxes = []; var boxes = [];
var clay = {} var clay = {}
layout.draw = function draw(size, fn, config = {}) clay.behave = layout.behave;
clay.contain = layout.contain;
clay.draw = function draw(size, fn, config = {})
{ {
lay_ctx.reset(); lay_ctx.reset();
boxes = []; boxes = [];
@@ -93,15 +97,15 @@ function create_view_fn(base_config)
} }
} }
layout.vstack = create_view_fn({ clay.vstack = create_view_fn({
contain: layout.contain.column | layout.contain.start, contain: layout.contain.column | layout.contain.start,
}); });
layout.hstack = create_view_fn({ clay.hstack = create_view_fn({
contain: layout.contain.row | layout.contain.start, contain: layout.contain.row | layout.contain.start,
}); });
layout.spacer = create_view_fn({ clay.spacer = create_view_fn({
behave: layout.behave.hfill | layout.behave.vfill behave: layout.behave.hfill | layout.behave.vfill
}); });
@@ -169,7 +173,7 @@ function rectify_configs(config_array)
return cleanobj; return cleanobj;
} }
layout.image = function image(path, ...configs) clay.image = function image(path, ...configs)
{ {
var config = rectify_configs(configs); var config = rectify_configs(configs);
var image = graphics.texture(path); var image = graphics.texture(path);
@@ -178,7 +182,7 @@ layout.image = function image(path, ...configs)
add_item(config); add_item(config);
} }
layout.text = function text(str, ...configs) clay.text = function text(str, ...configs)
{ {
var config = rectify_configs(configs); var config = rectify_configs(configs);
config.size ??= [0,0]; config.size ??= [0,0];
@@ -201,7 +205,7 @@ var button_base = Object.assign(Object.create(clay_base), {
hovered:{ hovered:{
} }
}); });
layout.button = function button(str, action, config = {}) clay.button = function button(str, action, config = {})
{ {
config.__proto__ = button_base; config.__proto__ = button_base;
config.font = graphics.get_font(config.font) config.font = graphics.get_font(config.font)
@@ -212,10 +216,10 @@ layout.button = function button(str, action, config = {})
} }
var hovered = undefined; var hovered = undefined;
layout.newframe = function() { hovered = undefined; } clay.newframe = function() { hovered = undefined; }
// mousepos given in hud coordinates // mousepos given in hud coordinates
layout.draw_commands = function draw_commands(cmds, pos = [0,0], mousepos = prosperon.camera.screen2hud(input.mouse.screenpos())) clay.draw_commands = function draw_commands(cmds, pos = [0,0], mousepos = prosperon.camera.screen2hud(input.mouse.screenpos()))
{ {
for (var cmd of cmds) { for (var cmd of cmds) {
var config = cmd.config; var config = cmd.config;
@@ -244,11 +248,11 @@ layout.draw_commands = function draw_commands(cmds, pos = [0,0], mousepos = pros
} }
var dbg_colors = {}; var dbg_colors = {};
layout.debug_colors = dbg_colors; clay.debug_colors = dbg_colors;
dbg_colors.content = [1,0,0,0.1]; dbg_colors.content = [1,0,0,0.1];
dbg_colors.boundingbox = [0,1,0,0,0.1]; dbg_colors.boundingbox = [0,1,0,0,0.1];
dbg_colors.margin = [0,0,1,0.1]; dbg_colors.margin = [0,0,1,0.1];
layout.draw_debug = function draw_debug(cmds, pos = [0,0]) clay.draw_debug = function draw_debug(cmds, pos = [0,0])
{ {
for (var i = 0; i < cmds.length; i++) { for (var i = 0; i < cmds.length; i++) {
var cmd = cmds[i]; var cmd = cmds[i];
@@ -260,11 +264,11 @@ layout.draw_debug = function draw_debug(cmds, pos = [0,0])
} }
} }
layout.inputs = {}; clay.inputs = {};
layout.inputs.mouse = {} clay.inputs.mouse = {}
layout.inputs.mouse.left = function() clay.inputs.mouse.left = function()
{ {
if (hovered && hovered.action) hovered.action(); if (hovered && hovered.action) hovered.action();
} }
return layout return clay

View File

@@ -1,5 +1,5 @@
var render = {} var render = {}
var config = use('config.js')
var math = use('math') var math = use('math')
var io = use('io') var io = use('io')
var os = use('os') var os = use('os')
@@ -7,10 +7,14 @@ var util = use('util')
var emitter = use('emitter') var emitter = use('emitter')
var controller = use('controller') var controller = use('controller')
var event = use('event') var event = use('event')
var imgui = use('imgui')
var sprite = use('sprite') var sprite = use('sprite')
var graphics = use('graphics') var graphics = use('graphics')
var config = use('config.js')
prosperon.camera = use('camera').make()
prosperon.camera.size = [config.width,config.height]
var base_pipeline = { var base_pipeline = {
vertex: "sprite.vert", vertex: "sprite.vert",
fragment: "sprite.frag", fragment: "sprite.frag",
@@ -527,7 +531,6 @@ function render_camera(cmds, camera)
full_upload(buffers) full_upload(buffers)
var pass = cmds.render_pass(camera.target); var pass = cmds.render_pass(camera.target);
var camera = prosperon.camera;
var pipeline = sprite_pipeline; var pipeline = sprite_pipeline;
bind_pipeline(pass,pipeline); bind_pipeline(pass,pipeline);
@@ -590,16 +593,11 @@ function render_camera(cmds, camera)
hud_queue = []; hud_queue = [];
} }
prosperon.camera = use('camera').make()
var swaps = []; var swaps = [];
function gpupresent() function gpupresent()
{ {
os.clean_transforms(); os.clean_transforms();
prosperon.prerender();
var cmds = render._main.acquire_cmd_buffer(); var cmds = render._main.acquire_cmd_buffer();
render_queue = sprite.to_queue().concat(render_queue);
render_camera(cmds, prosperon.camera); render_camera(cmds, prosperon.camera);
var swapchain_tex = cmds.acquire_swapchain(); var swapchain_tex = cmds.acquire_swapchain();
if (!swapchain_tex) if (!swapchain_tex)
@@ -616,13 +614,13 @@ function gpupresent()
}); });
// imgui // imgui
/* cmds.push_debug_group("imgui") cmds.push_debug_group("imgui")
imgui.prepend(cmds); imgui.prepend(cmds);
var pass = cmds.render_pass({ var pass = cmds.render_pass({
color_targets:[{texture:swapchain_tex}]}); color_targets:[{texture:swapchain_tex}]});
imgui.endframe(cmds,pass); imgui.endframe(cmds,pass);
pass.end(); pass.end();
cmds.pop_debug_group()*/ cmds.pop_debug_group()
} }
cmds.submit() cmds.submit()
} }
@@ -734,7 +732,6 @@ var observed_tex = undefined;
var debug = {} var debug = {}
debug.console = false debug.console = false
var imgui_fn = function imgui_fn() { var imgui_fn = function imgui_fn() {
return
imgui.newframe(); imgui.newframe();
if (debug.console) if (debug.console)
debug.console = imgui.window("console", _ => { debug.console = imgui.window("console", _ => {
@@ -807,45 +804,7 @@ var imgui_fn = function imgui_fn() {
}); });
*/ */
prosperon.imgui(); prosperon.imgui();
// imgui.endframe(render._main); imgui.endframe(render._main);
};
var waittime = 1/240;
var last_frame_time = 0;
var frame_t = 0;
// Ran once per frame
var fpses = [];
var timescale = 1
render.process = function process() {
var now = os.now();
var dt = now - last_frame_time;
if (dt < waittime) os.sleep(waittime-dt);
last_frame_time = os.now();
var dt = last_frame_time - frame_t;
frame_t = last_frame_time;
event.engine_input(e => {
prosperon.dispatch(e.type, e);
});
layout.newframe();
prosperon.appupdate(dt)
input.procdown()
emitter.update(dt * timescale)
os.update_timers(dt * timescale)
prosperon.update(dt*timescale)
current_queue = render_queue;
prosperon.draw()
current_queue = hud_queue;
prosperon.hud()
imgui_fn()
render._main.present();
tracy.end_frame();
}; };
// Some initialization // Some initialization
@@ -866,7 +825,13 @@ tracy.gpu_init()
render.queue = function(cmd) render.queue = function(cmd)
{ {
current_queue.push(cmd) if (Array.isArray(cmd))
for (var i of cmd) current_queue.push(i)
else
current_queue.push(cmd)
} }
render.setup_draw = function() { current_queue = render_queue; prosperon.draw() }
render.setup_hud = function() { current_queue = hud_queue; prosperon.hud() }
return render return render

View File

@@ -1,4 +1,4 @@
//var soloud = use('soloud') var soloud = use('soloud')
var tween = use('tween') var tween = use('tween')
var io = use('io') var io = use('io')
var res = use('resources') var res = use('resources')

View File

@@ -472,14 +472,14 @@ static int rets_SDL_GPUSwapchainComposition[] = {
SDL_GPU_SWAPCHAINCOMPOSITION_SDR, SDL_GPU_SWAPCHAINCOMPOSITION_SDR,
SDL_GPU_SWAPCHAINCOMPOSITION_SDR_LINEAR, SDL_GPU_SWAPCHAINCOMPOSITION_SDR_LINEAR,
SDL_GPU_SWAPCHAINCOMPOSITION_HDR_EXTENDED_LINEAR, SDL_GPU_SWAPCHAINCOMPOSITION_HDR_EXTENDED_LINEAR,
SDL_GPU_SWAPCHAINCOMPOSITION_HDR10_ST2084 // SDL_GPU_SWAPCHAINCOMPOSITION_HDR10_ST2084
}; };
static const char *vals_SDL_GPUSwapchainComposition[] = { static const char *vals_SDL_GPUSwapchainComposition[] = {
"sdr", "sdr",
"linear", "linear",
"hdr", "hdr",
"hdr10" // "hdr10"
}; };
JS2ENUM(SDL_GPUSwapchainComposition, rets_SDL_GPUSwapchainComposition, vals_SDL_GPUSwapchainComposition) JS2ENUM(SDL_GPUSwapchainComposition, rets_SDL_GPUSwapchainComposition, vals_SDL_GPUSwapchainComposition)
@@ -4252,7 +4252,7 @@ JSC_CCALL(gpu_make_sprite_queue,
} }
if (sort) qsort(sprites, quads, sizeof(sprite), sort_sprite); if (sort) qsort(sprites, quads, sizeof(sprite), sort_sprite);
else qsort(sprites, quads, sizeof(sprite), sort_sprite_texture); // else qsort(sprites, quads, sizeof(sprite), sort_sprite_texture);
struct quad_buffers buffers = quad_buffers_new(quads*4); struct quad_buffers buffers = quad_buffers_new(quads*4);
@@ -6977,12 +6977,6 @@ JSC_CCALL(os_clean_transforms,
clean_all(); clean_all();
) )
typedef struct {
const char *name;
const JSCFunctionListEntry *fn;
size_t fn_count;
} ModuleEntry;
JSC_CCALL(os_totalmem, return number2js(js, SDL_GetSystemRAM())) JSC_CCALL(os_totalmem, return number2js(js, SDL_GetSystemRAM()))
JSC_CCALL(os_platform, return JS_NewString(js,SDL_GetPlatform())) JSC_CCALL(os_platform, return JS_NewString(js,SDL_GetPlatform()))
JSC_CCALL(os_hostname, JSC_CCALL(os_hostname,
@@ -7195,29 +7189,19 @@ static const JSCFunctionListEntry js_event_funcs[] = {
MIST_FUNC_DEF(os, engine_input, 1), MIST_FUNC_DEF(os, engine_input, 1),
}; };
#define MISTLINE(NAME) { #NAME, js_##NAME##_funcs, countof(js_##NAME##_funcs) } typedef JSValue (*MODULEFN)(JSContext *js);
static ModuleEntry module_registry[] = { typedef struct {
MISTLINE(io), const char *name;
MISTLINE(os), MODULEFN fn;
MISTLINE(input), } ModuleEntry;
MISTLINE(time),
MISTLINE(math), static ModuleEntry *module_registry = NULL;
MISTLINE(spline),
MISTLINE(geometry),
MISTLINE(graphics),
MISTLINE(js),
MISTLINE(util),
MISTLINE(video),
MISTLINE(event),
};
JSC_SCALL(os_use_embed, JSC_SCALL(os_use_embed,
for (int i = 0; i < sizeof(module_registry)/sizeof(module_registry[0]); i++) { for (int i = 0; i < arrlen(module_registry); i++) {
if (strcmp(str,module_registry[i].name) == 0) { if (strcmp(str,module_registry[i].name) == 0) {
JSValue mod = JS_NewObject(js); ret = module_registry[i].fn(js);
JS_SetPropertyFunctionList(js,mod,module_registry[i].fn, module_registry[i].fn_count);
ret = mod;
break; break;
} }
} }
@@ -7392,6 +7376,24 @@ JSValue js_rtree_get_size(JSContext *js, JSValue self, int magic)
return number2js(js,rtree_count(tree)); return number2js(js,rtree_count(tree));
} }
int rtree_valuefn(const NUMTYPE *min, const NUMTYPE *max, const JSValue *value, struct rtree_iter_data *data)
{
JS_SetPropertyUint32(data->js, data->arr, data->n, JS_DupValue(data->js, *value));
data->n++;
return 1;
}
JSC_CCALL(rtree_values,
rtree *tree = js2rtree(js,self);
struct rtree_iter_data data = {0};
data.js = js;
data.arr = JS_NewArray(js);
data.n = 0;
rtree_scan(tree, rtree_valuefn, &data);
ret = data.arr;
)
static const JSCFunctionListEntry js_rtree_funcs[] = { static const JSCFunctionListEntry js_rtree_funcs[] = {
MIST_FUNC_DEF(rtree, add, 1), MIST_FUNC_DEF(rtree, add, 1),
MIST_FUNC_DEF(rtree, delete, 1), MIST_FUNC_DEF(rtree, delete, 1),
@@ -7399,6 +7401,7 @@ static const JSCFunctionListEntry js_rtree_funcs[] = {
JS_CGETSET_DEF("size", js_rtree_get_size,NULL), JS_CGETSET_DEF("size", js_rtree_get_size,NULL),
MIST_FUNC_DEF(rtree, forEach, 1), MIST_FUNC_DEF(rtree, forEach, 1),
MIST_FUNC_DEF(rtree, has, 1), MIST_FUNC_DEF(rtree, has, 1),
MIST_FUNC_DEF(rtree,values,0),
}; };
JSC_GETSET(sprite, layer, number) JSC_GETSET(sprite, layer, number)
@@ -7447,10 +7450,6 @@ JSValue js_soloud_use(JSContext *js);
JSValue js_tracy_use(JSContext *js); JSValue js_tracy_use(JSContext *js);
#endif #endif
#ifndef NEDITOR
JSValue js_imgui(JSContext *js);
#endif
static void signal_handler(int sig) { static void signal_handler(int sig) {
const char *str = NULL; const char *str = NULL;
switch(sig) { switch(sig) {
@@ -7483,7 +7482,47 @@ static void exit_handler()
script_stop(); script_stop();
} }
MISTUSE(io)
MISTUSE(os)
MISTUSE(input)
MISTUSE(time)
MISTUSE(math)
MISTUSE(spline)
MISTUSE(geometry)
MISTUSE(js)
MISTUSE(graphics)
MISTUSE(util)
MISTUSE(video)
MISTUSE(event)
#ifndef NEDITOR
JSValue js_imgui_use(JSContext *js);
#endif
#define MISTLINE(NAME) (ModuleEntry){#NAME, js_##NAME##_use}
void ffi_load(JSContext *js, int argc, char **argv) { void ffi_load(JSContext *js, int argc, char **argv) {
arrput(module_registry, MISTLINE(io));
arrput(module_registry, MISTLINE(os));
arrput(module_registry, MISTLINE(input));
arrput(module_registry, MISTLINE(time));
arrput(module_registry, MISTLINE(math));
arrput(module_registry, MISTLINE(spline));
arrput(module_registry, MISTLINE(geometry));
arrput(module_registry, MISTLINE(graphics));
arrput(module_registry, MISTLINE(js));
arrput(module_registry, MISTLINE(util));
arrput(module_registry, MISTLINE(video));
arrput(module_registry, MISTLINE(event));
arrput(module_registry, MISTLINE(soloud));
arrput(module_registry,MISTLINE(layout));
#ifndef NEDITOR
arrput(module_registry, MISTLINE(imgui));
#endif
#ifdef TRACY_ENABLE
arrput(module_registry, MISTLINE(tracy));
#endif
JSValue globalThis = JS_GetGlobalObject(js); JSValue globalThis = JS_GetGlobalObject(js);
QJSCLASSPREP_FUNCS(rtree) QJSCLASSPREP_FUNCS(rtree)
@@ -7540,17 +7579,6 @@ void ffi_load(JSContext *js, int argc, char **argv) {
JS_FreeValue(js,jsnumber); JS_FreeValue(js,jsnumber);
JS_FreeValue(js,number_proto); JS_FreeValue(js,number_proto);
JS_SetPropertyStr(js, globalThis, "layout", js_layout_use(js));
JS_SetPropertyStr(js, globalThis, "soloud", js_soloud_use(js));
#ifdef TRACY_ENABLE
JS_SetPropertyStr(js, globalThis, "tracy", js_tracy_use(js));
#endif
#ifndef NEDITOR
JS_SetPropertyStr(js, globalThis, "imgui", js_imgui(js));
#endif
x_atom = JS_NewAtom(js,"x"); x_atom = JS_NewAtom(js,"x");
y_atom = JS_NewAtom(js,"y"); y_atom = JS_NewAtom(js,"y");
width_atom = JS_NewAtom(js,"width"); width_atom = JS_NewAtom(js,"width");

View File

@@ -8,6 +8,8 @@
#include "imgui_impl_sdl3.h" #include "imgui_impl_sdl3.h"
#include "imgui_impl_sdlgpu3.h" #include "imgui_impl_sdlgpu3.h"
#include "qjs_macros.h"
extern "C" { extern "C" {
SDL_GPUDevice *js2SDL_GPUDevice(JSContext *js, JSValue v); SDL_GPUDevice *js2SDL_GPUDevice(JSContext *js, JSValue v);
SDL_GPURenderPass *js2SDL_GPURenderPass(JSContext *js, JSValue v); SDL_GPURenderPass *js2SDL_GPURenderPass(JSContext *js, JSValue v);
@@ -18,30 +20,6 @@ SDL_Window *js2SDL_Window(JSContext *js, JSValue v);
static int START = 0; static int START = 0;
#define JSC_CCALL(NAME, ...) static JSValue js_##NAME (JSContext *js, JSValue self, int argc, JSValue *argv) { \
JSValue ret = JS_UNDEFINED; \
__VA_ARGS__ ;\
return ret; \
} \
#define JSC_SCALL(NAME, ...) static JSValue js_##NAME (JSContext *js, JSValue self, int argc, JSValue *argv) { \
JSValue ret = JS_UNDEFINED; \
const char *str = JS_ToCString(js, argv[0]); \
__VA_ARGS__ ;\
JS_FreeCString(js, str); \
return ret; \
} \
#define JSC_SSALL(NAME, ...) static JSValue js_##NAME (JSContext *js, JSValue self, int argc, JSValue *argv) { \
JSValue ret = JS_UNDEFINED; \
const char *str = JS_ToCString(js, argv[0]); \
const char *str2 = JS_ToCString(js, argv[1]); \
__VA_ARGS__ ; \
JS_FreeCString(js, str); \
JS_FreeCString(js, str2); \
return ret; \
} \
static inline int js_arrlen(JSContext *js, JSValue v) static inline int js_arrlen(JSContext *js, JSValue v)
{ {
JSValue len = JS_GetPropertyStr(js, v, "length"); JSValue len = JS_GetPropertyStr(js, v, "length");
@@ -275,7 +253,7 @@ JSC_CCALL(imgui_plothovered,
return JS_NewBool(js,ImPlot::IsPlotHovered()); return JS_NewBool(js,ImPlot::IsPlotHovered());
) )
JSC_SSALL(imgui_plotaxes, JSC_SSCALL(imgui_plotaxes,
ImPlot::SetupAxes(str,str2); ImPlot::SetupAxes(str,str2);
) )
@@ -292,7 +270,7 @@ JSC_CCALL(imgui_fitaxis,
ImPlot::SetNextAxisToFit((js2number(js, argv[0]) == 0) ? ImAxis_X1 : ImAxis_Y1); ImPlot::SetNextAxisToFit((js2number(js, argv[0]) == 0) ? ImAxis_X1 : ImAxis_Y1);
) )
JSC_SSALL(imgui_textinput, JSC_SSCALL(imgui_textinput,
char buffer[512]; char buffer[512];
if (JS_IsUndefined(argv[1])) if (JS_IsUndefined(argv[1]))
buffer[0] = 0; buffer[0] = 0;
@@ -306,7 +284,7 @@ JSC_SSALL(imgui_textinput,
ret = JS_DupValue(js,argv[1]); ret = JS_DupValue(js,argv[1]);
) )
JSC_SSALL(imgui_textbox, JSC_SSCALL(imgui_textbox,
char buffer[512]; char buffer[512];
if (JS_IsUndefined(argv[1])) if (JS_IsUndefined(argv[1]))
buffer[0] = 0; buffer[0] = 0;
@@ -822,8 +800,8 @@ JSC_CCALL(imgui_init,
START = 1; START = 1;
) )
#define MIST_FUNC_DEF(CLASS,NAME,AMT) JS_CFUNC_DEF(#NAME, AMT, js_##CLASS##_##NAME) extern "C" {
static const JSCFunctionListEntry js_imgui_funcs[] = { const JSCFunctionListEntry js_imgui_funcs[] = {
MIST_FUNC_DEF(imgui, windowpos, 0), MIST_FUNC_DEF(imgui, windowpos, 0),
MIST_FUNC_DEF(imgui, plot2pixels, 1), MIST_FUNC_DEF(imgui, plot2pixels, 1),
MIST_FUNC_DEF(imgui, plotpos, 0), MIST_FUNC_DEF(imgui, plotpos, 0),
@@ -920,14 +898,13 @@ static const JSCFunctionListEntry js_imgui_funcs[] = {
MIST_FUNC_DEF(imgui, init, 2), MIST_FUNC_DEF(imgui, init, 2),
}; };
extern "C" {
void gui_input(SDL_Event *e) void gui_input(SDL_Event *e)
{ {
if (!START) return; if (!START) return;
ImGui_ImplSDL3_ProcessEvent(e); ImGui_ImplSDL3_ProcessEvent(e);
} }
JSValue js_imgui(JSContext *js) JSValue js_imgui_use(JSContext *js)
{ {
JSValue imgui = JS_NewObject(js); JSValue imgui = JS_NewObject(js);
JS_SetPropertyFunctionList(js, imgui, js_imgui_funcs, sizeof(js_imgui_funcs)/sizeof(js_imgui_funcs[0])); JS_SetPropertyFunctionList(js, imgui, js_imgui_funcs, sizeof(js_imgui_funcs)/sizeof(js_imgui_funcs[0]));
@@ -938,7 +915,7 @@ JSValue js_imgui(JSContext *js)
static int js_init_imgui(JSContext *js, JSModuleDef *m) { static int js_init_imgui(JSContext *js, JSModuleDef *m) {
JS_SetModuleExportList(js, m, js_imgui_funcs, sizeof(js_imgui_funcs)/sizeof(JSCFunctionListEntry)); JS_SetModuleExportList(js, m, js_imgui_funcs, sizeof(js_imgui_funcs)/sizeof(JSCFunctionListEntry));
JS_SetModuleExport(js, m, "default", js_imgui(js)); JS_SetModuleExport(js, m, "default", js_imgui_use(js));
return 0; return 0;
} }

View File

@@ -140,4 +140,14 @@ JSValue TYPE##_proto = JS_NewObject(js); \
JS_SetPropertyFunctionList(js, TYPE##_proto, js_##TYPE##_funcs, countof(js_##TYPE##_funcs)); \ JS_SetPropertyFunctionList(js, TYPE##_proto, js_##TYPE##_funcs, countof(js_##TYPE##_funcs)); \
JS_SetClassProto(js, js_##TYPE##_id, TYPE##_proto); \ JS_SetClassProto(js, js_##TYPE##_id, TYPE##_proto); \
#define MISTUSE(NAME) \
JSValue js_##NAME##_use(JSContext *js) { \
JSValue mod = JS_NewObject(js); \
JS_SetPropertyFunctionList(js,mod,js_##NAME##_funcs,countof(js_##NAME##_funcs)); \
return mod; } \
#define MISTLINE(NAME) (ModuleEntry){ #NAME, js_##NAME##_funcs, countof(js_##NAME##_funcs) }
#define countof(x) (sizeof(x)/sizeof((x)[0])) #define countof(x) (sizeof(x)/sizeof((x)[0]))