mirror of https://github.com/mode777/rayjs.git
more bindings
This commit is contained in:
parent
b48568aa87
commit
277a85f527
|
@ -1,17 +0,0 @@
|
|||
{
|
||||
"headers": [
|
||||
{
|
||||
"name": "raylib_core",
|
||||
"functions": [
|
||||
{ "name": "SetWindowTitle" },
|
||||
{ "name": "SetWindowPosition" },
|
||||
{ "name": "BeginDrawing" },
|
||||
{ "name": "EndDrawing" }
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "raylib_texture",
|
||||
"functions": []
|
||||
}
|
||||
]
|
||||
}
|
|
@ -214,6 +214,11 @@ export abstract class GenericCodeGenerator<T extends CodeGenerator> {
|
|||
if(fun) fun(sub)
|
||||
return sub
|
||||
}
|
||||
|
||||
public declareStruct(structName: string, varName: string, values: string[], isStatic: boolean = false){
|
||||
if(isStatic) this.inline("static ")
|
||||
this.statement(`${structName} ${varName} = { ${values.join(', ')} }`)
|
||||
}
|
||||
}
|
||||
|
||||
export class CodeGenerator extends GenericCodeGenerator<CodeGenerator>{
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { readFileSync, writeFileSync } from "fs";
|
||||
import { Bindings, RayLibApi } from "./interfaces";
|
||||
import { RayLibApi } from "./interfaces";
|
||||
import { ApiDescription } from "./api";
|
||||
import { RayLibHeader } from "./raylib-header";
|
||||
|
||||
|
@ -17,12 +17,28 @@ function main(){
|
|||
},
|
||||
createConstructor: true
|
||||
})
|
||||
core_gen.addApiStructByName("Vector2", {
|
||||
properties: {
|
||||
x: { get: true, set: true },
|
||||
y: { 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("InitWindow")
|
||||
core_gen.addApiFunctionByName("SetTargetFPS")
|
||||
core_gen.addApiFunctionByName("WindowShouldClose", null, { before: fun => fun.call("app_update_quickjs", []) })
|
||||
core_gen.addApiFunctionByName("ClearBackground")
|
||||
core_gen.addApiFunctionByName("CloseWindow")
|
||||
core_gen.addApiFunctionByName("DrawText")
|
||||
core_gen.addApiFunctionByName("DrawCircleV")
|
||||
core_gen.addApiFunctionByName("IsKeyDown")
|
||||
api.defines.filter(x => x.type === "COLOR").map(x => ({ name: x.name, values: (x.value.match(/\{([^}]+)\}/) || "")[1].split(',').map(x => x.trim()) })).forEach(x => {
|
||||
core_gen.exportGlobalStruct("Color", x.name, x.values)
|
||||
})
|
||||
core_gen.writeTo("src/bindings/js_raylib_core.h")
|
||||
|
||||
const texture_gen = new RayLibHeader("raylib_texture", apiDesc)
|
||||
|
|
|
@ -48,17 +48,4 @@ export interface RayLibApi {
|
|||
structs: RayLibStruct[],
|
||||
enums: RayLibEnum[],
|
||||
functions: RayLibFunction[]
|
||||
}
|
||||
|
||||
export interface BindingFunction {
|
||||
name: string
|
||||
}
|
||||
|
||||
export interface BindingHeader {
|
||||
name: string,
|
||||
functions: BindingFunction[],
|
||||
}
|
||||
|
||||
export interface Bindings {
|
||||
headers: BindingHeader
|
||||
}
|
|
@ -76,12 +76,17 @@ export abstract class GenericQuickJsGenerator<T extends QuickJsGenerator> extend
|
|||
return sub
|
||||
}
|
||||
|
||||
jsToC(type: string, name: string, src: string){
|
||||
jsToC(type: string, name: string, src: string, classIds: StructLookup = {}){
|
||||
switch (type) {
|
||||
case "const char *":
|
||||
this.statement(`${type} ${name} = JS_ToCString(ctx, ${src})`)
|
||||
this.statement(`if(${name} == NULL) return JS_EXCEPTION`)
|
||||
break;
|
||||
case "float":
|
||||
this.statement("double _double_"+name)
|
||||
this.statement(`JS_ToFloat64(ctx, &_double_${name}, ${src})`)
|
||||
this.statement(`${type} ${name} = (${type})_double_${name}`)
|
||||
break;
|
||||
case "int":
|
||||
this.statement(`${type} ${name}`)
|
||||
this.statement(`JS_ToInt32(ctx, &${name}, ${src})`)
|
||||
|
@ -92,7 +97,11 @@ export abstract class GenericQuickJsGenerator<T extends QuickJsGenerator> extend
|
|||
this.statement(`${type} ${name} = (${type})_int_${name}`)
|
||||
break;
|
||||
default:
|
||||
throw new Error("Cannot handle parameter type: " + type)
|
||||
const classId = classIds[type]
|
||||
if(!classId) throw new Error("Cannot convert into parameter type: " + type)
|
||||
this.jsOpqToStructPtr(type, name+"_ptr", src, classId)
|
||||
this.statement(`if(${name}_ptr == NULL) return JS_EXCEPTION`)
|
||||
this.declare(name, type, false, `*${name}_ptr`)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -102,18 +111,24 @@ export abstract class GenericQuickJsGenerator<T extends QuickJsGenerator> extend
|
|||
case "unsigned char":
|
||||
this.declare(name,'JSValue', false, `JS_NewInt32(ctx, ${src})`)
|
||||
break;
|
||||
case "bool":
|
||||
this.declare(name, 'JSValue', false, `JS_NewBool(ctx, ${src})`)
|
||||
break;
|
||||
case "float":
|
||||
this.declare(name, 'JSValue', false, `JS_NewFloat64(ctx, ${src})`)
|
||||
break;
|
||||
default:
|
||||
const classId = classIds[type]
|
||||
if(!classId) throw new Error("Cannot handle parameter type: " + type)
|
||||
if(!classId) throw new Error("Cannot convert parameter type to Javascript: " + 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+"_ptr", structType+"*", false, `(${structType}*)js_malloc(ctx, sizeof(${structType}))`)
|
||||
this.statement("*"+jsVar+"_ptr = " + srcVar)
|
||||
this.declare(jsVar, "JSValue", false, `JS_NewObjectClass(ctx, ${classId})`)
|
||||
this.call("JS_SetOpaque", [jsVar, "ptr"])
|
||||
this.call("JS_SetOpaque", [jsVar, jsVar+"_ptr"])
|
||||
}
|
||||
|
||||
jsCleanUpParameter(type: string, name: string) {
|
||||
|
@ -207,13 +222,17 @@ export abstract class GenericQuickJsGenerator<T extends QuickJsGenerator> extend
|
|||
return fun
|
||||
}
|
||||
|
||||
jsOpqToStructPtr(structType: string, structVar: string, srcVar: string, classId: string){
|
||||
this.declare(structVar, structType+"*", false, `(${structType}*)JS_GetOpaque2(ctx, ${srcVar}, ${classId})`)
|
||||
}
|
||||
|
||||
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.declareStruct(structName, "_struct", fields.map(x => x.name))
|
||||
body.jsStructToOpq(structName,"_return","_struct", classId)
|
||||
body.returnExp("_return")
|
||||
return body
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { ApiDescription, ApiFunction, ApiStruct } from "./api"
|
||||
import { CodeGenerator } from "./generation"
|
||||
import { QuickJsHeader } from "./quickjs"
|
||||
import { QuickJsGenerator, QuickJsHeader } from "./quickjs"
|
||||
|
||||
export interface StructBindingOptions {
|
||||
properties?: { [key:string]: { get?:boolean, set?:boolean } },
|
||||
|
@ -9,6 +9,11 @@ export interface StructBindingOptions {
|
|||
createConstructor?: boolean
|
||||
}
|
||||
|
||||
export interface FuncBindingOptions {
|
||||
before?: (gen: QuickJsGenerator) => void
|
||||
after?: (gen: QuickJsGenerator) => void
|
||||
}
|
||||
|
||||
|
||||
export class RayLibHeader extends QuickJsHeader {
|
||||
|
||||
|
@ -17,14 +22,15 @@ export class RayLibHeader extends QuickJsHeader {
|
|||
this.includes.include("raylib.h")
|
||||
}
|
||||
|
||||
addApiFunction(api: ApiFunction, jsName: string | null = null){
|
||||
addApiFunction(api: ApiFunction, jsName: string | null = null, options: FuncBindingOptions = {}){
|
||||
const jName = jsName || api.name.charAt(0).toLowerCase() + api.name.slice(1)
|
||||
|
||||
const fun = this.functions.jsBindingFunction(jName)
|
||||
if(options.before) options.before(fun)
|
||||
// read parameters
|
||||
for (let i = 0; i < api.params.length; i++) {
|
||||
const para = api.params[i]
|
||||
fun.jsToC(para.type,para.name,"argv["+i+"]")
|
||||
fun.jsToC(para.type,para.name,"argv["+i+"]", this.structLookup)
|
||||
}
|
||||
// call c function
|
||||
fun.call(api.name, api.params.map(x => x.name), api.returnType === "void" ? null : {type: api.returnType, name: "returnVal"})
|
||||
|
@ -32,6 +38,7 @@ export class RayLibHeader extends QuickJsHeader {
|
|||
for (const param of api.params) {
|
||||
fun.jsCleanUpParameter(param.type, param.name)
|
||||
}
|
||||
if(options.after) options.after(fun)
|
||||
// return result
|
||||
if(api.returnType === "void"){
|
||||
fun.statement("return JS_UNDEFINED")
|
||||
|
@ -44,10 +51,10 @@ export class RayLibHeader extends QuickJsHeader {
|
|||
this.moduleFunctionList.jsFuncDef(jName, api.argc, fun.getTag("_name"))
|
||||
}
|
||||
|
||||
addApiFunctionByName(name: string, jsName: string | null = null){
|
||||
addApiFunctionByName(name: string, jsName: string | null = null, options: FuncBindingOptions = {}){
|
||||
const func = this.api.getFunction(name)
|
||||
if(func === null) throw new Error("Function not in API: " + name)
|
||||
this.addApiFunction(func, jsName)
|
||||
this.addApiFunction(func, jsName, options)
|
||||
}
|
||||
|
||||
addApiStruct(struct: ApiStruct, destructor: ApiFunction | null, options?: StructBindingOptions){
|
||||
|
@ -86,6 +93,15 @@ export class RayLibHeader extends QuickJsHeader {
|
|||
}
|
||||
}
|
||||
|
||||
exportGlobalStruct(structName: string, exportName: string, values: string[]){
|
||||
this.moduleInit.declareStruct(structName,exportName+"_struct", values)
|
||||
const classId = this.structLookup[structName]
|
||||
if(!classId) throw new Error("Struct "+structName+" not found in register")
|
||||
this.moduleInit.jsStructToOpq(structName, exportName+"_js", exportName+"_struct", classId)
|
||||
this.moduleInit.call("JS_SetModuleExport", ["ctx","m",`"${exportName}"`, exportName+"_js"])
|
||||
this.moduleEntry.call("JS_AddModuleExport", ["ctx","m",`"${exportName}"`])
|
||||
}
|
||||
|
||||
addApiStructByName(structName: string, options?: StructBindingOptions){
|
||||
const struct = this.api.getStruct(structName)
|
||||
if(!struct) throw new Error("Struct not in API: "+ structName)
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
import * as rlc from "raylib.core"
|
||||
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
const screenWidth = 800;
|
||||
const screenHeight = 450;
|
||||
|
||||
rlc.initWindow(screenWidth, screenHeight, "raylib [core] example - basic window");
|
||||
|
||||
rlc.setTargetFPS(60); // Set our game to run at 60 frames-per-second
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
// Main game loop
|
||||
while (!rlc.windowShouldClose()) // Detect window close button or ESC key
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
// TODO: Update your variables here
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
rlc.beginDrawing();
|
||||
|
||||
rlc.clearBackground(rlc.RAYWHITE);
|
||||
|
||||
rlc.drawText("Congrats! You created your first window!", 190, 200, 20, rlc.LIGHTGRAY);
|
||||
|
||||
rlc.endDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
import * as rlc from "raylib.core"
|
||||
|
||||
const KEY_RIGHT = 262 // Key: Cursor right
|
||||
const KEY_LEFT = 263 // Key: Cursor left
|
||||
const KEY_DOWN = 264 // Key: Cursor down
|
||||
const KEY_UP = 265 // Key: Cursor up
|
||||
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
const screenWidth = 800;
|
||||
const screenHeight = 450;
|
||||
|
||||
rlc.initWindow(screenWidth, screenHeight, "raylib [core] example - keyboard input");
|
||||
|
||||
const ballPosition = new rlc.Vector2(screenWidth/2, screenHeight/2);
|
||||
|
||||
rlc.setTargetFPS(60); // Set our game to run at 60 frames-per-second
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
// Main game loop
|
||||
while (!rlc.windowShouldClose()) // Detect window close button or ESC key
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
if (rlc.isKeyDown(KEY_RIGHT)) ballPosition.x += 2;
|
||||
if (rlc.isKeyDown(KEY_LEFT)) ballPosition.x -= 2;
|
||||
if (rlc.isKeyDown(KEY_UP)) ballPosition.y -= 2;
|
||||
if (rlc.isKeyDown(KEY_DOWN)) ballPosition.y += 2;
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
rlc.beginDrawing();
|
||||
|
||||
rlc.clearBackground(rlc.RAYWHITE);
|
||||
|
||||
rlc.drawText("move the ball with arrow keys", 10, 10, 20, rlc.DARKGRAY);
|
||||
|
||||
rlc.drawCircleV(ballPosition, 50, rlc.MAROON);
|
||||
|
||||
rlc.endDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
rlc.closeWindow(); // Close window and OpenGL context
|
||||
//--------------------------------------------------------------------------------------
|
|
@ -258,6 +258,11 @@ class GenericCodeGenerator {
|
|||
fun(sub);
|
||||
return sub;
|
||||
}
|
||||
declareStruct(structName, varName, values, isStatic = false) {
|
||||
if (isStatic)
|
||||
this.inline("static ");
|
||||
this.statement(`${structName} ${varName} = { ${values.join(', ')} }`);
|
||||
}
|
||||
}
|
||||
exports.GenericCodeGenerator = GenericCodeGenerator;
|
||||
class CodeGenerator extends GenericCodeGenerator {
|
||||
|
@ -336,12 +341,17 @@ class GenericQuickJsGenerator extends generation_1.GenericCodeGenerator {
|
|||
const sub = this.function("js_" + jsName, "JSValue", args, true);
|
||||
return sub;
|
||||
}
|
||||
jsToC(type, name, src) {
|
||||
jsToC(type, name, src, classIds = {}) {
|
||||
switch (type) {
|
||||
case "const char *":
|
||||
this.statement(`${type} ${name} = JS_ToCString(ctx, ${src})`);
|
||||
this.statement(`if(${name} == NULL) return JS_EXCEPTION`);
|
||||
break;
|
||||
case "float":
|
||||
this.statement("double _double_" + name);
|
||||
this.statement(`JS_ToFloat64(ctx, &_double_${name}, ${src})`);
|
||||
this.statement(`${type} ${name} = (${type})_double_${name}`);
|
||||
break;
|
||||
case "int":
|
||||
this.statement(`${type} ${name}`);
|
||||
this.statement(`JS_ToInt32(ctx, &${name}, ${src})`);
|
||||
|
@ -352,7 +362,12 @@ class GenericQuickJsGenerator extends generation_1.GenericCodeGenerator {
|
|||
this.statement(`${type} ${name} = (${type})_int_${name}`);
|
||||
break;
|
||||
default:
|
||||
throw new Error("Cannot handle parameter type: " + type);
|
||||
const classId = classIds[type];
|
||||
if (!classId)
|
||||
throw new Error("Cannot convert into parameter type: " + type);
|
||||
this.jsOpqToStructPtr(type, name + "_ptr", src, classId);
|
||||
this.statement(`if(${name}_ptr == NULL) return JS_EXCEPTION`);
|
||||
this.declare(name, type, false, `*${name}_ptr`);
|
||||
}
|
||||
}
|
||||
jsToJs(type, name, src, classIds = {}) {
|
||||
|
@ -361,18 +376,24 @@ class GenericQuickJsGenerator extends generation_1.GenericCodeGenerator {
|
|||
case "unsigned char":
|
||||
this.declare(name, 'JSValue', false, `JS_NewInt32(ctx, ${src})`);
|
||||
break;
|
||||
case "bool":
|
||||
this.declare(name, 'JSValue', false, `JS_NewBool(ctx, ${src})`);
|
||||
break;
|
||||
case "float":
|
||||
this.declare(name, 'JSValue', false, `JS_NewFloat64(ctx, ${src})`);
|
||||
break;
|
||||
default:
|
||||
const classId = classIds[type];
|
||||
if (!classId)
|
||||
throw new Error("Cannot handle parameter type: " + type);
|
||||
throw new Error("Cannot convert parameter type to Javascript: " + 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 + "_ptr", structType + "*", false, `(${structType}*)js_malloc(ctx, sizeof(${structType}))`);
|
||||
this.statement("*" + jsVar + "_ptr = " + srcVar);
|
||||
this.declare(jsVar, "JSValue", false, `JS_NewObjectClass(ctx, ${classId})`);
|
||||
this.call("JS_SetOpaque", [jsVar, "ptr"]);
|
||||
this.call("JS_SetOpaque", [jsVar, jsVar + "_ptr"]);
|
||||
}
|
||||
jsCleanUpParameter(type, name) {
|
||||
switch (type) {
|
||||
|
@ -456,13 +477,16 @@ class GenericQuickJsGenerator extends generation_1.GenericCodeGenerator {
|
|||
fun.returnExp("JS_UNDEFINED");
|
||||
return fun;
|
||||
}
|
||||
jsOpqToStructPtr(structType, structVar, srcVar, classId) {
|
||||
this.declare(structVar, structType + "*", false, `(${structType}*)JS_GetOpaque2(ctx, ${srcVar}, ${classId})`);
|
||||
}
|
||||
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.declareStruct(structName, "_struct", fields.map(x => x.name));
|
||||
body.jsStructToOpq(structName, "_return", "_struct", classId);
|
||||
body.returnExp("_return");
|
||||
return body;
|
||||
|
@ -495,13 +519,15 @@ class RayLibHeader extends quickjs_1.QuickJsHeader {
|
|||
this.api = api;
|
||||
this.includes.include("raylib.h");
|
||||
}
|
||||
addApiFunction(api, jsName = null) {
|
||||
addApiFunction(api, jsName = null, options = {}) {
|
||||
const jName = jsName || api.name.charAt(0).toLowerCase() + api.name.slice(1);
|
||||
const fun = this.functions.jsBindingFunction(jName);
|
||||
if (options.before)
|
||||
options.before(fun);
|
||||
// read parameters
|
||||
for (let i = 0; i < api.params.length; i++) {
|
||||
const para = api.params[i];
|
||||
fun.jsToC(para.type, para.name, "argv[" + i + "]");
|
||||
fun.jsToC(para.type, para.name, "argv[" + i + "]", this.structLookup);
|
||||
}
|
||||
// call c function
|
||||
fun.call(api.name, api.params.map(x => x.name), api.returnType === "void" ? null : { type: api.returnType, name: "returnVal" });
|
||||
|
@ -509,6 +535,8 @@ class RayLibHeader extends quickjs_1.QuickJsHeader {
|
|||
for (const param of api.params) {
|
||||
fun.jsCleanUpParameter(param.type, param.name);
|
||||
}
|
||||
if (options.after)
|
||||
options.after(fun);
|
||||
// return result
|
||||
if (api.returnType === "void") {
|
||||
fun.statement("return JS_UNDEFINED");
|
||||
|
@ -520,11 +548,11 @@ class RayLibHeader extends quickjs_1.QuickJsHeader {
|
|||
// add binding to function declaration
|
||||
this.moduleFunctionList.jsFuncDef(jName, api.argc, fun.getTag("_name"));
|
||||
}
|
||||
addApiFunctionByName(name, jsName = null) {
|
||||
addApiFunctionByName(name, jsName = null, options = {}) {
|
||||
const func = this.api.getFunction(name);
|
||||
if (func === null)
|
||||
throw new Error("Function not in API: " + name);
|
||||
this.addApiFunction(func, jsName);
|
||||
this.addApiFunction(func, jsName, options);
|
||||
}
|
||||
addApiStruct(struct, destructor, options) {
|
||||
const classId = this.declarations.jsClassId(`js_${struct.name}_class_id`);
|
||||
|
@ -558,6 +586,15 @@ class RayLibHeader extends quickjs_1.QuickJsHeader {
|
|||
this.moduleEntry.call("JS_AddModuleExport", ["ctx", "m", '"' + struct.name + '"']);
|
||||
}
|
||||
}
|
||||
exportGlobalStruct(structName, exportName, values) {
|
||||
this.moduleInit.declareStruct(structName, exportName + "_struct", values);
|
||||
const classId = this.structLookup[structName];
|
||||
if (!classId)
|
||||
throw new Error("Struct " + structName + " not found in register");
|
||||
this.moduleInit.jsStructToOpq(structName, exportName + "_js", exportName + "_struct", classId);
|
||||
this.moduleInit.call("JS_SetModuleExport", ["ctx", "m", `"${exportName}"`, exportName + "_js"]);
|
||||
this.moduleEntry.call("JS_AddModuleExport", ["ctx", "m", `"${exportName}"`]);
|
||||
}
|
||||
addApiStructByName(structName, options) {
|
||||
const struct = this.api.getStruct(structName);
|
||||
if (!struct)
|
||||
|
@ -638,12 +675,28 @@ function main() {
|
|||
},
|
||||
createConstructor: true
|
||||
});
|
||||
core_gen.addApiStructByName("Vector2", {
|
||||
properties: {
|
||||
x: { get: true, set: true },
|
||||
y: { 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("InitWindow");
|
||||
core_gen.addApiFunctionByName("SetTargetFPS");
|
||||
core_gen.addApiFunctionByName("WindowShouldClose", null, { before: fun => fun.call("app_update_quickjs", []) });
|
||||
core_gen.addApiFunctionByName("ClearBackground");
|
||||
core_gen.addApiFunctionByName("CloseWindow");
|
||||
core_gen.addApiFunctionByName("DrawText");
|
||||
core_gen.addApiFunctionByName("DrawCircleV");
|
||||
core_gen.addApiFunctionByName("IsKeyDown");
|
||||
api.defines.filter(x => x.type === "COLOR").map(x => ({ name: x.name, values: (x.value.match(/\{([^}]+)\}/) || "")[1].split(',').map(x => x.trim()) })).forEach(x => {
|
||||
core_gen.exportGlobalStruct("Color", x.name, x.values);
|
||||
});
|
||||
core_gen.writeTo("src/bindings/js_raylib_core.h");
|
||||
const texture_gen = new raylib_header_1.RayLibHeader("raylib_texture", apiDesc);
|
||||
texture_gen.addApiStructByName("Image", {
|
||||
|
|
|
@ -1,191 +0,0 @@
|
|||
// Run with Node.js
|
||||
|
||||
const fs = require('fs');
|
||||
const { connect } = require('http2');
|
||||
let api, modules
|
||||
|
||||
async function main(){
|
||||
api = await readJson('thirdparty/raylib/parser/output/raylib_api.json')
|
||||
modules = await readJson('bindings.json')
|
||||
|
||||
const headers = modules.map(generateModule)
|
||||
|
||||
modules.forEach(async (header,i) => {
|
||||
await writeFile(`src/bindings/js_${header.name}.h`, headers[i])
|
||||
});
|
||||
}
|
||||
|
||||
class FunctionList {
|
||||
definitions = []
|
||||
|
||||
addFunctionDef(name, args, cname){
|
||||
this.definitions.push(`JS_CFUNC_DEF("${name}", ${args}, ${cname})`)
|
||||
}
|
||||
|
||||
addIntConst(name, val){
|
||||
this.definitions.push(`JS_PROP_INT32_DEF("${name}", ${val})`)
|
||||
}
|
||||
|
||||
generate(name){
|
||||
return `static const JSCFunctionListEntry js_${name}_funcs[] = {
|
||||
${this.definitions.map(x => " "+x).join(",\n")}
|
||||
};`
|
||||
}
|
||||
}
|
||||
|
||||
const generateModule = (mod) => {
|
||||
const fl = new FunctionList()
|
||||
let content = mod.functions.map(generateFunction(fl)).join("\n\n")
|
||||
content += "\n\n" + fl.generate(mod.name)
|
||||
return generateHeader(mod.name, content)
|
||||
}
|
||||
|
||||
const generateFunction = (functionList) => (func) => {
|
||||
const api = findFunction(func.name)
|
||||
const cfunc = new CFunction(func, api, functionList)
|
||||
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}; 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.generateParameterCheck().join("\n ")}
|
||||
${this.generateParameters().join("\n ")}
|
||||
${this.generateFunctionCall()}
|
||||
${this.generateParametersCleanup().join("\n ")}
|
||||
${this.generateReturn()}
|
||||
}`
|
||||
}
|
||||
}
|
||||
|
||||
const findFunction = (name) => findIn(api.functions,name)
|
||||
|
||||
const findIn = (arr, name) => arr.find(x => x.name == name)
|
||||
|
||||
|
||||
async function readJson(path){
|
||||
const c = await readFile(path)
|
||||
return JSON.parse(c)
|
||||
}
|
||||
|
||||
function readFile(path) {
|
||||
const p = new Promise((res,rej) => {
|
||||
fs.readFile(path, 'utf8', (err,data) => {
|
||||
if(err) rej(error)
|
||||
else res(data)
|
||||
})
|
||||
})
|
||||
return p
|
||||
}
|
||||
|
||||
function writeFile(path, data){
|
||||
return new Promise((res, rej) => {
|
||||
fs.writeFile(path, data, (err) => {
|
||||
if(err) rej(err)
|
||||
else res()
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
function generateHeader(name, content){
|
||||
return `
|
||||
#ifndef JS_${name}
|
||||
#define JS_${name}
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <quickjs.h>
|
||||
|
||||
#ifndef countof
|
||||
#define countof(x) (sizeof(x) / sizeof((x)[0]))
|
||||
#endif
|
||||
|
||||
${content}
|
||||
|
||||
static int js_${name}_init(JSContext *ctx, JSModuleDef *m){
|
||||
JS_SetModuleExportList(ctx, m, js_${name}_funcs,
|
||||
countof(js_${name}_funcs));
|
||||
}
|
||||
|
||||
JSModuleDef *js_init_module_${name}(JSContext *ctx, const char *module_name)
|
||||
{
|
||||
JSModuleDef *m;
|
||||
m = JS_NewCModule(ctx, module_name, js_${name}_init);
|
||||
if (!m)
|
||||
return NULL;
|
||||
|
||||
JS_AddModuleExportList(ctx, m, js_${name}_funcs,
|
||||
countof(js_${name}_funcs));
|
||||
|
||||
return m;
|
||||
}
|
||||
|
||||
#endif
|
||||
`
|
||||
}
|
||||
|
||||
main()
|
40
main.js
40
main.js
|
@ -1,19 +1,35 @@
|
|||
import { setWindowTitle, setWindowPosition, Color } from "raylib.core"
|
||||
import * as rlc from "raylib.core"
|
||||
import { loadImage } from "raylib.texture"
|
||||
import { gc } from "std"
|
||||
|
||||
const img = loadImage("assets/planet00.png")
|
||||
console.log(img.width)
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
const screenWidth = 800;
|
||||
const screenHeight = 450;
|
||||
|
||||
//const img = new Image("assets/planet00.png")
|
||||
rlc.initWindow(screenWidth, screenHeight, "raylib [core] example - basic window");
|
||||
|
||||
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)
|
||||
rlc.setTargetFPS(60); // Set our game to run at 60 frames-per-second
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
// Main game loop
|
||||
while (!rlc.windowShouldClose()) // Detect window close button or ESC key
|
||||
{
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
// TODO: Update your variables here
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
rlc.beginDrawing();
|
||||
|
||||
rlc.clearBackground(rlc.RAYWHITE);
|
||||
|
||||
rlc.drawText("Congrats! You created your first window!", 190, 200, 20, rlc.LIGHTGRAY);
|
||||
|
||||
rlc.endDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
|
|
|
@ -1,3 +0,0 @@
|
|||
export function test() {
|
||||
return 42
|
||||
}
|
|
@ -13,6 +13,7 @@
|
|||
#endif
|
||||
|
||||
static JSClassID js_Color_class_id;
|
||||
static JSClassID js_Vector2_class_id;
|
||||
|
||||
static void js_Color_finalizer(JSRuntime * rt, JSValue val) {
|
||||
Color* ptr = JS_GetOpaque(val, js_Color_class_id);
|
||||
|
@ -128,6 +129,74 @@ static int js_declare_Color(JSContext * ctx, JSModuleDef * m) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void js_Vector2_finalizer(JSRuntime * rt, JSValue val) {
|
||||
Vector2* ptr = JS_GetOpaque(val, js_Vector2_class_id);
|
||||
if(ptr) {
|
||||
TraceLog(LOG_INFO, "Finalize Vector2");
|
||||
js_free_rt(rt, ptr);
|
||||
}
|
||||
}
|
||||
|
||||
static JSValue js_Vector2_get_x(JSContext* ctx, JSValueConst this_val) {
|
||||
Vector2* ptr = JS_GetOpaque2(ctx, this_val, js_Vector2_class_id);
|
||||
if(!ptr) {
|
||||
return JS_EXCEPTION;
|
||||
}
|
||||
float x = ptr->x;
|
||||
JSValue ret = JS_NewFloat64(ctx, x);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static JSValue js_Vector2_set_x(JSContext* ctx, JSValueConst this_val, JSValueConst v) {
|
||||
Vector2* ptr = JS_GetOpaque2(ctx, this_val, js_Vector2_class_id);
|
||||
if(!ptr) {
|
||||
return JS_EXCEPTION;
|
||||
}
|
||||
double _double_value;
|
||||
JS_ToFloat64(ctx, &_double_value, v);
|
||||
float value = (float)_double_value;
|
||||
ptr->x = value;
|
||||
return JS_UNDEFINED;
|
||||
}
|
||||
|
||||
static JSValue js_Vector2_get_y(JSContext* ctx, JSValueConst this_val) {
|
||||
Vector2* ptr = JS_GetOpaque2(ctx, this_val, js_Vector2_class_id);
|
||||
if(!ptr) {
|
||||
return JS_EXCEPTION;
|
||||
}
|
||||
float y = ptr->y;
|
||||
JSValue ret = JS_NewFloat64(ctx, y);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static JSValue js_Vector2_set_y(JSContext* ctx, JSValueConst this_val, JSValueConst v) {
|
||||
Vector2* ptr = JS_GetOpaque2(ctx, this_val, js_Vector2_class_id);
|
||||
if(!ptr) {
|
||||
return JS_EXCEPTION;
|
||||
}
|
||||
double _double_value;
|
||||
JS_ToFloat64(ctx, &_double_value, v);
|
||||
float value = (float)_double_value;
|
||||
ptr->y = value;
|
||||
return JS_UNDEFINED;
|
||||
}
|
||||
|
||||
static const JSCFunctionListEntry js_Vector2_proto_funcs[] = {
|
||||
JS_CGETSET_DEF("x",js_Vector2_get_x,js_Vector2_set_x),
|
||||
JS_CGETSET_DEF("y",js_Vector2_get_y,js_Vector2_set_y),
|
||||
JS_PROP_STRING_DEF("[Symbol.toStringTag]","Vector2", JS_PROP_CONFIGURABLE),
|
||||
};
|
||||
|
||||
static int js_declare_Vector2(JSContext * ctx, JSModuleDef * m) {
|
||||
JS_NewClassID(&js_Vector2_class_id);
|
||||
JSClassDef js_Vector2_def = { .class_name = "Vector2", .finalizer = js_Vector2_finalizer };
|
||||
JS_NewClass(JS_GetRuntime(ctx), js_Vector2_class_id, &js_Vector2_def);
|
||||
JSValue proto = JS_NewObject(ctx);
|
||||
JS_SetPropertyFunctionList(ctx, proto, js_Vector2_proto_funcs, countof(js_Vector2_proto_funcs));
|
||||
JS_SetClassProto(ctx, js_Vector2_class_id, proto);
|
||||
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]);
|
||||
|
@ -142,10 +211,25 @@ static JSValue js_Color_constructor(JSContext * ctx, JSValueConst this_val, int
|
|||
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;
|
||||
Color* _return_ptr = (Color*)js_malloc(ctx, sizeof(Color));
|
||||
*_return_ptr = _struct;
|
||||
JSValue _return = JS_NewObjectClass(ctx, js_Color_class_id);
|
||||
JS_SetOpaque(_return, ptr);
|
||||
JS_SetOpaque(_return, _return_ptr);
|
||||
return _return;
|
||||
}
|
||||
|
||||
static JSValue js_Vector2_constructor(JSContext * ctx, JSValueConst this_val, int argc, JSValueConst * argv) {
|
||||
double _double_x;
|
||||
JS_ToFloat64(ctx, &_double_x, argv[0]);
|
||||
float x = (float)_double_x;
|
||||
double _double_y;
|
||||
JS_ToFloat64(ctx, &_double_y, argv[1]);
|
||||
float y = (float)_double_y;
|
||||
Vector2 _struct = { x, y };
|
||||
Vector2* _return_ptr = (Vector2*)js_malloc(ctx, sizeof(Vector2));
|
||||
*_return_ptr = _struct;
|
||||
JSValue _return = JS_NewObjectClass(ctx, js_Vector2_class_id);
|
||||
JS_SetOpaque(_return, _return_ptr);
|
||||
return _return;
|
||||
}
|
||||
|
||||
|
@ -176,11 +260,97 @@ static JSValue js_endDrawing(JSContext * ctx, JSValueConst this_val, int argc, J
|
|||
return JS_UNDEFINED;
|
||||
}
|
||||
|
||||
static JSValue js_initWindow(JSContext * ctx, JSValueConst this_val, int argc, JSValueConst * argv) {
|
||||
int width;
|
||||
JS_ToInt32(ctx, &width, argv[0]);
|
||||
int height;
|
||||
JS_ToInt32(ctx, &height, argv[1]);
|
||||
const char * title = JS_ToCString(ctx, argv[2]);
|
||||
if(title == NULL) return JS_EXCEPTION;
|
||||
InitWindow(width, height, title);
|
||||
JS_FreeCString(ctx, title);
|
||||
return JS_UNDEFINED;
|
||||
}
|
||||
|
||||
static JSValue js_setTargetFPS(JSContext * ctx, JSValueConst this_val, int argc, JSValueConst * argv) {
|
||||
int fps;
|
||||
JS_ToInt32(ctx, &fps, argv[0]);
|
||||
SetTargetFPS(fps);
|
||||
return JS_UNDEFINED;
|
||||
}
|
||||
|
||||
static JSValue js_windowShouldClose(JSContext * ctx, JSValueConst this_val, int argc, JSValueConst * argv) {
|
||||
app_update_quickjs();
|
||||
bool returnVal = WindowShouldClose();
|
||||
JSValue ret = JS_NewBool(ctx, returnVal);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static JSValue js_clearBackground(JSContext * ctx, JSValueConst this_val, int argc, JSValueConst * argv) {
|
||||
Color* color_ptr = (Color*)JS_GetOpaque2(ctx, argv[0], js_Color_class_id);
|
||||
if(color_ptr == NULL) return JS_EXCEPTION;
|
||||
Color color = *color_ptr;
|
||||
ClearBackground(color);
|
||||
return JS_UNDEFINED;
|
||||
}
|
||||
|
||||
static JSValue js_closeWindow(JSContext * ctx, JSValueConst this_val, int argc, JSValueConst * argv) {
|
||||
CloseWindow();
|
||||
return JS_UNDEFINED;
|
||||
}
|
||||
|
||||
static JSValue js_drawText(JSContext * ctx, JSValueConst this_val, int argc, JSValueConst * argv) {
|
||||
const char * text = JS_ToCString(ctx, argv[0]);
|
||||
if(text == NULL) return JS_EXCEPTION;
|
||||
int posX;
|
||||
JS_ToInt32(ctx, &posX, argv[1]);
|
||||
int posY;
|
||||
JS_ToInt32(ctx, &posY, argv[2]);
|
||||
int fontSize;
|
||||
JS_ToInt32(ctx, &fontSize, argv[3]);
|
||||
Color* color_ptr = (Color*)JS_GetOpaque2(ctx, argv[4], js_Color_class_id);
|
||||
if(color_ptr == NULL) return JS_EXCEPTION;
|
||||
Color color = *color_ptr;
|
||||
DrawText(text, posX, posY, fontSize, color);
|
||||
JS_FreeCString(ctx, text);
|
||||
return JS_UNDEFINED;
|
||||
}
|
||||
|
||||
static JSValue js_drawCircleV(JSContext * ctx, JSValueConst this_val, int argc, JSValueConst * argv) {
|
||||
Vector2* center_ptr = (Vector2*)JS_GetOpaque2(ctx, argv[0], js_Vector2_class_id);
|
||||
if(center_ptr == NULL) return JS_EXCEPTION;
|
||||
Vector2 center = *center_ptr;
|
||||
double _double_radius;
|
||||
JS_ToFloat64(ctx, &_double_radius, argv[1]);
|
||||
float radius = (float)_double_radius;
|
||||
Color* color_ptr = (Color*)JS_GetOpaque2(ctx, argv[2], js_Color_class_id);
|
||||
if(color_ptr == NULL) return JS_EXCEPTION;
|
||||
Color color = *color_ptr;
|
||||
DrawCircleV(center, radius, color);
|
||||
return JS_UNDEFINED;
|
||||
}
|
||||
|
||||
static JSValue js_isKeyDown(JSContext * ctx, JSValueConst this_val, int argc, JSValueConst * argv) {
|
||||
int key;
|
||||
JS_ToInt32(ctx, &key, argv[0]);
|
||||
bool returnVal = IsKeyDown(key);
|
||||
JSValue ret = JS_NewBool(ctx, returnVal);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const JSCFunctionListEntry js_raylib_core_funcs[] = {
|
||||
JS_CFUNC_DEF("setWindowTitle",1,js_setWindowTitle),
|
||||
JS_CFUNC_DEF("setWindowPosition",2,js_setWindowPosition),
|
||||
JS_CFUNC_DEF("beginDrawing",0,js_beginDrawing),
|
||||
JS_CFUNC_DEF("endDrawing",0,js_endDrawing),
|
||||
JS_CFUNC_DEF("initWindow",3,js_initWindow),
|
||||
JS_CFUNC_DEF("setTargetFPS",1,js_setTargetFPS),
|
||||
JS_CFUNC_DEF("windowShouldClose",0,js_windowShouldClose),
|
||||
JS_CFUNC_DEF("clearBackground",1,js_clearBackground),
|
||||
JS_CFUNC_DEF("closeWindow",0,js_closeWindow),
|
||||
JS_CFUNC_DEF("drawText",5,js_drawText),
|
||||
JS_CFUNC_DEF("drawCircleV",3,js_drawCircleV),
|
||||
JS_CFUNC_DEF("isKeyDown",1,js_isKeyDown),
|
||||
};
|
||||
|
||||
static int js_raylib_core_init(JSContext * ctx, JSModuleDef * m) {
|
||||
|
@ -188,6 +358,165 @@ static int js_raylib_core_init(JSContext * ctx, JSModuleDef * m) {
|
|||
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);
|
||||
js_declare_Vector2(ctx, m);
|
||||
JSValue Vector2_constr = JS_NewCFunction2(ctx, js_Vector2_constructor,"Vector2)", 2, JS_CFUNC_constructor_or_func, 0);
|
||||
JS_SetModuleExport(ctx, m, "Vector2", Vector2_constr);
|
||||
Color LIGHTGRAY_struct = { 200, 200, 200, 255 };
|
||||
Color* LIGHTGRAY_js_ptr = (Color*)js_malloc(ctx, sizeof(Color));
|
||||
*LIGHTGRAY_js_ptr = LIGHTGRAY_struct;
|
||||
JSValue LIGHTGRAY_js = JS_NewObjectClass(ctx, js_Color_class_id);
|
||||
JS_SetOpaque(LIGHTGRAY_js, LIGHTGRAY_js_ptr);
|
||||
JS_SetModuleExport(ctx, m, "LIGHTGRAY", LIGHTGRAY_js);
|
||||
Color GRAY_struct = { 130, 130, 130, 255 };
|
||||
Color* GRAY_js_ptr = (Color*)js_malloc(ctx, sizeof(Color));
|
||||
*GRAY_js_ptr = GRAY_struct;
|
||||
JSValue GRAY_js = JS_NewObjectClass(ctx, js_Color_class_id);
|
||||
JS_SetOpaque(GRAY_js, GRAY_js_ptr);
|
||||
JS_SetModuleExport(ctx, m, "GRAY", GRAY_js);
|
||||
Color DARKGRAY_struct = { 80, 80, 80, 255 };
|
||||
Color* DARKGRAY_js_ptr = (Color*)js_malloc(ctx, sizeof(Color));
|
||||
*DARKGRAY_js_ptr = DARKGRAY_struct;
|
||||
JSValue DARKGRAY_js = JS_NewObjectClass(ctx, js_Color_class_id);
|
||||
JS_SetOpaque(DARKGRAY_js, DARKGRAY_js_ptr);
|
||||
JS_SetModuleExport(ctx, m, "DARKGRAY", DARKGRAY_js);
|
||||
Color YELLOW_struct = { 253, 249, 0, 255 };
|
||||
Color* YELLOW_js_ptr = (Color*)js_malloc(ctx, sizeof(Color));
|
||||
*YELLOW_js_ptr = YELLOW_struct;
|
||||
JSValue YELLOW_js = JS_NewObjectClass(ctx, js_Color_class_id);
|
||||
JS_SetOpaque(YELLOW_js, YELLOW_js_ptr);
|
||||
JS_SetModuleExport(ctx, m, "YELLOW", YELLOW_js);
|
||||
Color GOLD_struct = { 255, 203, 0, 255 };
|
||||
Color* GOLD_js_ptr = (Color*)js_malloc(ctx, sizeof(Color));
|
||||
*GOLD_js_ptr = GOLD_struct;
|
||||
JSValue GOLD_js = JS_NewObjectClass(ctx, js_Color_class_id);
|
||||
JS_SetOpaque(GOLD_js, GOLD_js_ptr);
|
||||
JS_SetModuleExport(ctx, m, "GOLD", GOLD_js);
|
||||
Color ORANGE_struct = { 255, 161, 0, 255 };
|
||||
Color* ORANGE_js_ptr = (Color*)js_malloc(ctx, sizeof(Color));
|
||||
*ORANGE_js_ptr = ORANGE_struct;
|
||||
JSValue ORANGE_js = JS_NewObjectClass(ctx, js_Color_class_id);
|
||||
JS_SetOpaque(ORANGE_js, ORANGE_js_ptr);
|
||||
JS_SetModuleExport(ctx, m, "ORANGE", ORANGE_js);
|
||||
Color PINK_struct = { 255, 109, 194, 255 };
|
||||
Color* PINK_js_ptr = (Color*)js_malloc(ctx, sizeof(Color));
|
||||
*PINK_js_ptr = PINK_struct;
|
||||
JSValue PINK_js = JS_NewObjectClass(ctx, js_Color_class_id);
|
||||
JS_SetOpaque(PINK_js, PINK_js_ptr);
|
||||
JS_SetModuleExport(ctx, m, "PINK", PINK_js);
|
||||
Color RED_struct = { 230, 41, 55, 255 };
|
||||
Color* RED_js_ptr = (Color*)js_malloc(ctx, sizeof(Color));
|
||||
*RED_js_ptr = RED_struct;
|
||||
JSValue RED_js = JS_NewObjectClass(ctx, js_Color_class_id);
|
||||
JS_SetOpaque(RED_js, RED_js_ptr);
|
||||
JS_SetModuleExport(ctx, m, "RED", RED_js);
|
||||
Color MAROON_struct = { 190, 33, 55, 255 };
|
||||
Color* MAROON_js_ptr = (Color*)js_malloc(ctx, sizeof(Color));
|
||||
*MAROON_js_ptr = MAROON_struct;
|
||||
JSValue MAROON_js = JS_NewObjectClass(ctx, js_Color_class_id);
|
||||
JS_SetOpaque(MAROON_js, MAROON_js_ptr);
|
||||
JS_SetModuleExport(ctx, m, "MAROON", MAROON_js);
|
||||
Color GREEN_struct = { 0, 228, 48, 255 };
|
||||
Color* GREEN_js_ptr = (Color*)js_malloc(ctx, sizeof(Color));
|
||||
*GREEN_js_ptr = GREEN_struct;
|
||||
JSValue GREEN_js = JS_NewObjectClass(ctx, js_Color_class_id);
|
||||
JS_SetOpaque(GREEN_js, GREEN_js_ptr);
|
||||
JS_SetModuleExport(ctx, m, "GREEN", GREEN_js);
|
||||
Color LIME_struct = { 0, 158, 47, 255 };
|
||||
Color* LIME_js_ptr = (Color*)js_malloc(ctx, sizeof(Color));
|
||||
*LIME_js_ptr = LIME_struct;
|
||||
JSValue LIME_js = JS_NewObjectClass(ctx, js_Color_class_id);
|
||||
JS_SetOpaque(LIME_js, LIME_js_ptr);
|
||||
JS_SetModuleExport(ctx, m, "LIME", LIME_js);
|
||||
Color DARKGREEN_struct = { 0, 117, 44, 255 };
|
||||
Color* DARKGREEN_js_ptr = (Color*)js_malloc(ctx, sizeof(Color));
|
||||
*DARKGREEN_js_ptr = DARKGREEN_struct;
|
||||
JSValue DARKGREEN_js = JS_NewObjectClass(ctx, js_Color_class_id);
|
||||
JS_SetOpaque(DARKGREEN_js, DARKGREEN_js_ptr);
|
||||
JS_SetModuleExport(ctx, m, "DARKGREEN", DARKGREEN_js);
|
||||
Color SKYBLUE_struct = { 102, 191, 255, 255 };
|
||||
Color* SKYBLUE_js_ptr = (Color*)js_malloc(ctx, sizeof(Color));
|
||||
*SKYBLUE_js_ptr = SKYBLUE_struct;
|
||||
JSValue SKYBLUE_js = JS_NewObjectClass(ctx, js_Color_class_id);
|
||||
JS_SetOpaque(SKYBLUE_js, SKYBLUE_js_ptr);
|
||||
JS_SetModuleExport(ctx, m, "SKYBLUE", SKYBLUE_js);
|
||||
Color BLUE_struct = { 0, 121, 241, 255 };
|
||||
Color* BLUE_js_ptr = (Color*)js_malloc(ctx, sizeof(Color));
|
||||
*BLUE_js_ptr = BLUE_struct;
|
||||
JSValue BLUE_js = JS_NewObjectClass(ctx, js_Color_class_id);
|
||||
JS_SetOpaque(BLUE_js, BLUE_js_ptr);
|
||||
JS_SetModuleExport(ctx, m, "BLUE", BLUE_js);
|
||||
Color DARKBLUE_struct = { 0, 82, 172, 255 };
|
||||
Color* DARKBLUE_js_ptr = (Color*)js_malloc(ctx, sizeof(Color));
|
||||
*DARKBLUE_js_ptr = DARKBLUE_struct;
|
||||
JSValue DARKBLUE_js = JS_NewObjectClass(ctx, js_Color_class_id);
|
||||
JS_SetOpaque(DARKBLUE_js, DARKBLUE_js_ptr);
|
||||
JS_SetModuleExport(ctx, m, "DARKBLUE", DARKBLUE_js);
|
||||
Color PURPLE_struct = { 200, 122, 255, 255 };
|
||||
Color* PURPLE_js_ptr = (Color*)js_malloc(ctx, sizeof(Color));
|
||||
*PURPLE_js_ptr = PURPLE_struct;
|
||||
JSValue PURPLE_js = JS_NewObjectClass(ctx, js_Color_class_id);
|
||||
JS_SetOpaque(PURPLE_js, PURPLE_js_ptr);
|
||||
JS_SetModuleExport(ctx, m, "PURPLE", PURPLE_js);
|
||||
Color VIOLET_struct = { 135, 60, 190, 255 };
|
||||
Color* VIOLET_js_ptr = (Color*)js_malloc(ctx, sizeof(Color));
|
||||
*VIOLET_js_ptr = VIOLET_struct;
|
||||
JSValue VIOLET_js = JS_NewObjectClass(ctx, js_Color_class_id);
|
||||
JS_SetOpaque(VIOLET_js, VIOLET_js_ptr);
|
||||
JS_SetModuleExport(ctx, m, "VIOLET", VIOLET_js);
|
||||
Color DARKPURPLE_struct = { 112, 31, 126, 255 };
|
||||
Color* DARKPURPLE_js_ptr = (Color*)js_malloc(ctx, sizeof(Color));
|
||||
*DARKPURPLE_js_ptr = DARKPURPLE_struct;
|
||||
JSValue DARKPURPLE_js = JS_NewObjectClass(ctx, js_Color_class_id);
|
||||
JS_SetOpaque(DARKPURPLE_js, DARKPURPLE_js_ptr);
|
||||
JS_SetModuleExport(ctx, m, "DARKPURPLE", DARKPURPLE_js);
|
||||
Color BEIGE_struct = { 211, 176, 131, 255 };
|
||||
Color* BEIGE_js_ptr = (Color*)js_malloc(ctx, sizeof(Color));
|
||||
*BEIGE_js_ptr = BEIGE_struct;
|
||||
JSValue BEIGE_js = JS_NewObjectClass(ctx, js_Color_class_id);
|
||||
JS_SetOpaque(BEIGE_js, BEIGE_js_ptr);
|
||||
JS_SetModuleExport(ctx, m, "BEIGE", BEIGE_js);
|
||||
Color BROWN_struct = { 127, 106, 79, 255 };
|
||||
Color* BROWN_js_ptr = (Color*)js_malloc(ctx, sizeof(Color));
|
||||
*BROWN_js_ptr = BROWN_struct;
|
||||
JSValue BROWN_js = JS_NewObjectClass(ctx, js_Color_class_id);
|
||||
JS_SetOpaque(BROWN_js, BROWN_js_ptr);
|
||||
JS_SetModuleExport(ctx, m, "BROWN", BROWN_js);
|
||||
Color DARKBROWN_struct = { 76, 63, 47, 255 };
|
||||
Color* DARKBROWN_js_ptr = (Color*)js_malloc(ctx, sizeof(Color));
|
||||
*DARKBROWN_js_ptr = DARKBROWN_struct;
|
||||
JSValue DARKBROWN_js = JS_NewObjectClass(ctx, js_Color_class_id);
|
||||
JS_SetOpaque(DARKBROWN_js, DARKBROWN_js_ptr);
|
||||
JS_SetModuleExport(ctx, m, "DARKBROWN", DARKBROWN_js);
|
||||
Color WHITE_struct = { 255, 255, 255, 255 };
|
||||
Color* WHITE_js_ptr = (Color*)js_malloc(ctx, sizeof(Color));
|
||||
*WHITE_js_ptr = WHITE_struct;
|
||||
JSValue WHITE_js = JS_NewObjectClass(ctx, js_Color_class_id);
|
||||
JS_SetOpaque(WHITE_js, WHITE_js_ptr);
|
||||
JS_SetModuleExport(ctx, m, "WHITE", WHITE_js);
|
||||
Color BLACK_struct = { 0, 0, 0, 255 };
|
||||
Color* BLACK_js_ptr = (Color*)js_malloc(ctx, sizeof(Color));
|
||||
*BLACK_js_ptr = BLACK_struct;
|
||||
JSValue BLACK_js = JS_NewObjectClass(ctx, js_Color_class_id);
|
||||
JS_SetOpaque(BLACK_js, BLACK_js_ptr);
|
||||
JS_SetModuleExport(ctx, m, "BLACK", BLACK_js);
|
||||
Color BLANK_struct = { 0, 0, 0, 0 };
|
||||
Color* BLANK_js_ptr = (Color*)js_malloc(ctx, sizeof(Color));
|
||||
*BLANK_js_ptr = BLANK_struct;
|
||||
JSValue BLANK_js = JS_NewObjectClass(ctx, js_Color_class_id);
|
||||
JS_SetOpaque(BLANK_js, BLANK_js_ptr);
|
||||
JS_SetModuleExport(ctx, m, "BLANK", BLANK_js);
|
||||
Color MAGENTA_struct = { 255, 0, 255, 255 };
|
||||
Color* MAGENTA_js_ptr = (Color*)js_malloc(ctx, sizeof(Color));
|
||||
*MAGENTA_js_ptr = MAGENTA_struct;
|
||||
JSValue MAGENTA_js = JS_NewObjectClass(ctx, js_Color_class_id);
|
||||
JS_SetOpaque(MAGENTA_js, MAGENTA_js_ptr);
|
||||
JS_SetModuleExport(ctx, m, "MAGENTA", MAGENTA_js);
|
||||
Color RAYWHITE_struct = { 245, 245, 245, 255 };
|
||||
Color* RAYWHITE_js_ptr = (Color*)js_malloc(ctx, sizeof(Color));
|
||||
*RAYWHITE_js_ptr = RAYWHITE_struct;
|
||||
JSValue RAYWHITE_js = JS_NewObjectClass(ctx, js_Color_class_id);
|
||||
JS_SetOpaque(RAYWHITE_js, RAYWHITE_js_ptr);
|
||||
JS_SetModuleExport(ctx, m, "RAYWHITE", RAYWHITE_js);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -197,6 +526,33 @@ JSModuleDef * js_init_module_raylib_core(JSContext * ctx, const char * module_na
|
|||
if(!m) return NULL;
|
||||
JS_AddModuleExportList(ctx, m, js_raylib_core_funcs, countof(js_raylib_core_funcs));
|
||||
JS_AddModuleExport(ctx, m, "Color");
|
||||
JS_AddModuleExport(ctx, m, "Vector2");
|
||||
JS_AddModuleExport(ctx, m, "LIGHTGRAY");
|
||||
JS_AddModuleExport(ctx, m, "GRAY");
|
||||
JS_AddModuleExport(ctx, m, "DARKGRAY");
|
||||
JS_AddModuleExport(ctx, m, "YELLOW");
|
||||
JS_AddModuleExport(ctx, m, "GOLD");
|
||||
JS_AddModuleExport(ctx, m, "ORANGE");
|
||||
JS_AddModuleExport(ctx, m, "PINK");
|
||||
JS_AddModuleExport(ctx, m, "RED");
|
||||
JS_AddModuleExport(ctx, m, "MAROON");
|
||||
JS_AddModuleExport(ctx, m, "GREEN");
|
||||
JS_AddModuleExport(ctx, m, "LIME");
|
||||
JS_AddModuleExport(ctx, m, "DARKGREEN");
|
||||
JS_AddModuleExport(ctx, m, "SKYBLUE");
|
||||
JS_AddModuleExport(ctx, m, "BLUE");
|
||||
JS_AddModuleExport(ctx, m, "DARKBLUE");
|
||||
JS_AddModuleExport(ctx, m, "PURPLE");
|
||||
JS_AddModuleExport(ctx, m, "VIOLET");
|
||||
JS_AddModuleExport(ctx, m, "DARKPURPLE");
|
||||
JS_AddModuleExport(ctx, m, "BEIGE");
|
||||
JS_AddModuleExport(ctx, m, "BROWN");
|
||||
JS_AddModuleExport(ctx, m, "DARKBROWN");
|
||||
JS_AddModuleExport(ctx, m, "WHITE");
|
||||
JS_AddModuleExport(ctx, m, "BLACK");
|
||||
JS_AddModuleExport(ctx, m, "BLANK");
|
||||
JS_AddModuleExport(ctx, m, "MAGENTA");
|
||||
JS_AddModuleExport(ctx, m, "RAYWHITE");
|
||||
return m;
|
||||
}
|
||||
|
||||
|
|
|
@ -64,10 +64,10 @@ static JSValue js_loadImage(JSContext * ctx, JSValueConst this_val, int argc, JS
|
|||
if(fileName == NULL) return JS_EXCEPTION;
|
||||
Image returnVal = LoadImage(fileName);
|
||||
JS_FreeCString(ctx, fileName);
|
||||
Image* ptr = (Image*)js_malloc(ctx, sizeof(Image));
|
||||
*ptr = returnVal;
|
||||
Image* ret_ptr = (Image*)js_malloc(ctx, sizeof(Image));
|
||||
*ret_ptr = returnVal;
|
||||
JSValue ret = JS_NewObjectClass(ctx, js_Image_class_id);
|
||||
JS_SetOpaque(ret, ptr);
|
||||
JS_SetOpaque(ret, ret_ptr);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
62
src/main.c
62
src/main.c
|
@ -29,43 +29,45 @@
|
|||
//------------------------------------------------------------------------------------
|
||||
int main(int argc, char ** argv)
|
||||
{
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
const int screenWidth = 800;
|
||||
const int screenHeight = 450;
|
||||
|
||||
InitWindow(screenWidth, screenHeight, "raylib [core] example - basic window");
|
||||
|
||||
SetTargetFPS(60); // Set our game to run at 60 frames-per-second
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
app_init_quickjs(argc, argv);
|
||||
// // Initialization
|
||||
// //--------------------------------------------------------------------------------------
|
||||
// const int screenWidth = 800;
|
||||
// const int screenHeight = 450;
|
||||
|
||||
// Main game loop
|
||||
while (!WindowShouldClose()) // Detect window close button or ESC key
|
||||
{
|
||||
app_update_quickjs();
|
||||
// Update
|
||||
//----------------------------------------------------------------------------------
|
||||
// TODO: Update your variables here
|
||||
//----------------------------------------------------------------------------------
|
||||
// InitWindow(screenWidth, screenHeight, "raylib [core] example - basic window");
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
// SetTargetFPS(60); // Set our game to run at 60 frames-per-second
|
||||
// //--------------------------------------------------------------------------------------
|
||||
|
||||
ClearBackground(RAYWHITE);
|
||||
|
||||
DrawText("Congrats! You created your first window!", 190, 200, 20, LIGHTGRAY);
|
||||
// // Main game loop
|
||||
// while (!WindowShouldClose()) // Detect window close button or ESC key
|
||||
// {
|
||||
// app_update_quickjs();
|
||||
// // Update
|
||||
// //----------------------------------------------------------------------------------
|
||||
// // TODO: Update your variables here
|
||||
// //----------------------------------------------------------------------------------
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
// // Draw
|
||||
// //----------------------------------------------------------------------------------
|
||||
// BeginDrawing();
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//--------------------------------------------------------------------------------------
|
||||
// ClearBackground(RAYWHITE);
|
||||
|
||||
// DrawText("Congrats! You created your first window!", 190, 200, 20, LIGHTGRAY);
|
||||
|
||||
// EndDrawing();
|
||||
// //----------------------------------------------------------------------------------
|
||||
// }
|
||||
|
||||
|
||||
// // De-Initialization
|
||||
// //--------------------------------------------------------------------------------------
|
||||
// CloseWindow(); // Close window and OpenGL context
|
||||
// //--------------------------------------------------------------------------------------
|
||||
|
||||
app_dispose_quickjs();
|
||||
return 0;
|
||||
}
|
|
@ -4,8 +4,6 @@
|
|||
#include <raylib.h>
|
||||
|
||||
#include "common.h"
|
||||
#include "bindings/js_raylib_core.h"
|
||||
#include "bindings/js_raylib_texture.h"
|
||||
|
||||
static JSContext *JS_NewCustomContext(JSRuntime *rt);
|
||||
static int eval_buf(JSContext *ctx, const void *buf, int buf_len,
|
||||
|
@ -14,6 +12,26 @@ static int eval_buf(JSContext *ctx, const void *buf, int buf_len,
|
|||
static JSRuntime* rt;
|
||||
static JSContext* ctx;
|
||||
|
||||
int app_update_quickjs(){
|
||||
JSContext *ctx1;
|
||||
int err;
|
||||
|
||||
/* execute the pending jobs */
|
||||
for(;;) {
|
||||
err = JS_ExecutePendingJob(JS_GetRuntime(ctx), &ctx1);
|
||||
if (err <= 0) {
|
||||
if (err < 0) {
|
||||
js_std_dump_error(ctx1);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#include "bindings/js_raylib_core.h"
|
||||
#include "bindings/js_raylib_texture.h"
|
||||
|
||||
int app_init_quickjs(int argc, char** argv){
|
||||
rt = JS_NewRuntime();
|
||||
if (!rt)
|
||||
|
@ -39,14 +57,14 @@ int app_init_quickjs(int argc, char** argv){
|
|||
// "globalThis.os = os;\n";
|
||||
// eval_buf(ctx, str, strlen(str), "<input>", JS_EVAL_TYPE_MODULE);
|
||||
|
||||
const char* filename = "main.js";
|
||||
const char* filename = argc > 1 ? argv[1] : "main.js";
|
||||
const char* buf = LoadFileText(filename);
|
||||
size_t len = strlen(buf);
|
||||
if (!buf) {
|
||||
JS_ThrowReferenceError(ctx, "could not load module filename '%s'",
|
||||
filename);
|
||||
return -1;
|
||||
}
|
||||
size_t len = strlen(buf);
|
||||
int res = eval_buf(ctx, buf, len, "main", JS_EVAL_TYPE_MODULE);
|
||||
if(res){
|
||||
return res;
|
||||
|
@ -54,22 +72,7 @@ int app_init_quickjs(int argc, char** argv){
|
|||
return 0;
|
||||
}
|
||||
|
||||
int app_update_quickjs(){
|
||||
JSContext *ctx1;
|
||||
int err;
|
||||
|
||||
/* execute the pending jobs */
|
||||
for(;;) {
|
||||
err = JS_ExecutePendingJob(JS_GetRuntime(ctx), &ctx1);
|
||||
if (err <= 0) {
|
||||
if (err < 0) {
|
||||
js_std_dump_error(ctx1);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int app_dispose_quickjs(){
|
||||
//js_std_free_handlers(rt);
|
||||
|
|
Loading…
Reference in New Issue