mirror of https://github.com/mode777/rayjs.git
Switch to explicit resourceFree, add typescript example, add ArrayBuffer support
This commit is contained in:
parent
17ef4e6fd9
commit
aaf8fb16d8
|
@ -1,4 +1,4 @@
|
||||||
import { RayLibApi, RayLibFunction, RayLibStruct } from "./interfaces"
|
import { RayLibApi, RayLibFunction, RayLibStruct, RayLibType } from "./interfaces"
|
||||||
|
|
||||||
export class ApiFunction{
|
export class ApiFunction{
|
||||||
constructor(private api: RayLibFunction){
|
constructor(private api: RayLibFunction){
|
||||||
|
@ -9,6 +9,7 @@ export class ApiFunction{
|
||||||
get argc() { return this.api.params?.length || 0 }
|
get argc() { return this.api.params?.length || 0 }
|
||||||
get params() { return this.api.params || [] }
|
get params() { return this.api.params || [] }
|
||||||
get returnType() { return this.api.returnType }
|
get returnType() { return this.api.returnType }
|
||||||
|
set returnType(v) { this.api.returnType = v }
|
||||||
get description() { return this.api.description }
|
get description() { return this.api.description }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -33,6 +33,12 @@ function main(){
|
||||||
writeFileSync("bindings/raylib_math_api.json", JSON.stringify(mathApi))
|
writeFileSync("bindings/raylib_math_api.json", JSON.stringify(mathApi))
|
||||||
|
|
||||||
const api = <RayLibApi>JSON.parse(readFileSync("thirdparty/raylib/parser/output/raylib_api.json", 'utf8'))
|
const api = <RayLibApi>JSON.parse(readFileSync("thirdparty/raylib/parser/output/raylib_api.json", 'utf8'))
|
||||||
|
api.functions.push({
|
||||||
|
name: "SetModelMaterial",
|
||||||
|
description: "Replace material in slot materialIndex",
|
||||||
|
returnType: "void",
|
||||||
|
params: [{type: "Model *",name:"model"},{type:"int",name:"materialIndex"},{type:"Material",name:"material"}]
|
||||||
|
})
|
||||||
mathApi.forEach(x => api.functions.push(x))
|
mathApi.forEach(x => api.functions.push(x))
|
||||||
|
|
||||||
const apiDesc = new ApiDescription(api)
|
const apiDesc = new ApiDescription(api)
|
||||||
|
@ -122,6 +128,17 @@ function main(){
|
||||||
properties: {},
|
properties: {},
|
||||||
createConstructor: false
|
createConstructor: false
|
||||||
})
|
})
|
||||||
|
core.addApiStructByName("NPatchInfo",{
|
||||||
|
properties: {
|
||||||
|
source: { get: true, set: true },
|
||||||
|
left: { get: true, set: true },
|
||||||
|
top: { get: true, set: true },
|
||||||
|
right: { get: true, set: true },
|
||||||
|
bottom: { get: true, set: true },
|
||||||
|
layout: { get: true, set: true },
|
||||||
|
},
|
||||||
|
createConstructor: true
|
||||||
|
})
|
||||||
core.addApiStructByName("Image", {
|
core.addApiStructByName("Image", {
|
||||||
properties: {
|
properties: {
|
||||||
width: { get: true },
|
width: { get: true },
|
||||||
|
@ -129,7 +146,7 @@ function main(){
|
||||||
mipmaps: { get: true },
|
mipmaps: { get: true },
|
||||||
format: { get: true }
|
format: { get: true }
|
||||||
},
|
},
|
||||||
destructor: "UnloadImage"
|
//destructor: "UnloadImage"
|
||||||
})
|
})
|
||||||
core.addApiStructByName("Wave", {
|
core.addApiStructByName("Wave", {
|
||||||
properties: {
|
properties: {
|
||||||
|
@ -138,45 +155,79 @@ function main(){
|
||||||
sampleSize: { get: true },
|
sampleSize: { get: true },
|
||||||
channels: { get: true }
|
channels: { get: true }
|
||||||
},
|
},
|
||||||
destructor: "UnloadWave"
|
//destructor: "UnloadWave"
|
||||||
})
|
})
|
||||||
core.addApiStructByName("Sound", {
|
core.addApiStructByName("Sound", {
|
||||||
properties: {
|
properties: {
|
||||||
frameCount: { get: true }
|
frameCount: { get: true }
|
||||||
},
|
},
|
||||||
destructor: "UnloadSound"
|
//destructor: "UnloadSound"
|
||||||
})
|
})
|
||||||
core.addApiStructByName("Music", {
|
core.addApiStructByName("Music", {
|
||||||
properties: {
|
properties: {
|
||||||
frameCount: { get: true },
|
frameCount: { get: true },
|
||||||
looping: { get: true, set: true }
|
looping: { get: true, set: true }
|
||||||
},
|
},
|
||||||
destructor: "UnloadMusicStream"
|
//destructor: "UnloadMusicStream"
|
||||||
})
|
})
|
||||||
core.addApiStructByName("Model", {
|
core.addApiStructByName("Model", {
|
||||||
properties: {},
|
properties: {},
|
||||||
destructor: "UnloadModel"
|
//destructor: "UnloadModel"
|
||||||
})
|
})
|
||||||
core.addApiStructByName("Mesh", {
|
core.addApiStructByName("Mesh", {
|
||||||
properties: {},
|
properties: {
|
||||||
destructor: "UnloadMesh"
|
vertexCount: { get: true, set: true },
|
||||||
|
triangleCount: { get: true, set: true },
|
||||||
|
// TODO: Free previous pointers before overwriting
|
||||||
|
vertices: { set: true },
|
||||||
|
texcoords: { set: true },
|
||||||
|
texcoords2: { set: true },
|
||||||
|
normals: { set: true },
|
||||||
|
tangents: { set: true },
|
||||||
|
colors: { set: true },
|
||||||
|
indices: { set: true },
|
||||||
|
animVertices: { set: true },
|
||||||
|
animNormals: { set: true },
|
||||||
|
boneIds: { set: true },
|
||||||
|
boneWeights: { set: true },
|
||||||
|
},
|
||||||
|
createEmptyConstructor: true
|
||||||
|
//destructor: "UnloadMesh"
|
||||||
})
|
})
|
||||||
core.addApiStructByName("Shader", {
|
core.addApiStructByName("Shader", {
|
||||||
properties: {},
|
properties: {},
|
||||||
destructor: "UnloadShader"
|
//destructor: "UnloadShader"
|
||||||
})
|
})
|
||||||
core.addApiStructByName("Texture", {
|
core.addApiStructByName("Texture", {
|
||||||
properties: {
|
properties: {
|
||||||
width: { get: true },
|
width: { get: true },
|
||||||
height: { get: true }
|
height: { get: true }
|
||||||
},
|
},
|
||||||
destructor: "UnloadTexture"
|
//destructor: "UnloadTexture"
|
||||||
})
|
})
|
||||||
core.addApiStructByName("Font", {
|
core.addApiStructByName("Font", {
|
||||||
properties: {
|
properties: {
|
||||||
baseSize: { get: true }
|
baseSize: { get: true }
|
||||||
},
|
},
|
||||||
destructor: "UnloadFont"
|
//destructor: "UnloadFont"
|
||||||
|
})
|
||||||
|
core.addApiStructByName("RenderTexture", {
|
||||||
|
properties: { },
|
||||||
|
//destructor: "UnloadRenderTexture"
|
||||||
|
})
|
||||||
|
core.addApiStructByName("MaterialMap", {
|
||||||
|
properties: {
|
||||||
|
texture: { set: true },
|
||||||
|
color: { set: true, get: true },
|
||||||
|
value: { get: true, set: true }
|
||||||
|
},
|
||||||
|
//destructor: "UnloadMaterialMap"
|
||||||
|
})
|
||||||
|
core.addApiStructByName("Material", {
|
||||||
|
properties: {
|
||||||
|
shader: { set: true }
|
||||||
|
},
|
||||||
|
//destructor: "UnloadMaterial"
|
||||||
})
|
})
|
||||||
|
|
||||||
// Window-related functions
|
// Window-related functions
|
||||||
|
@ -245,8 +296,8 @@ function main(){
|
||||||
core.addApiFunctionByName("EndMode2D")
|
core.addApiFunctionByName("EndMode2D")
|
||||||
core.addApiFunctionByName("BeginMode3D")
|
core.addApiFunctionByName("BeginMode3D")
|
||||||
core.addApiFunctionByName("EndMode3D")
|
core.addApiFunctionByName("EndMode3D")
|
||||||
//core.addApiFunctionByName("BeginTextureMode")
|
core.addApiFunctionByName("BeginTextureMode")
|
||||||
//core.addApiFunctionByName("EndTextureMode")
|
core.addApiFunctionByName("EndTextureMode")
|
||||||
core.addApiFunctionByName("BeginShaderMode")
|
core.addApiFunctionByName("BeginShaderMode")
|
||||||
core.addApiFunctionByName("EndShaderMode")
|
core.addApiFunctionByName("EndShaderMode")
|
||||||
core.addApiFunctionByName("BeginBlendMode")
|
core.addApiFunctionByName("BeginBlendMode")
|
||||||
|
@ -297,7 +348,7 @@ function main(){
|
||||||
// core.addApiFunctionByName("SetShaderValueV")
|
// core.addApiFunctionByName("SetShaderValueV")
|
||||||
core.addApiFunctionByName("SetShaderValueMatrix")
|
core.addApiFunctionByName("SetShaderValueMatrix")
|
||||||
core.addApiFunctionByName("SetShaderValueTexture")
|
core.addApiFunctionByName("SetShaderValueTexture")
|
||||||
// "UnloadShader" called by finalizer
|
core.addApiFunctionByName("UnloadShader")
|
||||||
|
|
||||||
// ScreenSpaceRelatedFunctions
|
// ScreenSpaceRelatedFunctions
|
||||||
core.addApiFunctionByName("GetMouseRay")
|
core.addApiFunctionByName("GetMouseRay")
|
||||||
|
@ -488,7 +539,7 @@ function main(){
|
||||||
core.addApiFunctionByName("LoadImageFromTexture")
|
core.addApiFunctionByName("LoadImageFromTexture")
|
||||||
core.addApiFunctionByName("LoadImageFromScreen")
|
core.addApiFunctionByName("LoadImageFromScreen")
|
||||||
core.addApiFunctionByName("IsImageReady")
|
core.addApiFunctionByName("IsImageReady")
|
||||||
// UnloadImage called by destructor
|
core.addApiFunctionByName("UnloadImage")
|
||||||
core.addApiFunctionByName("ExportImage")
|
core.addApiFunctionByName("ExportImage")
|
||||||
// needed?
|
// needed?
|
||||||
// core.addApiFunctionByName("ExportImageAsCode")
|
// core.addApiFunctionByName("ExportImageAsCode")
|
||||||
|
@ -532,7 +583,15 @@ function main(){
|
||||||
core.addApiFunctionByName("ImageColorContrast")
|
core.addApiFunctionByName("ImageColorContrast")
|
||||||
core.addApiFunctionByName("ImageColorBrightness")
|
core.addApiFunctionByName("ImageColorBrightness")
|
||||||
core.addApiFunctionByName("ImageColorReplace")
|
core.addApiFunctionByName("ImageColorReplace")
|
||||||
//core.addApiFunctionByName("LoadImageColors")
|
const lic = <ApiFunction>apiDesc.getFunction("LoadImageColors")
|
||||||
|
lic.returnType = "unsigned char *"
|
||||||
|
core.addApiFunction(lic, null, { body: (gen) => {
|
||||||
|
gen.jsToC("Image","image","argv[0]", core.structLookup)
|
||||||
|
gen.call("LoadImageColors", ["image"], {name:"colors",type:"Color *"})
|
||||||
|
gen.statement("JSValue retVal = JS_NewArrayBufferCopy(ctx, (const uint8_t*)colors, image.width*image.height*sizeof(Color))")
|
||||||
|
gen.call("UnloadImageColors", ["colors"])
|
||||||
|
gen.returnExp("retVal")
|
||||||
|
}})
|
||||||
//core.addApiFunctionByName("LoadImagePalette")
|
//core.addApiFunctionByName("LoadImagePalette")
|
||||||
//core.addApiFunctionByName("UnloadImageColors")
|
//core.addApiFunctionByName("UnloadImageColors")
|
||||||
//core.addApiFunctionByName("UnloadImagePalette")
|
//core.addApiFunctionByName("UnloadImagePalette")
|
||||||
|
@ -561,11 +620,11 @@ function main(){
|
||||||
core.addApiFunctionByName("LoadTexture")
|
core.addApiFunctionByName("LoadTexture")
|
||||||
core.addApiFunctionByName("LoadTextureFromImage")
|
core.addApiFunctionByName("LoadTextureFromImage")
|
||||||
core.addApiFunctionByName("LoadTextureCubemap")
|
core.addApiFunctionByName("LoadTextureCubemap")
|
||||||
// core.addApiFunctionByName("LoadRenderTexture")
|
core.addApiFunctionByName("LoadRenderTexture")
|
||||||
core.addApiFunctionByName("IsTextureReady")
|
core.addApiFunctionByName("IsTextureReady")
|
||||||
// "UnloadTexture" called by finalizer
|
core.addApiFunctionByName("UnloadTexture")
|
||||||
// core.addApiFunctionByName("IsRenderTextureReady")
|
core.addApiFunctionByName("IsRenderTextureReady")
|
||||||
// core.addApiFunctionByName("UnloadRenderTexture")
|
core.addApiFunctionByName("UnloadRenderTexture")
|
||||||
// core.addApiFunctionByName("UpdateTexture")
|
// core.addApiFunctionByName("UpdateTexture")
|
||||||
// core.addApiFunctionByName("UpdateTextureRec")
|
// core.addApiFunctionByName("UpdateTextureRec")
|
||||||
|
|
||||||
|
@ -580,7 +639,7 @@ function main(){
|
||||||
core.addApiFunctionByName("DrawTextureEx")
|
core.addApiFunctionByName("DrawTextureEx")
|
||||||
core.addApiFunctionByName("DrawTextureRec")
|
core.addApiFunctionByName("DrawTextureRec")
|
||||||
core.addApiFunctionByName("DrawTexturePro")
|
core.addApiFunctionByName("DrawTexturePro")
|
||||||
// core.addApiFunctionByName("DrawTextureNPatch")
|
core.addApiFunctionByName("DrawTextureNPatch")
|
||||||
|
|
||||||
// Color/pixel related functions
|
// Color/pixel related functions
|
||||||
core.addApiFunctionByName("Fade")
|
core.addApiFunctionByName("Fade")
|
||||||
|
@ -611,7 +670,7 @@ function main(){
|
||||||
// core.addApiFunctionByName("LoadFontData")
|
// core.addApiFunctionByName("LoadFontData")
|
||||||
// core.addApiFunctionByName("GenImageFontAtlas")
|
// core.addApiFunctionByName("GenImageFontAtlas")
|
||||||
// core.addApiFunctionByName("UnloadFontData")
|
// core.addApiFunctionByName("UnloadFontData")
|
||||||
// "UnloadFont" called by finalizer
|
core.addApiFunctionByName("UnloadFont")
|
||||||
// core.addApiFunctionByName("ExportFontAsCode")
|
// core.addApiFunctionByName("ExportFontAsCode")
|
||||||
|
|
||||||
// Text drawing functions
|
// Text drawing functions
|
||||||
|
@ -668,12 +727,12 @@ function main(){
|
||||||
core.addApiFunctionByName("DrawPlane")
|
core.addApiFunctionByName("DrawPlane")
|
||||||
core.addApiFunctionByName("DrawRay")
|
core.addApiFunctionByName("DrawRay")
|
||||||
core.addApiFunctionByName("DrawGrid")
|
core.addApiFunctionByName("DrawGrid")
|
||||||
|
|
||||||
// model management functions
|
// model management functions
|
||||||
core.addApiFunctionByName("LoadModel")
|
core.addApiFunctionByName("LoadModel")
|
||||||
core.addApiFunctionByName("LoadModelFromMesh")
|
core.addApiFunctionByName("LoadModelFromMesh")
|
||||||
core.addApiFunctionByName("IsModelReady")
|
core.addApiFunctionByName("IsModelReady")
|
||||||
// "UnloadModel" called by finalizer
|
core.addApiFunctionByName("UnloadModel")
|
||||||
core.addApiFunctionByName("GetModelBoundingBox")
|
core.addApiFunctionByName("GetModelBoundingBox")
|
||||||
|
|
||||||
// model drawing functions
|
// model drawing functions
|
||||||
|
@ -689,10 +748,10 @@ function main(){
|
||||||
// Mesh management functions
|
// Mesh management functions
|
||||||
// TODO: Refcounting needed?
|
// TODO: Refcounting needed?
|
||||||
core.addApiFunctionByName("UploadMesh")
|
core.addApiFunctionByName("UploadMesh")
|
||||||
// core.addApiFunctionByName("UpdateMeshBuffer")
|
core.addApiFunctionByName("UpdateMeshBuffer")
|
||||||
// "UnloadMesh" called by finalizer
|
core.addApiFunctionByName("UnloadMesh")
|
||||||
//core.addApiFunctionByName("DrawMesh")
|
core.addApiFunctionByName("DrawMesh")
|
||||||
// core.addApiFunctionByName("DrawMeshInstanced")
|
core.addApiFunctionByName("DrawMeshInstanced")
|
||||||
core.addApiFunctionByName("ExportMesh")
|
core.addApiFunctionByName("ExportMesh")
|
||||||
core.addApiFunctionByName("GetMeshBoundingBox")
|
core.addApiFunctionByName("GetMeshBoundingBox")
|
||||||
core.addApiFunctionByName("GenMeshTangents")
|
core.addApiFunctionByName("GenMeshTangents")
|
||||||
|
@ -712,11 +771,12 @@ function main(){
|
||||||
|
|
||||||
// Material loading/unloading functions
|
// Material loading/unloading functions
|
||||||
// core.addApiFunctionByName("LoadMaterials")
|
// core.addApiFunctionByName("LoadMaterials")
|
||||||
// core.addApiFunctionByName("LoadMaterialDefault")
|
core.addApiFunctionByName("LoadMaterialDefault")
|
||||||
// core.addApiFunctionByName("IsMaterialReady")
|
core.addApiFunctionByName("IsMaterialReady")
|
||||||
// core.addApiFunctionByName("UnloadMaterial")
|
core.addApiFunctionByName("UnloadMaterial")
|
||||||
// core.addApiFunctionByName("SetMaterialTexture")
|
core.addApiFunctionByName("SetMaterialTexture")
|
||||||
// core.addApiFunctionByName("SetModelMeshMaterial")
|
core.addApiFunctionByName("SetModelMaterial")
|
||||||
|
core.addApiFunctionByName("SetModelMeshMaterial")
|
||||||
|
|
||||||
// Model animations loading/unloading functions
|
// Model animations loading/unloading functions
|
||||||
// core.addApiFunctionByName("LoadModelAnimations")
|
// core.addApiFunctionByName("LoadModelAnimations")
|
||||||
|
@ -751,8 +811,8 @@ function main(){
|
||||||
core.addApiFunctionByName("LoadSoundFromWave")
|
core.addApiFunctionByName("LoadSoundFromWave")
|
||||||
core.addApiFunctionByName("IsSoundReady")
|
core.addApiFunctionByName("IsSoundReady")
|
||||||
// core.addApiFunctionByName("UpdateSound")
|
// core.addApiFunctionByName("UpdateSound")
|
||||||
// "UnloadWave" called by finalizer
|
core.addApiFunctionByName("UnloadWave")
|
||||||
// "UnloadSound" called by finalizer
|
core.addApiFunctionByName("UnloadSound")
|
||||||
core.addApiFunctionByName("ExportWave")
|
core.addApiFunctionByName("ExportWave")
|
||||||
// core.addApiFunctionByName("ExportWaveAsCode")
|
// core.addApiFunctionByName("ExportWaveAsCode")
|
||||||
|
|
||||||
|
@ -775,7 +835,7 @@ function main(){
|
||||||
core.addApiFunctionByName("LoadMusicStream")
|
core.addApiFunctionByName("LoadMusicStream")
|
||||||
// core.addApiFunctionByName("LoadMusicStreamFromMemory")
|
// core.addApiFunctionByName("LoadMusicStreamFromMemory")
|
||||||
core.addApiFunctionByName("IsMusicReady")
|
core.addApiFunctionByName("IsMusicReady")
|
||||||
// "UnloadMusicStream" called by finalizer
|
core.addApiFunctionByName("UnloadMusicStream")
|
||||||
core.addApiFunctionByName("PlayMusicStream")
|
core.addApiFunctionByName("PlayMusicStream")
|
||||||
core.addApiFunctionByName("IsMusicStreamPlaying")
|
core.addApiFunctionByName("IsMusicStreamPlaying")
|
||||||
core.addApiFunctionByName("UpdateMusicStream")
|
core.addApiFunctionByName("UpdateMusicStream")
|
||||||
|
@ -941,6 +1001,9 @@ function main(){
|
||||||
api.enums.find(x => x.name === "CameraMode")?.values.forEach(x => core.exportGlobalConstant(x.name, x.description))
|
api.enums.find(x => x.name === "CameraMode")?.values.forEach(x => core.exportGlobalConstant(x.name, x.description))
|
||||||
api.enums.find(x => x.name === "ShaderLocationIndex")?.values.forEach(x => core.exportGlobalConstant(x.name, x.description))
|
api.enums.find(x => x.name === "ShaderLocationIndex")?.values.forEach(x => core.exportGlobalConstant(x.name, x.description))
|
||||||
api.enums.find(x => x.name === "ShaderUniformDataType")?.values.forEach(x => core.exportGlobalConstant(x.name, x.description))
|
api.enums.find(x => x.name === "ShaderUniformDataType")?.values.forEach(x => core.exportGlobalConstant(x.name, x.description))
|
||||||
|
api.enums.find(x => x.name === "MaterialMapIndex")?.values.forEach(x => core.exportGlobalConstant(x.name, x.description))
|
||||||
|
core.exportGlobalConstant("MATERIAL_MAP_DIFFUSE", "Albedo material (same as: MATERIAL_MAP_DIFFUSE")
|
||||||
|
core.exportGlobalConstant("MATERIAL_MAP_SPECULAR", "Metalness material (same as: MATERIAL_MAP_SPECULAR)")
|
||||||
core.writeTo("src/bindings/js_raylib_core.h")
|
core.writeTo("src/bindings/js_raylib_core.h")
|
||||||
core.typings.writeTo("examples/lib.raylib.d.ts")
|
core.typings.writeTo("examples/lib.raylib.d.ts")
|
||||||
}
|
}
|
||||||
|
|
|
@ -78,6 +78,19 @@ export abstract class GenericQuickJsGenerator<T extends QuickJsGenerator> extend
|
||||||
|
|
||||||
jsToC(type: string, name: string, src: string, classIds: StructLookup = {}, supressDeclaration = false){
|
jsToC(type: string, name: string, src: string, classIds: StructLookup = {}, supressDeclaration = false){
|
||||||
switch (type) {
|
switch (type) {
|
||||||
|
// Array Buffer
|
||||||
|
case "const void *":
|
||||||
|
case "void *":
|
||||||
|
case "float *":
|
||||||
|
case "unsigned short *":
|
||||||
|
case "unsigned char *":
|
||||||
|
this.declare(name+"_size", "size_t")
|
||||||
|
this.declare(name+"_js", "void *", false, `(void *)JS_GetArrayBuffer(ctx, &${name}_size, ${src})`)
|
||||||
|
this.if(name+"_js == NULL").returnExp("JS_EXCEPTION")
|
||||||
|
this.declare(name, type, false, "malloc("+name+"_size)")
|
||||||
|
this.call("memcpy", ["(void *)"+name, "(const void *)"+name+"_js", name+"_size"])
|
||||||
|
break;
|
||||||
|
// String
|
||||||
case "const char *":
|
case "const char *":
|
||||||
case "char *":
|
case "char *":
|
||||||
if(!supressDeclaration) this.statement(`${type} ${name} = (${type})JS_ToCString(ctx, ${src})`)
|
if(!supressDeclaration) this.statement(`${type} ${name} = (${type})JS_ToCString(ctx, ${src})`)
|
||||||
|
@ -111,6 +124,7 @@ export abstract class GenericQuickJsGenerator<T extends QuickJsGenerator> extend
|
||||||
if(!supressDeclaration) this.statement(`${type} ${name} = JS_ToBool(ctx, ${src})`)
|
if(!supressDeclaration) this.statement(`${type} ${name} = JS_ToBool(ctx, ${src})`)
|
||||||
else this.statement(`${name} = JS_ToBool(ctx, ${src})`)
|
else this.statement(`${name} = JS_ToBool(ctx, ${src})`)
|
||||||
break;
|
break;
|
||||||
|
// Structs / Struct *
|
||||||
default:
|
default:
|
||||||
const isConst = type.startsWith('const')
|
const isConst = type.startsWith('const')
|
||||||
const isPointer = type.endsWith(' *')
|
const isPointer = type.endsWith(' *')
|
||||||
|
@ -163,9 +177,17 @@ export abstract class GenericQuickJsGenerator<T extends QuickJsGenerator> extend
|
||||||
|
|
||||||
jsCleanUpParameter(type: string, name: string) {
|
jsCleanUpParameter(type: string, name: string) {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
|
case "char *":
|
||||||
case "const char *":
|
case "const char *":
|
||||||
this.statement(`JS_FreeCString(ctx, ${name})`)
|
this.statement(`JS_FreeCString(ctx, ${name})`)
|
||||||
break;
|
break;
|
||||||
|
case "const void *":
|
||||||
|
case "void *":
|
||||||
|
case "float *":
|
||||||
|
case "unsigned short *":
|
||||||
|
case "unsigned char *":
|
||||||
|
this.statement(`free((void *)${name})`)
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -206,7 +228,7 @@ export abstract class GenericQuickJsGenerator<T extends QuickJsGenerator> extend
|
||||||
const body = this.function(`js_${structName}_finalizer`, "void", args, true)
|
const body = this.function(`js_${structName}_finalizer`, "void", args, true)
|
||||||
body.statement(`${structName}* ptr = JS_GetOpaque(val, ${classId})`)
|
body.statement(`${structName}* ptr = JS_GetOpaque(val, ${classId})`)
|
||||||
body.if("ptr", cond => {
|
body.if("ptr", cond => {
|
||||||
//cond.call("TraceLog", ["LOG_INFO",`"Finalize ${structName}"`])
|
//cond.call("TraceLog", ["LOG_INFO",`"Finalize ${structName} %p"`,"ptr"])
|
||||||
if(onFinalize) onFinalize(<T>cond, "ptr")
|
if(onFinalize) onFinalize(<T>cond, "ptr")
|
||||||
cond.call("js_free_rt", ["rt","ptr"])
|
cond.call("js_free_rt", ["rt","ptr"])
|
||||||
})
|
})
|
||||||
|
@ -230,9 +252,6 @@ export abstract class GenericQuickJsGenerator<T extends QuickJsGenerator> extend
|
||||||
const args = [{type: "JSContext*", name: "ctx" }, {type: "JSValueConst", name: "this_val"}]
|
const args = [{type: "JSContext*", name: "ctx" }, {type: "JSValueConst", name: "this_val"}]
|
||||||
const fun = this.function(`js_${structName}_get_${field}`,"JSValue",args,true)
|
const fun = this.function(`js_${structName}_get_${field}`,"JSValue",args,true)
|
||||||
fun.declare("ptr", structName+"*", false, `JS_GetOpaque2(ctx, this_val, ${classId})`)
|
fun.declare("ptr", structName+"*", false, `JS_GetOpaque2(ctx, this_val, ${classId})`)
|
||||||
fun.if("!ptr", cond => {
|
|
||||||
cond.returnExp("JS_EXCEPTION")
|
|
||||||
})
|
|
||||||
fun.declare(field, type, false, "ptr->"+field)
|
fun.declare(field, type, false, "ptr->"+field)
|
||||||
fun.jsToJs(type, "ret", field, classIds)
|
fun.jsToJs(type, "ret", field, classIds)
|
||||||
fun.returnExp("ret")
|
fun.returnExp("ret")
|
||||||
|
@ -243,9 +262,6 @@ export abstract class GenericQuickJsGenerator<T extends QuickJsGenerator> extend
|
||||||
const args = [{type: "JSContext*", name: "ctx" }, {type: "JSValueConst", name: "this_val"},{type: "JSValueConst", name: "v"}]
|
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)
|
const fun = this.function(`js_${structName}_set_${field}`,"JSValue",args,true)
|
||||||
fun.declare("ptr", structName+"*", false, `JS_GetOpaque2(ctx, this_val, ${classId})`)
|
fun.declare("ptr", structName+"*", false, `JS_GetOpaque2(ctx, this_val, ${classId})`)
|
||||||
fun.if("!ptr", cond => {
|
|
||||||
cond.returnExp("JS_EXCEPTION")
|
|
||||||
})
|
|
||||||
fun.jsToC(type, "value", "v", classIds);
|
fun.jsToC(type, "value", "v", classIds);
|
||||||
fun.statement("ptr->"+field+" = value")
|
fun.statement("ptr->"+field+" = value")
|
||||||
fun.returnExp("JS_UNDEFINED")
|
fun.returnExp("JS_UNDEFINED")
|
||||||
|
|
|
@ -8,6 +8,7 @@ export interface StructBindingOptions {
|
||||||
destructor?: string,
|
destructor?: string,
|
||||||
construct?: string,
|
construct?: string,
|
||||||
createConstructor?: boolean
|
createConstructor?: boolean
|
||||||
|
createEmptyConstructor?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface FuncBindingOptions {
|
export interface FuncBindingOptions {
|
||||||
|
@ -95,8 +96,8 @@ export class RayLibHeader extends QuickJsHeader {
|
||||||
|
|
||||||
this.moduleInit.call(classDecl.getTag("_name"), ["ctx", "m"])
|
this.moduleInit.call(classDecl.getTag("_name"), ["ctx", "m"])
|
||||||
|
|
||||||
if(options?.createConstructor){
|
if(options?.createConstructor || options?.createEmptyConstructor){
|
||||||
const body = this.functions.jsStructConstructor(struct.name, struct.fields, classId, this.structLookup)
|
const body = this.functions.jsStructConstructor(struct.name, options?.createEmptyConstructor ? [] : struct.fields, classId, this.structLookup)
|
||||||
|
|
||||||
this.moduleInit.statement(`JSValue ${struct.name}_constr = JS_NewCFunction2(ctx, ${body.getTag("_name")},"${struct.name})", ${struct.fields.length}, JS_CFUNC_constructor_or_func, 0)`)
|
this.moduleInit.statement(`JSValue ${struct.name}_constr = JS_NewCFunction2(ctx, ${body.getTag("_name")},"${struct.name})", ${struct.fields.length}, JS_CFUNC_constructor_or_func, 0)`)
|
||||||
this.moduleInit.call("JS_SetModuleExport", ["ctx","m", `"${struct.name}"`, struct.name+"_constr"])
|
this.moduleInit.call("JS_SetModuleExport", ["ctx","m", `"${struct.name}"`, struct.name+"_constr"])
|
||||||
|
|
|
@ -26,7 +26,7 @@ export class TypeScriptDeclaration {
|
||||||
addStruct(api: ApiStruct, options: StructBindingOptions){
|
addStruct(api: ApiStruct, options: StructBindingOptions){
|
||||||
var fields = api.fields.filter(x => !!(options.properties || {})[x.name]).map(x => ({name: x.name, description: x.description, type: this.toJsType(x.type)}))
|
var fields = api.fields.filter(x => !!(options.properties || {})[x.name]).map(x => ({name: x.name, description: x.description, type: this.toJsType(x.type)}))
|
||||||
this.structs.tsDeclareInterface(api.name, fields)
|
this.structs.tsDeclareInterface(api.name, fields)
|
||||||
this.structs.tsDeclareType(api.name, !!options.createConstructor, fields)
|
this.structs.tsDeclareType(api.name, !!(options.createConstructor || options.createEmptyConstructor), options.createEmptyConstructor ? [] : fields)
|
||||||
}
|
}
|
||||||
|
|
||||||
private toJsType(type: string){
|
private toJsType(type: string){
|
||||||
|
@ -38,6 +38,10 @@ export class TypeScriptDeclaration {
|
||||||
case "float":
|
case "float":
|
||||||
case "double":
|
case "double":
|
||||||
return "number"
|
return "number"
|
||||||
|
case "unsigned char *":
|
||||||
|
case "unsigned short *":
|
||||||
|
case "float *":
|
||||||
|
return "ArrayBuffer"
|
||||||
case "bool":
|
case "bool":
|
||||||
return "boolean"
|
return "boolean"
|
||||||
case "const char *":
|
case "const char *":
|
||||||
|
@ -47,14 +51,19 @@ export class TypeScriptDeclaration {
|
||||||
case "const void *":
|
case "const void *":
|
||||||
return "any"
|
return "any"
|
||||||
case "Camera":
|
case "Camera":
|
||||||
|
case "Camera *":
|
||||||
return "Camera3D"
|
return "Camera3D"
|
||||||
case "Texture2D":
|
case "Texture2D":
|
||||||
|
case "Texture2D *":
|
||||||
case "TextureCubemap":
|
case "TextureCubemap":
|
||||||
return "Texture"
|
return "Texture"
|
||||||
|
case "RenderTexture2D":
|
||||||
|
case "RenderTexture2D *":
|
||||||
|
return "RenderTexture"
|
||||||
case "Quaternion":
|
case "Quaternion":
|
||||||
return "Vector4"
|
return "Vector4"
|
||||||
default:
|
default:
|
||||||
return type.replace(" *", "")
|
return type.replace(" *", "").replace("const ", "")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Binary file not shown.
After Width: | Height: | Size: 44 KiB |
|
@ -0,0 +1,118 @@
|
||||||
|
/*******************************************************************************************
|
||||||
|
*
|
||||||
|
* raylib [models] example - first person maze
|
||||||
|
*
|
||||||
|
* Example originally created with raylib 2.5, last time updated with raylib 3.5
|
||||||
|
*
|
||||||
|
* Example licensed under an unmodified zlib/libpng license, which is an OSI-certified,
|
||||||
|
* BSD-like license that allows static linking with closed source software
|
||||||
|
*
|
||||||
|
* Copyright (c) 2019-2023 Ramon Santamaria (@raysan5)
|
||||||
|
*
|
||||||
|
********************************************************************************************/
|
||||||
|
// Initialization
|
||||||
|
//--------------------------------------------------------------------------------------
|
||||||
|
const screenWidth = 800;
|
||||||
|
const screenHeight = 450;
|
||||||
|
|
||||||
|
initWindow(screenWidth, screenHeight, "raylib [models] example - first person maze");
|
||||||
|
|
||||||
|
// Define the camera to look into our 3d world
|
||||||
|
const camera = new Camera3D(new Vector3(0.2, 0.4, 0.2),new Vector3(0.185, 0.4, 0.0),new Vector3(0,1,0), 45, CAMERA_PERSPECTIVE);
|
||||||
|
const position = new Vector3(0,0,0); // Set model position
|
||||||
|
|
||||||
|
const imMap = loadImage("assets/cubicmap.png"); // Load cubicmap image (RAM)
|
||||||
|
const cubicmap = loadTextureFromImage(imMap); // Convert image to texture to display (VRAM)
|
||||||
|
const mesh = genMeshCubicmap(imMap, new Vector3(1.0, 1.0, 1.0));
|
||||||
|
const model = loadModelFromMesh(mesh);
|
||||||
|
|
||||||
|
// NOTE: By default each cube is mapped to one part of texture atlas
|
||||||
|
const texture = loadTexture("assets/cubicmap_atlas.png"); // Load map texture
|
||||||
|
//model.materials[0].maps[MATERIAL_MAP_DIFFUSE].texture = texture; // Set map diffuse texture
|
||||||
|
const mat = loadMaterialDefault()
|
||||||
|
setMaterialTexture(mat, MATERIAL_MAP_DIFFUSE, texture)
|
||||||
|
setModelMaterial(model,0,mat)
|
||||||
|
|
||||||
|
// Get map image data to be used for collision detection
|
||||||
|
const mapPixels = new Uint8Array(loadImageColors(imMap));
|
||||||
|
unloadImage(imMap); // Unload image from RAM
|
||||||
|
|
||||||
|
let mapPosition = new Vector3( -16.0, 0.0, -8.0); // Set model position
|
||||||
|
|
||||||
|
disableCursor(); // Limit cursor to relative movement inside the window
|
||||||
|
|
||||||
|
setTargetFPS(60); // Set our game to run at 60 frames-per-second
|
||||||
|
//--------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// Main game loop
|
||||||
|
while (!windowShouldClose()) // Detect window close button or ESC key
|
||||||
|
{
|
||||||
|
// Update
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
let oldCamPos = camera.position; // Store old camera position
|
||||||
|
|
||||||
|
updateCamera(camera, CAMERA_FIRST_PERSON);
|
||||||
|
|
||||||
|
// Check player collision (we simplify to 2D collision detection)
|
||||||
|
const playerPos = new Vector2(camera.position.x, camera.position.z);
|
||||||
|
const playerRadius = 0.1; // Collision radius (player is modelled as a cilinder for collision)
|
||||||
|
|
||||||
|
let playerCellX = Math.floor(playerPos.x - mapPosition.x + 0.5);
|
||||||
|
let playerCellY = Math.floor(playerPos.y - mapPosition.z + 0.5);
|
||||||
|
|
||||||
|
// Out-of-limits security check
|
||||||
|
if (playerCellX < 0) playerCellX = 0;
|
||||||
|
else if (playerCellX >= cubicmap.width) playerCellX = cubicmap.width - 1;
|
||||||
|
|
||||||
|
if (playerCellY < 0) playerCellY = 0;
|
||||||
|
else if (playerCellY >= cubicmap.height) playerCellY = cubicmap.height - 1;
|
||||||
|
|
||||||
|
// Check map collisions using image data and player position
|
||||||
|
// TODO: Improvement: Just check player surrounding cells for collision
|
||||||
|
for (let y = 0; y < cubicmap.height; y++)
|
||||||
|
{
|
||||||
|
for (let x = 0; x < cubicmap.width; x++)
|
||||||
|
{
|
||||||
|
const pixelValR = mapPixels[((y*cubicmap.width + x)*4)]
|
||||||
|
if ((pixelValR == 255) && // Collision: white pixel, only check R channel
|
||||||
|
(checkCollisionCircleRec(playerPos, playerRadius, new Rectangle(
|
||||||
|
mapPosition.x - 0.5 + x*1.0,
|
||||||
|
mapPosition.z - 0.5 + y*1.0, 1.0, 1.0 ))))
|
||||||
|
{
|
||||||
|
// Collision detected, reset camera position
|
||||||
|
camera.position = oldCamPos;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// Draw
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
beginDrawing();
|
||||||
|
|
||||||
|
clearBackground(RAYWHITE);
|
||||||
|
|
||||||
|
beginMode3D(camera);
|
||||||
|
drawModel(model, mapPosition, 1.0, WHITE); // Draw maze map
|
||||||
|
endMode3D();
|
||||||
|
|
||||||
|
drawTextureEx(cubicmap, new Vector2(getScreenWidth() - cubicmap.width*4.0 - 20, 20.0), 0.0, 4.0, WHITE);
|
||||||
|
drawRectangleLines(getScreenWidth() - cubicmap.width*4 - 20, 20, cubicmap.width*4, cubicmap.height*4, GREEN);
|
||||||
|
|
||||||
|
// Draw player position radar
|
||||||
|
drawRectangle(getScreenWidth() - cubicmap.width*4 - 20 + playerCellX*4, 20 + playerCellY*4, 4, 4, RED);
|
||||||
|
|
||||||
|
drawFPS(10, 10);
|
||||||
|
|
||||||
|
endDrawing();
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
}
|
||||||
|
|
||||||
|
// De-Initialization
|
||||||
|
//--------------------------------------------------------------------------------------
|
||||||
|
unloadTexture(cubicmap); // Unload cubicmap texture
|
||||||
|
unloadTexture(texture); // Unload map texture
|
||||||
|
unloadModel(model); // Unload map model
|
||||||
|
|
||||||
|
closeWindow(); // Close window and OpenGL context
|
||||||
|
//--------------------------------------------------------------------------------------
|
|
@ -28,4 +28,8 @@ while (!windowShouldClose()) // Detect window close button or ESC key
|
||||||
endDrawing();
|
endDrawing();
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
}
|
}
|
||||||
|
// De-Initialization
|
||||||
|
//--------------------------------------------------------------------------------------
|
||||||
|
closeWindow(); // Close window and OpenGL context
|
||||||
|
//--------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
|
@ -83,5 +83,6 @@ while (!windowShouldClose()) // Detect window close button or ESC key
|
||||||
|
|
||||||
// De-Initialization
|
// De-Initialization
|
||||||
//--------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------
|
||||||
|
unloadTexture(texBunny);
|
||||||
closeWindow(); // Close window and OpenGL context
|
closeWindow(); // Close window and OpenGL context
|
||||||
//--------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------
|
|
@ -0,0 +1,50 @@
|
||||||
|
// Initialization
|
||||||
|
//--------------------------------------------------------------------------------------
|
||||||
|
const screenWidth = 800;
|
||||||
|
const screenHeight = 450;
|
||||||
|
|
||||||
|
initWindow(screenWidth, screenHeight, "raylib [core] example - javascript mesh generation");
|
||||||
|
|
||||||
|
const mesh = new Mesh()
|
||||||
|
mesh.vertexCount = 3
|
||||||
|
mesh.triangleCount = 1
|
||||||
|
const v1 = new Vector3(screenWidth/2, 0, 0)
|
||||||
|
const v2 = new Vector3(0, screenHeight, 0 )
|
||||||
|
const v3 = new Vector3(screenWidth, screenHeight, 0)
|
||||||
|
mesh.indices = new Uint16Array([0,1,2]).buffer
|
||||||
|
mesh.vertices = new Float32Array([
|
||||||
|
v1.x, v1.y, v1.z,
|
||||||
|
v2.x, v2.y, v2.z,
|
||||||
|
v3.x, v3.y, v3.z
|
||||||
|
]).buffer
|
||||||
|
uploadMesh(mesh, false) // If your forget to upload to GPU drawMesh will segfault
|
||||||
|
const material = loadMaterialDefault()
|
||||||
|
const matrix = matrixIdentity()
|
||||||
|
|
||||||
|
setTargetFPS(60); // Set our game to run at 60 frames-per-second
|
||||||
|
//--------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// Main game loop
|
||||||
|
while (!windowShouldClose()) // Detect window close button or ESC key
|
||||||
|
{
|
||||||
|
// Update
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// Draw
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
beginDrawing();
|
||||||
|
|
||||||
|
clearBackground(RAYWHITE);
|
||||||
|
drawMesh(mesh, material, matrix)
|
||||||
|
drawText("Mesh created from Javascript ArrayBuffers", 190, 200, 20, LIGHTGRAY);
|
||||||
|
|
||||||
|
endDrawing();
|
||||||
|
//----------------------------------------------------------------------------------
|
||||||
|
}
|
||||||
|
// De-Initialization
|
||||||
|
//--------------------------------------------------------------------------------------
|
||||||
|
unloadMaterial(material)
|
||||||
|
unloadMesh(mesh)
|
||||||
|
closeWindow(); // Close window and OpenGL context
|
||||||
|
//--------------------------------------------------------------------------------------
|
|
@ -122,6 +122,24 @@ interface Matrix {
|
||||||
declare var Matrix: {
|
declare var Matrix: {
|
||||||
prototype: Matrix;
|
prototype: Matrix;
|
||||||
}
|
}
|
||||||
|
interface NPatchInfo {
|
||||||
|
/** Texture source rectangle */
|
||||||
|
source: Rectangle,
|
||||||
|
/** Left border offset */
|
||||||
|
left: number,
|
||||||
|
/** Top border offset */
|
||||||
|
top: number,
|
||||||
|
/** Right border offset */
|
||||||
|
right: number,
|
||||||
|
/** Bottom border offset */
|
||||||
|
bottom: number,
|
||||||
|
/** Layout of the n-patch: 3x3, 1x3 or 3x1 */
|
||||||
|
layout: number,
|
||||||
|
}
|
||||||
|
declare var NPatchInfo: {
|
||||||
|
prototype: NPatchInfo;
|
||||||
|
new(source: Rectangle, left: number, top: number, right: number, bottom: number, layout: number): NPatchInfo;
|
||||||
|
}
|
||||||
interface Image {
|
interface Image {
|
||||||
/** Image base width */
|
/** Image base width */
|
||||||
width: number,
|
width: number,
|
||||||
|
@ -170,9 +188,36 @@ declare var Model: {
|
||||||
prototype: Model;
|
prototype: Model;
|
||||||
}
|
}
|
||||||
interface Mesh {
|
interface Mesh {
|
||||||
|
/** Number of vertices stored in arrays */
|
||||||
|
vertexCount: number,
|
||||||
|
/** Number of triangles stored (indexed or not) */
|
||||||
|
triangleCount: number,
|
||||||
|
/** Vertex position (XYZ - 3 components per vertex) (shader-location = 0) */
|
||||||
|
vertices: ArrayBuffer,
|
||||||
|
/** Vertex texture coordinates (UV - 2 components per vertex) (shader-location = 1) */
|
||||||
|
texcoords: ArrayBuffer,
|
||||||
|
/** Vertex texture second coordinates (UV - 2 components per vertex) (shader-location = 5) */
|
||||||
|
texcoords2: ArrayBuffer,
|
||||||
|
/** Vertex normals (XYZ - 3 components per vertex) (shader-location = 2) */
|
||||||
|
normals: ArrayBuffer,
|
||||||
|
/** Vertex tangents (XYZW - 4 components per vertex) (shader-location = 4) */
|
||||||
|
tangents: ArrayBuffer,
|
||||||
|
/** Vertex colors (RGBA - 4 components per vertex) (shader-location = 3) */
|
||||||
|
colors: ArrayBuffer,
|
||||||
|
/** Vertex indices (in case vertex data comes indexed) */
|
||||||
|
indices: ArrayBuffer,
|
||||||
|
/** Animated vertex positions (after bones transformations) */
|
||||||
|
animVertices: ArrayBuffer,
|
||||||
|
/** Animated normals (after bones transformations) */
|
||||||
|
animNormals: ArrayBuffer,
|
||||||
|
/** Vertex bone ids, max 255 bone ids, up to 4 bones influence by vertex (skinning) */
|
||||||
|
boneIds: ArrayBuffer,
|
||||||
|
/** Vertex bone weight, up to 4 bones influence by vertex (skinning) */
|
||||||
|
boneWeights: ArrayBuffer,
|
||||||
}
|
}
|
||||||
declare var Mesh: {
|
declare var Mesh: {
|
||||||
prototype: Mesh;
|
prototype: Mesh;
|
||||||
|
new(): Mesh;
|
||||||
}
|
}
|
||||||
interface Shader {
|
interface Shader {
|
||||||
}
|
}
|
||||||
|
@ -195,6 +240,29 @@ interface Font {
|
||||||
declare var Font: {
|
declare var Font: {
|
||||||
prototype: Font;
|
prototype: Font;
|
||||||
}
|
}
|
||||||
|
interface RenderTexture {
|
||||||
|
}
|
||||||
|
declare var RenderTexture: {
|
||||||
|
prototype: RenderTexture;
|
||||||
|
}
|
||||||
|
interface MaterialMap {
|
||||||
|
/** Material map texture */
|
||||||
|
texture: Texture,
|
||||||
|
/** Material map color */
|
||||||
|
color: Color,
|
||||||
|
/** Material map value */
|
||||||
|
value: number,
|
||||||
|
}
|
||||||
|
declare var MaterialMap: {
|
||||||
|
prototype: MaterialMap;
|
||||||
|
}
|
||||||
|
interface Material {
|
||||||
|
/** Material shader */
|
||||||
|
shader: Shader,
|
||||||
|
}
|
||||||
|
declare var Material: {
|
||||||
|
prototype: Material;
|
||||||
|
}
|
||||||
/** Initialize window and OpenGL context */
|
/** Initialize window and OpenGL context */
|
||||||
declare function initWindow(width: number, height: number, title: string): void;
|
declare function initWindow(width: number, height: number, title: string): void;
|
||||||
/** Check if KEY_ESCAPE pressed or Close icon pressed */
|
/** Check if KEY_ESCAPE pressed or Close icon pressed */
|
||||||
|
@ -307,6 +375,10 @@ declare function endMode2D(): void;
|
||||||
declare function beginMode3D(camera: Camera3D): void;
|
declare function beginMode3D(camera: Camera3D): void;
|
||||||
/** Ends 3D mode and returns to default 2D orthographic mode */
|
/** Ends 3D mode and returns to default 2D orthographic mode */
|
||||||
declare function endMode3D(): void;
|
declare function endMode3D(): void;
|
||||||
|
/** Begin drawing to render texture */
|
||||||
|
declare function beginTextureMode(target: RenderTexture): void;
|
||||||
|
/** Ends drawing to render texture */
|
||||||
|
declare function endTextureMode(): void;
|
||||||
/** Begin custom shader drawing */
|
/** Begin custom shader drawing */
|
||||||
declare function beginShaderMode(shader: Shader): void;
|
declare function beginShaderMode(shader: Shader): void;
|
||||||
/** End custom shader drawing (use default shader) */
|
/** End custom shader drawing (use default shader) */
|
||||||
|
@ -333,6 +405,8 @@ declare function setShaderValue(shader: Shader, locIndex: number, value: any, un
|
||||||
declare function setShaderValueMatrix(shader: Shader, locIndex: number, mat: Matrix): void;
|
declare function setShaderValueMatrix(shader: Shader, locIndex: number, mat: Matrix): void;
|
||||||
/** Set shader uniform value for texture (sampler2d) */
|
/** Set shader uniform value for texture (sampler2d) */
|
||||||
declare function setShaderValueTexture(shader: Shader, locIndex: number, texture: Texture): void;
|
declare function setShaderValueTexture(shader: Shader, locIndex: number, texture: Texture): void;
|
||||||
|
/** Unload shader from GPU memory (VRAM) */
|
||||||
|
declare function unloadShader(shader: Shader): void;
|
||||||
/** Get a ray trace from mouse position */
|
/** Get a ray trace from mouse position */
|
||||||
declare function getMouseRay(mousePosition: Vector2, camera: Camera3D): Ray;
|
declare function getMouseRay(mousePosition: Vector2, camera: Camera3D): Ray;
|
||||||
/** Get camera transform matrix (view matrix) */
|
/** Get camera transform matrix (view matrix) */
|
||||||
|
@ -492,9 +566,9 @@ declare function getGesturePinchVector(): Vector2;
|
||||||
/** Get gesture pinch angle */
|
/** Get gesture pinch angle */
|
||||||
declare function getGesturePinchAngle(): number;
|
declare function getGesturePinchAngle(): number;
|
||||||
/** Update camera position for selected mode */
|
/** Update camera position for selected mode */
|
||||||
declare function updateCamera(camera: Camera, mode: number): void;
|
declare function updateCamera(camera: Camera3D, mode: number): void;
|
||||||
/** Update camera movement/rotation */
|
/** Update camera movement/rotation */
|
||||||
declare function updateCameraPro(camera: Camera, movement: Vector3, rotation: Vector3, zoom: number): void;
|
declare function updateCameraPro(camera: Camera3D, movement: Vector3, rotation: Vector3, zoom: number): void;
|
||||||
/** Draw a pixel */
|
/** Draw a pixel */
|
||||||
declare function drawPixel(posX: number, posY: number, color: Color): void;
|
declare function drawPixel(posX: number, posY: number, color: Color): void;
|
||||||
/** Draw a pixel (Vector version) */
|
/** Draw a pixel (Vector version) */
|
||||||
|
@ -589,6 +663,8 @@ declare function loadImageFromTexture(texture: Texture): Image;
|
||||||
declare function loadImageFromScreen(): Image;
|
declare function loadImageFromScreen(): Image;
|
||||||
/** Check if an image is ready */
|
/** Check if an image is ready */
|
||||||
declare function isImageReady(image: Image): boolean;
|
declare function isImageReady(image: Image): boolean;
|
||||||
|
/** Unload image from CPU memory (RAM) */
|
||||||
|
declare function unloadImage(image: Image): void;
|
||||||
/** Export image data to file, returns true on success */
|
/** Export image data to file, returns true on success */
|
||||||
declare function exportImage(image: Image, fileName: string): boolean;
|
declare function exportImage(image: Image, fileName: string): boolean;
|
||||||
/** Generate image: plain color */
|
/** Generate image: plain color */
|
||||||
|
@ -663,6 +739,8 @@ declare function imageColorContrast(image: Image, contrast: number): void;
|
||||||
declare function imageColorBrightness(image: Image, brightness: number): void;
|
declare function imageColorBrightness(image: Image, brightness: number): void;
|
||||||
/** Modify image color: replace color */
|
/** Modify image color: replace color */
|
||||||
declare function imageColorReplace(image: Image, color: Color, replace: Color): void;
|
declare function imageColorReplace(image: Image, color: Color, replace: Color): void;
|
||||||
|
/** Load color data from image as a Color array (RGBA - 32bit) */
|
||||||
|
declare function loadImageColors(image: Image): ArrayBuffer;
|
||||||
/** Get image alpha border rectangle */
|
/** Get image alpha border rectangle */
|
||||||
declare function getImageAlphaBorder(image: Image, threshold: number): Rectangle;
|
declare function getImageAlphaBorder(image: Image, threshold: number): Rectangle;
|
||||||
/** Get image pixel color at (x, y) position */
|
/** Get image pixel color at (x, y) position */
|
||||||
|
@ -705,10 +783,18 @@ declare function loadTexture(fileName: string): Texture;
|
||||||
declare function loadTextureFromImage(image: Image): Texture;
|
declare function loadTextureFromImage(image: Image): Texture;
|
||||||
/** Load cubemap from image, multiple image cubemap layouts supported */
|
/** Load cubemap from image, multiple image cubemap layouts supported */
|
||||||
declare function loadTextureCubemap(image: Image, layout: number): Texture;
|
declare function loadTextureCubemap(image: Image, layout: number): Texture;
|
||||||
|
/** Load texture for rendering (framebuffer) */
|
||||||
|
declare function loadRenderTexture(width: number, height: number): RenderTexture;
|
||||||
/** Check if a texture is ready */
|
/** Check if a texture is ready */
|
||||||
declare function isTextureReady(texture: Texture): boolean;
|
declare function isTextureReady(texture: Texture): boolean;
|
||||||
|
/** Unload texture from GPU memory (VRAM) */
|
||||||
|
declare function unloadTexture(texture: Texture): void;
|
||||||
|
/** Check if a render texture is ready */
|
||||||
|
declare function isRenderTextureReady(target: RenderTexture): boolean;
|
||||||
|
/** Unload render texture from GPU memory (VRAM) */
|
||||||
|
declare function unloadRenderTexture(target: RenderTexture): void;
|
||||||
/** Generate GPU mipmaps for a texture */
|
/** Generate GPU mipmaps for a texture */
|
||||||
declare function genTextureMipmaps(texture: Texture2D): void;
|
declare function genTextureMipmaps(texture: Texture): void;
|
||||||
/** Set texture scaling filter mode */
|
/** Set texture scaling filter mode */
|
||||||
declare function setTextureFilter(texture: Texture, filter: number): void;
|
declare function setTextureFilter(texture: Texture, filter: number): void;
|
||||||
/** Set texture wrapping mode */
|
/** Set texture wrapping mode */
|
||||||
|
@ -723,6 +809,8 @@ declare function drawTextureEx(texture: Texture, position: Vector2, rotation: nu
|
||||||
declare function drawTextureRec(texture: Texture, source: Rectangle, position: Vector2, tint: Color): void;
|
declare function drawTextureRec(texture: Texture, source: Rectangle, position: Vector2, tint: Color): void;
|
||||||
/** Draw a part of a texture defined by a rectangle with 'pro' parameters */
|
/** Draw a part of a texture defined by a rectangle with 'pro' parameters */
|
||||||
declare function drawTexturePro(texture: Texture, source: Rectangle, dest: Rectangle, origin: Vector2, rotation: number, tint: Color): void;
|
declare function drawTexturePro(texture: Texture, source: Rectangle, dest: Rectangle, origin: Vector2, rotation: number, tint: Color): void;
|
||||||
|
/** Draws a texture (or part of it) that stretches or shrinks nicely */
|
||||||
|
declare function drawTextureNPatch(texture: Texture, nPatchInfo: NPatchInfo, dest: Rectangle, origin: Vector2, rotation: number, tint: Color): void;
|
||||||
/** Get color with alpha applied, alpha goes from 0.0f to 1.0f */
|
/** Get color with alpha applied, alpha goes from 0.0f to 1.0f */
|
||||||
declare function fade(color: Color, alpha: number): Color;
|
declare function fade(color: Color, alpha: number): Color;
|
||||||
/** Get hexadecimal value for a Color */
|
/** Get hexadecimal value for a Color */
|
||||||
|
@ -757,6 +845,8 @@ declare function loadFont(fileName: string): Font;
|
||||||
declare function loadFontFromImage(image: Image, key: Color, firstChar: number): Font;
|
declare function loadFontFromImage(image: Image, key: Color, firstChar: number): Font;
|
||||||
/** Check if a font is ready */
|
/** Check if a font is ready */
|
||||||
declare function isFontReady(font: Font): boolean;
|
declare function isFontReady(font: Font): boolean;
|
||||||
|
/** Unload font from GPU memory (VRAM) */
|
||||||
|
declare function unloadFont(font: Font): void;
|
||||||
/** Draw current FPS */
|
/** Draw current FPS */
|
||||||
declare function drawFPS(posX: number, posY: number): void;
|
declare function drawFPS(posX: number, posY: number): void;
|
||||||
/** Draw text (using default font) */
|
/** Draw text (using default font) */
|
||||||
|
@ -821,6 +911,8 @@ declare function loadModel(fileName: string): Model;
|
||||||
declare function loadModelFromMesh(mesh: Mesh): Model;
|
declare function loadModelFromMesh(mesh: Mesh): Model;
|
||||||
/** Check if a model is ready */
|
/** Check if a model is ready */
|
||||||
declare function isModelReady(model: Model): boolean;
|
declare function isModelReady(model: Model): boolean;
|
||||||
|
/** Unload model (including meshes) from memory (RAM and/or VRAM) */
|
||||||
|
declare function unloadModel(model: Model): void;
|
||||||
/** Compute model bounding box limits (considers all meshes) */
|
/** Compute model bounding box limits (considers all meshes) */
|
||||||
declare function getModelBoundingBox(model: Model): BoundingBox;
|
declare function getModelBoundingBox(model: Model): BoundingBox;
|
||||||
/** Draw a model (with texture if set) */
|
/** Draw a model (with texture if set) */
|
||||||
|
@ -841,6 +933,14 @@ declare function drawBillboardRec(camera: Camera3D, texture: Texture, source: Re
|
||||||
declare function drawBillboardPro(camera: Camera3D, texture: Texture, source: Rectangle, position: Vector3, up: Vector3, size: Vector2, origin: Vector2, rotation: number, tint: Color): void;
|
declare function drawBillboardPro(camera: Camera3D, texture: Texture, source: Rectangle, position: Vector3, up: Vector3, size: Vector2, origin: Vector2, rotation: number, tint: Color): void;
|
||||||
/** Upload mesh vertex data in GPU and provide VAO/VBO ids */
|
/** Upload mesh vertex data in GPU and provide VAO/VBO ids */
|
||||||
declare function uploadMesh(mesh: Mesh, dynamic: boolean): void;
|
declare function uploadMesh(mesh: Mesh, dynamic: boolean): void;
|
||||||
|
/** Update mesh vertex data in GPU for a specific buffer index */
|
||||||
|
declare function updateMeshBuffer(mesh: Mesh, index: number, data: any, dataSize: number, offset: number): void;
|
||||||
|
/** Unload mesh data from CPU and GPU */
|
||||||
|
declare function unloadMesh(mesh: Mesh): void;
|
||||||
|
/** Draw a 3d mesh with material and transform */
|
||||||
|
declare function drawMesh(mesh: Mesh, material: Material, transform: Matrix): void;
|
||||||
|
/** Draw multiple mesh instances with material and different transforms */
|
||||||
|
declare function drawMeshInstanced(mesh: Mesh, material: Material, transforms: Matrix, instances: number): void;
|
||||||
/** Export mesh data to file, returns true on success */
|
/** Export mesh data to file, returns true on success */
|
||||||
declare function exportMesh(mesh: Mesh, fileName: string): boolean;
|
declare function exportMesh(mesh: Mesh, fileName: string): boolean;
|
||||||
/** Compute mesh bounding box limits */
|
/** Compute mesh bounding box limits */
|
||||||
|
@ -869,6 +969,18 @@ declare function genMeshKnot(radius: number, size: number, radSeg: number, sides
|
||||||
declare function genMeshHeightmap(heightmap: Image, size: Vector3): Mesh;
|
declare function genMeshHeightmap(heightmap: Image, size: Vector3): Mesh;
|
||||||
/** Generate cubes-based map mesh from image data */
|
/** Generate cubes-based map mesh from image data */
|
||||||
declare function genMeshCubicmap(cubicmap: Image, cubeSize: Vector3): Mesh;
|
declare function genMeshCubicmap(cubicmap: Image, cubeSize: Vector3): Mesh;
|
||||||
|
/** Load default material (Supports: DIFFUSE, SPECULAR, NORMAL maps) */
|
||||||
|
declare function loadMaterialDefault(): Material;
|
||||||
|
/** Check if a material is ready */
|
||||||
|
declare function isMaterialReady(material: Material): boolean;
|
||||||
|
/** Unload material from GPU memory (VRAM) */
|
||||||
|
declare function unloadMaterial(material: Material): void;
|
||||||
|
/** Set texture for a material map type (MATERIAL_MAP_DIFFUSE, MATERIAL_MAP_SPECULAR...) */
|
||||||
|
declare function setMaterialTexture(material: Material, mapType: number, texture: Texture): void;
|
||||||
|
/** Replace material in slot materialIndex */
|
||||||
|
declare function setModelMaterial(model: Model, materialIndex: number, material: Material): void;
|
||||||
|
/** Set material for a mesh */
|
||||||
|
declare function setModelMeshMaterial(model: Model, meshId: number, materialId: number): void;
|
||||||
/** Check collision between two spheres */
|
/** Check collision between two spheres */
|
||||||
declare function checkCollisionSpheres(center1: Vector3, radius1: number, center2: Vector3, radius2: number): boolean;
|
declare function checkCollisionSpheres(center1: Vector3, radius1: number, center2: Vector3, radius2: number): boolean;
|
||||||
/** Check collision between two bounding boxes */
|
/** Check collision between two bounding boxes */
|
||||||
|
@ -903,6 +1015,10 @@ declare function loadSound(fileName: string): Sound;
|
||||||
declare function loadSoundFromWave(wave: Wave): Sound;
|
declare function loadSoundFromWave(wave: Wave): Sound;
|
||||||
/** Checks if a sound is ready */
|
/** Checks if a sound is ready */
|
||||||
declare function isSoundReady(sound: Sound): boolean;
|
declare function isSoundReady(sound: Sound): boolean;
|
||||||
|
/** Unload wave data */
|
||||||
|
declare function unloadWave(wave: Wave): void;
|
||||||
|
/** Unload sound */
|
||||||
|
declare function unloadSound(sound: Sound): void;
|
||||||
/** Export wave data to file, returns true on success */
|
/** Export wave data to file, returns true on success */
|
||||||
declare function exportWave(wave: Wave, fileName: string): boolean;
|
declare function exportWave(wave: Wave, fileName: string): boolean;
|
||||||
/** Play a sound */
|
/** Play a sound */
|
||||||
|
@ -931,6 +1047,8 @@ declare function waveFormat(wave: Wave, sampleRate: number, sampleSize: number,
|
||||||
declare function loadMusicStream(fileName: string): Music;
|
declare function loadMusicStream(fileName: string): Music;
|
||||||
/** Checks if a music stream is ready */
|
/** Checks if a music stream is ready */
|
||||||
declare function isMusicReady(music: Music): boolean;
|
declare function isMusicReady(music: Music): boolean;
|
||||||
|
/** Unload music stream */
|
||||||
|
declare function unloadMusicStream(music: Music): void;
|
||||||
/** Start music playing */
|
/** Start music playing */
|
||||||
declare function playMusicStream(music: Music): void;
|
declare function playMusicStream(music: Music): void;
|
||||||
/** Check if music is playing */
|
/** Check if music is playing */
|
||||||
|
@ -1042,9 +1160,9 @@ declare function vector3CrossProduct(v1: Vector3, v2: Vector3): Vector3;
|
||||||
/** */
|
/** */
|
||||||
declare function vector3Perpendicular(v: Vector3): Vector3;
|
declare function vector3Perpendicular(v: Vector3): Vector3;
|
||||||
/** */
|
/** */
|
||||||
declare function vector3Length(v: const Vector3): number;
|
declare function vector3Length(v: Vector3): number;
|
||||||
/** */
|
/** */
|
||||||
declare function vector3LengthSqr(v: const Vector3): number;
|
declare function vector3LengthSqr(v: Vector3): number;
|
||||||
/** */
|
/** */
|
||||||
declare function vector3DotProduct(v1: Vector3, v2: Vector3): number;
|
declare function vector3DotProduct(v1: Vector3, v2: Vector3): number;
|
||||||
/** */
|
/** */
|
||||||
|
@ -1667,3 +1785,29 @@ declare var SHADER_UNIFORM_IVEC3: number;
|
||||||
declare var SHADER_UNIFORM_IVEC4: number;
|
declare var SHADER_UNIFORM_IVEC4: number;
|
||||||
/** Shader uniform type: sampler2d */
|
/** Shader uniform type: sampler2d */
|
||||||
declare var SHADER_UNIFORM_SAMPLER2D: number;
|
declare var SHADER_UNIFORM_SAMPLER2D: number;
|
||||||
|
/** Albedo material (same as: MATERIAL_MAP_DIFFUSE) */
|
||||||
|
declare var MATERIAL_MAP_ALBEDO: number;
|
||||||
|
/** Metalness material (same as: MATERIAL_MAP_SPECULAR) */
|
||||||
|
declare var MATERIAL_MAP_METALNESS: number;
|
||||||
|
/** Normal material */
|
||||||
|
declare var MATERIAL_MAP_NORMAL: number;
|
||||||
|
/** Roughness material */
|
||||||
|
declare var MATERIAL_MAP_ROUGHNESS: number;
|
||||||
|
/** Ambient occlusion material */
|
||||||
|
declare var MATERIAL_MAP_OCCLUSION: number;
|
||||||
|
/** Emission material */
|
||||||
|
declare var MATERIAL_MAP_EMISSION: number;
|
||||||
|
/** Heightmap material */
|
||||||
|
declare var MATERIAL_MAP_HEIGHT: number;
|
||||||
|
/** Cubemap material (NOTE: Uses GL_TEXTURE_CUBE_MAP) */
|
||||||
|
declare var MATERIAL_MAP_CUBEMAP: number;
|
||||||
|
/** Irradiance material (NOTE: Uses GL_TEXTURE_CUBE_MAP) */
|
||||||
|
declare var MATERIAL_MAP_IRRADIANCE: number;
|
||||||
|
/** Prefilter material (NOTE: Uses GL_TEXTURE_CUBE_MAP) */
|
||||||
|
declare var MATERIAL_MAP_PREFILTER: number;
|
||||||
|
/** Brdf material */
|
||||||
|
declare var MATERIAL_MAP_BRDF: number;
|
||||||
|
/** Albedo material (same as: MATERIAL_MAP_DIFFUSE */
|
||||||
|
declare var MATERIAL_MAP_DIFFUSE: number;
|
||||||
|
/** Metalness material (same as: MATERIAL_MAP_SPECULAR) */
|
||||||
|
declare var MATERIAL_MAP_SPECULAR: number;
|
||||||
|
|
|
@ -10,7 +10,6 @@
|
||||||
* Copyright (c) 2015-2023 Ramon Santamaria (@raysan5)
|
* Copyright (c) 2015-2023 Ramon Santamaria (@raysan5)
|
||||||
*
|
*
|
||||||
********************************************************************************************/
|
********************************************************************************************/
|
||||||
|
|
||||||
// Initialization
|
// Initialization
|
||||||
//--------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------
|
||||||
const screenWidth = 800;
|
const screenWidth = 800;
|
||||||
|
@ -26,19 +25,23 @@ const fovy = 45.0; // Camera field-of-view Y
|
||||||
const projection = CAMERA_PERSPECTIVE; // Camera projection type
|
const projection = CAMERA_PERSPECTIVE; // Camera projection type
|
||||||
const camera = new Camera3D(position, target, up, fovy, projection)
|
const camera = new Camera3D(position, target, up, fovy, projection)
|
||||||
|
|
||||||
const image = loadImage("assets/cubicmap.png"); // Load cubicmap image (RAM)
|
let image = loadImage("assets/cubicmap.png"); // Load cubicmap image (RAM)
|
||||||
const cubicmap = loadTextureFromImage(image); // Convert image to texture to display (VRAM)
|
let cubicmap = loadTextureFromImage(image); // Convert image to texture to display (VRAM)
|
||||||
|
|
||||||
const mesh = genMeshCubicmap(image, new Vector3(1.0, 1.0, 1.0));
|
const mesh = genMeshCubicmap(image, new Vector3(1.0, 1.0, 1.0));
|
||||||
const model = loadModelFromMesh(mesh);
|
const model = loadModelFromMesh(mesh);
|
||||||
|
|
||||||
// NOTE: By default each cube is mapped to one part of texture atlas
|
// NOTE: By default each cube is mapped to one part of texture atlas
|
||||||
const texture = loadTexture("assets/cubicmap_atlas.png"); // Load map texture
|
let texture = loadTexture("assets/cubicmap_atlas.png"); // Load map texture
|
||||||
|
|
||||||
//model.materials[0].maps[MATERIAL_MAP_DIFFUSE].texture = texture; // Set map diffuse texture
|
//model.materials[0].maps[MATERIAL_MAP_DIFFUSE].texture = texture; // Set map diffuse texture
|
||||||
|
const mat = loadMaterialDefault()
|
||||||
|
setMaterialTexture(mat, MATERIAL_MAP_DIFFUSE, texture)
|
||||||
|
setModelMaterial(model,0,mat)
|
||||||
|
|
||||||
const mapPosition = new Vector3(-16.0, 0.0, -8.0); // Set model position
|
const mapPosition = new Vector3(-16.0, 0.0, -8.0); // Set model position
|
||||||
|
|
||||||
image = null; // Unload cubesmap image from RAM, already uploaded to VRAM
|
unloadImage(image); // Unload cubesmap image from RAM, already uploaded to VRAM
|
||||||
|
|
||||||
setTargetFPS(60); // Set our game to run at 60 frames-per-second
|
setTargetFPS(60); // Set our game to run at 60 frames-per-second
|
||||||
//--------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------
|
||||||
|
@ -50,7 +53,7 @@ while (!windowShouldClose()) // Detect window close button or ESC key
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
updateCamera(camera, CAMERA_ORBITAL);
|
updateCamera(camera, CAMERA_ORBITAL);
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
|
|
||||||
// Draw
|
// Draw
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
beginDrawing();
|
beginDrawing();
|
||||||
|
@ -77,9 +80,9 @@ while (!windowShouldClose()) // Detect window close button or ESC key
|
||||||
|
|
||||||
// De-Initialization
|
// De-Initialization
|
||||||
//--------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------
|
||||||
cubicmap = null // Unload cubicmap texture
|
unloadTexture(cubicmap);
|
||||||
texture = null // Unload map texture
|
unloadTexture(texture);
|
||||||
model = null // Unload map model
|
unloadModel(model);
|
||||||
|
|
||||||
closeWindow(); // Close window and OpenGL context
|
closeWindow(); // Close window and OpenGL context
|
||||||
//--------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------
|
||||||
|
|
|
@ -23,7 +23,7 @@ const viewCenterLoc = getShaderLocation(shader, "viewCenter");
|
||||||
const runTimeLoc = getShaderLocation(shader, "runTime");
|
const runTimeLoc = getShaderLocation(shader, "runTime");
|
||||||
const resolutionLoc = getShaderLocation(shader, "resolution");
|
const resolutionLoc = getShaderLocation(shader, "resolution");
|
||||||
|
|
||||||
let resolution = new Vector2(getRenderWidth(), getRenderHeight());
|
let resolution = new Vector2(getRenderWidth()*2, getRenderHeight()*2);
|
||||||
setShaderValue(shader, resolutionLoc, resolution, SHADER_UNIFORM_VEC2);
|
setShaderValue(shader, resolutionLoc, resolution, SHADER_UNIFORM_VEC2);
|
||||||
|
|
||||||
let runTime = 0.0;
|
let runTime = 0.0;
|
||||||
|
@ -75,5 +75,6 @@ while (!windowShouldClose()) // Detect window close button or ESC key
|
||||||
|
|
||||||
// De-Initialization
|
// De-Initialization
|
||||||
//--------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------
|
||||||
|
unloadShader(shader)
|
||||||
closeWindow(); // Close window and OpenGL context
|
closeWindow(); // Close window and OpenGL context
|
||||||
//--------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------
|
||||||
|
|
|
@ -0,0 +1,367 @@
|
||||||
|
/******/ (() => { // webpackBootstrap
|
||||||
|
/******/ "use strict";
|
||||||
|
/******/ var __webpack_modules__ = ({
|
||||||
|
|
||||||
|
/***/ "./src/examples.ts":
|
||||||
|
/*!*************************!*\
|
||||||
|
!*** ./src/examples.ts ***!
|
||||||
|
\*************************/
|
||||||
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
||||||
|
|
||||||
|
|
||||||
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
||||||
|
exports.FirstPersonMaze = exports.GameController = void 0;
|
||||||
|
const systems_1 = __webpack_require__(/*! ./systems */ "./src/systems.ts");
|
||||||
|
class GameController extends systems_1.SystemContainer {
|
||||||
|
constructor() {
|
||||||
|
super(...arguments);
|
||||||
|
this.systems = [
|
||||||
|
new BasicWindow(),
|
||||||
|
new FirstPersonMaze()
|
||||||
|
];
|
||||||
|
}
|
||||||
|
load() {
|
||||||
|
super.load();
|
||||||
|
this.currentIndex = 0;
|
||||||
|
this.currentId = this.addSystem(this.systems[this.currentIndex]);
|
||||||
|
}
|
||||||
|
update(dt) {
|
||||||
|
if (isKeyPressed(KEY_RIGHT)) {
|
||||||
|
this.removeSystem(this.currentId);
|
||||||
|
this.currentIndex = (this.currentIndex + 1) % this.systems.length;
|
||||||
|
this.currentId = this.addSystem(this.systems[this.currentIndex]);
|
||||||
|
}
|
||||||
|
super.update(dt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
exports.GameController = GameController;
|
||||||
|
class BasicWindow extends systems_1.SystemBase {
|
||||||
|
draw() {
|
||||||
|
super.draw();
|
||||||
|
drawText("Congrats! You created your first window!", 190, 200, 20, LIGHTGRAY);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
class FirstPersonMaze extends systems_1.SystemBase {
|
||||||
|
load() {
|
||||||
|
super.load();
|
||||||
|
// Define the camera to look into our 3d world
|
||||||
|
this.camera = new Camera3D(new Vector3(0.2, 0.4, 0.2), new Vector3(0.185, 0.4, 0.0), new Vector3(0, 1, 0), 45, CAMERA_PERSPECTIVE);
|
||||||
|
const position = new Vector3(0, 0, 0); // Set model position
|
||||||
|
const imMap = loadImage("assets/cubicmap.png"); // Load cubicmap image (RAM)
|
||||||
|
this.cubicmap = loadTextureFromImage(imMap); // Convert image to texture to display (VRAM)
|
||||||
|
const mesh = genMeshCubicmap(imMap, new Vector3(1.0, 1.0, 1.0));
|
||||||
|
this.model = loadModelFromMesh(mesh);
|
||||||
|
// NOTE: By default each cube is mapped to one part of texture atlas
|
||||||
|
this.texture = loadTexture("assets/cubicmap_atlas.png"); // Load map texture
|
||||||
|
//model.materials[0].maps[MATERIAL_MAP_DIFFUSE].texture = texture; // Set map diffuse texture
|
||||||
|
const mat = loadMaterialDefault();
|
||||||
|
setMaterialTexture(mat, MATERIAL_MAP_DIFFUSE, this.texture);
|
||||||
|
setModelMaterial(this.model, 0, mat);
|
||||||
|
// Get map image data to be used for collision detection
|
||||||
|
this.mapPixels = new Uint8Array(loadImageColors(imMap));
|
||||||
|
unloadImage(imMap); // Unload image from RAM
|
||||||
|
this.mapPosition = new Vector3(-16.0, 0.0, -8.0); // Set model position
|
||||||
|
disableCursor();
|
||||||
|
}
|
||||||
|
update(dt) {
|
||||||
|
super.update(dt);
|
||||||
|
let oldCamPos = this.camera.position; // Store old camera position
|
||||||
|
updateCamera(this.camera, CAMERA_FIRST_PERSON);
|
||||||
|
// Check player collision (we simplify to 2D collision detection)
|
||||||
|
const playerPos = new Vector2(this.camera.position.x, this.camera.position.z);
|
||||||
|
const playerRadius = 0.1; // Collision radius (player is modelled as a cilinder for collision)
|
||||||
|
this.playerCellX = Math.floor(playerPos.x - this.mapPosition.x + 0.5);
|
||||||
|
this.playerCellY = Math.floor(playerPos.y - this.mapPosition.z + 0.5);
|
||||||
|
// Out-of-limits security check
|
||||||
|
if (this.playerCellX < 0)
|
||||||
|
this.playerCellX = 0;
|
||||||
|
else if (this.playerCellX >= this.cubicmap.width)
|
||||||
|
this.playerCellX = this.cubicmap.width - 1;
|
||||||
|
if (this.playerCellY < 0)
|
||||||
|
this.playerCellY = 0;
|
||||||
|
else if (this.playerCellY >= this.cubicmap.height)
|
||||||
|
this.playerCellY = this.cubicmap.height - 1;
|
||||||
|
// Check map collisions using image data and player position
|
||||||
|
// TODO: Improvement: Just check player surrounding cells for collision
|
||||||
|
for (let y = 0; y < this.cubicmap.height; y++) {
|
||||||
|
for (let x = 0; x < this.cubicmap.width; x++) {
|
||||||
|
const pixelValR = this.mapPixels[((y * this.cubicmap.width + x) * 4)];
|
||||||
|
if ((pixelValR == 255) && // Collision: white pixel, only check R channel
|
||||||
|
(checkCollisionCircleRec(playerPos, playerRadius, new Rectangle(this.mapPosition.x - 0.5 + x * 1.0, this.mapPosition.z - 0.5 + y * 1.0, 1.0, 1.0)))) {
|
||||||
|
// Collision detected, reset camera position
|
||||||
|
this.camera.position = oldCamPos;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
draw() {
|
||||||
|
super.draw();
|
||||||
|
beginMode3D(this.camera);
|
||||||
|
drawModel(this.model, this.mapPosition, 1.0, WHITE); // Draw maze map
|
||||||
|
endMode3D();
|
||||||
|
drawTextureEx(this.cubicmap, new Vector2(getScreenWidth() - this.cubicmap.width * 4.0 - 20, 20.0), 0.0, 4.0, WHITE);
|
||||||
|
drawRectangleLines(getScreenWidth() - this.cubicmap.width * 4 - 20, 20, this.cubicmap.width * 4, this.cubicmap.height * 4, GREEN);
|
||||||
|
// Draw player position radar
|
||||||
|
drawRectangle(getScreenWidth() - this.cubicmap.width * 4 - 20 + this.playerCellX * 4, 20 + this.playerCellY * 4, 4, 4, RED);
|
||||||
|
drawFPS(10, 10);
|
||||||
|
}
|
||||||
|
unload() {
|
||||||
|
enableCursor();
|
||||||
|
unloadTexture(this.cubicmap); // Unload cubicmap texture
|
||||||
|
unloadTexture(this.texture); // Unload map texture
|
||||||
|
unloadModel(this.model); // Unload map model
|
||||||
|
super.unload();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
exports.FirstPersonMaze = FirstPersonMaze;
|
||||||
|
|
||||||
|
|
||||||
|
/***/ }),
|
||||||
|
|
||||||
|
/***/ "./src/game.ts":
|
||||||
|
/*!*********************!*\
|
||||||
|
!*** ./src/game.ts ***!
|
||||||
|
\*********************/
|
||||||
|
/***/ ((__unused_webpack_module, exports, __webpack_require__) => {
|
||||||
|
|
||||||
|
|
||||||
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
||||||
|
exports.Game = void 0;
|
||||||
|
const systems_1 = __webpack_require__(/*! ./systems */ "./src/systems.ts");
|
||||||
|
class Game {
|
||||||
|
constructor(width, height, title) {
|
||||||
|
this.width = width;
|
||||||
|
this.height = height;
|
||||||
|
this.title = title;
|
||||||
|
this.clearColor = RAYWHITE;
|
||||||
|
this.systemHost = new systems_1.SystemHost();
|
||||||
|
this.quit = false;
|
||||||
|
}
|
||||||
|
run() {
|
||||||
|
initWindow(this.width, this.height, this.title);
|
||||||
|
setTargetFPS(60);
|
||||||
|
while (!(this.quit = windowShouldClose())) {
|
||||||
|
this.systemHost.loadSystems();
|
||||||
|
this.systemHost.updateSystems();
|
||||||
|
beginDrawing();
|
||||||
|
clearBackground(this.clearColor);
|
||||||
|
this.systemHost.drawSystems();
|
||||||
|
this.systemHost.unloadSystems();
|
||||||
|
endDrawing();
|
||||||
|
}
|
||||||
|
this.systemHost.requestShutdown();
|
||||||
|
closeWindow();
|
||||||
|
}
|
||||||
|
addSystem(system) {
|
||||||
|
return this.systemHost.addSystem(system);
|
||||||
|
}
|
||||||
|
removeSystem(id) {
|
||||||
|
return this.systemHost.removeSystem(id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
exports.Game = Game;
|
||||||
|
|
||||||
|
|
||||||
|
/***/ }),
|
||||||
|
|
||||||
|
/***/ "./src/systems.ts":
|
||||||
|
/*!************************!*\
|
||||||
|
!*** ./src/systems.ts ***!
|
||||||
|
\************************/
|
||||||
|
/***/ ((__unused_webpack_module, exports) => {
|
||||||
|
|
||||||
|
|
||||||
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
||||||
|
exports.SystemHost = exports.SystemContainer = exports.SystemBase = void 0;
|
||||||
|
class SystemBase {
|
||||||
|
constructor() {
|
||||||
|
this.isFinished = false;
|
||||||
|
}
|
||||||
|
load() {
|
||||||
|
this.promise = new Promise((res, rej) => this.complete = res);
|
||||||
|
}
|
||||||
|
unload() {
|
||||||
|
this.complete();
|
||||||
|
}
|
||||||
|
draw() { }
|
||||||
|
update(dt) { }
|
||||||
|
stop() {
|
||||||
|
this.isFinished = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
exports.SystemBase = SystemBase;
|
||||||
|
class SystemContainer extends SystemBase {
|
||||||
|
constructor() {
|
||||||
|
super(...arguments);
|
||||||
|
this.systemHost = new SystemHost();
|
||||||
|
}
|
||||||
|
update(dt) {
|
||||||
|
this.systemHost.loadSystems();
|
||||||
|
this.systemHost.updateSystems();
|
||||||
|
}
|
||||||
|
draw() {
|
||||||
|
this.systemHost.drawSystems();
|
||||||
|
this.systemHost.unloadSystems();
|
||||||
|
}
|
||||||
|
unload() {
|
||||||
|
this.systemHost.requestShutdown();
|
||||||
|
super.unload();
|
||||||
|
}
|
||||||
|
addSystem(system) {
|
||||||
|
return this.systemHost.addSystem(system);
|
||||||
|
}
|
||||||
|
removeSystem(id) {
|
||||||
|
return this.systemHost.removeSystem(id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
exports.SystemContainer = SystemContainer;
|
||||||
|
class SystemHost {
|
||||||
|
constructor() {
|
||||||
|
this.systems = new Map();
|
||||||
|
this.unloadQueue = new Set();
|
||||||
|
this.loadQueue = new Set();
|
||||||
|
this.updateOrder = [];
|
||||||
|
this.updateOrderRev = [];
|
||||||
|
this.systemPrio = 0;
|
||||||
|
}
|
||||||
|
addSystem(system) {
|
||||||
|
const id = this.systemPrio++;
|
||||||
|
this.systems.set(id, system);
|
||||||
|
this.loadQueue.add(id);
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
removeSystem(id) {
|
||||||
|
if (this.systems.has(id)) {
|
||||||
|
this.unloadQueue.add(id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
refreshUpdateOrder() {
|
||||||
|
this.updateOrder = Array.from(this.systems.keys()).sort((a, b) => a - b);
|
||||||
|
this.updateOrderRev = this.updateOrder.reverse();
|
||||||
|
}
|
||||||
|
loadSystems() {
|
||||||
|
if (this.loadQueue.size === 0)
|
||||||
|
return;
|
||||||
|
this.refreshUpdateOrder();
|
||||||
|
for (const id of this.updateOrder) {
|
||||||
|
if (this.loadQueue.has(id))
|
||||||
|
this.systems.get(id)?.load();
|
||||||
|
}
|
||||||
|
this.loadQueue.clear();
|
||||||
|
}
|
||||||
|
unloadSystems() {
|
||||||
|
if (this.unloadQueue.size === 0)
|
||||||
|
return;
|
||||||
|
for (const id of this.updateOrderRev) {
|
||||||
|
if (this.unloadQueue.has(id)) {
|
||||||
|
this.systems.get(id)?.unload();
|
||||||
|
this.systems.delete(id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.refreshUpdateOrder();
|
||||||
|
this.unloadQueue.clear();
|
||||||
|
}
|
||||||
|
updateSystems() {
|
||||||
|
for (const id of this.updateOrder) {
|
||||||
|
this.systems.get(id)?.update(getFrameTime());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
drawSystems() {
|
||||||
|
for (const id of this.updateOrder) {
|
||||||
|
const sys = this.systems.get(id);
|
||||||
|
sys?.draw();
|
||||||
|
if (sys?.isFinished)
|
||||||
|
this.unloadQueue.add(id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
requestShutdown() {
|
||||||
|
for (const id of this.updateOrderRev) {
|
||||||
|
this.systems.get(id)?.unload();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
exports.SystemHost = SystemHost;
|
||||||
|
|
||||||
|
|
||||||
|
/***/ })
|
||||||
|
|
||||||
|
/******/ });
|
||||||
|
/************************************************************************/
|
||||||
|
/******/ // The module cache
|
||||||
|
/******/ var __webpack_module_cache__ = {};
|
||||||
|
/******/
|
||||||
|
/******/ // The require function
|
||||||
|
/******/ function __webpack_require__(moduleId) {
|
||||||
|
/******/ // Check if module is in cache
|
||||||
|
/******/ var cachedModule = __webpack_module_cache__[moduleId];
|
||||||
|
/******/ if (cachedModule !== undefined) {
|
||||||
|
/******/ return cachedModule.exports;
|
||||||
|
/******/ }
|
||||||
|
/******/ // Create a new module (and put it into the cache)
|
||||||
|
/******/ var module = __webpack_module_cache__[moduleId] = {
|
||||||
|
/******/ // no module.id needed
|
||||||
|
/******/ // no module.loaded needed
|
||||||
|
/******/ exports: {}
|
||||||
|
/******/ };
|
||||||
|
/******/
|
||||||
|
/******/ // Execute the module function
|
||||||
|
/******/ __webpack_modules__[moduleId](module, module.exports, __webpack_require__);
|
||||||
|
/******/
|
||||||
|
/******/ // Return the exports of the module
|
||||||
|
/******/ return module.exports;
|
||||||
|
/******/ }
|
||||||
|
/******/
|
||||||
|
/************************************************************************/
|
||||||
|
var __webpack_exports__ = {};
|
||||||
|
// This entry need to be wrapped in an IIFE because it need to be isolated against other modules in the chunk.
|
||||||
|
(() => {
|
||||||
|
var exports = __webpack_exports__;
|
||||||
|
/*!**********************!*\
|
||||||
|
!*** ./src/index.ts ***!
|
||||||
|
\**********************/
|
||||||
|
|
||||||
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
||||||
|
const examples_1 = __webpack_require__(/*! ./examples */ "./src/examples.ts");
|
||||||
|
const game_1 = __webpack_require__(/*! ./game */ "./src/game.ts");
|
||||||
|
const systems_1 = __webpack_require__(/*! ./systems */ "./src/systems.ts");
|
||||||
|
class MySys extends systems_1.SystemBase {
|
||||||
|
load() {
|
||||||
|
super.load();
|
||||||
|
this.mesh = new Mesh();
|
||||||
|
this.mesh.vertexCount = 3;
|
||||||
|
this.mesh.triangleCount = 1;
|
||||||
|
const v1 = new Vector3(400, 0, 0);
|
||||||
|
const v2 = new Vector3(0, 450, 0);
|
||||||
|
const v3 = new Vector3(800, 450, 0);
|
||||||
|
this.mesh.indices = new Uint16Array([0, 1, 2]).buffer;
|
||||||
|
this.mesh.vertices = new Float32Array([
|
||||||
|
v1.x, v1.y, v1.z,
|
||||||
|
v2.x, v2.y, v2.z,
|
||||||
|
v3.x, v3.y, v3.z
|
||||||
|
]).buffer;
|
||||||
|
// If your forget to upload to GPU draw will segfault
|
||||||
|
uploadMesh(this.mesh, false);
|
||||||
|
this.material = loadMaterialDefault();
|
||||||
|
this.matrix = matrixIdentity();
|
||||||
|
}
|
||||||
|
update(dt) {
|
||||||
|
this.matrix = matrixRotateZ(getTime());
|
||||||
|
}
|
||||||
|
draw() {
|
||||||
|
drawMesh(this.mesh, this.material, this.matrix);
|
||||||
|
}
|
||||||
|
unload() {
|
||||||
|
super.unload();
|
||||||
|
unloadMaterial(this.material);
|
||||||
|
unloadMesh(this.mesh);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const game = new game_1.Game(800, 450, "Typescript Game");
|
||||||
|
game.addSystem(new examples_1.GameController());
|
||||||
|
game.addSystem(new MySys());
|
||||||
|
game.run();
|
||||||
|
|
||||||
|
})();
|
||||||
|
|
||||||
|
/******/ })()
|
||||||
|
;
|
|
@ -0,0 +1 @@
|
||||||
|
node_modules/
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,20 @@
|
||||||
|
{
|
||||||
|
"name": "bindings",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "",
|
||||||
|
"scripts": {
|
||||||
|
"test": "echo \"Error: no test specified\" && exit 1",
|
||||||
|
"build": "webpack --config webpack.config.js",
|
||||||
|
"watch": "webpack --watch --config webpack.config.js --mode development"
|
||||||
|
},
|
||||||
|
"keywords": [],
|
||||||
|
"author": "",
|
||||||
|
"license": "ISC",
|
||||||
|
"devDependencies": {
|
||||||
|
"ts-loader": "^9.4.2",
|
||||||
|
"ts-node": "^10.9.1",
|
||||||
|
"typescript": "^5.0.4",
|
||||||
|
"webpack": "^5.82.0",
|
||||||
|
"webpack-cli": "^5.0.2"
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,135 @@
|
||||||
|
import { SystemBase, SystemContainer } from "./systems";
|
||||||
|
|
||||||
|
export class GameController extends SystemContainer {
|
||||||
|
private currentId!: number
|
||||||
|
private currentIndex!: number
|
||||||
|
private systems = [
|
||||||
|
new BasicWindow(),
|
||||||
|
new FirstPersonMaze()
|
||||||
|
]
|
||||||
|
|
||||||
|
load(): void {
|
||||||
|
super.load()
|
||||||
|
this.currentIndex = 0
|
||||||
|
this.currentId = this.addSystem(this.systems[this.currentIndex])
|
||||||
|
}
|
||||||
|
|
||||||
|
update(dt: number): void {
|
||||||
|
if(isKeyPressed(KEY_RIGHT)){
|
||||||
|
this.removeSystem(this.currentId)
|
||||||
|
this.currentIndex = (this.currentIndex+1)%this.systems.length
|
||||||
|
this.currentId = this.addSystem(this.systems[this.currentIndex])
|
||||||
|
}
|
||||||
|
super.update(dt)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class BasicWindow extends SystemBase {
|
||||||
|
draw(): void {
|
||||||
|
super.draw()
|
||||||
|
drawText("Congrats! You created your first window!", 190, 200, 20, LIGHTGRAY);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class FirstPersonMaze extends SystemBase {
|
||||||
|
|
||||||
|
private camera!: Camera3D;
|
||||||
|
private playerCellX!: number;
|
||||||
|
private playerCellY!: number;
|
||||||
|
private cubicmap!: Texture;
|
||||||
|
private texture!: Texture;
|
||||||
|
private mapPixels!: Uint8Array;
|
||||||
|
private model!: Model;
|
||||||
|
private mapPosition!: Vector3;
|
||||||
|
|
||||||
|
load(): void {
|
||||||
|
super.load()
|
||||||
|
// Define the camera to look into our 3d world
|
||||||
|
this.camera = new Camera3D(new Vector3(0.2, 0.4, 0.2), new Vector3(0.185, 0.4, 0.0), new Vector3(0, 1, 0), 45, CAMERA_PERSPECTIVE);
|
||||||
|
const position = new Vector3(0, 0, 0); // Set model position
|
||||||
|
|
||||||
|
const imMap = loadImage("assets/cubicmap.png"); // Load cubicmap image (RAM)
|
||||||
|
this.cubicmap = loadTextureFromImage(imMap); // Convert image to texture to display (VRAM)
|
||||||
|
const mesh = genMeshCubicmap(imMap, new Vector3(1.0, 1.0, 1.0));
|
||||||
|
this.model = loadModelFromMesh(mesh);
|
||||||
|
|
||||||
|
// NOTE: By default each cube is mapped to one part of texture atlas
|
||||||
|
this.texture = loadTexture("assets/cubicmap_atlas.png"); // Load map texture
|
||||||
|
|
||||||
|
//model.materials[0].maps[MATERIAL_MAP_DIFFUSE].texture = texture; // Set map diffuse texture
|
||||||
|
const mat = loadMaterialDefault();
|
||||||
|
setMaterialTexture(mat, MATERIAL_MAP_DIFFUSE, this.texture);
|
||||||
|
setModelMaterial(this.model, 0, mat);
|
||||||
|
|
||||||
|
// Get map image data to be used for collision detection
|
||||||
|
this.mapPixels = new Uint8Array(loadImageColors(imMap));
|
||||||
|
unloadImage(imMap); // Unload image from RAM
|
||||||
|
|
||||||
|
this.mapPosition = new Vector3(-16.0, 0.0, -8.0); // Set model position
|
||||||
|
|
||||||
|
disableCursor();
|
||||||
|
}
|
||||||
|
|
||||||
|
update(dt: number): void {
|
||||||
|
super.update(dt);
|
||||||
|
let oldCamPos = this.camera.position; // Store old camera position
|
||||||
|
|
||||||
|
updateCamera(this.camera, CAMERA_FIRST_PERSON);
|
||||||
|
|
||||||
|
// Check player collision (we simplify to 2D collision detection)
|
||||||
|
const playerPos = new Vector2(this.camera.position.x, this.camera.position.z);
|
||||||
|
const playerRadius = 0.1; // Collision radius (player is modelled as a cilinder for collision)
|
||||||
|
|
||||||
|
this.playerCellX = Math.floor(playerPos.x - this.mapPosition.x + 0.5);
|
||||||
|
this.playerCellY = Math.floor(playerPos.y - this.mapPosition.z + 0.5);
|
||||||
|
|
||||||
|
// Out-of-limits security check
|
||||||
|
if (this.playerCellX < 0)
|
||||||
|
this.playerCellX = 0;
|
||||||
|
else if (this.playerCellX >= this.cubicmap.width)
|
||||||
|
this.playerCellX = this.cubicmap.width - 1;
|
||||||
|
|
||||||
|
if (this.playerCellY < 0)
|
||||||
|
this.playerCellY = 0;
|
||||||
|
else if (this.playerCellY >= this.cubicmap.height)
|
||||||
|
this.playerCellY = this.cubicmap.height - 1;
|
||||||
|
|
||||||
|
// Check map collisions using image data and player position
|
||||||
|
// TODO: Improvement: Just check player surrounding cells for collision
|
||||||
|
for (let y = 0; y < this.cubicmap.height; y++) {
|
||||||
|
for (let x = 0; x < this.cubicmap.width; x++) {
|
||||||
|
const pixelValR = this.mapPixels[((y * this.cubicmap.width + x) * 4)];
|
||||||
|
if ((pixelValR == 255) && // Collision: white pixel, only check R channel
|
||||||
|
(checkCollisionCircleRec(playerPos, playerRadius, new Rectangle(
|
||||||
|
this.mapPosition.x - 0.5 + x * 1.0,
|
||||||
|
this.mapPosition.z - 0.5 + y * 1.0, 1.0, 1.0)))) {
|
||||||
|
// Collision detected, reset camera position
|
||||||
|
this.camera.position = oldCamPos;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
draw(): void {
|
||||||
|
super.draw()
|
||||||
|
beginMode3D(this.camera);
|
||||||
|
drawModel(this.model, this.mapPosition, 1.0, WHITE); // Draw maze map
|
||||||
|
endMode3D();
|
||||||
|
|
||||||
|
drawTextureEx(this.cubicmap, new Vector2(getScreenWidth() - this.cubicmap.width * 4.0 - 20, 20.0), 0.0, 4.0, WHITE);
|
||||||
|
drawRectangleLines(getScreenWidth() - this.cubicmap.width * 4 - 20, 20, this.cubicmap.width * 4, this.cubicmap.height * 4, GREEN);
|
||||||
|
|
||||||
|
// Draw player position radar
|
||||||
|
drawRectangle(getScreenWidth() - this.cubicmap.width * 4 - 20 + this.playerCellX * 4, 20 + this.playerCellY * 4, 4, 4, RED);
|
||||||
|
|
||||||
|
drawFPS(10, 10);
|
||||||
|
}
|
||||||
|
|
||||||
|
unload(): void {
|
||||||
|
enableCursor();
|
||||||
|
unloadTexture(this.cubicmap); // Unload cubicmap texture
|
||||||
|
unloadTexture(this.texture); // Unload map texture
|
||||||
|
unloadModel(this.model); // Unload map model
|
||||||
|
super.unload()
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,38 @@
|
||||||
|
import { System, SystemHost } from "./systems"
|
||||||
|
|
||||||
|
export class Game {
|
||||||
|
public clearColor = RAYWHITE
|
||||||
|
private systemHost = new SystemHost()
|
||||||
|
private quit = false
|
||||||
|
|
||||||
|
constructor(public readonly width: number,
|
||||||
|
public readonly height: number,
|
||||||
|
public readonly title: string){
|
||||||
|
}
|
||||||
|
|
||||||
|
public run(){
|
||||||
|
initWindow(this.width,this.height,this.title)
|
||||||
|
setTargetFPS(60)
|
||||||
|
while(!(this.quit = windowShouldClose())){
|
||||||
|
this.systemHost.loadSystems()
|
||||||
|
this.systemHost.updateSystems()
|
||||||
|
beginDrawing()
|
||||||
|
clearBackground(this.clearColor)
|
||||||
|
this.systemHost.drawSystems()
|
||||||
|
this.systemHost.unloadSystems()
|
||||||
|
endDrawing()
|
||||||
|
}
|
||||||
|
this.systemHost.requestShutdown()
|
||||||
|
closeWindow()
|
||||||
|
}
|
||||||
|
|
||||||
|
addSystem(system: System){
|
||||||
|
return this.systemHost.addSystem(system)
|
||||||
|
}
|
||||||
|
|
||||||
|
removeSystem(id: number){
|
||||||
|
return this.systemHost.removeSystem(id)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,46 @@
|
||||||
|
import { GameController } from "./examples";
|
||||||
|
import { Game } from "./game";
|
||||||
|
import { SystemBase, SystemContainer } from "./systems";
|
||||||
|
|
||||||
|
class MySys extends SystemBase {
|
||||||
|
mesh!: Mesh;
|
||||||
|
material!: Material
|
||||||
|
matrix!: Matrix
|
||||||
|
|
||||||
|
load(): void {
|
||||||
|
super.load()
|
||||||
|
this.mesh = new Mesh()
|
||||||
|
this.mesh.vertexCount = 3
|
||||||
|
this.mesh.triangleCount = 1
|
||||||
|
const v1 = new Vector3(400, 0, 0)
|
||||||
|
const v2 = new Vector3(0, 450, 0 )
|
||||||
|
const v3 = new Vector3(800, 450, 0)
|
||||||
|
this.mesh.indices = new Uint16Array([0,1,2]).buffer
|
||||||
|
this.mesh.vertices = new Float32Array([
|
||||||
|
v1.x, v1.y, v1.z,
|
||||||
|
v2.x, v2.y, v2.z,
|
||||||
|
v3.x, v3.y, v3.z
|
||||||
|
]).buffer
|
||||||
|
// If your forget to upload to GPU draw will segfault
|
||||||
|
uploadMesh(this.mesh, false)
|
||||||
|
this.material = loadMaterialDefault()
|
||||||
|
this.matrix = matrixIdentity()
|
||||||
|
}
|
||||||
|
update(dt: number): void {
|
||||||
|
this.matrix = matrixRotateZ(getTime())
|
||||||
|
}
|
||||||
|
draw(): void {
|
||||||
|
drawMesh(this.mesh, this.material, this.matrix)
|
||||||
|
}
|
||||||
|
unload(): void {
|
||||||
|
super.unload()
|
||||||
|
unloadMaterial(this.material)
|
||||||
|
unloadMesh(this.mesh)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const game = new Game(800,450,"Typescript Game")
|
||||||
|
game.addSystem(new GameController())
|
||||||
|
game.addSystem(new MySys())
|
||||||
|
game.run()
|
|
@ -0,0 +1,122 @@
|
||||||
|
export interface System {
|
||||||
|
isFinished: boolean;
|
||||||
|
load(): void;
|
||||||
|
unload(): void;
|
||||||
|
draw(): void;
|
||||||
|
update(dt: number): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export abstract class SystemBase implements System {
|
||||||
|
|
||||||
|
public promise!: Promise<void>
|
||||||
|
private complete!: () => void
|
||||||
|
public isFinished = false
|
||||||
|
|
||||||
|
load(): void {
|
||||||
|
this.promise = new Promise((res,rej) => this.complete = res)
|
||||||
|
}
|
||||||
|
|
||||||
|
unload(): void {
|
||||||
|
this.complete()
|
||||||
|
}
|
||||||
|
draw(): void {}
|
||||||
|
update(dt: number): void {}
|
||||||
|
stop(){
|
||||||
|
this.isFinished = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class SystemContainer extends SystemBase {
|
||||||
|
private systemHost = new SystemHost()
|
||||||
|
|
||||||
|
update(dt: number): void {
|
||||||
|
this.systemHost.loadSystems()
|
||||||
|
this.systemHost.updateSystems()
|
||||||
|
}
|
||||||
|
|
||||||
|
draw(): void {
|
||||||
|
this.systemHost.drawSystems()
|
||||||
|
this.systemHost.unloadSystems()
|
||||||
|
}
|
||||||
|
|
||||||
|
unload(): void {
|
||||||
|
this.systemHost.requestShutdown()
|
||||||
|
super.unload()
|
||||||
|
}
|
||||||
|
|
||||||
|
addSystem(system: System){
|
||||||
|
return this.systemHost.addSystem(system)
|
||||||
|
}
|
||||||
|
|
||||||
|
removeSystem(id: number){
|
||||||
|
return this.systemHost.removeSystem(id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class SystemHost {
|
||||||
|
private systems = new Map<number,System>()
|
||||||
|
private unloadQueue = new Set<number>()
|
||||||
|
private loadQueue = new Set<number>()
|
||||||
|
private updateOrder: number[] = []
|
||||||
|
private updateOrderRev: number[] = []
|
||||||
|
private systemPrio = 0
|
||||||
|
|
||||||
|
public addSystem(system: System){
|
||||||
|
const id = this.systemPrio++
|
||||||
|
this.systems.set(id, system)
|
||||||
|
this.loadQueue.add(id)
|
||||||
|
return id
|
||||||
|
}
|
||||||
|
|
||||||
|
public removeSystem(id: number){
|
||||||
|
if(this.systems.has(id)) {
|
||||||
|
this.unloadQueue.add(id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private refreshUpdateOrder(){
|
||||||
|
this.updateOrder = Array.from(this.systems.keys()).sort((a, b) => a - b);
|
||||||
|
this.updateOrderRev = this.updateOrder.reverse()
|
||||||
|
}
|
||||||
|
|
||||||
|
public loadSystems(){
|
||||||
|
if(this.loadQueue.size === 0) return
|
||||||
|
this.refreshUpdateOrder()
|
||||||
|
for (const id of this.updateOrder) {
|
||||||
|
if(this.loadQueue.has(id)) this.systems.get(id)?.load()
|
||||||
|
}
|
||||||
|
this.loadQueue.clear()
|
||||||
|
}
|
||||||
|
|
||||||
|
public unloadSystems(){
|
||||||
|
if(this.unloadQueue.size === 0) return
|
||||||
|
for (const id of this.updateOrderRev) {
|
||||||
|
if(this.unloadQueue.has(id)) {
|
||||||
|
this.systems.get(id)?.unload()
|
||||||
|
this.systems.delete(id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.refreshUpdateOrder()
|
||||||
|
this.unloadQueue.clear()
|
||||||
|
}
|
||||||
|
|
||||||
|
public updateSystems(){
|
||||||
|
for (const id of this.updateOrder) {
|
||||||
|
this.systems.get(id)?.update(getFrameTime())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public drawSystems(){
|
||||||
|
for (const id of this.updateOrder) {
|
||||||
|
const sys = this.systems.get(id)
|
||||||
|
sys?.draw()
|
||||||
|
if(sys?.isFinished) this.unloadQueue.add(id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public requestShutdown(){
|
||||||
|
for (const id of this.updateOrderRev) {
|
||||||
|
this.systems.get(id)?.unload()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,13 @@
|
||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"target": "es2020",
|
||||||
|
"module": "commonjs",
|
||||||
|
"esModuleInterop": true,
|
||||||
|
"resolveJsonModule": true,
|
||||||
|
"strict": true,
|
||||||
|
"types": [
|
||||||
|
"../lib.raylib"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,24 @@
|
||||||
|
const path = require('path');
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
entry: './src/index.ts',
|
||||||
|
devtool: false,
|
||||||
|
target: "node",
|
||||||
|
mode: 'production',
|
||||||
|
module: {
|
||||||
|
rules: [
|
||||||
|
{
|
||||||
|
test: /\.tsx?$/,
|
||||||
|
use: 'ts-loader',
|
||||||
|
exclude: /node_modules/,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
resolve: {
|
||||||
|
extensions: ['.tsx', '.ts', '.js'],
|
||||||
|
},
|
||||||
|
output: {
|
||||||
|
filename: 'ts_game.js',
|
||||||
|
path: path.resolve(__dirname, '..'),
|
||||||
|
},
|
||||||
|
};
|
|
@ -20,6 +20,7 @@ class ApiFunction {
|
||||||
get argc() { return this.api.params?.length || 0; }
|
get argc() { return this.api.params?.length || 0; }
|
||||||
get params() { return this.api.params || []; }
|
get params() { return this.api.params || []; }
|
||||||
get returnType() { return this.api.returnType; }
|
get returnType() { return this.api.returnType; }
|
||||||
|
set returnType(v) { this.api.returnType = v; }
|
||||||
get description() { return this.api.description; }
|
get description() { return this.api.description; }
|
||||||
}
|
}
|
||||||
exports.ApiFunction = ApiFunction;
|
exports.ApiFunction = ApiFunction;
|
||||||
|
@ -378,6 +379,19 @@ class GenericQuickJsGenerator extends generation_1.GenericCodeGenerator {
|
||||||
}
|
}
|
||||||
jsToC(type, name, src, classIds = {}, supressDeclaration = false) {
|
jsToC(type, name, src, classIds = {}, supressDeclaration = false) {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
|
// Array Buffer
|
||||||
|
case "const void *":
|
||||||
|
case "void *":
|
||||||
|
case "float *":
|
||||||
|
case "unsigned short *":
|
||||||
|
case "unsigned char *":
|
||||||
|
this.declare(name + "_size", "size_t");
|
||||||
|
this.declare(name + "_js", "void *", false, `(void *)JS_GetArrayBuffer(ctx, &${name}_size, ${src})`);
|
||||||
|
this.if(name + "_js == NULL").returnExp("JS_EXCEPTION");
|
||||||
|
this.declare(name, type, false, "malloc(" + name + "_size)");
|
||||||
|
this.call("memcpy", ["(void *)" + name, "(const void *)" + name + "_js", name + "_size"]);
|
||||||
|
break;
|
||||||
|
// String
|
||||||
case "const char *":
|
case "const char *":
|
||||||
case "char *":
|
case "char *":
|
||||||
if (!supressDeclaration)
|
if (!supressDeclaration)
|
||||||
|
@ -422,6 +436,7 @@ class GenericQuickJsGenerator extends generation_1.GenericCodeGenerator {
|
||||||
else
|
else
|
||||||
this.statement(`${name} = JS_ToBool(ctx, ${src})`);
|
this.statement(`${name} = JS_ToBool(ctx, ${src})`);
|
||||||
break;
|
break;
|
||||||
|
// Structs / Struct *
|
||||||
default:
|
default:
|
||||||
const isConst = type.startsWith('const');
|
const isConst = type.startsWith('const');
|
||||||
const isPointer = type.endsWith(' *');
|
const isPointer = type.endsWith(' *');
|
||||||
|
@ -474,9 +489,17 @@ class GenericQuickJsGenerator extends generation_1.GenericCodeGenerator {
|
||||||
}
|
}
|
||||||
jsCleanUpParameter(type, name) {
|
jsCleanUpParameter(type, name) {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
|
case "char *":
|
||||||
case "const char *":
|
case "const char *":
|
||||||
this.statement(`JS_FreeCString(ctx, ${name})`);
|
this.statement(`JS_FreeCString(ctx, ${name})`);
|
||||||
break;
|
break;
|
||||||
|
case "const void *":
|
||||||
|
case "void *":
|
||||||
|
case "float *":
|
||||||
|
case "unsigned short *":
|
||||||
|
case "unsigned char *":
|
||||||
|
this.statement(`free((void *)${name})`);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -511,7 +534,7 @@ class GenericQuickJsGenerator extends generation_1.GenericCodeGenerator {
|
||||||
const body = this.function(`js_${structName}_finalizer`, "void", args, true);
|
const body = this.function(`js_${structName}_finalizer`, "void", args, true);
|
||||||
body.statement(`${structName}* ptr = JS_GetOpaque(val, ${classId})`);
|
body.statement(`${structName}* ptr = JS_GetOpaque(val, ${classId})`);
|
||||||
body.if("ptr", cond => {
|
body.if("ptr", cond => {
|
||||||
//cond.call("TraceLog", ["LOG_INFO",`"Finalize ${structName}"`])
|
//cond.call("TraceLog", ["LOG_INFO",`"Finalize ${structName} %p"`,"ptr"])
|
||||||
if (onFinalize)
|
if (onFinalize)
|
||||||
onFinalize(cond, "ptr");
|
onFinalize(cond, "ptr");
|
||||||
cond.call("js_free_rt", ["rt", "ptr"]);
|
cond.call("js_free_rt", ["rt", "ptr"]);
|
||||||
|
@ -534,9 +557,6 @@ class GenericQuickJsGenerator extends generation_1.GenericCodeGenerator {
|
||||||
const args = [{ type: "JSContext*", name: "ctx" }, { type: "JSValueConst", name: "this_val" }];
|
const args = [{ type: "JSContext*", name: "ctx" }, { type: "JSValueConst", name: "this_val" }];
|
||||||
const fun = this.function(`js_${structName}_get_${field}`, "JSValue", args, true);
|
const fun = this.function(`js_${structName}_get_${field}`, "JSValue", args, true);
|
||||||
fun.declare("ptr", structName + "*", false, `JS_GetOpaque2(ctx, this_val, ${classId})`);
|
fun.declare("ptr", structName + "*", false, `JS_GetOpaque2(ctx, this_val, ${classId})`);
|
||||||
fun.if("!ptr", cond => {
|
|
||||||
cond.returnExp("JS_EXCEPTION");
|
|
||||||
});
|
|
||||||
fun.declare(field, type, false, "ptr->" + field);
|
fun.declare(field, type, false, "ptr->" + field);
|
||||||
fun.jsToJs(type, "ret", field, classIds);
|
fun.jsToJs(type, "ret", field, classIds);
|
||||||
fun.returnExp("ret");
|
fun.returnExp("ret");
|
||||||
|
@ -546,9 +566,6 @@ class GenericQuickJsGenerator extends generation_1.GenericCodeGenerator {
|
||||||
const args = [{ type: "JSContext*", name: "ctx" }, { type: "JSValueConst", name: "this_val" }, { type: "JSValueConst", name: "v" }];
|
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);
|
const fun = this.function(`js_${structName}_set_${field}`, "JSValue", args, true);
|
||||||
fun.declare("ptr", structName + "*", false, `JS_GetOpaque2(ctx, this_val, ${classId})`);
|
fun.declare("ptr", structName + "*", false, `JS_GetOpaque2(ctx, this_val, ${classId})`);
|
||||||
fun.if("!ptr", cond => {
|
|
||||||
cond.returnExp("JS_EXCEPTION");
|
|
||||||
});
|
|
||||||
fun.jsToC(type, "value", "v", classIds);
|
fun.jsToC(type, "value", "v", classIds);
|
||||||
fun.statement("ptr->" + field + " = value");
|
fun.statement("ptr->" + field + " = value");
|
||||||
fun.returnExp("JS_UNDEFINED");
|
fun.returnExp("JS_UNDEFINED");
|
||||||
|
@ -667,8 +684,8 @@ class RayLibHeader extends quickjs_1.QuickJsHeader {
|
||||||
classFuncList.jsPropStringDef("[Symbol.toStringTag]", struct.name);
|
classFuncList.jsPropStringDef("[Symbol.toStringTag]", struct.name);
|
||||||
const classDecl = this.structs.jsClassDeclaration(struct.name, classId, finalizer.getTag("_name"), classFuncList.getTag("_name"));
|
const classDecl = this.structs.jsClassDeclaration(struct.name, classId, finalizer.getTag("_name"), classFuncList.getTag("_name"));
|
||||||
this.moduleInit.call(classDecl.getTag("_name"), ["ctx", "m"]);
|
this.moduleInit.call(classDecl.getTag("_name"), ["ctx", "m"]);
|
||||||
if (options?.createConstructor) {
|
if (options?.createConstructor || options?.createEmptyConstructor) {
|
||||||
const body = this.functions.jsStructConstructor(struct.name, struct.fields, classId, this.structLookup);
|
const body = this.functions.jsStructConstructor(struct.name, options?.createEmptyConstructor ? [] : struct.fields, classId, this.structLookup);
|
||||||
this.moduleInit.statement(`JSValue ${struct.name}_constr = JS_NewCFunction2(ctx, ${body.getTag("_name")},"${struct.name})", ${struct.fields.length}, JS_CFUNC_constructor_or_func, 0)`);
|
this.moduleInit.statement(`JSValue ${struct.name}_constr = JS_NewCFunction2(ctx, ${body.getTag("_name")},"${struct.name})", ${struct.fields.length}, JS_CFUNC_constructor_or_func, 0)`);
|
||||||
this.moduleInit.call("JS_SetModuleExport", ["ctx", "m", `"${struct.name}"`, struct.name + "_constr"]);
|
this.moduleInit.call("JS_SetModuleExport", ["ctx", "m", `"${struct.name}"`, struct.name + "_constr"]);
|
||||||
this.moduleEntry.call("JS_AddModuleExport", ["ctx", "m", '"' + struct.name + '"']);
|
this.moduleEntry.call("JS_AddModuleExport", ["ctx", "m", '"' + struct.name + '"']);
|
||||||
|
@ -734,7 +751,7 @@ class TypeScriptDeclaration {
|
||||||
addStruct(api, options) {
|
addStruct(api, options) {
|
||||||
var fields = api.fields.filter(x => !!(options.properties || {})[x.name]).map(x => ({ name: x.name, description: x.description, type: this.toJsType(x.type) }));
|
var fields = api.fields.filter(x => !!(options.properties || {})[x.name]).map(x => ({ name: x.name, description: x.description, type: this.toJsType(x.type) }));
|
||||||
this.structs.tsDeclareInterface(api.name, fields);
|
this.structs.tsDeclareInterface(api.name, fields);
|
||||||
this.structs.tsDeclareType(api.name, !!options.createConstructor, fields);
|
this.structs.tsDeclareType(api.name, !!(options.createConstructor || options.createEmptyConstructor), options.createEmptyConstructor ? [] : fields);
|
||||||
}
|
}
|
||||||
toJsType(type) {
|
toJsType(type) {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
|
@ -745,6 +762,10 @@ class TypeScriptDeclaration {
|
||||||
case "float":
|
case "float":
|
||||||
case "double":
|
case "double":
|
||||||
return "number";
|
return "number";
|
||||||
|
case "unsigned char *":
|
||||||
|
case "unsigned short *":
|
||||||
|
case "float *":
|
||||||
|
return "ArrayBuffer";
|
||||||
case "bool":
|
case "bool":
|
||||||
return "boolean";
|
return "boolean";
|
||||||
case "const char *":
|
case "const char *":
|
||||||
|
@ -754,14 +775,19 @@ class TypeScriptDeclaration {
|
||||||
case "const void *":
|
case "const void *":
|
||||||
return "any";
|
return "any";
|
||||||
case "Camera":
|
case "Camera":
|
||||||
|
case "Camera *":
|
||||||
return "Camera3D";
|
return "Camera3D";
|
||||||
case "Texture2D":
|
case "Texture2D":
|
||||||
|
case "Texture2D *":
|
||||||
case "TextureCubemap":
|
case "TextureCubemap":
|
||||||
return "Texture";
|
return "Texture";
|
||||||
|
case "RenderTexture2D":
|
||||||
|
case "RenderTexture2D *":
|
||||||
|
return "RenderTexture";
|
||||||
case "Quaternion":
|
case "Quaternion":
|
||||||
return "Vector4";
|
return "Vector4";
|
||||||
default:
|
default:
|
||||||
return type.replace(" *", "");
|
return type.replace(" *", "").replace("const ", "");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
writeTo(filename) {
|
writeTo(filename) {
|
||||||
|
@ -891,6 +917,12 @@ function main() {
|
||||||
const mathApi = parseMathHeader();
|
const mathApi = parseMathHeader();
|
||||||
(0, fs_1.writeFileSync)("bindings/raylib_math_api.json", JSON.stringify(mathApi));
|
(0, fs_1.writeFileSync)("bindings/raylib_math_api.json", JSON.stringify(mathApi));
|
||||||
const api = JSON.parse((0, fs_1.readFileSync)("thirdparty/raylib/parser/output/raylib_api.json", 'utf8'));
|
const api = JSON.parse((0, fs_1.readFileSync)("thirdparty/raylib/parser/output/raylib_api.json", 'utf8'));
|
||||||
|
api.functions.push({
|
||||||
|
name: "SetModelMaterial",
|
||||||
|
description: "Replace material in slot materialIndex",
|
||||||
|
returnType: "void",
|
||||||
|
params: [{ type: "Model *", name: "model" }, { type: "int", name: "materialIndex" }, { type: "Material", name: "material" }]
|
||||||
|
});
|
||||||
mathApi.forEach(x => api.functions.push(x));
|
mathApi.forEach(x => api.functions.push(x));
|
||||||
const apiDesc = new api_1.ApiDescription(api);
|
const apiDesc = new api_1.ApiDescription(api);
|
||||||
const core = new raylib_header_1.RayLibHeader("raylib_core", apiDesc);
|
const core = new raylib_header_1.RayLibHeader("raylib_core", apiDesc);
|
||||||
|
@ -979,6 +1011,17 @@ function main() {
|
||||||
properties: {},
|
properties: {},
|
||||||
createConstructor: false
|
createConstructor: false
|
||||||
});
|
});
|
||||||
|
core.addApiStructByName("NPatchInfo", {
|
||||||
|
properties: {
|
||||||
|
source: { get: true, set: true },
|
||||||
|
left: { get: true, set: true },
|
||||||
|
top: { get: true, set: true },
|
||||||
|
right: { get: true, set: true },
|
||||||
|
bottom: { get: true, set: true },
|
||||||
|
layout: { get: true, set: true },
|
||||||
|
},
|
||||||
|
createConstructor: true
|
||||||
|
});
|
||||||
core.addApiStructByName("Image", {
|
core.addApiStructByName("Image", {
|
||||||
properties: {
|
properties: {
|
||||||
width: { get: true },
|
width: { get: true },
|
||||||
|
@ -986,7 +1029,7 @@ function main() {
|
||||||
mipmaps: { get: true },
|
mipmaps: { get: true },
|
||||||
format: { get: true }
|
format: { get: true }
|
||||||
},
|
},
|
||||||
destructor: "UnloadImage"
|
//destructor: "UnloadImage"
|
||||||
});
|
});
|
||||||
core.addApiStructByName("Wave", {
|
core.addApiStructByName("Wave", {
|
||||||
properties: {
|
properties: {
|
||||||
|
@ -995,45 +1038,79 @@ function main() {
|
||||||
sampleSize: { get: true },
|
sampleSize: { get: true },
|
||||||
channels: { get: true }
|
channels: { get: true }
|
||||||
},
|
},
|
||||||
destructor: "UnloadWave"
|
//destructor: "UnloadWave"
|
||||||
});
|
});
|
||||||
core.addApiStructByName("Sound", {
|
core.addApiStructByName("Sound", {
|
||||||
properties: {
|
properties: {
|
||||||
frameCount: { get: true }
|
frameCount: { get: true }
|
||||||
},
|
},
|
||||||
destructor: "UnloadSound"
|
//destructor: "UnloadSound"
|
||||||
});
|
});
|
||||||
core.addApiStructByName("Music", {
|
core.addApiStructByName("Music", {
|
||||||
properties: {
|
properties: {
|
||||||
frameCount: { get: true },
|
frameCount: { get: true },
|
||||||
looping: { get: true, set: true }
|
looping: { get: true, set: true }
|
||||||
},
|
},
|
||||||
destructor: "UnloadMusicStream"
|
//destructor: "UnloadMusicStream"
|
||||||
});
|
});
|
||||||
core.addApiStructByName("Model", {
|
core.addApiStructByName("Model", {
|
||||||
properties: {},
|
properties: {},
|
||||||
destructor: "UnloadModel"
|
//destructor: "UnloadModel"
|
||||||
});
|
});
|
||||||
core.addApiStructByName("Mesh", {
|
core.addApiStructByName("Mesh", {
|
||||||
properties: {},
|
properties: {
|
||||||
destructor: "UnloadMesh"
|
vertexCount: { get: true, set: true },
|
||||||
|
triangleCount: { get: true, set: true },
|
||||||
|
// TODO: Free previous pointers before overwriting
|
||||||
|
vertices: { set: true },
|
||||||
|
texcoords: { set: true },
|
||||||
|
texcoords2: { set: true },
|
||||||
|
normals: { set: true },
|
||||||
|
tangents: { set: true },
|
||||||
|
colors: { set: true },
|
||||||
|
indices: { set: true },
|
||||||
|
animVertices: { set: true },
|
||||||
|
animNormals: { set: true },
|
||||||
|
boneIds: { set: true },
|
||||||
|
boneWeights: { set: true },
|
||||||
|
},
|
||||||
|
createEmptyConstructor: true
|
||||||
|
//destructor: "UnloadMesh"
|
||||||
});
|
});
|
||||||
core.addApiStructByName("Shader", {
|
core.addApiStructByName("Shader", {
|
||||||
properties: {},
|
properties: {},
|
||||||
destructor: "UnloadShader"
|
//destructor: "UnloadShader"
|
||||||
});
|
});
|
||||||
core.addApiStructByName("Texture", {
|
core.addApiStructByName("Texture", {
|
||||||
properties: {
|
properties: {
|
||||||
width: { get: true },
|
width: { get: true },
|
||||||
height: { get: true }
|
height: { get: true }
|
||||||
},
|
},
|
||||||
destructor: "UnloadTexture"
|
//destructor: "UnloadTexture"
|
||||||
});
|
});
|
||||||
core.addApiStructByName("Font", {
|
core.addApiStructByName("Font", {
|
||||||
properties: {
|
properties: {
|
||||||
baseSize: { get: true }
|
baseSize: { get: true }
|
||||||
},
|
},
|
||||||
destructor: "UnloadFont"
|
//destructor: "UnloadFont"
|
||||||
|
});
|
||||||
|
core.addApiStructByName("RenderTexture", {
|
||||||
|
properties: {},
|
||||||
|
//destructor: "UnloadRenderTexture"
|
||||||
|
});
|
||||||
|
core.addApiStructByName("MaterialMap", {
|
||||||
|
properties: {
|
||||||
|
texture: { set: true },
|
||||||
|
color: { set: true, get: true },
|
||||||
|
value: { get: true, set: true }
|
||||||
|
},
|
||||||
|
//destructor: "UnloadMaterialMap"
|
||||||
|
});
|
||||||
|
core.addApiStructByName("Material", {
|
||||||
|
properties: {
|
||||||
|
shader: { set: true }
|
||||||
|
},
|
||||||
|
//destructor: "UnloadMaterial"
|
||||||
});
|
});
|
||||||
// Window-related functions
|
// Window-related functions
|
||||||
core.addApiFunctionByName("InitWindow");
|
core.addApiFunctionByName("InitWindow");
|
||||||
|
@ -1098,8 +1175,8 @@ function main() {
|
||||||
core.addApiFunctionByName("EndMode2D");
|
core.addApiFunctionByName("EndMode2D");
|
||||||
core.addApiFunctionByName("BeginMode3D");
|
core.addApiFunctionByName("BeginMode3D");
|
||||||
core.addApiFunctionByName("EndMode3D");
|
core.addApiFunctionByName("EndMode3D");
|
||||||
//core.addApiFunctionByName("BeginTextureMode")
|
core.addApiFunctionByName("BeginTextureMode");
|
||||||
//core.addApiFunctionByName("EndTextureMode")
|
core.addApiFunctionByName("EndTextureMode");
|
||||||
core.addApiFunctionByName("BeginShaderMode");
|
core.addApiFunctionByName("BeginShaderMode");
|
||||||
core.addApiFunctionByName("EndShaderMode");
|
core.addApiFunctionByName("EndShaderMode");
|
||||||
core.addApiFunctionByName("BeginBlendMode");
|
core.addApiFunctionByName("BeginBlendMode");
|
||||||
|
@ -1148,7 +1225,7 @@ function main() {
|
||||||
// core.addApiFunctionByName("SetShaderValueV")
|
// core.addApiFunctionByName("SetShaderValueV")
|
||||||
core.addApiFunctionByName("SetShaderValueMatrix");
|
core.addApiFunctionByName("SetShaderValueMatrix");
|
||||||
core.addApiFunctionByName("SetShaderValueTexture");
|
core.addApiFunctionByName("SetShaderValueTexture");
|
||||||
// "UnloadShader" called by finalizer
|
core.addApiFunctionByName("UnloadShader");
|
||||||
// ScreenSpaceRelatedFunctions
|
// ScreenSpaceRelatedFunctions
|
||||||
core.addApiFunctionByName("GetMouseRay");
|
core.addApiFunctionByName("GetMouseRay");
|
||||||
core.addApiFunctionByName("GetCameraMatrix");
|
core.addApiFunctionByName("GetCameraMatrix");
|
||||||
|
@ -1322,7 +1399,7 @@ function main() {
|
||||||
core.addApiFunctionByName("LoadImageFromTexture");
|
core.addApiFunctionByName("LoadImageFromTexture");
|
||||||
core.addApiFunctionByName("LoadImageFromScreen");
|
core.addApiFunctionByName("LoadImageFromScreen");
|
||||||
core.addApiFunctionByName("IsImageReady");
|
core.addApiFunctionByName("IsImageReady");
|
||||||
// UnloadImage called by destructor
|
core.addApiFunctionByName("UnloadImage");
|
||||||
core.addApiFunctionByName("ExportImage");
|
core.addApiFunctionByName("ExportImage");
|
||||||
// needed?
|
// needed?
|
||||||
// core.addApiFunctionByName("ExportImageAsCode")
|
// core.addApiFunctionByName("ExportImageAsCode")
|
||||||
|
@ -1364,7 +1441,15 @@ function main() {
|
||||||
core.addApiFunctionByName("ImageColorContrast");
|
core.addApiFunctionByName("ImageColorContrast");
|
||||||
core.addApiFunctionByName("ImageColorBrightness");
|
core.addApiFunctionByName("ImageColorBrightness");
|
||||||
core.addApiFunctionByName("ImageColorReplace");
|
core.addApiFunctionByName("ImageColorReplace");
|
||||||
//core.addApiFunctionByName("LoadImageColors")
|
const lic = apiDesc.getFunction("LoadImageColors");
|
||||||
|
lic.returnType = "unsigned char *";
|
||||||
|
core.addApiFunction(lic, null, { body: (gen) => {
|
||||||
|
gen.jsToC("Image", "image", "argv[0]", core.structLookup);
|
||||||
|
gen.call("LoadImageColors", ["image"], { name: "colors", type: "Color *" });
|
||||||
|
gen.statement("JSValue retVal = JS_NewArrayBufferCopy(ctx, (const uint8_t*)colors, image.width*image.height*sizeof(Color))");
|
||||||
|
gen.call("UnloadImageColors", ["colors"]);
|
||||||
|
gen.returnExp("retVal");
|
||||||
|
} });
|
||||||
//core.addApiFunctionByName("LoadImagePalette")
|
//core.addApiFunctionByName("LoadImagePalette")
|
||||||
//core.addApiFunctionByName("UnloadImageColors")
|
//core.addApiFunctionByName("UnloadImageColors")
|
||||||
//core.addApiFunctionByName("UnloadImagePalette")
|
//core.addApiFunctionByName("UnloadImagePalette")
|
||||||
|
@ -1391,11 +1476,11 @@ function main() {
|
||||||
core.addApiFunctionByName("LoadTexture");
|
core.addApiFunctionByName("LoadTexture");
|
||||||
core.addApiFunctionByName("LoadTextureFromImage");
|
core.addApiFunctionByName("LoadTextureFromImage");
|
||||||
core.addApiFunctionByName("LoadTextureCubemap");
|
core.addApiFunctionByName("LoadTextureCubemap");
|
||||||
// core.addApiFunctionByName("LoadRenderTexture")
|
core.addApiFunctionByName("LoadRenderTexture");
|
||||||
core.addApiFunctionByName("IsTextureReady");
|
core.addApiFunctionByName("IsTextureReady");
|
||||||
// "UnloadTexture" called by finalizer
|
core.addApiFunctionByName("UnloadTexture");
|
||||||
// core.addApiFunctionByName("IsRenderTextureReady")
|
core.addApiFunctionByName("IsRenderTextureReady");
|
||||||
// core.addApiFunctionByName("UnloadRenderTexture")
|
core.addApiFunctionByName("UnloadRenderTexture");
|
||||||
// core.addApiFunctionByName("UpdateTexture")
|
// core.addApiFunctionByName("UpdateTexture")
|
||||||
// core.addApiFunctionByName("UpdateTextureRec")
|
// core.addApiFunctionByName("UpdateTextureRec")
|
||||||
// Texture configuration functions
|
// Texture configuration functions
|
||||||
|
@ -1408,7 +1493,7 @@ function main() {
|
||||||
core.addApiFunctionByName("DrawTextureEx");
|
core.addApiFunctionByName("DrawTextureEx");
|
||||||
core.addApiFunctionByName("DrawTextureRec");
|
core.addApiFunctionByName("DrawTextureRec");
|
||||||
core.addApiFunctionByName("DrawTexturePro");
|
core.addApiFunctionByName("DrawTexturePro");
|
||||||
// core.addApiFunctionByName("DrawTextureNPatch")
|
core.addApiFunctionByName("DrawTextureNPatch");
|
||||||
// Color/pixel related functions
|
// Color/pixel related functions
|
||||||
core.addApiFunctionByName("Fade");
|
core.addApiFunctionByName("Fade");
|
||||||
core.addApiFunctionByName("ColorToInt");
|
core.addApiFunctionByName("ColorToInt");
|
||||||
|
@ -1436,7 +1521,7 @@ function main() {
|
||||||
// core.addApiFunctionByName("LoadFontData")
|
// core.addApiFunctionByName("LoadFontData")
|
||||||
// core.addApiFunctionByName("GenImageFontAtlas")
|
// core.addApiFunctionByName("GenImageFontAtlas")
|
||||||
// core.addApiFunctionByName("UnloadFontData")
|
// core.addApiFunctionByName("UnloadFontData")
|
||||||
// "UnloadFont" called by finalizer
|
core.addApiFunctionByName("UnloadFont");
|
||||||
// core.addApiFunctionByName("ExportFontAsCode")
|
// core.addApiFunctionByName("ExportFontAsCode")
|
||||||
// Text drawing functions
|
// Text drawing functions
|
||||||
core.addApiFunctionByName("DrawFPS");
|
core.addApiFunctionByName("DrawFPS");
|
||||||
|
@ -1491,7 +1576,7 @@ function main() {
|
||||||
core.addApiFunctionByName("LoadModel");
|
core.addApiFunctionByName("LoadModel");
|
||||||
core.addApiFunctionByName("LoadModelFromMesh");
|
core.addApiFunctionByName("LoadModelFromMesh");
|
||||||
core.addApiFunctionByName("IsModelReady");
|
core.addApiFunctionByName("IsModelReady");
|
||||||
// "UnloadModel" called by finalizer
|
core.addApiFunctionByName("UnloadModel");
|
||||||
core.addApiFunctionByName("GetModelBoundingBox");
|
core.addApiFunctionByName("GetModelBoundingBox");
|
||||||
// model drawing functions
|
// model drawing functions
|
||||||
core.addApiFunctionByName("DrawModel");
|
core.addApiFunctionByName("DrawModel");
|
||||||
|
@ -1505,10 +1590,10 @@ function main() {
|
||||||
// Mesh management functions
|
// Mesh management functions
|
||||||
// TODO: Refcounting needed?
|
// TODO: Refcounting needed?
|
||||||
core.addApiFunctionByName("UploadMesh");
|
core.addApiFunctionByName("UploadMesh");
|
||||||
// core.addApiFunctionByName("UpdateMeshBuffer")
|
core.addApiFunctionByName("UpdateMeshBuffer");
|
||||||
// "UnloadMesh" called by finalizer
|
core.addApiFunctionByName("UnloadMesh");
|
||||||
//core.addApiFunctionByName("DrawMesh")
|
core.addApiFunctionByName("DrawMesh");
|
||||||
// core.addApiFunctionByName("DrawMeshInstanced")
|
core.addApiFunctionByName("DrawMeshInstanced");
|
||||||
core.addApiFunctionByName("ExportMesh");
|
core.addApiFunctionByName("ExportMesh");
|
||||||
core.addApiFunctionByName("GetMeshBoundingBox");
|
core.addApiFunctionByName("GetMeshBoundingBox");
|
||||||
core.addApiFunctionByName("GenMeshTangents");
|
core.addApiFunctionByName("GenMeshTangents");
|
||||||
|
@ -1526,11 +1611,12 @@ function main() {
|
||||||
core.addApiFunctionByName("GenMeshCubicmap");
|
core.addApiFunctionByName("GenMeshCubicmap");
|
||||||
// Material loading/unloading functions
|
// Material loading/unloading functions
|
||||||
// core.addApiFunctionByName("LoadMaterials")
|
// core.addApiFunctionByName("LoadMaterials")
|
||||||
// core.addApiFunctionByName("LoadMaterialDefault")
|
core.addApiFunctionByName("LoadMaterialDefault");
|
||||||
// core.addApiFunctionByName("IsMaterialReady")
|
core.addApiFunctionByName("IsMaterialReady");
|
||||||
// core.addApiFunctionByName("UnloadMaterial")
|
core.addApiFunctionByName("UnloadMaterial");
|
||||||
// core.addApiFunctionByName("SetMaterialTexture")
|
core.addApiFunctionByName("SetMaterialTexture");
|
||||||
// core.addApiFunctionByName("SetModelMeshMaterial")
|
core.addApiFunctionByName("SetModelMaterial");
|
||||||
|
core.addApiFunctionByName("SetModelMeshMaterial");
|
||||||
// Model animations loading/unloading functions
|
// Model animations loading/unloading functions
|
||||||
// core.addApiFunctionByName("LoadModelAnimations")
|
// core.addApiFunctionByName("LoadModelAnimations")
|
||||||
// core.addApiFunctionByName("UpdateModelAnimation")
|
// core.addApiFunctionByName("UpdateModelAnimation")
|
||||||
|
@ -1560,8 +1646,8 @@ function main() {
|
||||||
core.addApiFunctionByName("LoadSoundFromWave");
|
core.addApiFunctionByName("LoadSoundFromWave");
|
||||||
core.addApiFunctionByName("IsSoundReady");
|
core.addApiFunctionByName("IsSoundReady");
|
||||||
// core.addApiFunctionByName("UpdateSound")
|
// core.addApiFunctionByName("UpdateSound")
|
||||||
// "UnloadWave" called by finalizer
|
core.addApiFunctionByName("UnloadWave");
|
||||||
// "UnloadSound" called by finalizer
|
core.addApiFunctionByName("UnloadSound");
|
||||||
core.addApiFunctionByName("ExportWave");
|
core.addApiFunctionByName("ExportWave");
|
||||||
// core.addApiFunctionByName("ExportWaveAsCode")
|
// core.addApiFunctionByName("ExportWaveAsCode")
|
||||||
// Wave/Sound management functions
|
// Wave/Sound management functions
|
||||||
|
@ -1582,7 +1668,7 @@ function main() {
|
||||||
core.addApiFunctionByName("LoadMusicStream");
|
core.addApiFunctionByName("LoadMusicStream");
|
||||||
// core.addApiFunctionByName("LoadMusicStreamFromMemory")
|
// core.addApiFunctionByName("LoadMusicStreamFromMemory")
|
||||||
core.addApiFunctionByName("IsMusicReady");
|
core.addApiFunctionByName("IsMusicReady");
|
||||||
// "UnloadMusicStream" called by finalizer
|
core.addApiFunctionByName("UnloadMusicStream");
|
||||||
core.addApiFunctionByName("PlayMusicStream");
|
core.addApiFunctionByName("PlayMusicStream");
|
||||||
core.addApiFunctionByName("IsMusicStreamPlaying");
|
core.addApiFunctionByName("IsMusicStreamPlaying");
|
||||||
core.addApiFunctionByName("UpdateMusicStream");
|
core.addApiFunctionByName("UpdateMusicStream");
|
||||||
|
@ -1742,6 +1828,9 @@ function main() {
|
||||||
api.enums.find(x => x.name === "CameraMode")?.values.forEach(x => core.exportGlobalConstant(x.name, x.description));
|
api.enums.find(x => x.name === "CameraMode")?.values.forEach(x => core.exportGlobalConstant(x.name, x.description));
|
||||||
api.enums.find(x => x.name === "ShaderLocationIndex")?.values.forEach(x => core.exportGlobalConstant(x.name, x.description));
|
api.enums.find(x => x.name === "ShaderLocationIndex")?.values.forEach(x => core.exportGlobalConstant(x.name, x.description));
|
||||||
api.enums.find(x => x.name === "ShaderUniformDataType")?.values.forEach(x => core.exportGlobalConstant(x.name, x.description));
|
api.enums.find(x => x.name === "ShaderUniformDataType")?.values.forEach(x => core.exportGlobalConstant(x.name, x.description));
|
||||||
|
api.enums.find(x => x.name === "MaterialMapIndex")?.values.forEach(x => core.exportGlobalConstant(x.name, x.description));
|
||||||
|
core.exportGlobalConstant("MATERIAL_MAP_DIFFUSE", "Albedo material (same as: MATERIAL_MAP_DIFFUSE");
|
||||||
|
core.exportGlobalConstant("MATERIAL_MAP_SPECULAR", "Metalness material (same as: MATERIAL_MAP_SPECULAR)");
|
||||||
core.writeTo("src/bindings/js_raylib_core.h");
|
core.writeTo("src/bindings/js_raylib_core.h");
|
||||||
core.typings.writeTo("examples/lib.raylib.d.ts");
|
core.typings.writeTo("examples/lib.raylib.d.ts");
|
||||||
}
|
}
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -29,6 +29,13 @@ int app_update_quickjs(){
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SetModelMaterial(Model *model, int materialIndex, Material material)
|
||||||
|
{
|
||||||
|
if(model->materialCount <= materialIndex) return;
|
||||||
|
UnloadMaterial(model->materials[materialIndex]);
|
||||||
|
model->materials[materialIndex] = material;
|
||||||
|
}
|
||||||
|
|
||||||
#include "bindings/js_raylib_core.h"
|
#include "bindings/js_raylib_core.h"
|
||||||
|
|
||||||
int app_init_quickjs(int argc, char** argv){
|
int app_init_quickjs(int argc, char** argv){
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
Subproject commit 5573f0f1c7b29bfe46d0b70487e4adb4d01cba62
|
Subproject commit a48bb6e1ed7b33190e486ba65b7875f0dff73701
|
Loading…
Reference in New Issue