messages
Some checks failed
Build and Deploy / build-linux (push) Successful in 1m11s
Build and Deploy / build-windows (CLANG64) (push) Failing after 6m17s
Build and Deploy / package-dist (push) Has been skipped
Build and Deploy / deploy-itch (push) Has been skipped
Build and Deploy / deploy-gitea (push) Has been skipped

This commit is contained in:
2025-03-19 12:40:31 -05:00
parent 8627fc52ef
commit 9410af3a69
11 changed files with 127 additions and 273 deletions

View File

@@ -137,7 +137,7 @@ deps += dependency('soloud', static:true)
deps += dependency('libqrencode', static: true)
sources = []
src += ['anim.c', 'config.c', 'datastream.c','font.c','HandmadeMath.c','jsffi.c','model.c','render.c','script.c','simplex.c','spline.c', 'timer.c', 'transform.c','prosperon.c', 'wildmatch.c', 'sprite.c', 'rtree.c', 'qjs_dmon.c', 'qjs_nota.c', 'qjs_enet.c', 'qjs_soloud.c', 'qjs_qr.c', 'qjs_wota.c', 'monocypher.c']
src += ['anim.c', 'config.c', 'datastream.c','font.c','HandmadeMath.c','jsffi.c','model.c','render.c','script.c','simplex.c','spline.c', 'transform.c','prosperon.c', 'wildmatch.c', 'sprite.c', 'rtree.c', 'qjs_dmon.c', 'qjs_nota.c', 'qjs_enet.c', 'qjs_soloud.c', 'qjs_qr.c', 'qjs_wota.c', 'monocypher.c']
# quirc src
src += ['thirdparty/quirc/quirc.c', 'thirdparty/quirc/decode.c','thirdparty/quirc/identify.c', 'thirdparty/quirc/version_db.c']

View File

@@ -235,27 +235,6 @@ prosperon.c_types.datastream[prosperon.DOC].callback = `A function to call whene
`;
//
// timer
//
prosperon.c_types.timer[prosperon.DOC] = {}
prosperon.c_types.timer[prosperon.DOC][prosperon.DOC] = `A scheduled callback or countdown. Freed automatically once no longer referenced
or once it completes.
`;
prosperon.c_types.timer[prosperon.DOC].remain = `Get or set how many seconds remain before the timer triggers.
:param value: (when setting) A float specifying new time remaining.
:return: The current time left (when getting), or None (when setting).
`;
prosperon.c_types.timer[prosperon.DOC].fn = `Get or set the function called when the timer expires.
:param value: (when setting) The function.
:return: The function or undefined if none is set.
`;
//
// rtree
//
@@ -367,22 +346,6 @@ prosperon.c_types.SDL_Cursor[prosperon.DOC] = {}
prosperon.c_types.SDL_Cursor[prosperon.DOC][prosperon.DOC] = `An SDL cursor handle. Freed automatically on GC. No direct methods.
`;
//
// SDL_Thread
//
prosperon.c_types.SDL_Thread[prosperon.DOC] = {}
prosperon.c_types.SDL_Thread[prosperon.DOC][prosperon.DOC] = `A handle to an SDL-created thread. Freed on GC after join.
Note: The engine generally doesn't expose custom usage for threads.
`;
prosperon.c_types.SDL_Thread[prosperon.DOC].wait = `Block until this thread terminates.
:return: None
`;
//
// SDL_Window
//

View File

