diff --git a/bindings/src/index.ts b/bindings/src/index.ts index 74afb58..441aae3 100644 --- a/bindings/src/index.ts +++ b/bindings/src/index.ts @@ -301,11 +301,29 @@ function main(){ //destructor: "UnloadMaterial" } - getStruct(api.structs, "VrDeviceInfo")!.binding = { + const structDI = getStruct(api.structs, "VrDeviceInfo")! + structDI.fields.filter(x => x.name === "lensDistortionValues")[0].type = "Vector4" + structDI.binding = { createEmptyConstructor: true, properties: { hResolution: { set: true, get: true }, - + vResolution: { set: true, get: true }, + hScreenSize: { set: true, get: true }, + vScreenSize: { set: true, get: true }, + vScreenCenter: { set: true, get: true }, + eyeToScreenDistance: { set: true, get: true }, + lensSeparationDistance: { set: true, get: true }, + interpupillaryDistance: { set: true, get: true }, + // lensDistortionValues: { + // set: true, + // get: true, + // overrideRead(fn) { + // fn.line("// TODO") + // }, + // overrideWrite(fn) { + // fn.line("// TODO") + // }, + // }, } } diff --git a/bindings/src/interfaces.ts b/bindings/src/interfaces.ts index bc0716a..75df315 100644 --- a/bindings/src/interfaces.ts +++ b/bindings/src/interfaces.ts @@ -1,7 +1,7 @@ import { QuickJsGenerator } from "./quickjs" export interface StructBindingOptions { - properties?: { [key:string]: { get?:boolean, set?:boolean } }, + properties?: { [key:string]: { get?: boolean, overrideRead?: (fn: QuickJsGenerator) => void, set?:boolean, overrideWrite?: (fn: QuickJsGenerator) => void } }, destructor?: RayLibFunction, construct?: string, createConstructor?: boolean @@ -27,7 +27,7 @@ export interface ParamBindingOptions { typeAlias?: string } -export type RayLibType = "void" | "const char *" | "bool" | "float" | "unsigned char" | "void *" | "int" | "usigned int" | "Texture" | "Rectangle" | "Image" | "Rectangle *" | "GylphInfo *" | "Texture2D" | "Vector3" | "Vector2" | "float *" | "unsigned char *" | "unsigned short *" | "unsigned int *" | "Shader" | "MaterialMap *" | "float[4]" | "Vector3" +export type RayLibType = string export interface RayLibDefine { name: string, diff --git a/bindings/src/quickjs.ts b/bindings/src/quickjs.ts index f00912c..d333780 100644 --- a/bindings/src/quickjs.ts +++ b/bindings/src/quickjs.ts @@ -251,22 +251,28 @@ export abstract class GenericQuickJsGenerator extend return body } - jsStructGetter(structName: string, classId: string, field: string, type: string, classIds: StructLookup){ + jsStructGetter(structName: string, classId: string, field: string, type: string, classIds: StructLookup, overrideRead?: (gen: QuickJsGenerator) => void){ const args = [{type: "JSContext*", name: "ctx" }, {type: "JSValueConst", name: "this_val"}] const fun = this.function(`js_${structName}_get_${field}`,"JSValue",args,true) fun.declare("ptr", structName+"*", false, `JS_GetOpaque2(ctx, this_val, ${classId})`) - fun.declare(field, type, false, "ptr->"+field) + if(overrideRead) { overrideRead(fun) } + else { + fun.declare(field, type, false, "ptr->"+field) + } fun.jsToJs(type, "ret", field, classIds) fun.returnExp("ret") return fun } - jsStructSetter(structName: string, classId: string, field: string, type: string, classIds: StructLookup){ + jsStructSetter(structName: string, classId: string, field: string, type: string, classIds: StructLookup, overrideWrite?: (gen: QuickJsGenerator) => void){ const args = [{type: "JSContext*", name: "ctx" }, {type: "JSValueConst", name: "this_val"},{type: "JSValueConst", name: "v"}] const fun = this.function(`js_${structName}_set_${field}`,"JSValue",args,true) fun.declare("ptr", structName+"*", false, `JS_GetOpaque2(ctx, this_val, ${classId})`) fun.jsToC(type, "value", "v", classIds); - fun.statement("ptr->"+field+" = value") + if(overrideWrite){ overrideWrite(fun) } + else { + fun.statement("ptr->"+field+" = value") + } fun.returnExp("JS_UNDEFINED") return fun } diff --git a/bindings/src/raylib-header.ts b/bindings/src/raylib-header.ts index 4ea5a84..6ea9f49 100644 --- a/bindings/src/raylib-header.ts +++ b/bindings/src/raylib-header.ts @@ -84,8 +84,8 @@ export class RayLibHeader extends QuickJsHeader { const el = options.properties[field] let _get: CodeGenerator | undefined = undefined let _set: CodeGenerator | undefined = undefined - if(el.get) _get = this.structs.jsStructGetter(struct.name, classId, field, type, /*Be carefull when allocating memory in a getter*/this.structLookup) - if(el.set) _set = this.structs.jsStructSetter(struct.name, classId, field, type, this.structLookup) + if(el.get) _get = this.structs.jsStructGetter(struct.name, classId, field, type, /*Be carefull when allocating memory in a getter*/this.structLookup, el.overrideRead) + if(el.set) _set = this.structs.jsStructSetter(struct.name, classId, field, type, this.structLookup, el.overrideWrite) propDeclarations.jsGetSetDef(field, _get?.getTag("_name"), _set?.getTag("_name")) } } diff --git a/examples/lib.raylib.d.ts b/examples/lib.raylib.d.ts index 55218f8..8eb5ed6 100644 --- a/examples/lib.raylib.d.ts +++ b/examples/lib.raylib.d.ts @@ -319,9 +319,26 @@ declare var Music: { prototype: Music; } interface VrDeviceInfo { + /** Horizontal resolution in pixels */ + hResolution: number, + /** Vertical resolution in pixels */ + vResolution: number, + /** Horizontal size in meters */ + hScreenSize: number, + /** Vertical size in meters */ + vScreenSize: number, + /** Screen center in meters */ + vScreenCenter: number, + /** Distance between eye and display in meters */ + eyeToScreenDistance: number, + /** Lens separation distance in meters */ + lensSeparationDistance: number, + /** IPD (distance between pupils) in meters */ + interpupillaryDistance: number, } declare var VrDeviceInfo: { prototype: VrDeviceInfo; + new(): VrDeviceInfo; } interface VrStereoConfig { } @@ -472,6 +489,14 @@ declare function endBlendMode(): void; declare function beginScissorMode(x: number, y: number, width: number, height: number): void; /** End scissor mode */ declare function endScissorMode(): void; +/** Begin stereo rendering (requires VR simulator) */ +declare function beginVrStereoMode(config: VrStereoConfig): void; +/** End stereo rendering (requires VR simulator) */ +declare function endVrStereoMode(): void; +/** Load VR stereo config for VR simulator device parameters */ +declare function loadVrStereoConfig(device: VrDeviceInfo): VrStereoConfig; +/** Unload VR stereo config */ +declare function unloadVrStereoConfig(config: VrStereoConfig): void; /** Load shader from files and bind default locations */ declare function loadShader(vsFileName: string | undefined | null, fsFileName: string | undefined | null): Shader; /** Load shader from code strings and bind default locations */ diff --git a/generate-bindings.js b/generate-bindings.js index ec5c34c..805c7dc 100644 --- a/generate-bindings.js +++ b/generate-bindings.js @@ -600,21 +600,31 @@ class GenericQuickJsGenerator extends generation_1.GenericCodeGenerator { body.statement("return 0"); return body; } - jsStructGetter(structName, classId, field, type, classIds) { + jsStructGetter(structName, classId, field, type, classIds, overrideRead) { const args = [{ type: "JSContext*", name: "ctx" }, { type: "JSValueConst", name: "this_val" }]; const fun = this.function(`js_${structName}_get_${field}`, "JSValue", args, true); fun.declare("ptr", structName + "*", false, `JS_GetOpaque2(ctx, this_val, ${classId})`); - fun.declare(field, type, false, "ptr->" + field); + if (overrideRead) { + overrideRead(fun); + } + else { + fun.declare(field, type, false, "ptr->" + field); + } fun.jsToJs(type, "ret", field, classIds); fun.returnExp("ret"); return fun; } - jsStructSetter(structName, classId, field, type, classIds) { + jsStructSetter(structName, classId, field, type, classIds, overrideWrite) { const args = [{ type: "JSContext*", name: "ctx" }, { type: "JSValueConst", name: "this_val" }, { type: "JSValueConst", name: "v" }]; const fun = this.function(`js_${structName}_set_${field}`, "JSValue", args, true); fun.declare("ptr", structName + "*", false, `JS_GetOpaque2(ctx, this_val, ${classId})`); fun.jsToC(type, "value", "v", classIds); - fun.statement("ptr->" + field + " = value"); + if (overrideWrite) { + overrideWrite(fun); + } + else { + fun.statement("ptr->" + field + " = value"); + } fun.returnExp("JS_UNDEFINED"); return fun; } @@ -736,9 +746,9 @@ class RayLibHeader extends quickjs_1.QuickJsHeader { let _get = undefined; let _set = undefined; if (el.get) - _get = this.structs.jsStructGetter(struct.name, classId, field, type, /*Be carefull when allocating memory in a getter*/ this.structLookup); + _get = this.structs.jsStructGetter(struct.name, classId, field, type, /*Be carefull when allocating memory in a getter*/ this.structLookup, el.overrideRead); if (el.set) - _set = this.structs.jsStructSetter(struct.name, classId, field, type, this.structLookup); + _set = this.structs.jsStructSetter(struct.name, classId, field, type, this.structLookup, el.overrideWrite); propDeclarations.jsGetSetDef(field, _get?.getTag("_name"), _set?.getTag("_name")); } } @@ -1224,6 +1234,31 @@ function main() { }, //destructor: "UnloadMaterial" }; + const structDI = getStruct(api.structs, "VrDeviceInfo"); + structDI.fields.filter(x => x.name === "lensDistortionValues")[0].type = "Vector4"; + structDI.binding = { + createEmptyConstructor: true, + properties: { + hResolution: { set: true, get: true }, + vResolution: { set: true, get: true }, + hScreenSize: { set: true, get: true }, + vScreenSize: { set: true, get: true }, + vScreenCenter: { set: true, get: true }, + eyeToScreenDistance: { set: true, get: true }, + lensSeparationDistance: { set: true, get: true }, + interpupillaryDistance: { set: true, get: true }, + // lensDistortionValues: { + // set: true, + // get: true, + // overrideRead(fn) { + // fn.line("// TODO") + // }, + // overrideWrite(fn) { + // fn.line("// TODO") + // }, + // }, + } + }; getFunction(api.functions, "EndDrawing").binding = { after: gen => gen.call("app_update_quickjs", []) }; ignore("SetWindowIcons"); ignore("GetWindowHandle"); @@ -1232,10 +1267,10 @@ function main() { ignore("SwapScreenBuffer"); ignore("PollInputEvents"); ignore("WaitTime"); - ignore("BeginVrStereoMode"); - ignore("EndVrStereoMode"); - ignore("LoadVrStereoConfig"); - ignore("UnloadVrStereoConfig"); + //ignore("BeginVrStereoMode") + //ignore("EndVrStereoMode") + //ignore("LoadVrStereoConfig") + //ignore("UnloadVrStereoConfig") getFunction(api.functions, "SetShaderValue").binding = { body: (gen) => { gen.jsToC("Shader", "shader", "argv[0]", core.structLookup); gen.jsToC("int", "locIndex", "argv[1]", core.structLookup); diff --git a/src/bindings/js_raylib_core.h b/src/bindings/js_raylib_core.h index 3ee6c3d..3c9a758 100644 --- a/src/bindings/js_raylib_core.h +++ b/src/bindings/js_raylib_core.h @@ -1776,7 +1776,141 @@ static void js_VrDeviceInfo_finalizer(JSRuntime * rt, JSValue val) { } } +static JSValue js_VrDeviceInfo_get_hResolution(JSContext* ctx, JSValueConst this_val) { + VrDeviceInfo* ptr = JS_GetOpaque2(ctx, this_val, js_VrDeviceInfo_class_id); + int hResolution = ptr->hResolution; + JSValue ret = JS_NewInt32(ctx, hResolution); + return ret; +} + +static JSValue js_VrDeviceInfo_set_hResolution(JSContext* ctx, JSValueConst this_val, JSValueConst v) { + VrDeviceInfo* ptr = JS_GetOpaque2(ctx, this_val, js_VrDeviceInfo_class_id); + int value; + JS_ToInt32(ctx, &value, v); + ptr->hResolution = value; + return JS_UNDEFINED; +} + +static JSValue js_VrDeviceInfo_get_vResolution(JSContext* ctx, JSValueConst this_val) { + VrDeviceInfo* ptr = JS_GetOpaque2(ctx, this_val, js_VrDeviceInfo_class_id); + int vResolution = ptr->vResolution; + JSValue ret = JS_NewInt32(ctx, vResolution); + return ret; +} + +static JSValue js_VrDeviceInfo_set_vResolution(JSContext* ctx, JSValueConst this_val, JSValueConst v) { + VrDeviceInfo* ptr = JS_GetOpaque2(ctx, this_val, js_VrDeviceInfo_class_id); + int value; + JS_ToInt32(ctx, &value, v); + ptr->vResolution = value; + return JS_UNDEFINED; +} + +static JSValue js_VrDeviceInfo_get_hScreenSize(JSContext* ctx, JSValueConst this_val) { + VrDeviceInfo* ptr = JS_GetOpaque2(ctx, this_val, js_VrDeviceInfo_class_id); + float hScreenSize = ptr->hScreenSize; + JSValue ret = JS_NewFloat64(ctx, hScreenSize); + return ret; +} + +static JSValue js_VrDeviceInfo_set_hScreenSize(JSContext* ctx, JSValueConst this_val, JSValueConst v) { + VrDeviceInfo* ptr = JS_GetOpaque2(ctx, this_val, js_VrDeviceInfo_class_id); + double _double_value; + JS_ToFloat64(ctx, &_double_value, v); + float value = (float)_double_value; + ptr->hScreenSize = value; + return JS_UNDEFINED; +} + +static JSValue js_VrDeviceInfo_get_vScreenSize(JSContext* ctx, JSValueConst this_val) { + VrDeviceInfo* ptr = JS_GetOpaque2(ctx, this_val, js_VrDeviceInfo_class_id); + float vScreenSize = ptr->vScreenSize; + JSValue ret = JS_NewFloat64(ctx, vScreenSize); + return ret; +} + +static JSValue js_VrDeviceInfo_set_vScreenSize(JSContext* ctx, JSValueConst this_val, JSValueConst v) { + VrDeviceInfo* ptr = JS_GetOpaque2(ctx, this_val, js_VrDeviceInfo_class_id); + double _double_value; + JS_ToFloat64(ctx, &_double_value, v); + float value = (float)_double_value; + ptr->vScreenSize = value; + return JS_UNDEFINED; +} + +static JSValue js_VrDeviceInfo_get_vScreenCenter(JSContext* ctx, JSValueConst this_val) { + VrDeviceInfo* ptr = JS_GetOpaque2(ctx, this_val, js_VrDeviceInfo_class_id); + float vScreenCenter = ptr->vScreenCenter; + JSValue ret = JS_NewFloat64(ctx, vScreenCenter); + return ret; +} + +static JSValue js_VrDeviceInfo_set_vScreenCenter(JSContext* ctx, JSValueConst this_val, JSValueConst v) { + VrDeviceInfo* ptr = JS_GetOpaque2(ctx, this_val, js_VrDeviceInfo_class_id); + double _double_value; + JS_ToFloat64(ctx, &_double_value, v); + float value = (float)_double_value; + ptr->vScreenCenter = value; + return JS_UNDEFINED; +} + +static JSValue js_VrDeviceInfo_get_eyeToScreenDistance(JSContext* ctx, JSValueConst this_val) { + VrDeviceInfo* ptr = JS_GetOpaque2(ctx, this_val, js_VrDeviceInfo_class_id); + float eyeToScreenDistance = ptr->eyeToScreenDistance; + JSValue ret = JS_NewFloat64(ctx, eyeToScreenDistance); + return ret; +} + +static JSValue js_VrDeviceInfo_set_eyeToScreenDistance(JSContext* ctx, JSValueConst this_val, JSValueConst v) { + VrDeviceInfo* ptr = JS_GetOpaque2(ctx, this_val, js_VrDeviceInfo_class_id); + double _double_value; + JS_ToFloat64(ctx, &_double_value, v); + float value = (float)_double_value; + ptr->eyeToScreenDistance = value; + return JS_UNDEFINED; +} + +static JSValue js_VrDeviceInfo_get_lensSeparationDistance(JSContext* ctx, JSValueConst this_val) { + VrDeviceInfo* ptr = JS_GetOpaque2(ctx, this_val, js_VrDeviceInfo_class_id); + float lensSeparationDistance = ptr->lensSeparationDistance; + JSValue ret = JS_NewFloat64(ctx, lensSeparationDistance); + return ret; +} + +static JSValue js_VrDeviceInfo_set_lensSeparationDistance(JSContext* ctx, JSValueConst this_val, JSValueConst v) { + VrDeviceInfo* ptr = JS_GetOpaque2(ctx, this_val, js_VrDeviceInfo_class_id); + double _double_value; + JS_ToFloat64(ctx, &_double_value, v); + float value = (float)_double_value; + ptr->lensSeparationDistance = value; + return JS_UNDEFINED; +} + +static JSValue js_VrDeviceInfo_get_interpupillaryDistance(JSContext* ctx, JSValueConst this_val) { + VrDeviceInfo* ptr = JS_GetOpaque2(ctx, this_val, js_VrDeviceInfo_class_id); + float interpupillaryDistance = ptr->interpupillaryDistance; + JSValue ret = JS_NewFloat64(ctx, interpupillaryDistance); + return ret; +} + +static JSValue js_VrDeviceInfo_set_interpupillaryDistance(JSContext* ctx, JSValueConst this_val, JSValueConst v) { + VrDeviceInfo* ptr = JS_GetOpaque2(ctx, this_val, js_VrDeviceInfo_class_id); + double _double_value; + JS_ToFloat64(ctx, &_double_value, v); + float value = (float)_double_value; + ptr->interpupillaryDistance = value; + return JS_UNDEFINED; +} + static const JSCFunctionListEntry js_VrDeviceInfo_proto_funcs[] = { + JS_CGETSET_DEF("hResolution",js_VrDeviceInfo_get_hResolution,js_VrDeviceInfo_set_hResolution), + JS_CGETSET_DEF("vResolution",js_VrDeviceInfo_get_vResolution,js_VrDeviceInfo_set_vResolution), + JS_CGETSET_DEF("hScreenSize",js_VrDeviceInfo_get_hScreenSize,js_VrDeviceInfo_set_hScreenSize), + JS_CGETSET_DEF("vScreenSize",js_VrDeviceInfo_get_vScreenSize,js_VrDeviceInfo_set_vScreenSize), + JS_CGETSET_DEF("vScreenCenter",js_VrDeviceInfo_get_vScreenCenter,js_VrDeviceInfo_set_vScreenCenter), + JS_CGETSET_DEF("eyeToScreenDistance",js_VrDeviceInfo_get_eyeToScreenDistance,js_VrDeviceInfo_set_eyeToScreenDistance), + JS_CGETSET_DEF("lensSeparationDistance",js_VrDeviceInfo_get_lensSeparationDistance,js_VrDeviceInfo_set_lensSeparationDistance), + JS_CGETSET_DEF("interpupillaryDistance",js_VrDeviceInfo_get_interpupillaryDistance,js_VrDeviceInfo_set_interpupillaryDistance), JS_PROP_STRING_DEF("[Symbol.toStringTag]","VrDeviceInfo", JS_PROP_CONFIGURABLE), }; @@ -2162,6 +2296,15 @@ static JSValue js_BoundingBox_constructor(JSContext * ctx, JSValueConst this_val return _return; } +static JSValue js_VrDeviceInfo_constructor(JSContext * ctx, JSValueConst this_val, int argc, JSValueConst * argv) { + VrDeviceInfo _struct = { }; + VrDeviceInfo* _return_ptr = (VrDeviceInfo*)js_malloc(ctx, sizeof(VrDeviceInfo)); + *_return_ptr = _struct; + JSValue _return = JS_NewObjectClass(ctx, js_VrDeviceInfo_class_id); + JS_SetOpaque(_return, _return_ptr); + return _return; +} + static JSValue js_initWindow(JSContext * ctx, JSValueConst this_val, int argc, JSValueConst * argv) { int width; JS_ToInt32(ctx, &width, argv[0]); @@ -2594,6 +2737,39 @@ static JSValue js_endScissorMode(JSContext * ctx, JSValueConst this_val, int arg return JS_UNDEFINED; } +static JSValue js_beginVrStereoMode(JSContext * ctx, JSValueConst this_val, int argc, JSValueConst * argv) { + VrStereoConfig* config_ptr = (VrStereoConfig*)JS_GetOpaque2(ctx, argv[0], js_VrStereoConfig_class_id); + if(config_ptr == NULL) return JS_EXCEPTION; + VrStereoConfig config = *config_ptr; + BeginVrStereoMode(config); + return JS_UNDEFINED; +} + +static JSValue js_endVrStereoMode(JSContext * ctx, JSValueConst this_val, int argc, JSValueConst * argv) { + EndVrStereoMode(); + return JS_UNDEFINED; +} + +static JSValue js_loadVrStereoConfig(JSContext * ctx, JSValueConst this_val, int argc, JSValueConst * argv) { + VrDeviceInfo* device_ptr = (VrDeviceInfo*)JS_GetOpaque2(ctx, argv[0], js_VrDeviceInfo_class_id); + if(device_ptr == NULL) return JS_EXCEPTION; + VrDeviceInfo device = *device_ptr; + VrStereoConfig returnVal = LoadVrStereoConfig(device); + VrStereoConfig* ret_ptr = (VrStereoConfig*)js_malloc(ctx, sizeof(VrStereoConfig)); + *ret_ptr = returnVal; + JSValue ret = JS_NewObjectClass(ctx, js_VrStereoConfig_class_id); + JS_SetOpaque(ret, ret_ptr); + return ret; +} + +static JSValue js_unloadVrStereoConfig(JSContext * ctx, JSValueConst this_val, int argc, JSValueConst * argv) { + VrStereoConfig* config_ptr = (VrStereoConfig*)JS_GetOpaque2(ctx, argv[0], js_VrStereoConfig_class_id); + if(config_ptr == NULL) return JS_EXCEPTION; + VrStereoConfig config = *config_ptr; + UnloadVrStereoConfig(config); + return JS_UNDEFINED; +} + static JSValue js_loadShader(JSContext * ctx, JSValueConst this_val, int argc, JSValueConst * argv) { const char * vsFileName = (JS_IsNull(argv[0]) || JS_IsUndefined(argv[0])) ? NULL : (const char *)JS_ToCString(ctx, argv[0]); const char * fsFileName = (JS_IsNull(argv[1]) || JS_IsUndefined(argv[1])) ? NULL : (const char *)JS_ToCString(ctx, argv[1]); @@ -9969,6 +10145,10 @@ static const JSCFunctionListEntry js_raylib_core_funcs[] = { JS_CFUNC_DEF("endBlendMode",0,js_endBlendMode), JS_CFUNC_DEF("beginScissorMode",4,js_beginScissorMode), JS_CFUNC_DEF("endScissorMode",0,js_endScissorMode), + JS_CFUNC_DEF("beginVrStereoMode",1,js_beginVrStereoMode), + JS_CFUNC_DEF("endVrStereoMode",0,js_endVrStereoMode), + JS_CFUNC_DEF("loadVrStereoConfig",1,js_loadVrStereoConfig), + JS_CFUNC_DEF("unloadVrStereoConfig",1,js_unloadVrStereoConfig), JS_CFUNC_DEF("loadShader",2,js_loadShader), JS_CFUNC_DEF("loadShaderFromMemory",2,js_loadShaderFromMemory), JS_CFUNC_DEF("isShaderReady",1,js_isShaderReady), @@ -10576,6 +10756,8 @@ static int js_raylib_core_init(JSContext * ctx, JSModuleDef * m) { js_declare_Sound(ctx, m); js_declare_Music(ctx, m); js_declare_VrDeviceInfo(ctx, m); + JSValue VrDeviceInfo_constr = JS_NewCFunction2(ctx, js_VrDeviceInfo_constructor,"VrDeviceInfo)", 10, JS_CFUNC_constructor_or_func, 0); + JS_SetModuleExport(ctx, m, "VrDeviceInfo", VrDeviceInfo_constr); js_declare_VrStereoConfig(ctx, m); js_declare_FilePathList(ctx, m); js_declare_Light(ctx, m); @@ -11384,6 +11566,7 @@ JSModuleDef * js_init_module_raylib_core(JSContext * ctx, const char * module_na JS_AddModuleExport(ctx, m, "Mesh"); JS_AddModuleExport(ctx, m, "Ray"); JS_AddModuleExport(ctx, m, "BoundingBox"); + JS_AddModuleExport(ctx, m, "VrDeviceInfo"); JS_AddModuleExport(ctx, m, "LIGHTGRAY"); JS_AddModuleExport(ctx, m, "GRAY"); JS_AddModuleExport(ctx, m, "DARKGRAY");