diff --git a/bindings.json b/bindings.json index 13ceb9a..6fa0f43 100644 --- a/bindings.json +++ b/bindings.json @@ -2,8 +2,10 @@ { "name": "raylib_core", "functions": [ - { "name": "SetWindowTitle", "jsName": "setWindowTitle" }, - { "name": "SetWindowPosition", "jsName": "setWindowPosition" } + { "name": "SetWindowTitle" }, + { "name": "SetWindowPosition" }, + { "name": "BeginDrawing" }, + { "name": "EndDrawing" } ] } ] \ No newline at end of file diff --git a/generate_bindings.js b/generate_bindings.js index 2a8e1f6..a1e0eb7 100644 --- a/generate_bindings.js +++ b/generate_bindings.js @@ -46,32 +46,76 @@ const generateFunction = (functionList) => (func) => { return cfunc.generate() } +const generateParameterCheck = (func) => (param, i) => { + const errMsg = `${func.name} argument ${param.name} (${i}) needs to be` + switch(param.type){ + case "const char *": + return `if(!JS_IsString(argv[${i}])) return JS_ThrowReferenceError(ctx, "${errMsg} a string");` + case "int": + return `if(!JS_IsNumber(argv[${i}])) return JS_ThrowReferenceError(ctx, "${errMsg} a number");` + default: + throw new Error("Unknown parameter type: "+param.type) + } +} + const generateParameter = (param,i) => { switch(param.type){ case "const char *": return `${param.type} ${param.name} = JS_ToCString(ctx, argv[${i}]);` case "int": - return `${param.type} ${param.name};\n JS_ToInt32(ctx, &${param.name}, argv[${i}]);` + return `${param.type} ${param.name}; JS_ToInt32(ctx, &${param.name}, argv[${i}]);` + default: + throw new Error("Unknown parameter type: "+param.type) + } +} + +const generateParameterCleanup = (param,i) => { + switch(param.type){ + case "const char *": + return `JS_FreeCString(ctx, ${param.name});` + default: + return "" } } class CFunction { constructor(func, api, functionList){ this.func = func + this.func.jsName = this.func.jsName || this.func.name.charAt(0).toLowerCase() + this.func.name.slice(1); this.api = api + this.api.params = this.api.params || []; this.functionList = functionList this.functionName = `js_${func.jsName}` } + generateParameterCheck(){ + return this.api.params.map(generateParameterCheck(this.api)) + } + generateParameters(){ return this.api.params.map(generateParameter) } + generateFunctionCall(){ + return `${(this.api.returnType === 'void' ? '' : `${this.api.returnType} result = `)}${this.api.name}(${this.api.params.map(x => x.name).join(", ")});` + } + + generateReturn(){ + return this.api.returnType === 'void' ? 'return JS_UNDEFINED;' : 'return result' + } + + generateParametersCleanup(){ + return this.api.params.map(generateParameterCleanup).filter(x => x !== "") + } + generate(){ this.functionList.addFunctionDef(this.func.jsName, this.api.params.length, this.functionName) return `static JSValue ${this.functionName}(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv){ -${this.generateParameters().map(x => " "+x).join("\n")} - return JS_UNDEFINED; + ${this.generateParameterCheck().join("\n ")} + ${this.generateParameters().join("\n ")} + ${this.generateFunctionCall()} + ${this.generateParametersCleanup().join("\n ")} + ${this.generateReturn()} }` } } diff --git a/main.js b/main.js index 10e92a7..17835fe 100644 --- a/main.js +++ b/main.js @@ -1,5 +1,6 @@ -import { setWindowTitle } from "raylib.core" +import { setWindowTitle, setWindowPosition } from "raylib.core" -console.log(setWindowTitle("Test")) +setWindowTitle("My Window") +setWindowPosition(50,50) diff --git a/src/bindings/js_raylib_core.h b/src/bindings/js_raylib_core.h index 7fbec86..070fde5 100644 --- a/src/bindings/js_raylib_core.h +++ b/src/bindings/js_raylib_core.h @@ -13,21 +13,44 @@ #endif static JSValue js_setWindowTitle(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv){ - const char * title = JS_ToCString(ctx, argv[0]); + if(!JS_IsString(argv[0])) return JS_ThrowReferenceError(ctx, "SetWindowTitle argument title (0) needs to be a string"); + const char * title = JS_ToCString(ctx, argv[0]); + SetWindowTitle(title); + JS_FreeCString(ctx, title); return JS_UNDEFINED; } static JSValue js_setWindowPosition(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv){ - int x; - JS_ToInt32(ctx, &x, argv[0]); - int y; - JS_ToInt32(ctx, &y, argv[1]); + if(!JS_IsNumber(argv[0])) return JS_ThrowReferenceError(ctx, "SetWindowPosition argument x (0) needs to be a number"); + if(!JS_IsNumber(argv[1])) return JS_ThrowReferenceError(ctx, "SetWindowPosition argument y (1) needs to be a number"); + int x; JS_ToInt32(ctx, &x, argv[0]); + int y; JS_ToInt32(ctx, &y, argv[1]); + SetWindowPosition(x, y); + + return JS_UNDEFINED; +} + +static JSValue js_beginDrawing(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv){ + + + BeginDrawing(); + + return JS_UNDEFINED; +} + +static JSValue js_endDrawing(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv){ + + + EndDrawing(); + return JS_UNDEFINED; } static const JSCFunctionListEntry js_raylib_core_funcs[] = { JS_CFUNC_DEF("setWindowTitle", 1, js_setWindowTitle), - JS_CFUNC_DEF("setWindowPosition", 2, js_setWindowPosition) + JS_CFUNC_DEF("setWindowPosition", 2, js_setWindowPosition), + JS_CFUNC_DEF("beginDrawing", 0, js_beginDrawing), + JS_CFUNC_DEF("endDrawing", 0, js_endDrawing) }; static int js_raylib_core_init(JSContext *ctx, JSModuleDef *m){ diff --git a/src/quickjs.c b/src/quickjs.c index f1b474f..8ab1455 100644 --- a/src/quickjs.c +++ b/src/quickjs.c @@ -71,7 +71,7 @@ int app_update_quickjs(){ } int app_dispose_quickjs(){ - js_std_free_handlers(rt); + //js_std_free_handlers(rt); JS_FreeContext(ctx); JS_FreeRuntime(rt); return 0; @@ -86,7 +86,7 @@ static JSContext *JS_NewCustomContext(JSRuntime *rt) return NULL; /* system modules */ - //js_init_module_std(ctx, "std"); + js_init_module_std(ctx, "std"); //js_init_module_os(ctx, "os"); js_init_module_raylib_core(ctx, "raylib.core"); return ctx;