@@ -62,7 +62,6 @@ Object.defineProperty(Function.prototype, "hashify", {
var io = use_embed('io')
var RESPATH = 'scripts/modules/resources.js'
var canonical = io.realdir(RESPATH) + 'resources.js'
var content = io.slurp(RESPATH)
@@ -88,6 +87,8 @@ prosperon.PATH = [
"scripts/modules/ext/",
]
console.print("HERE")
// path is the path of a module or script to resolve
var script_fn = function script_fn(path) {
var parsed = {}
@@ -222,6 +223,8 @@ console[prosperon.DOC] = {
clear: "Clear console."
}
var BASEPATH = 'scripts/core/base.js'
var script = io.slurp(BASEPATH)
var fnname = "base"
@@ -245,7 +248,7 @@ function add_timer(obj, fn, seconds) {
else stop.seconds = timer.remain
}
var timer = os.make_timer(execute)
// var timer = os.make_timer(execute)
timer.remain = seconds
stop.remain = seconds
@@ -395,6 +398,8 @@ Register.check_registers = function check_registers(obj) {
}
}
Register.add_cb("appupdate")
Register.add_cb("update").doc = "Called once per frame."
Register.add_cb("physupdate")
@@ -488,6 +493,8 @@ actor.spawn = function spawn(script, config, callback) {
return underling
}
actor.clear = function actor_clear() {
this[UNDERLINGS].forEach(p => {
p.kill()
@@ -521,16 +528,23 @@ actor.delay = function(fn, seconds) {
}
actor.delay.doc = `Call 'fn' after 'seconds' with 'this' set to the actor.`
var act = use('actor')
actor[UNDERLINGS] = new Set()
globalThis.mixin("color")
var DOCPATH = 'scripts/core/doc.js'
var script = io.slurp(DOCPATH)
var fnname = "doc"
script = `(function ${fnname}() { ${script}; })`
js.eval(DOCPATH, script)()
//js.eval(DOCPATH, script)()
/*
When handling a message, the message appears like this:
@@ -555,6 +569,7 @@ js.eval(DOCPATH, script)()
}
*/
var enet = use('enet')
var util = use('util')
var math = use('math')
@@ -564,8 +579,6 @@ var nota = use('nota')
var HEADER = Symbol()
var ar = 60 // seconds before reclamation
var $actor = {
toString: print_actor
}
@@ -744,13 +757,8 @@ $_.stop = function(actor) {
}
$_.stop[prosperon.DOC] = "The stop function stops an underling."
var unneeded_fn = $_.stop
var unneeded_time = ar
$_.unneeded = function(fn, seconds = ar) {
if (typeof fn !== 'function') throw new Error('Must supply a function to unneeded.')
unneeded_fn = fn
unneeded_time = seconds
$_.unneeded = function(fn, seconds) {
os.unnneeded(fn, seconds);
}
$_.unneeded[prosperon.DOC] = "registers a function that is called when the actor..."
@@ -852,7 +860,7 @@ if (prosperon.args.program) actor.spawn(prosperon.args.program)
function destroyself() {
console.log(`Got the message to destroy self.`)
if (overling) actor_send(overling, { type: "stopped", id: prosperon.id })
doexit = true
os.destroy(prosperon.id);
}
function handle_actor_disconnect(id) {
@@ -879,7 +887,6 @@ function handle_message(msg) {
return
}
}
unneeded_timer()
switch (msg.type) {
case "user":
var letter = msg.data
@@ -922,9 +929,6 @@ function handle_message(msg) {
var greeter = greeters[msg.id]
if (greeter) greeter({type: "actor_started", actor: create_actor(msg)})
}
unneeded_timer = $_.delay(unneeded_fn, unneeded_time)
}
var unneeded_timer = $_.delay($_.stop, ar)
})()

View File

@@ -4,7 +4,6 @@ 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 tracy = use('tracy')
@@ -30,7 +29,7 @@ function step() {
dt = last_frame_time - frame_t
frame_t = last_frame_time
event.engine_input(e => prosperon.dispatch(e.type, e))
// event.engine_input(e => prosperon.dispatch(e.type, e))
layout.newframe()
prosperon.appupdate(dt)

View File

@@ -22,7 +22,6 @@
#include "par/par_streamlines.h"
#include "par/par_shapes.h"
#include <stdint.h>
#include "timer.h"
#include "cute_aseprite.h"
#include "cgltf.h"
#include "physfs.h"
@@ -69,7 +68,6 @@ typedef struct rtree rtree;
int randombytes(void *buf, size_t n);
static Uint32 timer_cb_event;
static int trace = 0;
#ifdef __APPLE__
@@ -1086,15 +1084,6 @@ static void js_transform_mark(JSRuntime *rt, JSValueConst val, JS_MarkFunc *mark
QJSCLASSMARK(transform)
QJSCLASS(font)
QJSCLASS(datastream)
static JSClassID js_timer_id;
static void js_timer_mark(JSRuntime *rt, JSValueConst val, JS_MarkFunc *mark_func) {
timer *t = JS_GetOpaque(val,js_timer_id);
if (!t) return;
JS_MarkValue(rt, t->fn, mark_func);
}
QJSCLASSMARK(timer)
QJSCLASS(SDL_Window)
QJSCLASS(SDL_Renderer)
QJSCLASS(SDL_Camera)
@@ -6257,14 +6246,6 @@ static const JSCFunctionListEntry js_datastream_funcs[] = {
CGETSET_ADD(datastream, callback),
};
JSC_GETSET_CALLBACK(timer, fn)
JSC_GETSET(timer, remain, number)
static const JSCFunctionListEntry js_timer_funcs[] = {
CGETSET_ADD(timer, remain),
CGETSET_ADD(timer, fn),
};
JSC_GETSET(font, linegap, number)
JSC_GET(font, height, number)
JSC_GET(font, ascent, number)
@@ -6506,9 +6487,6 @@ JSC_SSCALL(os_eval,
ret = JS_Eval(js, str2, strlen(str2), str, JS_EVAL_FLAG_STRICT);
)
JSC_CCALL(os_make_timer, return timer2js(js,timer_make(js,argv[0])))
JSC_CCALL(os_update_timers, timer_update(js, js2number(js,argv[0])))
Uint32 timer_cb(prosperon_rt *actor, SDL_TimerID id, Uint32 interval)
{
int idx = hmgeti(actor->timers, id);
@@ -7142,6 +7120,7 @@ JSC_CCALL(os_mailbox_push,
const char *id = JS_ToCString(js, argv[0]);
prosperon_rt *target = get_actor(id);
JS_FreeCString(js,id);
if (!target)
return JS_ThrowInternalError(js, "No mailbox found for given ID");
@@ -7159,57 +7138,27 @@ JSC_CCALL(os_mailbox_push,
)
JSC_CCALL(os_register_actor,
printf("calling registera ctor for context %p\n", js);
prosperon_rt *rt = JS_GetContextOpaque(js);
printf("context after get_opaque: %p\n", js);
char *id = JS_ToCString(js, argv[0]);
printf("context after get_id: %p\n", js);
char *err = register_actor(id, rt);
printf("context after register_actor: %p\n", js);
if (err) return JS_ThrowInternalError(js, "Could not register actor: %s", err);
rt->message_handle = JS_DupValue(js, argv[1]);
printf("context after dup_value: %p\n", js);
const char *fnstr = JS_ToCString(js, rt->message_handle);
printf("context after get_fnstr: %p\n", js);
printf("registered %s\n", fnstr);
JS_FreeCString(js, fnstr);
rt->context = js;
printf("jsvalue is in context %p\n", js);
int tag = JS_VALUE_GET_TAG(rt->message_handle);
printf("message_handle tag: %d\n", tag);
if (tag == 0) printf(" as int: %d\n", JS_VALUE_GET_INT(rt->message_handle));
else printf(" as ptr: %p\n", JS_VALUE_GET_PTR(rt->message_handle));
JS_FreeCString(js, id);
)
JSC_CCALL(os_mailbox_exist,
const char *id = JS_ToCString(js, argv[0]);
prosperon_rt *actor = get_actor(id);
printf("actor from %s is %p\n", id, actor);
JS_FreeCString(js, id);
return JS_NewBool(js, actor ? 1 : 0);
)
JSC_CCALL(os_waitevent,
SDL_Event event;
double secs;
JS_ToFloat64(js, &secs, argv[1]);
while (SDL_WaitEventTimeout(&event, secs*1000.0f)) {
if (event.type == timer_cb_event) {
JSValue *fn = event.user.data1;
JSValue ret = JS_Call(js, *fn, JS_UNDEFINED, 0, NULL);
JS_FreeValue(js,*fn);
free(fn);
uncaught_exception(js,ret);
} else {
gui_input(&event);
JSValue e = event2js(js,event);
JSValue ret = JS_Call(js,argv[0], JS_UNDEFINED, 1, &e);
uncaught_exception(js,ret);
}
}
return JS_UNDEFINED;
JSC_CCALL(os_unneeded,
prosperon_rt *actor = JS_GetContextOpaque(js);
actor->unneeded = JS_DupValue(js, argv[1]);
actor->unneeded_secs = js2number(js, argv[2]);
)
JSValue js_os_get_trace(JSContext *js, JSValue self)
@@ -7223,6 +7172,11 @@ JSValue js_os_set_trace(JSContext *js, JSValue self, JSValue value)
return JS_UNDEFINED;
}
JSC_CCALL(os_destroy,
prosperon_rt *rt = JS_GetContextOpaque(js);
actor_free(rt);
)
static const JSCFunctionListEntry js_os_funcs[] = {
MIST_FUNC_DEF(os, make_transform, 0),
MIST_FUNC_DEF(os, clean_transforms, 0),
@@ -7242,9 +7196,6 @@ static const JSCFunctionListEntry js_os_funcs[] = {
MIST_FUNC_DEF(os, openurl, 1),
MIST_FUNC_DEF(os, make_timer, 1),
MIST_FUNC_DEF(os, update_timers, 1),
MIST_FUNC_DEF(os, sleep, 1),
MIST_FUNC_DEF(os, battery_pct, 0),
MIST_FUNC_DEF(os, battery_voltage, 0),
@@ -7261,13 +7212,14 @@ static const JSCFunctionListEntry js_os_funcs[] = {
MIST_FUNC_DEF(os, system, 1),
MIST_FUNC_DEF(os, createprocess, 0),
MIST_FUNC_DEF(os, createactor, 1),
MIST_FUNC_DEF(os, waitevent, 2),
MIST_FUNC_DEF(os, mailbox_push, 2),
MIST_FUNC_DEF(os, mailbox_exist, 1),
MIST_FUNC_DEF(os, addtimer, 3),
MIST_FUNC_DEF(os, removetimer, 2),
MIST_FUNC_DEF(os, register_actor, 2),
MIST_FUNC_DEF(os, unneeded, 2),
MIST_FUNC_DEF(os, destroy, 0),
};
JSC_CCALL(js_dump_class, return js_get_object_class_distribution(js))
@@ -7339,43 +7291,6 @@ static const JSCFunctionListEntry js_video_funcs[] = {
MIST_FUNC_DEF(os, make_video, 1),
};
// Polls and handles all input events
JSValue js_os_engine_input(JSContext *js, JSValue self, int argc, JSValue *argv) {
SDL_Event event;
while (SDL_PollEvent(&event)) {
if (event.type == timer_cb_event) {
JSValue *fn = event.user.data1;
JSValue ret = JS_Call(js, *fn, JS_UNDEFINED, 0, NULL);
JS_FreeValue(js,*fn);
uncaught_exception(js,ret);
continue;
}
gui_input(&event);
JSValue e = event2js(js,event);
JSValue ret = JS_Call(js,argv[0], JS_UNDEFINED, 1, &e);
uncaught_exception(js,ret);
}
return JS_UNDEFINED;
}
JSC_CCALL(os_push_event,
SDL_UserEvent e;
SDL_zero(e);
e.type = SDL_EVENT_USER;
e.timestamp = SDL_GetTicksNS();
e.code = 0;
JSValue fn = JS_DupValue(js,argv[0]);
e.data1 = malloc(sizeof(JSValue));
*(JSValue*)e.data1 = fn;
SDL_PushEvent(&e);
)
static const JSCFunctionListEntry js_event_funcs[] = {
MIST_FUNC_DEF(os, push_event, 1),
MIST_FUNC_DEF(os, engine_input, 1),
};
JSC_SCALL(os_use_embed,
prosperon_rt *rt = JS_GetContextOpaque(js);
ModuleEntry *module_registry = rt->module_registry;
@@ -7841,7 +7756,6 @@ MISTUSE(js)
MISTUSE(graphics)
MISTUSE(util)
MISTUSE(video)
MISTUSE(event)
MISTUSE(camera)
MISTUSE(debug)
MISTUSE(crypto)
@@ -7867,7 +7781,7 @@ void ffi_load(JSContext *js)
arrput(rt->module_registry, MISTLINE(js));
arrput(rt->module_registry, MISTLINE(util));
arrput(rt->module_registry, MISTLINE(video));
arrput(rt->module_registry, MISTLINE(event));
arrput(rt->module_registry, MISTLINE(soloud));
arrput(rt->module_registry, MISTLINE(layout));
arrput(rt->module_registry, MISTLINE(miniz));
@@ -7920,10 +7834,7 @@ void ffi_load(JSContext *js)
QJSCLASSPREP_FUNCS(transform);
QJSCLASSPREP_FUNCS(font);
QJSCLASSPREP_FUNCS(datastream);
QJSCLASSPREP_FUNCS(timer);
timer_cb_event = SDL_RegisterEvents(1);
JS_SetPropertyStr(js, globalThis, "use_dyn", JS_NewCFunction(js,js_os_use_dyn,"use_dyn", 1));
JS_SetPropertyStr(js, globalThis, "use_embed", JS_NewCFunction(js,js_os_use_embed,"use_embed", 1));

View File

@@ -108,16 +108,62 @@ if (!ret) {
return 1;
}
void free_actor(prosperon_rt *actor)
Uint32 actor_remove_cb(prosperon_rt *actor, Uint32 id, Uint32 interval)
{
for (int i = 0; i < actor->cmd.argc; i++) free(actor->cmd.argv[i]);
script_stop(actor->context);
JSRuntime *rt = JS_GetRuntime(actor->context);
arrfree(actor->messages);
SDL_DestroyMutex(actor->mutex);
actor_free(actor);
}
void actor_free(prosperon_rt *actor)
{
// first, remove it from the queue
shdel(actors, actor->id);
JSContext *js = actor->context;
SDL_LockMutex(actor->mutex);
JS_FreeValue(js, actor->cycle_fn);
JS_FreeValue(js, actor->idx_buffer);
JS_FreeValue(js, actor->message_handle);
JS_FreeValue(js, actor->on_exception);
SDL_RemoveTimer(actor->ar);
for (int i = 0; i < arrlen(actor->js_swapchains); i++)
JS_FreeValue(js, actor->js_swapchains[i]);
for (int i = 0; i < arrlen(actor->events); i++)
JS_FreeValue(js, actor->events[i]);
for (int i = 0; i < hmlen(actor->timers); i++)
JS_FreeValue(js, actor->timers[i].value);
// free(actor->timers);
arrfree(actor->js_swapchains);
arrfree(actor->events);
arrfree(actor->messages);
arrfree(actor->module_registry);
free(actor);
SDL_DestroyMutex(actor->mutex);
JSRuntime *rt = JS_GetRuntime(js);
JS_FreeContext(js);
JS_FreeRuntime(rt);
free(actor->id);
free(actor);
}
void set_actor_state(prosperon_rt *actor)
{
SDL_LockMutex(actor->mutex);
if (arrlen(actor->messages) == 0) {
actor->state = ACTOR_IDLE;
actor->ar = SDL_AddTimerNS(1e9, actor_remove_cb, actor);
} else {
actor->state = ACTOR_READY;
SDL_LockMutex(queue_mutex);
arrput(ready_queue, actor);
SDL_SignalCondition(queue_cond);
SDL_UnlockMutex(queue_mutex);
}
SDL_UnlockMutex(actor->mutex);
}
// this function should be called to spin off a new thread with actor
@@ -131,6 +177,8 @@ prosperon_rt *create_actor(int argc, char **argv)
script_startup(rt);
set_actor_state(rt);
return rt;
}
@@ -141,36 +189,31 @@ void js_dofree(JSRuntime *rt, void *opaque, void *ptr)
void run_actor_turn(prosperon_rt *actor)
{
SDL_LockMutex(actor->mutex);
if (actor->state != ACTOR_READY) goto END;
if (arrlen(actor->messages) == 0) {
actor->state = ACTOR_IDLE;
goto END;
}
struct message msg = actor->messages[0];
arrdel(actor->messages, 0);
JSValue arg = JS_NewArrayBuffer(actor->context, msg.data, msg.size, js_dofree, NULL, 0);
printf("running actor %p, fn? %d. context %p\n", actor, JS_IsFunction(actor->context, actor->message_handle), actor->context);
int tag = JS_VALUE_GET_TAG(actor->message_handle);
printf("message_handle tag: %d, value: %llu\n", tag, actor->message_handle);
if (tag >= 0) printf(" as ptr: %p\n", JS_VALUE_GET_PTR(actor->message_handle));
JSValue fstr = JS_ToString(actor->context, actor->message_handle);
const char *fnstr = JS_ToCString(actor->context, fstr);
printf("function is %s\n", fnstr ? fnstr : "(null)");
JS_FreeCString(actor->context, fnstr);
JSValue result = JS_Call(actor->context, actor->message_handle, JS_UNDEFINED, 1, &arg);
printf("exception? %d\n", JS_IsException(result));
if (JS_IsException(result)) {
JSValue exception = JS_GetException(actor->context);
const char *err_str = JS_ToCString(actor->context, exception);
printf("exception details: %s\n", err_str ? err_str : "(null)");
JS_FreeCString(actor->context, err_str);
JS_FreeValue(actor->context, exception);
}
uncaught_exception(actor->context, result);
printf("ran actor %p\n", actor);
END:
SDL_UnlockMutex(actor->mutex);
SDL_LockMutex(actor->mutex);
actor->state = ACTOR_RUNNING;
// Process all messages until the message queue is empty
while (arrlen(actor->messages) > 0) {
struct message msg = actor->messages[0];
arrdel(actor->messages, 0);
JSValue arg = JS_NewArrayBuffer(actor->context, msg.data, msg.size, js_dofree, NULL, 0);
JSValue result = JS_Call(actor->context, actor->message_handle, JS_UNDEFINED, 1, &arg);
uncaught_exception(actor->context, result);
JS_FreeValue(actor->context, arg); // Free the argument after use
}
// After all messages are processed, process one event if any exist
while (arrlen(actor->messages) > 0) {
JSValue event = actor->events[0];
arrdel(actor->events, 0);
JSValue result = JS_Call(actor->context, event, JS_UNDEFINED, 0, NULL);
uncaught_exception(actor->context, result);
JS_FreeValue(actor->context, event);
}
// Update state and re-queue if necessary
set_actor_state(actor);
SDL_UnlockMutex(actor->mutex);
}
int reclaimer_thread(void *data)
@@ -337,16 +380,19 @@ prosperon_rt *get_actor(char *id)
char *register_actor(char *id, prosperon_rt *actor)
{
if (shgeti(actors, id) != -1) return "Actor with given ID already exists.";
actor->id = strdup(id);
shput(actors, id, actor);
printf("registerd actor %s as %p\n", id, actor);
return NULL;
}
void send_message(prosperon_rt *target, struct message msg)
{
printf("sending message to actor %p\n", target);
SDL_LockMutex(target->mutex);
arrput(target->messages, msg);
if (target->ar) {
SDL_RemoveTimer(target->ar);
target->ar = 0;
}
SDL_UnlockMutex(target->mutex);
actor_signal(target);
@@ -354,7 +400,6 @@ void send_message(prosperon_rt *target, struct message msg)
void actor_signal(prosperon_rt *actor)
{
printf("waking actor %p\n", actor);
SDL_LockMutex(actor->mutex);
if (actor->state != ACTOR_READY) {
actor->state = ACTOR_READY;

View File

@@ -43,11 +43,14 @@ struct message {
typedef struct prosperon_rt {
cmdargs cmd; // args this actor was started with
JSContext *context; // The context this actor uses
char *id;
MTRand mrand;
JSValue cycle_fn;
JSValue idx_buffer;
JSValue on_exception;
JSValue message_handle;
JSValue unneeded;
double unneeded_secs;
int idx_count;
ModuleEntry *module_registry;
JSValue *js_swapchains;
@@ -56,6 +59,7 @@ typedef struct prosperon_rt {
SDL_Mutex *mutex; // blocks access to modifying this actor
struct message *messages;
int state; //
Uint32 ar; // "actor removal" timer
} prosperon_rt;
prosperon_rt *get_actor(char *id);
@@ -64,4 +68,5 @@ prosperon_rt *create_actor();
void actor_signal(prosperon_rt *actor);
void actor_turn(prosperon_rt *actor);
void send_message(prosperon_rt *actor, struct message msg);
void actor_free(prosperon_rt *actor);
#endif

View File

@@ -155,7 +155,6 @@ void script_startup(prosperon_rt *prt) {
JS_SetContextOpaque(js, prt);
prt->context = js;
printf("started actor %p with context %p\n", prt, prt->context);
ffi_load(js);
@@ -176,21 +175,6 @@ void script_startup(prosperon_rt *prt) {
SDL_UnlockMutex(prt->mutex);
}
void script_stop(JSContext *js)
{
prosperon_rt *prt = JS_GetContextOpaque(js);
JS_FreeValue(js, prt->cycle_fn);
JS_FreeValue(js, prt->idx_buffer);
for (int i = 0; i < arrlen(prt->js_swapchains); i++)
JS_FreeValue(js, prt->js_swapchains[i]);
free(prt);
JSRuntime *rt = JS_GetRuntime(js);
JS_FreeContext(js);
JS_FreeRuntime(rt);
}
void uncaught_exception(JSContext *js, JSValue v)
{
if (!JS_IsException(v)) {

View File

@@ -6,7 +6,6 @@
#include "prosperon.h"
void script_startup(prosperon_rt *rt);
void script_stop(JSContext*);
void script_evalf(JSContext *js, const char *format, ...);
JSValue script_eval(JSContext *js, const char *file, const char *script);

View File

@@ -1,42 +0,0 @@
#include "timer.h"
#include <stdio.h>
#include "stb_ds.h"
timer **timers;
timer *timer_make(JSContext *js, JSValue fn)
{
timer *t = calloc(sizeof(*t),1);
t->fn = JS_DupValue(js,fn);
arrput(timers, t);
return t;
}
void timer_free(JSRuntime *rt, timer *t)
{
for (int i = 0; i < arrlen(timers); i++) {
if (timers[i] == t) {
arrdelswap(timers,i);
break;
}
}
JS_FreeValueRT(rt, t->fn);
free(t);
}
void timer_update(JSContext *js, double dt)
{
for (int i = 0; i < arrlen(timers); i++) {
if (timers[i]->remain <= -10000) continue;
timers[i]->remain -= dt;
if (timers[i]->remain <= 0) {
timers[i]->remain = -10000;
JSValue fn = JS_DupValue(js, timers[i]->fn);
JSValue r = JS_Call(js,fn, JS_UNDEFINED, 0, NULL);
uncaught_exception(js,r);
JS_FreeValue(js, fn);
}
}
}

View File

@@ -1,14 +0,0 @@
#ifndef TIMER_H
#include "script.h"
typedef struct timer {
double remain;
JSValue fn;
} timer;
timer *timer_make(JSContext *js, JSValue fn);
void timer_free(JSRuntime *rt, timer *t);
void timer_update(JSContext *js, double dt);
#endif