Add header parser for raygui

This commit is contained in:
Alexander Klingenbeck 2023-05-26 22:09:53 +02:00
parent b070c9ace7
commit 5412dd1116
9 changed files with 156 additions and 233 deletions

View File

@ -0,0 +1,64 @@
import { RayLibEnumValue, RayLibFieldDescription, RayLibParamDescription } from "./interfaces"
import { RayLibAlias, RayLibDefine, RayLibStruct, RayLibEnum, RayLibFunction } from "./interfaces"
export class HeaderParser {
parseEnums(input: string): RayLibEnum[] {
const matches = [...input.matchAll(/((?:\/\/.+\n)*)typedef enum {\n([^}]+)} ([^;]+)/gm)]
return matches.map(groups => {
return {
description: this.parseComments(groups[1]),
values: this.parseEnumValues(groups[2]),
name: groups[3],
}
})
}
parseEnumValues(input: string): RayLibEnumValue[] {
let lastNumber = 0
return input.split('\n')
.map(line => line.trim().match(/([^ ,]+)(?: = ([0-9]+))?,?(?: *)(?:\/\/ (.+))?/))
.filter(x => x !== null && !x[0].startsWith("/"))
.map(groups => {
let val = lastNumber = groups![2] ? parseInt(groups![2]) : lastNumber
lastNumber++
return {
name: groups![1],
description: groups![3] || "",
value: val
}
})
}
parseComments(input: string){
return input.split('\n').map(x => x.replace("// ","")).join('\n').trim()
}
parseFunctionDefinitions(input: string): RayLibFunction[] {
const matches = [...input.matchAll(/^[A-Z]+API (.+?)(\w+)\(([^\)]+)\);(?:[^\/]+\/\/ (.+))?/gm)]
return matches.map(groups => ({
returnType: groups![1].trim(),
name: groups![2],
params: this.parseFunctionArgs(groups![3]),
description: groups![4] || ""
}))
}
parseFunctions(input: string): RayLibFunction[] {
const matches = [...input.matchAll(/((?:\/\/ .+\n)*)[A-Z]+API\s+([\w<>]+)\s+([\w<>]+)\((.*)\)/gm)]
console.log(matches[0])
return matches.map(groups => ({
returnType: groups![1].trim(),
name: groups![2],
params: this.parseFunctionArgs(groups![3]),
description: groups![4] || ""
}))
}
parseFunctionArgs(input: string): RayLibParamDescription[] {
return input.split(',').filter(x => x !== 'void').map(arg => {
arg = arg.trim().replace(" *", "* ")
const frags = arg.split(' ')
const name = frags.pop()
const type = frags.join(' ').replace("*", " *")
return { name: name || "", type: type.trim() }
})
}
}

View File

@ -2,6 +2,7 @@ import { readFileSync, writeFileSync } from "fs";
import { RayLibApi, RayLibFunction, RayLibType } from "./interfaces";
import { ApiDescription, ApiFunction } from "./api";
import { RayLibHeader } from "./raylib-header";
import { HeaderParser } from "./header-parser";
function parseHeader(path: string, prefix: string): RayLibFunction[] {
const i = readFileSync(path, 'utf8')
@ -38,10 +39,17 @@ function main(){
returnType: "void",
params: [{type: "Model *",name:"model"},{type:"int",name:"materialIndex"},{type:"Material",name:"material"}]
})
const rguiHeader = readFileSync("thirdparty/raylib/examples/shapes/raygui.h","utf8");
const parser = new HeaderParser()
//writeFileSync("enums.json",JSON.stringify(parser.parseEnums(rayguiHeader)))
//writeFileSync("functions.json",JSON.stringify(parser.parseFunctions(rayguiHeader)))
const rmathHeader = readFileSync("thirdparty/raylib/src/raymath.h","utf8");
const mathApi = parseHeader("thirdparty/raylib/src/raymath.h", "RMAPI");
mathApi.forEach(x => api.functions.push(x))
const rcameraHeader = readFileSync("thirdparty/raylib/src/rcamera.h","utf8");
const cameraApi = parseHeader("thirdparty/raylib/src/rcamera.h", "RLAPI");
//cameraApi.forEach(x => console.log(`core.addApiFunctionByName("${x.name}")`))
cameraApi.forEach(x => api.functions.push(x))

