more bindings

This commit is contained in:
Alexander Klingenbeck 2023-05-10 23:26:53 +02:00
parent b48568aa87
commit 277a85f527
16 changed files with 658 additions and 315 deletions

View File

@ -1,17 +0,0 @@
{
"headers": [
{
"name": "raylib_core",
"functions": [
{ "name": "SetWindowTitle" },
{ "name": "SetWindowPosition" },
{ "name": "BeginDrawing" },
{ "name": "EndDrawing" }
]
},
{
"name": "raylib_texture",
"functions": []
}
]
}

View File

@ -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>{

View File

@ -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)

View File

@ -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
}

View File

@ -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

View File

@ -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)

33
examples/basic_window.js Normal file
View File

@ -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();
//----------------------------------------------------------------------------------
}

48
examples/input_keys.js Normal file
View File

@ -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
//--------------------------------------------------------------------------------------

View File

@ -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", {

View File

@ -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
View File

@ -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();
//----------------------------------------------------------------------------------
}

View File

@ -1,3 +0,0 @@
export function test() {
return 42
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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);