diff --git a/bindings/src/index.ts b/bindings/src/index.ts index 134624b..43c4329 100644 --- a/bindings/src/index.ts +++ b/bindings/src/index.ts @@ -14,12 +14,15 @@ function main(){ g: { get: true, set: true }, b: { get: true, set: true }, a: { get: true, set: true }, - } + }, + createConstructor: true }) core_gen.addApiFunctionByName("SetWindowTitle") core_gen.addApiFunctionByName("SetWindowPosition") core_gen.addApiFunctionByName("BeginDrawing") core_gen.addApiFunctionByName("EndDrawing") + core_gen.addApiFunctionByName("ClearBackground") + core_gen.addApiFunctionByName("DrawText") core_gen.writeTo("src/bindings/js_raylib_core.h") const texture_gen = new RayLibHeader("raylib_texture", apiDesc) diff --git a/bindings/src/quickjs.ts b/bindings/src/quickjs.ts index 4424c5a..8a37c3e 100644 --- a/bindings/src/quickjs.ts +++ b/bindings/src/quickjs.ts @@ -1,6 +1,6 @@ import { writeFileSync } from "fs"; import { ApiFunction } from "./api" -import { CodeGenerator, CodeWriter, GenericCodeGenerator } from "./generation" +import { CodeGenerator, CodeWriter, FunctionArgument, GenericCodeGenerator } from "./generation" export type StructLookup = { [struct: string]: string } @@ -109,10 +109,6 @@ export abstract class GenericQuickJsGenerator extend } } - jsConstructStruct(structName: string){ - - } - jsStructToOpq(structType: string, jsVar: string, srcVar: string, classId: string){ this.declare("ptr", structType+"*", false, `(${structType}*)js_malloc(ctx, sizeof(${structType}))`) this.statement("*ptr = " + srcVar) @@ -210,6 +206,19 @@ export abstract class GenericQuickJsGenerator extend fun.returnExp("JS_UNDEFINED") return fun } + + jsStructConstructor(structName: string, fields: FunctionArgument[], classId: string){ + const body = this.jsBindingFunction(structName + "_constructor") + for (let i = 0; i < fields.length; i++) { + const para = fields[i] + body.jsToC(para.type,para.name,"argv["+i+"]") + } + body.statement(`${structName} _struct = { ${fields.map(x => x.name).join(', ')} }`) + body.jsStructToOpq(structName,"_return","_struct", classId) + body.returnExp("_return") + return body + } + } export class QuickJsGenerator extends GenericQuickJsGenerator { diff --git a/bindings/src/raylib-header.ts b/bindings/src/raylib-header.ts index 2c1af86..07feccb 100644 --- a/bindings/src/raylib-header.ts +++ b/bindings/src/raylib-header.ts @@ -6,13 +6,12 @@ export interface StructBindingOptions { properties?: { [key:string]: { get?:boolean, set?:boolean } }, destructor?: string, construct?: string, + createConstructor?: boolean } export class RayLibHeader extends QuickJsHeader { - - constructor(name: string, private api: ApiDescription){ super(name) this.includes.include("raylib.h") @@ -76,7 +75,15 @@ export class RayLibHeader extends QuickJsHeader { const classDecl = this.structs.jsClassDeclaration(struct.name, classId, finalizer.getTag("_name"), classFuncList.getTag("_name")) this.moduleInit.call(classDecl.getTag("_name"), ["ctx", "m"]) - // OPT: 7. expose class and constructor + + if(options?.createConstructor){ + const body = this.functions.jsStructConstructor(struct.name, struct.fields, classId) + + this.moduleInit.statement(`JSValue ${struct.name}_constr = JS_NewCFunction2(ctx, ${body.getTag("_name")},"${struct.name})", ${struct.fields.length}, JS_CFUNC_constructor_or_func, 0)`) + this.moduleInit.call("JS_SetModuleExport", ["ctx","m", `"${struct.name}"`, struct.name+"_constr"]) + + this.moduleEntry.call("JS_AddModuleExport", ["ctx","m",'"'+struct.name+'"']) + } } addApiStructByName(structName: string, options?: StructBindingOptions){ diff --git a/generate-bindings.js b/generate-bindings.js index 336a571..5d42dcc 100644 --- a/generate-bindings.js +++ b/generate-bindings.js @@ -368,8 +368,6 @@ class GenericQuickJsGenerator extends generation_1.GenericCodeGenerator { this.jsStructToOpq(type, name, src, classId); } } - jsConstructStruct(structName) { - } jsStructToOpq(structType, jsVar, srcVar, classId) { this.declare("ptr", structType + "*", false, `(${structType}*)js_malloc(ctx, sizeof(${structType}))`); this.statement("*ptr = " + srcVar); @@ -458,6 +456,17 @@ class GenericQuickJsGenerator extends generation_1.GenericCodeGenerator { fun.returnExp("JS_UNDEFINED"); return fun; } + jsStructConstructor(structName, fields, classId) { + const body = this.jsBindingFunction(structName + "_constructor"); + for (let i = 0; i < fields.length; i++) { + const para = fields[i]; + body.jsToC(para.type, para.name, "argv[" + i + "]"); + } + body.statement(`${structName} _struct = { ${fields.map(x => x.name).join(', ')} }`); + body.jsStructToOpq(structName, "_return", "_struct", classId); + body.returnExp("_return"); + return body; + } } exports.GenericQuickJsGenerator = GenericQuickJsGenerator; class QuickJsGenerator extends GenericQuickJsGenerator { @@ -542,7 +551,12 @@ class RayLibHeader extends quickjs_1.QuickJsHeader { classFuncList.jsPropStringDef("[Symbol.toStringTag]", struct.name); const classDecl = this.structs.jsClassDeclaration(struct.name, classId, finalizer.getTag("_name"), classFuncList.getTag("_name")); this.moduleInit.call(classDecl.getTag("_name"), ["ctx", "m"]); - // OPT: 7. expose class and constructor + if (options?.createConstructor) { + const body = this.functions.jsStructConstructor(struct.name, struct.fields, classId); + this.moduleInit.statement(`JSValue ${struct.name}_constr = JS_NewCFunction2(ctx, ${body.getTag("_name")},"${struct.name})", ${struct.fields.length}, JS_CFUNC_constructor_or_func, 0)`); + this.moduleInit.call("JS_SetModuleExport", ["ctx", "m", `"${struct.name}"`, struct.name + "_constr"]); + this.moduleEntry.call("JS_AddModuleExport", ["ctx", "m", '"' + struct.name + '"']); + } } addApiStructByName(structName, options) { const struct = this.api.getStruct(structName); @@ -621,12 +635,15 @@ function main() { g: { get: true, set: true }, b: { get: true, set: true }, a: { get: true, set: true }, - } + }, + createConstructor: true }); core_gen.addApiFunctionByName("SetWindowTitle"); core_gen.addApiFunctionByName("SetWindowPosition"); core_gen.addApiFunctionByName("BeginDrawing"); core_gen.addApiFunctionByName("EndDrawing"); + core_gen.addApiFunctionByName("ClearBackground"); + core_gen.addApiFunctionByName("DrawText"); core_gen.writeTo("src/bindings/js_raylib_core.h"); const texture_gen = new raylib_header_1.RayLibHeader("raylib_texture", apiDesc); texture_gen.addApiStructByName("Image", { diff --git a/main.js b/main.js index f692f04..606feb4 100644 --- a/main.js +++ b/main.js @@ -1,4 +1,4 @@ -import { setWindowTitle, setWindowPosition } from "raylib.core" +import { setWindowTitle, setWindowPosition, Color } from "raylib.core" import { loadImage } from "raylib.texture" import { gc } from "std" @@ -9,6 +9,10 @@ console.log(img.width) gc() +const color = new Color(1,2,3,4) +color.r = 10 +console.log(color.r,color.g,color.b,color.a, color) + setWindowTitle("My Window") setWindowPosition(20,50) diff --git a/src/bindings/js_raylib_core.h b/src/bindings/js_raylib_core.h index 2376f5e..c0cf290 100644 --- a/src/bindings/js_raylib_core.h +++ b/src/bindings/js_raylib_core.h @@ -128,6 +128,27 @@ static int js_declare_Color(JSContext * ctx, JSModuleDef * m) { return 0; } +static JSValue js_Color_constructor(JSContext * ctx, JSValueConst this_val, int argc, JSValueConst * argv) { + int _int_r; + JS_ToInt32(ctx, &_int_r, argv[0]); + unsigned char r = (unsigned char)_int_r; + int _int_g; + JS_ToInt32(ctx, &_int_g, argv[1]); + unsigned char g = (unsigned char)_int_g; + int _int_b; + JS_ToInt32(ctx, &_int_b, argv[2]); + unsigned char b = (unsigned char)_int_b; + int _int_a; + JS_ToInt32(ctx, &_int_a, argv[3]); + unsigned char a = (unsigned char)_int_a; + Color _struct = { r, g, b, a }; + Color* ptr = (Color*)js_malloc(ctx, sizeof(Color)); + *ptr = _struct; + JSValue _return = JS_NewObjectClass(ctx, js_Color_class_id); + JS_SetOpaque(_return, ptr); + return _return; +} + static JSValue js_setWindowTitle(JSContext * ctx, JSValueConst this_val, int argc, JSValueConst * argv) { const char * title = JS_ToCString(ctx, argv[0]); if(title == NULL) return JS_EXCEPTION; @@ -165,6 +186,8 @@ static const JSCFunctionListEntry js_raylib_core_funcs[] = { static int js_raylib_core_init(JSContext * ctx, JSModuleDef * m) { JS_SetModuleExportList(ctx, m,js_raylib_core_funcs,countof(js_raylib_core_funcs)); js_declare_Color(ctx, m); + JSValue Color_constr = JS_NewCFunction2(ctx, js_Color_constructor,"Color)", 4, JS_CFUNC_constructor_or_func, 0); + JS_SetModuleExport(ctx, m, "Color", Color_constr); return 0; } @@ -173,6 +196,7 @@ JSModuleDef * js_init_module_raylib_core(JSContext * ctx, const char * module_na m = JS_NewCModule(ctx, module_name, js_raylib_core_init); if(!m) return NULL; JS_AddModuleExportList(ctx, m, js_raylib_core_funcs, countof(js_raylib_core_funcs)); + JS_AddModuleExport(ctx, m, "Color"); return m; } diff --git a/thirdparty/raylib b/thirdparty/raylib index 5573f0f..a48bb6e 160000 --- a/thirdparty/raylib +++ b/thirdparty/raylib @@ -1 +1 @@ -Subproject commit 5573f0f1c7b29bfe46d0b70487e4adb4d01cba62 +Subproject commit a48bb6e1ed7b33190e486ba65b7875f0dff73701