View File

@ -1,95 +0,0 @@
/*******************************************************************************************
*
* raylib [models] example - Cubicmap loading and drawing
*
* Example originally created with raylib 1.8, 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) 2015-2023 Ramon Santamaria (@raysan5)
*
********************************************************************************************/
#include "raylib.h"
//------------------------------------------------------------------------------------
// Program main entry point
//------------------------------------------------------------------------------------
int main(void)
{
// Initialization
//--------------------------------------------------------------------------------------
const int screenWidth = 800;
const int screenHeight = 450;
InitWindow(screenWidth, screenHeight, "raylib [models] example - cubesmap loading and drawing");
// Define the camera to look into our 3d world
Camera camera = { 0 };
camera.position = (Vector3){ 16.0f, 14.0f, 16.0f }; // Camera position
camera.target = (Vector3){ 0.0f, 0.0f, 0.0f }; // Camera looking at point
camera.up = (Vector3){ 0.0f, 1.0f, 0.0f }; // Camera up vector (rotation towards target)
camera.fovy = 45.0f; // Camera field-of-view Y
camera.projection = CAMERA_PERSPECTIVE; // Camera projection type
Image image = LoadImage("resources/cubicmap.png"); // Load cubicmap image (RAM)
Texture2D cubicmap = LoadTextureFromImage(image); // Convert image to texture to display (VRAM)
Mesh mesh = GenMeshCubicmap(image, (Vector3){ 1.0f, 1.0f, 1.0f });
Model model = LoadModelFromMesh(mesh);
// NOTE: By default each cube is mapped to one part of texture atlas
Texture2D texture = LoadTexture("resources/cubicmap_atlas.png"); // Load map texture
model.materials[0].maps[MATERIAL_MAP_DIFFUSE].texture = texture; // Set map diffuse texture
Vector3 mapPosition = { -16.0f, 0.0f, -8.0f }; // Set model position
UnloadImage(image); // Unload cubesmap image from RAM, already uploaded to VRAM
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
//----------------------------------------------------------------------------------
UpdateCamera(&camera, CAMERA_ORBITAL);
//----------------------------------------------------------------------------------
// Draw
//----------------------------------------------------------------------------------
BeginDrawing();
ClearBackground(RAYWHITE);
BeginMode3D(camera);
DrawModel(model, mapPosition, 1.0f, WHITE);
EndMode3D();
DrawTextureEx(cubicmap, (Vector2){ screenWidth - cubicmap.width*4.0f - 20, 20.0f }, 0.0f, 4.0f, WHITE);
DrawRectangleLines(screenWidth - cubicmap.width*4 - 20, 20, cubicmap.width*4, cubicmap.height*4, GREEN);
DrawText("cubicmap image used to", 658, 90, 10, GRAY);
DrawText("generate map 3d model", 658, 104, 10, GRAY);
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
//--------------------------------------------------------------------------------------
return 0;
}

View File

