mirror of https://github.com/mode777/rayjs.git
update binding generator
This commit is contained in:
parent
fd97c55510
commit
bdba35dda4
|
@ -3,6 +3,7 @@
|
|||
"sdl.h": "c",
|
||||
"vs.sc.mtl.bin.h": "c",
|
||||
"embedded_shader.h": "c",
|
||||
"common.h": "c"
|
||||
"common.h": "c",
|
||||
"raylib.h": "c"
|
||||
}
|
||||
}
|
|
@ -8,6 +8,14 @@ function main(){
|
|||
const apiDesc = new ApiDescription(api)
|
||||
|
||||
const core_gen = new RayLibHeader("raylib_core", apiDesc)
|
||||
core_gen.addApiStructByName("Color", {
|
||||
properties: {
|
||||
r: { get: true, set: true },
|
||||
g: { get: true, set: true },
|
||||
b: { get: true, set: true },
|
||||
a: { get: true, set: true },
|
||||
}
|
||||
})
|
||||
core_gen.addApiFunctionByName("SetWindowTitle")
|
||||
core_gen.addApiFunctionByName("SetWindowPosition")
|
||||
core_gen.addApiFunctionByName("BeginDrawing")
|
||||
|
@ -15,7 +23,14 @@ function main(){
|
|||
core_gen.writeTo("src/bindings/js_raylib_core.h")
|
||||
|
||||
const texture_gen = new RayLibHeader("raylib_texture", apiDesc)
|
||||
texture_gen.addApiStructByName("Image", "UnloadImage", { properties: { width: { get: true } } })
|
||||
texture_gen.addApiStructByName("Image", {
|
||||
properties: {
|
||||
width: { get: true },
|
||||
height: { get: true }
|
||||
},
|
||||
destructor: "UnloadImage"
|
||||
})
|
||||
texture_gen.addApiFunctionByName("LoadImage")
|
||||
texture_gen.writeTo("src/bindings/js_raylib_texture.h")
|
||||
}
|
||||
|
||||
|
|
|
@ -2,8 +2,11 @@ import { writeFileSync } from "fs";
|
|||
import { ApiFunction } from "./api"
|
||||
import { CodeGenerator, CodeWriter, GenericCodeGenerator } from "./generation"
|
||||
|
||||
export type StructLookup = { [struct: string]: string }
|
||||
|
||||
export class QuickJsHeader {
|
||||
|
||||
public readonly structLookup: StructLookup = {}
|
||||
public readonly moduleFunctionList: QuickJsGenerator
|
||||
public readonly structs: QuickJsGenerator
|
||||
public readonly functions: QuickJsGenerator
|
||||
|
@ -48,6 +51,10 @@ export class QuickJsHeader {
|
|||
moduleEntryFunc.statement("return m")
|
||||
}
|
||||
|
||||
registerStruct(struct: string, classId: string){
|
||||
this.structLookup[struct] = classId;
|
||||
}
|
||||
|
||||
public writeTo(filename: string){
|
||||
const writer = new CodeWriter()
|
||||
writer.writeGenerator(this.root)
|
||||
|
@ -70,32 +77,45 @@ export abstract class GenericQuickJsGenerator<T extends QuickJsGenerator> extend
|
|||
}
|
||||
|
||||
jsToC(type: string, name: string, src: string){
|
||||
this.inline(`${type} ${name}`)
|
||||
switch (type) {
|
||||
case "const char *":
|
||||
this.statement(` = JS_ToCString(ctx, ${src})`)
|
||||
this.statement(`${type} ${name} = JS_ToCString(ctx, ${src})`)
|
||||
this.statement(`if(${name} == NULL) return JS_EXCEPTION`)
|
||||
break;
|
||||
case "int":
|
||||
this.statement('')
|
||||
this.statement(`${type} ${name}`)
|
||||
this.statement(`JS_ToInt32(ctx, &${name}, ${src})`)
|
||||
break;
|
||||
case "unsigned char":
|
||||
this.statement(`int _tmp`)
|
||||
this.statement(`JS_ToInt32(ctx, &_tmp, ${src})`)
|
||||
this.statement(`${type} ${name} = (${type})_tmp`)
|
||||
break;
|
||||
default:
|
||||
throw new Error("Cannot handle parameter type: " + type)
|
||||
}
|
||||
}
|
||||
|
||||
jsToJs(type: string, name: string, src: string){
|
||||
this.inline(`JSValue ${name}`)
|
||||
jsToJs(type: string, name: string, src: string, classIds: StructLookup = {}){
|
||||
switch (type) {
|
||||
case "int":
|
||||
this.statement(` = JS_NewInt32(ctx, ${src})`)
|
||||
case "unsigned char":
|
||||
this.declare(name,'JSValue', false, `JS_NewInt32(ctx, ${src})`)
|
||||
break;
|
||||
default:
|
||||
throw new Error("Cannot handle parameter type: " + type)
|
||||
const classId = classIds[type]
|
||||
if(!classId) throw new Error("Cannot handle parameter type: " + type)
|
||||
this.jsStructToOpq(type, name, src, classId)
|
||||
}
|
||||
}
|
||||
|
||||
jsStructToOpq(structType: string, jsVar: string, srcVar: string, classId: string){
|
||||
this.declare("ptr", structType+"*", false, `(${structType}*)js_malloc(ctx, sizeof(${structType}))`)
|
||||
this.statement("*ptr = " + srcVar)
|
||||
this.declare(jsVar, "JSValue", false, `JS_NewObjectClass(ctx, ${classId})`)
|
||||
this.call("JS_SetOpaque", [jsVar, "ptr"])
|
||||
}
|
||||
|
||||
jsCleanUpParameter(type: string, name: string) {
|
||||
switch (type) {
|
||||
case "const char *":
|
||||
|
@ -141,7 +161,7 @@ export abstract class GenericQuickJsGenerator<T extends QuickJsGenerator> extend
|
|||
const body = this.function(`js_${structName}_finalizer`, "void", args, true)
|
||||
body.statement(`${structName}* ptr = JS_GetOpaque(val, ${classId})`)
|
||||
body.if("ptr", cond => {
|
||||
cond.call("puts", ["\"Finalize "+structName+"\""])
|
||||
cond.call("TraceLog", ["LOG_INFO",`"Finalize ${structName}"`])
|
||||
if(onFinalize) onFinalize(<T>cond, "ptr")
|
||||
cond.call("js_free_rt", ["rt","ptr"])
|
||||
})
|
||||
|
@ -173,6 +193,19 @@ export abstract class GenericQuickJsGenerator<T extends QuickJsGenerator> extend
|
|||
fun.returnExp("ret")
|
||||
return fun
|
||||
}
|
||||
|
||||
jsStructSetter(structName: string, classId: string, field: string, type: string){
|
||||
const args = [{type: "JSContext*", name: "ctx" }, {type: "JSValueConst", name: "this_val"},{type: "JSValueConst", name: "v"}]
|
||||
const fun = this.function(`js_${structName}_set_${field}`,"JSValue",args,true)
|
||||
fun.declare("ptr", structName+"*", false, `JS_GetOpaque2(ctx, this_val, ${classId})`)
|
||||
fun.if("!ptr", cond => {
|
||||
cond.returnExp("JS_EXCEPTION")
|
||||
})
|
||||
fun.jsToC(type, "value", "v");
|
||||
fun.statement("ptr->"+field+" = value")
|
||||
fun.returnExp("JS_UNDEFINED")
|
||||
return fun
|
||||
}
|
||||
}
|
||||
|
||||
export class QuickJsGenerator extends GenericQuickJsGenerator<QuickJsGenerator> {
|
||||
|
|
|
@ -3,12 +3,16 @@ import { CodeGenerator } from "./generation"
|
|||
import { QuickJsHeader } from "./quickjs"
|
||||
|
||||
export interface StructBindingOptions {
|
||||
properties?: { [key:string]: { get?:boolean, set?:boolean } }
|
||||
properties?: { [key:string]: { get?:boolean, set?:boolean } },
|
||||
destructor?: string,
|
||||
construct?: string,
|
||||
}
|
||||
|
||||
|
||||
export class RayLibHeader extends QuickJsHeader {
|
||||
|
||||
|
||||
|
||||
constructor(name: string, private api: ApiDescription){
|
||||
super(name)
|
||||
this.includes.include("raylib.h")
|
||||
|
@ -33,8 +37,8 @@ export class RayLibHeader extends QuickJsHeader {
|
|||
if(api.returnType === "void"){
|
||||
fun.statement("return JS_UNDEFINED")
|
||||
} else {
|
||||
fun.jsToJs(api.returnType, "ret", "returnVal")
|
||||
fun.returnExp("returnVal")
|
||||
fun.jsToJs(api.returnType, "ret", "returnVal", this.structLookup)
|
||||
fun.returnExp("ret")
|
||||
}
|
||||
|
||||
// add binding to function declaration
|
||||
|
@ -49,7 +53,7 @@ export class RayLibHeader extends QuickJsHeader {
|
|||
|
||||
addApiStruct(struct: ApiStruct, destructor: ApiFunction | null, options?: StructBindingOptions){
|
||||
const classId = this.declarations.jsClassId(`js_${struct.name}_class_id`)
|
||||
|
||||
this.registerStruct(struct.name, classId)
|
||||
const finalizer = this.structs.jsStructFinalizer(classId, struct.name, (gen,ptr) => destructor && gen.call(destructor.name, ["*"+ptr]))
|
||||
|
||||
const propDeclarations = this.structs.createGenerator()
|
||||
|
@ -61,26 +65,27 @@ export class RayLibHeader extends QuickJsHeader {
|
|||
let _get: CodeGenerator | undefined = undefined
|
||||
let _set: CodeGenerator | undefined = undefined
|
||||
if(el.get) _get = this.structs.jsStructGetter(struct.name, classId, field, type)
|
||||
propDeclarations.jsGetSetDef(field, _get?.getTag("_name"), undefined)
|
||||
if(el.set) _set = this.structs.jsStructSetter(struct.name, classId, field, type)
|
||||
propDeclarations.jsGetSetDef(field, _get?.getTag("_name"), _set?.getTag("_name"))
|
||||
}
|
||||
}
|
||||
|
||||
const classFuncList = this.structs.jsFunctionList(`js_${struct.name}_proto_funcs`)
|
||||
classFuncList.child(propDeclarations)
|
||||
classFuncList.jsPropStringDef("[Symbol.toStringTag]", "Image")
|
||||
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
|
||||
}
|
||||
|
||||
addApiStructByName(structName: string, destructorName: string | null = null, options?: StructBindingOptions){
|
||||
addApiStructByName(structName: string, options?: StructBindingOptions){
|
||||
const struct = this.api.getStruct(structName)
|
||||
if(!struct) throw new Error("Struct not in API: "+ structName)
|
||||
let destructor: ApiFunction | null = null
|
||||
if(destructorName !== null){
|
||||
destructor = this.api.getFunction(destructorName)
|
||||
if(!destructor) throw new Error("Destructor func not in API: "+ destructorName)
|
||||
if(options?.destructor){
|
||||
destructor = this.api.getFunction(options.destructor)
|
||||
if(!destructor) throw new Error("Destructor func not in API: "+ options.destructor)
|
||||
}
|
||||
this.addApiStruct(struct, destructor, options)
|
||||
}
|
||||
|
|
|
@ -284,6 +284,7 @@ const generation_1 = __webpack_require__(/*! ./generation */ "./src/generation.t
|
|||
class QuickJsHeader {
|
||||
constructor(name) {
|
||||
this.name = name;
|
||||
this.structLookup = {};
|
||||
const root = this.root = new QuickJsGenerator();
|
||||
const body = this.body = root.header("JS_" + this.name + "_GUARD");
|
||||
const includes = this.includes = body.child();
|
||||
|
@ -314,6 +315,9 @@ class QuickJsHeader {
|
|||
moduleEntry.statement(`JS_AddModuleExportList(ctx, m, ${this.moduleFunctionList.getTag("_name")}, countof(${this.moduleFunctionList.getTag("_name")}))`);
|
||||
moduleEntryFunc.statement("return m");
|
||||
}
|
||||
registerStruct(struct, classId) {
|
||||
this.structLookup[struct] = classId;
|
||||
}
|
||||
writeTo(filename) {
|
||||
const writer = new generation_1.CodeWriter();
|
||||
writer.writeGenerator(this.root);
|
||||
|
@ -333,30 +337,43 @@ class GenericQuickJsGenerator extends generation_1.GenericCodeGenerator {
|
|||
return sub;
|
||||
}
|
||||
jsToC(type, name, src) {
|
||||
this.inline(`${type} ${name}`);
|
||||
switch (type) {
|
||||
case "const char *":
|
||||
this.statement(` = JS_ToCString(ctx, ${src})`);
|
||||
this.statement(`${type} ${name} = JS_ToCString(ctx, ${src})`);
|
||||
this.statement(`if(${name} == NULL) return JS_EXCEPTION`);
|
||||
break;
|
||||
case "int":
|
||||
this.statement('');
|
||||
this.statement(`${type} ${name}`);
|
||||
this.statement(`JS_ToInt32(ctx, &${name}, ${src})`);
|
||||
break;
|
||||
default:
|
||||
throw new Error("Cannot handle parameter type: " + type);
|
||||
}
|
||||
}
|
||||
jsToJs(type, name, src) {
|
||||
this.inline(`JSValue ${name}`);
|
||||
switch (type) {
|
||||
case "int":
|
||||
this.statement(` = JS_NewInt32(ctx, ${src})`);
|
||||
case "unsigned char":
|
||||
this.statement(`int _tmp`);
|
||||
this.statement(`JS_ToInt32(ctx, &_tmp, ${src})`);
|
||||
this.statement(`${type} ${name} = (${type})_tmp`);
|
||||
break;
|
||||
default:
|
||||
throw new Error("Cannot handle parameter type: " + type);
|
||||
}
|
||||
}
|
||||
jsToJs(type, name, src, classIds = {}) {
|
||||
switch (type) {
|
||||
case "int":
|
||||
case "unsigned char":
|
||||
this.declare(name, 'JSValue', false, `JS_NewInt32(ctx, ${src})`);
|
||||
break;
|
||||
default:
|
||||
const classId = classIds[type];
|
||||
if (!classId)
|
||||
throw new Error("Cannot handle parameter type: " + type);
|
||||
this.jsStructToOpq(type, name, src, classId);
|
||||
}
|
||||
}
|
||||
jsStructToOpq(structType, jsVar, srcVar, classId) {
|
||||
this.declare("ptr", structType + "*", false, `(${structType}*)js_malloc(ctx, sizeof(${structType}))`);
|
||||
this.statement("*ptr = " + srcVar);
|
||||
this.declare(jsVar, "JSValue", false, `JS_NewObjectClass(ctx, ${classId})`);
|
||||
this.call("JS_SetOpaque", [jsVar, "ptr"]);
|
||||
}
|
||||
jsCleanUpParameter(type, name) {
|
||||
switch (type) {
|
||||
case "const char *":
|
||||
|
@ -396,7 +413,7 @@ class GenericQuickJsGenerator extends generation_1.GenericCodeGenerator {
|
|||
const body = this.function(`js_${structName}_finalizer`, "void", args, true);
|
||||
body.statement(`${structName}* ptr = JS_GetOpaque(val, ${classId})`);
|
||||
body.if("ptr", cond => {
|
||||
cond.call("puts", ["\"Finalize " + structName + "\""]);
|
||||
cond.call("TraceLog", ["LOG_INFO", `"Finalize ${structName}"`]);
|
||||
if (onFinalize)
|
||||
onFinalize(cond, "ptr");
|
||||
cond.call("js_free_rt", ["rt", "ptr"]);
|
||||
|
@ -427,6 +444,18 @@ class GenericQuickJsGenerator extends generation_1.GenericCodeGenerator {
|
|||
fun.returnExp("ret");
|
||||
return fun;
|
||||
}
|
||||
jsStructSetter(structName, classId, field, type) {
|
||||
const args = [{ type: "JSContext*", name: "ctx" }, { type: "JSValueConst", name: "this_val" }, { type: "JSValueConst", name: "v" }];
|
||||
const fun = this.function(`js_${structName}_set_${field}`, "JSValue", args, true);
|
||||
fun.declare("ptr", structName + "*", false, `JS_GetOpaque2(ctx, this_val, ${classId})`);
|
||||
fun.if("!ptr", cond => {
|
||||
cond.returnExp("JS_EXCEPTION");
|
||||
});
|
||||
fun.jsToC(type, "value", "v");
|
||||
fun.statement("ptr->" + field + " = value");
|
||||
fun.returnExp("JS_UNDEFINED");
|
||||
return fun;
|
||||
}
|
||||
}
|
||||
exports.GenericQuickJsGenerator = GenericQuickJsGenerator;
|
||||
class QuickJsGenerator extends GenericQuickJsGenerator {
|
||||
|
@ -474,8 +503,8 @@ class RayLibHeader extends quickjs_1.QuickJsHeader {
|
|||
fun.statement("return JS_UNDEFINED");
|
||||
}
|
||||
else {
|
||||
fun.jsToJs(api.returnType, "ret", "returnVal");
|
||||
fun.returnExp("returnVal");
|
||||
fun.jsToJs(api.returnType, "ret", "returnVal", this.structLookup);
|
||||
fun.returnExp("ret");
|
||||
}
|
||||
// add binding to function declaration
|
||||
this.moduleFunctionList.jsFuncDef(jName, api.argc, fun.getTag("_name"));
|
||||
|
@ -488,6 +517,7 @@ class RayLibHeader extends quickjs_1.QuickJsHeader {
|
|||
}
|
||||
addApiStruct(struct, destructor, options) {
|
||||
const classId = this.declarations.jsClassId(`js_${struct.name}_class_id`);
|
||||
this.registerStruct(struct.name, classId);
|
||||
const finalizer = this.structs.jsStructFinalizer(classId, struct.name, (gen, ptr) => destructor && gen.call(destructor.name, ["*" + ptr]));
|
||||
const propDeclarations = this.structs.createGenerator();
|
||||
if (options && options.properties) {
|
||||
|
@ -500,25 +530,27 @@ class RayLibHeader extends quickjs_1.QuickJsHeader {
|
|||
let _set = undefined;
|
||||
if (el.get)
|
||||
_get = this.structs.jsStructGetter(struct.name, classId, field, type);
|
||||
propDeclarations.jsGetSetDef(field, _get?.getTag("_name"), undefined);
|
||||
if (el.set)
|
||||
_set = this.structs.jsStructSetter(struct.name, classId, field, type);
|
||||
propDeclarations.jsGetSetDef(field, _get?.getTag("_name"), _set?.getTag("_name"));
|
||||
}
|
||||
}
|
||||
const classFuncList = this.structs.jsFunctionList(`js_${struct.name}_proto_funcs`);
|
||||
classFuncList.child(propDeclarations);
|
||||
classFuncList.jsPropStringDef("[Symbol.toStringTag]", "Image");
|
||||
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
|
||||
}
|
||||
addApiStructByName(structName, destructorName = null, options) {
|
||||
addApiStructByName(structName, options) {
|
||||
const struct = this.api.getStruct(structName);
|
||||
if (!struct)
|
||||
throw new Error("Struct not in API: " + structName);
|
||||
let destructor = null;
|
||||
if (destructorName !== null) {
|
||||
destructor = this.api.getFunction(destructorName);
|
||||
if (options?.destructor) {
|
||||
destructor = this.api.getFunction(options.destructor);
|
||||
if (!destructor)
|
||||
throw new Error("Destructor func not in API: " + destructorName);
|
||||
throw new Error("Destructor func not in API: " + options.destructor);
|
||||
}
|
||||
this.addApiStruct(struct, destructor, options);
|
||||
}
|
||||
|
@ -581,13 +613,28 @@ function main() {
|
|||
const api = JSON.parse((0, fs_1.readFileSync)("thirdparty/raylib/parser/output/raylib_api.json", 'utf8'));
|
||||
const apiDesc = new api_1.ApiDescription(api);
|
||||
const core_gen = new raylib_header_1.RayLibHeader("raylib_core", apiDesc);
|
||||
core_gen.addApiStructByName("Color", {
|
||||
properties: {
|
||||
r: { get: true, set: true },
|
||||
g: { get: true, set: true },
|
||||
b: { get: true, set: true },
|
||||
a: { get: true, set: true },
|
||||
}
|
||||
});
|
||||
core_gen.addApiFunctionByName("SetWindowTitle");
|
||||
core_gen.addApiFunctionByName("SetWindowPosition");
|
||||
core_gen.addApiFunctionByName("BeginDrawing");
|
||||
core_gen.addApiFunctionByName("EndDrawing");
|
||||
core_gen.writeTo("src/bindings/js_raylib_core.h");
|
||||
const texture_gen = new raylib_header_1.RayLibHeader("raylib_texture", apiDesc);
|
||||
texture_gen.addApiStructByName("Image", "UnloadImage", { properties: { width: { get: true } } });
|
||||
texture_gen.addApiStructByName("Image", {
|
||||
properties: {
|
||||
width: { get: true },
|
||||
height: { get: true }
|
||||
},
|
||||
destructor: "UnloadImage"
|
||||
});
|
||||
texture_gen.addApiFunctionByName("LoadImage");
|
||||
texture_gen.writeTo("src/bindings/js_raylib_texture.h");
|
||||
}
|
||||
main();
|
||||
|
|
14
main.js
14
main.js
|
@ -1,15 +1,15 @@
|
|||
import { setWindowTitle, setWindowPosition } from "raylib.core"
|
||||
import { loadImage, Image } from "raylib.texture"
|
||||
import { loadImage } from "raylib.texture"
|
||||
import { gc } from "std"
|
||||
|
||||
console.log(loadImage("assets/planet00.png"))
|
||||
|
||||
const img = new Image("assets/planet00.png")
|
||||
|
||||
gc()
|
||||
const img = loadImage("assets/planet00.png")
|
||||
console.log(img.width)
|
||||
|
||||
//const img = new Image("assets/planet00.png")
|
||||
|
||||
gc()
|
||||
|
||||
setWindowTitle("My Window")
|
||||
setWindowPosition(1920,50)
|
||||
setWindowPosition(20,50)
|
||||
|
||||
|
||||
|
|
|
@ -12,6 +12,121 @@
|
|||
#define countof(x) (sizeof(x) / sizeof((x)[0]))
|
||||
#endif
|
||||
|
||||
static JSClassID js_Color_class_id;
|
||||
|
||||
static void js_Color_finalizer(JSRuntime * rt, JSValue val) {
|
||||
Color* ptr = JS_GetOpaque(val, js_Color_class_id);
|
||||
if(ptr) {
|
||||
TraceLog(LOG_INFO, "Finalize Color");
|
||||
js_free_rt(rt, ptr);
|
||||
}
|
||||
}
|
||||
|
||||
static JSValue js_Color_get_r(JSContext* ctx, JSValueConst this_val) {
|
||||
Color* ptr = JS_GetOpaque2(ctx, this_val, js_Color_class_id);
|
||||
if(!ptr) {
|
||||
return JS_EXCEPTION;
|
||||
}
|
||||
unsigned char r = ptr->r;
|
||||
JSValue ret = JS_NewInt32(ctx, r);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static JSValue js_Color_set_r(JSContext* ctx, JSValueConst this_val, JSValueConst v) {
|
||||
Color* ptr = JS_GetOpaque2(ctx, this_val, js_Color_class_id);
|
||||
if(!ptr) {
|
||||
return JS_EXCEPTION;
|
||||
}
|
||||
int _tmp;
|
||||
JS_ToInt32(ctx, &_tmp, v);
|
||||
unsigned char value = (unsigned char)_tmp;
|
||||
ptr->r = value;
|
||||
return JS_UNDEFINED;
|
||||
}
|
||||
|
||||
static JSValue js_Color_get_g(JSContext* ctx, JSValueConst this_val) {
|
||||
Color* ptr = JS_GetOpaque2(ctx, this_val, js_Color_class_id);
|
||||
if(!ptr) {
|
||||
return JS_EXCEPTION;
|
||||
}
|
||||
unsigned char g = ptr->g;
|
||||
JSValue ret = JS_NewInt32(ctx, g);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static JSValue js_Color_set_g(JSContext* ctx, JSValueConst this_val, JSValueConst v) {
|
||||
Color* ptr = JS_GetOpaque2(ctx, this_val, js_Color_class_id);
|
||||
if(!ptr) {
|
||||
return JS_EXCEPTION;
|
||||
}
|
||||
int _tmp;
|
||||
JS_ToInt32(ctx, &_tmp, v);
|
||||
unsigned char value = (unsigned char)_tmp;
|
||||
ptr->g = value;
|
||||
return JS_UNDEFINED;
|
||||
}
|
||||
|
||||
static JSValue js_Color_get_b(JSContext* ctx, JSValueConst this_val) {
|
||||
Color* ptr = JS_GetOpaque2(ctx, this_val, js_Color_class_id);
|
||||
if(!ptr) {
|
||||
return JS_EXCEPTION;
|
||||
}
|
||||
unsigned char b = ptr->b;
|
||||
JSValue ret = JS_NewInt32(ctx, b);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static JSValue js_Color_set_b(JSContext* ctx, JSValueConst this_val, JSValueConst v) {
|
||||
Color* ptr = JS_GetOpaque2(ctx, this_val, js_Color_class_id);
|
||||
if(!ptr) {
|
||||
return JS_EXCEPTION;
|
||||
}
|
||||
int _tmp;
|
||||
JS_ToInt32(ctx, &_tmp, v);
|
||||
unsigned char value = (unsigned char)_tmp;
|
||||
ptr->b = value;
|
||||
return JS_UNDEFINED;
|
||||
}
|
||||
|
||||
static JSValue js_Color_get_a(JSContext* ctx, JSValueConst this_val) {
|
||||
Color* ptr = JS_GetOpaque2(ctx, this_val, js_Color_class_id);
|
||||
if(!ptr) {
|
||||
return JS_EXCEPTION;
|
||||
}
|
||||
unsigned char a = ptr->a;
|
||||
JSValue ret = JS_NewInt32(ctx, a);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static JSValue js_Color_set_a(JSContext* ctx, JSValueConst this_val, JSValueConst v) {
|
||||
Color* ptr = JS_GetOpaque2(ctx, this_val, js_Color_class_id);
|
||||
if(!ptr) {
|
||||
return JS_EXCEPTION;
|
||||
}
|
||||
int _tmp;
|
||||
JS_ToInt32(ctx, &_tmp, v);
|
||||
unsigned char value = (unsigned char)_tmp;
|
||||
ptr->a = value;
|
||||
return JS_UNDEFINED;
|
||||
}
|
||||
|
||||
static const JSCFunctionListEntry js_Color_proto_funcs[] = {
|
||||
JS_CGETSET_DEF("r",js_Color_get_r,js_Color_set_r),
|
||||
JS_CGETSET_DEF("g",js_Color_get_g,js_Color_set_g),
|
||||
JS_CGETSET_DEF("b",js_Color_get_b,js_Color_set_b),
|
||||
JS_CGETSET_DEF("a",js_Color_get_a,js_Color_set_a),
|
||||
JS_PROP_STRING_DEF("[Symbol.toStringTag]","Color", JS_PROP_CONFIGURABLE),
|
||||
};
|
||||
|
||||
static int js_declare_Color(JSContext * ctx, JSModuleDef * m) {
|
||||
JS_NewClassID(&js_Color_class_id);
|
||||
JSClassDef js_Color_def = { .class_name = "Color", .finalizer = js_Color_finalizer };
|
||||
JS_NewClass(JS_GetRuntime(ctx), js_Color_class_id, &js_Color_def);
|
||||
JSValue proto = JS_NewObject(ctx);
|
||||
JS_SetPropertyFunctionList(ctx, proto, js_Color_proto_funcs, countof(js_Color_proto_funcs));
|
||||
JS_SetClassProto(ctx, js_Color_class_id, proto);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static JSValue js_setWindowTitle(JSContext * ctx, JSValueConst this_val, int argc, JSValueConst * argv) {
|
||||
const char * title = JS_ToCString(ctx, argv[0]);
|
||||
|
@ -49,6 +164,7 @@ 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);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -17,7 +17,7 @@ static JSClassID js_Image_class_id;
|
|||
static void js_Image_finalizer(JSRuntime * rt, JSValue val) {
|
||||
Image* ptr = JS_GetOpaque(val, js_Image_class_id);
|
||||
if(ptr) {
|
||||
puts("Finalize Image");
|
||||
TraceLog(LOG_INFO, "Finalize Image");
|
||||
UnloadImage(*ptr);
|
||||
js_free_rt(rt, ptr);
|
||||
}
|
||||
|
@ -33,8 +33,19 @@ static JSValue js_Image_get_width(JSContext* ctx, JSValueConst this_val) {
|
|||
return ret;
|
||||
}
|
||||
|
||||
static JSValue js_Image_get_height(JSContext* ctx, JSValueConst this_val) {
|
||||
Image* ptr = JS_GetOpaque2(ctx, this_val, js_Image_class_id);
|
||||
if(!ptr) {
|
||||
return JS_EXCEPTION;
|
||||
}
|
||||
int height = ptr->height;
|
||||
JSValue ret = JS_NewInt32(ctx, height);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const JSCFunctionListEntry js_Image_proto_funcs[] = {
|
||||
JS_CGETSET_DEF("width",js_Image_get_width,NULL),
|
||||
JS_CGETSET_DEF("height",js_Image_get_height,NULL),
|
||||
JS_PROP_STRING_DEF("[Symbol.toStringTag]","Image", JS_PROP_CONFIGURABLE),
|
||||
};
|
||||
|
||||
|
@ -48,7 +59,20 @@ static int js_declare_Image(JSContext * ctx, JSModuleDef * m) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
static JSValue js_loadImage(JSContext * ctx, JSValueConst this_val, int argc, JSValueConst * argv) {
|
||||
const char * fileName = JS_ToCString(ctx, argv[0]);
|
||||
if(fileName == NULL) return JS_EXCEPTION;
|
||||
Image returnVal = LoadImage(fileName);
|
||||
JS_FreeCString(ctx, fileName);
|
||||
Image* ptr = (Image*)js_malloc(ctx, sizeof(Image));
|
||||
*ptr = returnVal;
|
||||
JSValue ret = JS_NewObjectClass(ctx, js_Image_class_id);
|
||||
JS_SetOpaque(ret, ptr);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const JSCFunctionListEntry js_raylib_texture_funcs[] = {
|
||||
JS_CFUNC_DEF("loadImage",1,js_loadImage),
|
||||
};
|
||||
|
||||
static int js_raylib_texture_init(JSContext * ctx, JSModuleDef * m) {
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit 5573f0f1c7b29bfe46d0b70487e4adb4d01cba62
|
||||
Subproject commit a48bb6e1ed7b33190e486ba65b7875f0dff73701
|
Loading…
Reference in New Issue