@ -25,14 +25,14 @@ const fovy = 45.0; // Camera field-of-view Y
const projection = CAMERA_PERSPECTIVE; // Camera projection type
const camera = new Camera3D(position, target, up, fovy, projection)
let image = loadImage("../assets/cubicmap.png"); // Load cubicmap image (RAM)
let image = loadImage("resources/cubicmap.png"); // Load cubicmap image (RAM)
let cubicmap = loadTextureFromImage(image); // Convert image to texture to display (VRAM)
const mesh = genMeshCubicmap(image, 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
let texture = loadTexture("../assets/cubicmap_atlas.png"); // Load map texture
let texture = loadTexture("resources/cubicmap_atlas.png"); // Load map texture
//model.materials[0].maps[MATERIAL_MAP_DIFFUSE].texture = texture; // Set map diffuse texture
const mat = loadMaterialDefault()

View File

@ -1,133 +0,0 @@
/*******************************************************************************************
*
* 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)
*
********************************************************************************************/
#include "raylib.h"
#include <stdlib.h> // Required for: free()
//------------------------------------------------------------------------------------
// Program main entry point
//------------------------------------------------------------------------------------
int main(void)
{
// Initialization
//--------------------------------------------------------------------------------------
const int screenWidth = 800;
const int screenHeight = 450;
InitWindow(screenWidth, screenHeight, "raylib [models] example - first person maze");
// Define the camera to look into our 3d world
Camera camera = { 0 };
camera.position = (Vector3){ 0.2f, 0.4f, 0.2f }; // Camera position
camera.target = (Vector3){ 0.185f, 0.4f, 0.0f }; // Camera looking at point
camera.up = (Vector3){ 0.0f, 1.0f, 0.0f }; // Camera up vector (rotation towards target)
camera.fovy = 45.0f; // Camera field-of-view Y
camera.projection = CAMERA_PERSPECTIVE; // Camera projection type
Vector3 position = { 0.0f, 0.0f, 0.0f }; // Set model position
Image imMap = LoadImage("resources/cubicmap.png"); // Load cubicmap image (RAM)
Texture2D cubicmap = LoadTextureFromImage(imMap); // Convert image to texture to display (VRAM)
Mesh mesh = GenMeshCubicmap(imMap, (Vector3){ 1.0f, 1.0f, 1.0f });
Model model = LoadModelFromMesh(mesh);
// NOTE: By default each cube is mapped to one part of texture atlas
Texture2D texture = LoadTexture("resources/cubicmap_atlas.png"); // Load map texture
model.materials[0].maps[MATERIAL_MAP_DIFFUSE].texture = texture; // Set map diffuse texture
// Get map image data to be used for collision detection
Color *mapPixels = LoadImageColors(imMap);
UnloadImage(imMap); // Unload image from RAM
Vector3 mapPosition = { -16.0f, 0.0f, -8.0f }; // 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
//----------------------------------------------------------------------------------
Vector3 oldCamPos = camera.position; // Store old camera position
UpdateCamera(&camera, CAMERA_FIRST_PERSON);
// Check player collision (we simplify to 2D collision detection)
Vector2 playerPos = { camera.position.x, camera.position.z };
float playerRadius = 0.1f; // Collision radius (player is modelled as a cilinder for collision)
int playerCellX = (int)(playerPos.x - mapPosition.x + 0.5f);
int playerCellY = (int)(playerPos.y - mapPosition.z + 0.5f);
// 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 (int y = 0; y < cubicmap.height; y++)
{
for (int x = 0; x < cubicmap.width; x++)
{
if ((mapPixels[y*cubicmap.width + x].r == 255) && // Collision: white pixel, only check R channel
(CheckCollisionCircleRec(playerPos, playerRadius,
(Rectangle){ mapPosition.x - 0.5f + x*1.0f, mapPosition.z - 0.5f + y*1.0f, 1.0f, 1.0f })))
{
// Collision detected, reset camera position
camera.position = oldCamPos;
}
}
}
//----------------------------------------------------------------------------------
// Draw
//----------------------------------------------------------------------------------
BeginDrawing();
ClearBackground(RAYWHITE);
BeginMode3D(camera);
DrawModel(model, mapPosition, 1.0f, WHITE); // Draw maze map
EndMode3D();
DrawTextureEx(cubicmap, (Vector2){ GetScreenWidth() - cubicmap.width*4.0f - 20, 20.0f }, 0.0f, 4.0f, 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
//--------------------------------------------------------------------------------------
UnloadImageColors(mapPixels); // Unload color array
UnloadTexture(cubicmap); // Unload cubicmap texture
UnloadTexture(texture); // Unload map texture
UnloadModel(model); // Unload map model
CloseWindow(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------
return 0;
}

View File

@ -21,13 +21,13 @@ initWindow(screenWidth, screenHeight, "raylib [models] example - first person ma
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 imMap = loadImage("resources/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
const texture = loadTexture("resources/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)

View File

@ -309,6 +309,78 @@ class CodeGenerator extends GenericCodeGenerator {
exports.CodeGenerator = CodeGenerator;
/***/ }),
/***/ "./src/header-parser.ts":
/*!******************************!*\
!*** ./src/header-parser.ts ***!
\******************************/
/***/ ((__unused_webpack_module, exports) => {
Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.HeaderParser = void 0;
class HeaderParser {
parseEnums(input) {
const matches = [...input.matchAll(/((?:\/\/.+\n)*)typedef enum {\n([^}]+)} ([^;]+)/gm)];
return matches.map(groups => {
return {
description: this.parseComments(groups[1]),
values: this.parseEnumValues(groups[2]),
name: groups[3],
};
});
}
parseEnumValues(input) {
let lastNumber = 0;
return input.split('\n')
.map(line => line.trim().match(/([^ ,]+)(?: = ([0-9]+))?,?(?: *)(?:\/\/ (.+))?/))
.filter(x => x !== null && !x[0].startsWith("/"))
.map(groups => {
let val = lastNumber = groups[2] ? parseInt(groups[2]) : lastNumber;
lastNumber++;
return {
name: groups[1],
description: groups[3] || "",
value: val
};
});
}
parseComments(input) {
return input.split('\n').map(x => x.replace("// ", "")).join('\n').trim();
}
parseFunctionDefinitions(input) {
const matches = [...input.matchAll(/^[A-Z]+API (.+?)(\w+)\(([^\)]+)\);(?:[^\/]+\/\/ (.+))?/gm)];
return matches.map(groups => ({
returnType: groups[1].trim(),
name: groups[2],
params: this.parseFunctionArgs(groups[3]),
description: groups[4] || ""
}));
}
parseFunctions(input) {
const matches = [...input.matchAll(/((?:\/\/ .+\n)*)[A-Z]+API\s+([\w<>]+)\s+([\w<>]+)\((.*)\)/gm)];
console.log(matches[0]);
return matches.map(groups => ({
returnType: groups[1].trim(),
name: groups[2],
params: this.parseFunctionArgs(groups[3]),
description: groups[4] || ""
}));
}
parseFunctionArgs(input) {
return input.split(',').filter(x => x !== 'void').map(arg => {
arg = arg.trim().replace(" *", "* ");
const frags = arg.split(' ');
const name = frags.pop();
const type = frags.join(' ').replace("*", " *");
return { name: name || "", type: type.trim() };
});
}
}
exports.HeaderParser = HeaderParser;
/***/ }),
/***/ "./src/quickjs.ts":
@ -895,6 +967,7 @@ Object.defineProperty(exports, "__esModule", ({ value: true }));
const fs_1 = __webpack_require__(/*! fs */ "fs");
const api_1 = __webpack_require__(/*! ./api */ "./src/api.ts");
const raylib_header_1 = __webpack_require__(/*! ./raylib-header */ "./src/raylib-header.ts");
const header_parser_1 = __webpack_require__(/*! ./header-parser */ "./src/header-parser.ts");
function parseHeader(path, prefix) {
const i = (0, fs_1.readFileSync)(path, 'utf8');
const regex = new RegExp(`((?:\\/\\/ .+\\n)*)${prefix}\\s+([\\w<>]+)\\s+([\\w<>]+)\\((.*)\\)`, 'gm');
@ -926,8 +999,14 @@ function main() {
returnType: "void",
params: [{ type: "Model *", name: "model" }, { type: "int", name: "materialIndex" }, { type: "Material", name: "material" }]
});
const rguiHeader = (0, fs_1.readFileSync)("thirdparty/raylib/examples/shapes/raygui.h", "utf8");
const parser = new header_parser_1.HeaderParser();
//writeFileSync("enums.json",JSON.stringify(parser.parseEnums(rayguiHeader)))
//writeFileSync("functions.json",JSON.stringify(parser.parseFunctions(rayguiHeader)))
const rmathHeader = (0, fs_1.readFileSync)("thirdparty/raylib/src/raymath.h", "utf8");
const mathApi = parseHeader("thirdparty/raylib/src/raymath.h", "RMAPI");
mathApi.forEach(x => api.functions.push(x));
const rcameraHeader = (0, fs_1.readFileSync)("thirdparty/raylib/src/rcamera.h", "utf8");
const cameraApi = parseHeader("thirdparty/raylib/src/rcamera.h", "RLAPI");
//cameraApi.forEach(x => console.log(`core.addApiFunctionByName("${x.name}")`))
cameraApi.forEach(x => api.functions.push(x));