mirror of
https://github.com/Not-Nik/raylib-zig.git
synced 2025-09-09 12:07:27 +00:00
commit
6ee4dee3df
142
build.zig
142
build.zig
@ -10,7 +10,12 @@ const Program = struct {
|
||||
desc: []const u8,
|
||||
};
|
||||
|
||||
pub fn link(b: *std.Build, exe: *std.Build.Step.Compile, target: std.zig.CrossTarget, optimize: std.builtin.Mode) void {
|
||||
pub fn link(
|
||||
b: *std.Build,
|
||||
exe: *std.Build.Step.Compile,
|
||||
target: std.zig.CrossTarget,
|
||||
optimize: std.builtin.Mode,
|
||||
) void {
|
||||
const raylib = b.dependency("raylib", .{
|
||||
.target = target,
|
||||
.optimize = optimize,
|
||||
@ -44,12 +49,10 @@ pub fn link(b: *std.Build, exe: *std.Build.Step.Compile, target: std.zig.CrossTa
|
||||
exe.linkSystemLibrary("Xcursor");
|
||||
},
|
||||
.emscripten, .wasi => {
|
||||
//when using emscripten,
|
||||
// the libries don't need to be linked
|
||||
// because emscripten is going
|
||||
// to do that later.
|
||||
// When using emscripten, the libries don't need to be linked
|
||||
// because emscripten is going to do that later.
|
||||
},
|
||||
else => { // linux and possibly others
|
||||
else => { // Linux and possibly others.
|
||||
exe.linkSystemLibrary("GL");
|
||||
exe.linkSystemLibrary("rt");
|
||||
exe.linkSystemLibrary("dl");
|
||||
@ -61,7 +64,11 @@ pub fn link(b: *std.Build, exe: *std.Build.Step.Compile, target: std.zig.CrossTa
|
||||
exe.linkLibrary(art);
|
||||
}
|
||||
|
||||
pub fn getArtifact(b: *std.Build, target: std.zig.CrossTarget, optimize: std.builtin.Mode) *std.Build.Step.Compile {
|
||||
pub fn getArtifact(
|
||||
b: *std.Build,
|
||||
target: std.zig.CrossTarget,
|
||||
optimize: std.builtin.Mode,
|
||||
) *std.Build.Step.Compile {
|
||||
const raylib = b.dependency("raylib", .{
|
||||
.target = target,
|
||||
.optimize = optimize,
|
||||
@ -70,7 +77,7 @@ pub fn getArtifact(b: *std.Build, target: std.zig.CrossTarget, optimize: std.bui
|
||||
return raylib.artifact("raylib");
|
||||
}
|
||||
|
||||
//TODO: make these not comptime
|
||||
// TODO: Make these not comptime.
|
||||
pub fn getModule(b: *std.Build, comptime rl_path: []const u8) *std.Build.Module {
|
||||
if (b.modules.contains("raylib")) {
|
||||
return b.modules.get("raylib").?;
|
||||
@ -88,12 +95,18 @@ pub fn getModuleInternal(b: *std.Build) *std.Build.Module {
|
||||
pub const math = struct {
|
||||
pub fn getModule(b: *std.Build, comptime rl_path: []const u8) *std.Build.Module {
|
||||
var raylib = rl.getModule(b, rl_path);
|
||||
return b.addModule("raylib-math", .{ .source_file = .{ .path = rl_path ++ "/lib/raylib-zig-math.zig" }, .dependencies = &.{.{ .name = "raylib-zig", .module = raylib }} });
|
||||
return b.addModule("raylib-math", .{
|
||||
.source_file = .{ .path = rl_path ++ "/lib/raylib-zig-math.zig" },
|
||||
.dependencies = &.{.{ .name = "raylib-zig", .module = raylib }},
|
||||
});
|
||||
}
|
||||
|
||||
fn getModuleInternal(b: *std.Build) *std.Build.Module {
|
||||
var raylib = rl.getModuleInternal(b);
|
||||
return b.addModule("raylib-math", .{ .source_file = .{ .path = "lib/raylib-zig-math.zig" }, .dependencies = &.{.{ .name = "raylib-zig", .module = raylib }} });
|
||||
return b.addModule("raylib-math", .{
|
||||
.source_file = .{ .path = "lib/raylib-zig-math.zig" },
|
||||
.dependencies = &.{.{ .name = "raylib-zig", .module = raylib }},
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
@ -177,7 +190,9 @@ pub fn build(b: *std.Build) !void {
|
||||
exe_lib.addModule("raylib", raylib);
|
||||
exe_lib.addModule("raylib-math", raylib_math);
|
||||
const raylib_artifact = getArtifact(b, target, optimize);
|
||||
// Note that raylib itself isn't actually added to the exe_lib output file, so it also needs to be linked with emscripten.
|
||||
|
||||
// Note that raylib itself isn't actually added to the exe_lib
|
||||
// output file, so it also needs to be linked with emscripten.
|
||||
exe_lib.linkLibrary(raylib_artifact);
|
||||
const link_step = try linkWithEmscripten(b, &[_]*std.Build.Step.Compile{ exe_lib, raylib_artifact });
|
||||
link_step.addArg("--embed-file");
|
||||
@ -188,7 +203,12 @@ pub fn build(b: *std.Build) !void {
|
||||
const run_option = b.step(ex.name, ex.desc);
|
||||
run_option.dependOn(&run_step.step);
|
||||
} else {
|
||||
const exe = b.addExecutable(.{ .name = ex.name, .root_source_file = .{ .path = ex.path }, .optimize = optimize, .target = target });
|
||||
const exe = b.addExecutable(.{
|
||||
.name = ex.name,
|
||||
.root_source_file = .{ .path = ex.path },
|
||||
.optimize = optimize,
|
||||
.target = target,
|
||||
});
|
||||
rl.link(b, exe, target, optimize);
|
||||
exe.addModule("raylib", raylib);
|
||||
exe.addModule("raylib-math", raylib_math);
|
||||
@ -203,11 +223,11 @@ pub fn build(b: *std.Build) !void {
|
||||
const emccOutputDir = "zig-out" ++ std.fs.path.sep_str ++ "htmlout" ++ std.fs.path.sep_str;
|
||||
const emccOutputFile = "index.html";
|
||||
pub fn emscriptenRunStep(b: *std.Build) !*std.Build.Step.Run {
|
||||
//find emrun
|
||||
// Find emrun.
|
||||
if (b.sysroot == null) {
|
||||
@panic("Pass '--sysroot \"[path to emsdk installation]/upstream/emscripten\"'");
|
||||
}
|
||||
//If compiling on windows , use emrun.bat
|
||||
// If compiling on windows , use emrun.bat.
|
||||
const emrunExe = switch (builtin.os.tag) {
|
||||
.windows => "emrun.bat",
|
||||
else => "emrun",
|
||||
@ -221,36 +241,56 @@ pub fn emscriptenRunStep(b: *std.Build) !*std.Build.Step.Run {
|
||||
return run_cmd;
|
||||
}
|
||||
|
||||
//Creates the static library to build a project for Emscripten
|
||||
pub fn compileForEmscripten(b: *std.Build, name: []const u8, root_source_file: []const u8, target: std.zig.CrossTarget, optimize: std.builtin.Mode) *std.Build.Step.Compile {
|
||||
// TODO: It might be a good idea to create a custom compile step,
|
||||
// that does both the compile to static library and the link with emcc
|
||||
// By overidding the make function of the step,
|
||||
// However it might also be a bad idea since it messes with the build system itself.
|
||||
// Creates the static library to build a project for Emscripten.
|
||||
pub fn compileForEmscripten(
|
||||
b: *std.Build,
|
||||
name: []const u8,
|
||||
root_source_file: []const u8,
|
||||
target: std.zig.CrossTarget,
|
||||
optimize: std.builtin.Mode,
|
||||
) *std.Build.Step.Compile {
|
||||
// TODO: It might be a good idea to create a custom compile step, that does
|
||||
// both the compile to static library and the link with emcc by overidding
|
||||
// the make function of the step. However it might also be a bad idea since
|
||||
// it messes with the build system itself.
|
||||
|
||||
const new_target = updateTargetForWeb(target);
|
||||
|
||||
//the project is built as a library and linked later
|
||||
const exe_lib = b.addStaticLibrary(.{ .name = name, .root_source_file = .{ .path = root_source_file }, .target = new_target, .optimize = optimize });
|
||||
// The project is built as a library and linked later.
|
||||
const exe_lib = b.addStaticLibrary(.{
|
||||
.name = name,
|
||||
.root_source_file = .{ .path = root_source_file },
|
||||
.target = new_target,
|
||||
.optimize = optimize,
|
||||
});
|
||||
|
||||
//There are some symbols that need to be defined in C.
|
||||
// There are some symbols that need to be defined in C.
|
||||
const webhack_c_file_step = b.addWriteFiles();
|
||||
const webhack_c_file = webhack_c_file_step.add("webhack.c", webhack_c);
|
||||
exe_lib.addCSourceFile(.{ .file = webhack_c_file, .flags = &[_][]u8{} });
|
||||
//Since it's creating a static library, the symbols raylib uses to webgl and glfw don't need to be linked by emscripten yet.
|
||||
// Since it's creating a static library, the symbols raylib uses to webgl
|
||||
// and glfw don't need to be linked by emscripten yet.
|
||||
exe_lib.step.dependOn(&webhack_c_file_step.step);
|
||||
return exe_lib;
|
||||
}
|
||||
|
||||
//links a set of items together using emscripten.
|
||||
// Will accept objects and static libraries as items to link
|
||||
// As for files to include, it is recomended to have a single resources directory and just pass the entire directory
|
||||
// instead of passing every file individually. The entire path given will be the path to read the file within the program.
|
||||
// So, if "resources/image.png" is passed, your program will use "resources/image.png" as the path to load the file.
|
||||
// TODO: test if shared libraries are accepted, I don't remember if emcc can link a shared library with a project or not
|
||||
// TODO: add a parameter that allows a custom output directory
|
||||
pub fn linkWithEmscripten(b: *std.Build, itemsToLink: []const *std.Build.Step.Compile) !*std.Build.Step.Run {
|
||||
//Raylib uses --sysroot in order to find emscripten, so do the same here
|
||||
// Links a set of items together using emscripten.
|
||||
//
|
||||
// Will accept objects and static libraries as items to link. As for files to
|
||||
// include, it is recomended to have a single resources directory and just pass
|
||||
// the entire directory instead of passing every file individually. The entire
|
||||
// path given will be the path to read the file within the program. So, if
|
||||
// "resources/image.png" is passed, your program will use "resources/image.png"
|
||||
// as the path to load the file.
|
||||
//
|
||||
// TODO: Test if shared libraries are accepted, I don't remember if emcc can
|
||||
// link a shared library with a project or not.
|
||||
// TODO: Add a parameter that allows a custom output directory.
|
||||
pub fn linkWithEmscripten(
|
||||
b: *std.Build,
|
||||
itemsToLink: []const *std.Build.Step.Compile,
|
||||
) !*std.Build.Step.Run {
|
||||
// Raylib uses --sysroot in order to find emscripten, so do the same here.
|
||||
if (b.sysroot == null) {
|
||||
@panic("Pass '--sysroot \"[path to emsdk installation]/upstream/emscripten\"'");
|
||||
}
|
||||
@ -261,26 +301,39 @@ pub fn linkWithEmscripten(b: *std.Build, itemsToLink: []const *std.Build.Step.Co
|
||||
var emcc_run_arg = try b.allocator.alloc(u8, b.sysroot.?.len + emccExe.len + 1);
|
||||
defer b.allocator.free(emcc_run_arg);
|
||||
|
||||
emcc_run_arg = try std.fmt.bufPrint(emcc_run_arg, "{s}" ++ std.fs.path.sep_str ++ "{s}", .{ b.sysroot.?, emccExe });
|
||||
emcc_run_arg = try std.fmt.bufPrint(
|
||||
emcc_run_arg,
|
||||
"{s}" ++ std.fs.path.sep_str ++ "{s}",
|
||||
.{ b.sysroot.?, emccExe },
|
||||
);
|
||||
|
||||
//create the output directory because emcc can't do it.
|
||||
// Create the output directory because emcc can't do it.
|
||||
const mkdir_command = b.addSystemCommand(&[_][]const u8{ "mkdir", "-p", emccOutputDir });
|
||||
//Actually link everything together
|
||||
|
||||
// Actually link everything together.
|
||||
const emcc_command = b.addSystemCommand(&[_][]const u8{emcc_run_arg});
|
||||
|
||||
for (itemsToLink) |item| {
|
||||
emcc_command.addFileArg(item.getEmittedBin());
|
||||
emcc_command.step.dependOn(&item.step);
|
||||
}
|
||||
//This puts the file in zig-out/htmlout/index.html
|
||||
// This puts the file in zig-out/htmlout/index.html.
|
||||
emcc_command.step.dependOn(&mkdir_command.step);
|
||||
emcc_command.addArgs(&[_][]const u8{ "-o", emccOutputDir ++ emccOutputFile, "-sFULL-ES3=1", "-sUSE_GLFW=3", "-sASYNCIFY", "-O3", "--emrun" });
|
||||
emcc_command.addArgs(&[_][]const u8{
|
||||
"-o",
|
||||
emccOutputDir ++ emccOutputFile,
|
||||
"-sFULL-ES3=1",
|
||||
"-sUSE_GLFW=3",
|
||||
"-sASYNCIFY",
|
||||
"-O3",
|
||||
"--emrun",
|
||||
});
|
||||
return emcc_command;
|
||||
}
|
||||
|
||||
//TODO: see if zig's standard library already has somehing like this
|
||||
// TODO: See if zig's standard library already has somehing like this.
|
||||
fn lastIndexOf(string: []const u8, character: u8) usize {
|
||||
//interestingly, zig has no nice way of iterating a slice backwards
|
||||
// Interestingly, Zig has no nice way of iterating a slice backwards.
|
||||
for (0..string.len) |i| {
|
||||
const index = string.len - i - 1;
|
||||
if (string[index] == character) return index;
|
||||
@ -288,11 +341,12 @@ fn lastIndexOf(string: []const u8, character: u8) usize {
|
||||
return string.len - 1;
|
||||
}
|
||||
// TODO: each zig update, remove this and see if everything still works.
|
||||
// https://github.com/ziglang/zig/issues/16776 is where the issue is submitted
|
||||
// https://github.com/ziglang/zig/issues/16776 is where the issue is submitted.
|
||||
fn updateTargetForWeb(target: std.zig.CrossTarget) std.zig.CrossTarget {
|
||||
//zig building to emscripten doesn't work, because the zig standard library is missing some things in the C system.
|
||||
// "std/c.zig" is missing fd_t, which causes compilation to fail.
|
||||
// So build to wasi instead, until it gets fixed.
|
||||
// Zig building to emscripten doesn't work, because the Zig standard library
|
||||
// is missing some things in the C system. "std/c.zig" is missing fd_t,
|
||||
// which causes compilation to fail. So build to wasi instead, until it gets
|
||||
// fixed.
|
||||
return std.zig.CrossTarget{
|
||||
.cpu_arch = target.cpu_arch,
|
||||
.cpu_model = target.cpu_model,
|
||||
|
@ -28,7 +28,12 @@ pub fn main() anyerror!void {
|
||||
|
||||
spacing += @as(i32, @intFromFloat(buildings[i].width));
|
||||
|
||||
buildColors[i] = rl.Color.init(@as(u8, @intCast(rl.getRandomValue(200, 240))), @as(u8, @intCast(rl.getRandomValue(200, 240))), @as(u8, @intCast(rl.getRandomValue(200, 250))), 255);
|
||||
buildColors[i] = rl.Color.init(
|
||||
@as(u8, @intCast(rl.getRandomValue(200, 240))),
|
||||
@as(u8, @intCast(rl.getRandomValue(200, 240))),
|
||||
@as(u8, @intCast(rl.getRandomValue(200, 250))),
|
||||
255,
|
||||
);
|
||||
}
|
||||
|
||||
var camera = rl.Camera2D{
|
||||
@ -97,8 +102,20 @@ pub fn main() anyerror!void {
|
||||
|
||||
rl.drawRectangleRec(player, rl.Color.red);
|
||||
|
||||
rl.drawLine(@as(i32, @intFromFloat(camera.target.x)), -screenHeight * 10, @as(i32, @intFromFloat(camera.target.x)), screenHeight * 10, rl.Color.green);
|
||||
rl.drawLine(-screenWidth * 10, @as(i32, @intFromFloat(camera.target.y)), screenWidth * 10, @as(i32, @intFromFloat(camera.target.y)), rl.Color.green);
|
||||
rl.drawLine(
|
||||
@as(i32, @intFromFloat(camera.target.x)),
|
||||
-screenHeight * 10,
|
||||
@as(i32, @intFromFloat(camera.target.x)),
|
||||
screenHeight * 10,
|
||||
rl.Color.green,
|
||||
);
|
||||
rl.drawLine(
|
||||
-screenWidth * 10,
|
||||
@as(i32, @intFromFloat(camera.target.y)),
|
||||
screenWidth * 10,
|
||||
@as(i32, @intFromFloat(camera.target.y)),
|
||||
rl.Color.green,
|
||||
);
|
||||
}
|
||||
|
||||
rl.drawText("SCREEN AREA", 640, 10, 20, rl.Color.red);
|
||||
|
@ -27,8 +27,17 @@ pub fn main() anyerror!void {
|
||||
|
||||
for (0..heights.len) |i| {
|
||||
heights[i] = @as(f32, @floatFromInt(rl.getRandomValue(1, 12)));
|
||||
positions[i] = rl.Vector3.init(@as(f32, @floatFromInt(rl.getRandomValue(-15, 15))), heights[i] / 2.0, @as(f32, @floatFromInt(rl.getRandomValue(-15, 15))));
|
||||
colors[i] = rl.Color.init(@as(u8, @intCast(rl.getRandomValue(20, 255))), @as(u8, @intCast(rl.getRandomValue(10, 55))), 30, 255);
|
||||
positions[i] = rl.Vector3.init(
|
||||
@as(f32, @floatFromInt(rl.getRandomValue(-15, 15))),
|
||||
heights[i] / 2.0,
|
||||
@as(f32, @floatFromInt(rl.getRandomValue(-15, 15))),
|
||||
);
|
||||
colors[i] = rl.Color.init(
|
||||
@as(u8, @intCast(rl.getRandomValue(20, 255))),
|
||||
@as(u8, @intCast(rl.getRandomValue(10, 55))),
|
||||
30,
|
||||
255,
|
||||
);
|
||||
}
|
||||
|
||||
rl.setTargetFPS(60); // Set our game to run at 60 frames-per-second
|
||||
|
@ -36,7 +36,13 @@ pub fn main() anyerror!void {
|
||||
|
||||
rl.drawText("Use mouse wheel to move the cube up and down!", 10, 10, 20, rl.Color.gray);
|
||||
|
||||
rl.drawText(rl.textFormat("Box position Y: %03i", .{@as(i32, @intFromFloat(boxPositionY))}), 10, 40, 20, rl.Color.light_gray);
|
||||
rl.drawText(
|
||||
rl.textFormat("Box position Y: %03i", .{@as(i32, @intFromFloat(boxPositionY))}),
|
||||
10,
|
||||
40,
|
||||
20,
|
||||
rl.Color.light_gray,
|
||||
);
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
}
|
||||
|
@ -69,7 +69,13 @@ pub fn main() anyerror!void {
|
||||
|
||||
// Draw circle and touch index number
|
||||
rl.drawCircleV(touchPosition, 34, rl.Color.orange);
|
||||
rl.drawText(rl.textFormat("%d", .{i}), @as(i32, @intFromFloat(touchPosition.x)) - 10, @as(i32, @intFromFloat(touchPosition.y)) - 70, 40, rl.Color.black);
|
||||
rl.drawText(
|
||||
rl.textFormat("%d", .{i}),
|
||||
@as(i32, @intFromFloat(touchPosition.x)) - 10,
|
||||
@as(i32, @intFromFloat(touchPosition.y)) - 70,
|
||||
40,
|
||||
rl.Color.black,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,129 +0,0 @@
|
||||
//
|
||||
// models_loading
|
||||
// Zig version:
|
||||
// Author: Nikolas Wipper
|
||||
// Date: 2020-02-15
|
||||
//
|
||||
|
||||
usingnamespace @import("raylib");
|
||||
|
||||
const resourceDir = "raylib/examples/models/resources/";
|
||||
|
||||
pub fn main() anyerror!void {
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
const screenWidth = 800;
|
||||
const screenHeight = 450;
|
||||
|
||||
InitWindow(screenWidth, screenHeight, "raylib [models] example - models loading");
|
||||
|
||||
// Define the camera to look into our 3d world
|
||||
var camera = Camera{
|
||||
.position = Vector3{ .x = 50.0, .y = 50.0, .z = 50.0 }, // Camera position
|
||||
.target = Vector3{ .x = 0.0, .y = 10.0, .z = 0.0 }, // Camera looking at point
|
||||
.up = Vector3{ .x = 0.0, .y = 1.0, .z = 0.0 }, // Camera up vector (rotation towards target)
|
||||
.fovy = 45.0, // Camera field-of-view Y
|
||||
.projection = CameraProjection.CAMERA_PERSPECTIVE, // Camera mode type
|
||||
};
|
||||
|
||||
var model = LoadModel(resourceDir ++ "models/castle.obj"); // Load model
|
||||
var texture = LoadTexture(resourceDir ++ "models/castle_diffuse.png"); // Load model texture
|
||||
model.materials[0].maps[@enumToInt(MAP_DIFFUSE)].texture = texture; // Set map diffuse texture
|
||||
|
||||
var position = Vector3{ .x = 0.0, .y = 0.0, .z = 0.0 }; // Set model position
|
||||
|
||||
var bounds = MeshBoundingBox(model.meshes[0]); // Set model bounds
|
||||
|
||||
// NOTE: bounds are calculated from the original size of the model,
|
||||
// if model is scaled on drawing, bounds must be also scaled
|
||||
|
||||
camera.SetMode(CameraMode.CAMERA_FREE); // Set a free camera mode
|
||||
|
||||
var selected = false; // Selected object flag
|
||||
|
||||
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
|
||||
//----------------------------------------------------------------------------------
|
||||
camera.Update();
|
||||
|
||||
// Load new models/textures on drag&drop
|
||||
if (IsFileDropped()) {
|
||||
var count: c_int = 0;
|
||||
var droppedFiles = GetDroppedFiles(&count);
|
||||
|
||||
if (count == 1) // Only support one file dropped
|
||||
{
|
||||
if (IsFileExtension(droppedFiles[0], ".obj") or
|
||||
IsFileExtension(droppedFiles[0], ".gltf") or
|
||||
IsFileExtension(droppedFiles[0], ".iqm")) // Model file formats supported
|
||||
{
|
||||
UnloadModel(model); // Unload previous model
|
||||
model = LoadModel(droppedFiles[0]); // Load new model
|
||||
model.materials[0].maps[@enumToInt(MAP_DIFFUSE)].texture = texture; // Set current map diffuse texture
|
||||
|
||||
bounds = MeshBoundingBox(model.meshes[0]);
|
||||
|
||||
// TODO: Move camera position from target enough distance to visualize model properly
|
||||
} else if (IsFileExtension(droppedFiles[0], ".png")) // Texture file formats supported
|
||||
{
|
||||
// Unload current model texture and load new one
|
||||
UnloadTexture(texture);
|
||||
texture = LoadTexture(droppedFiles[0]);
|
||||
model.materials[0].maps[@enumToInt(MAP_DIFFUSE)].texture = texture;
|
||||
}
|
||||
}
|
||||
|
||||
ClearDroppedFiles(); // Clear internal buffers
|
||||
}
|
||||
|
||||
// Select model on mouse click
|
||||
if (IsMouseButtonPressed(MouseButton.MOUSE_LEFT_BUTTON)) {
|
||||
// Check collision between ray and box
|
||||
if (CheckCollisionRayBox(GetMouseRay(GetMousePosition(), camera), bounds)) {
|
||||
selected = !selected;
|
||||
} else {
|
||||
selected = false;
|
||||
}
|
||||
}
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
|
||||
ClearBackground(RAYWHITE);
|
||||
|
||||
camera.Begin();
|
||||
|
||||
DrawModel(model, position, 1.0, WHITE); // Draw 3d model with texture
|
||||
|
||||
DrawGrid(20, 10.0); // Draw a grid
|
||||
|
||||
if (selected) DrawBoundingBox(bounds, GREEN); // Draw selection box
|
||||
|
||||
camera.End();
|
||||
|
||||
DrawText("Drag & drop model to load mesh/texture.", 10, GetScreenHeight() - 20, 10, DARKGRAY);
|
||||
if (selected) DrawText("MODEL SELECTED", GetScreenWidth() - 110, 10, 10, GREEN);
|
||||
|
||||
DrawText("(c) Castle 3D model by Alberto Cano", screenWidth - 200, screenHeight - 20, 10, GRAY);
|
||||
|
||||
DrawFPS(10, 10);
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
UnloadTexture(texture); // Unload texture
|
||||
UnloadModel(model); // Unload model
|
||||
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//--------------------------------------------------------------------------------------
|
||||
}
|
@ -1,126 +0,0 @@
|
||||
// This is a zig port of rlights.h by Ryan Roden-Corrent (rcorre).
|
||||
// The original notice follows:
|
||||
//
|
||||
// *********************************************************************************************
|
||||
//
|
||||
// raylib.lights - Some useful functions to deal with lights data
|
||||
//
|
||||
// CONFIGURATION:
|
||||
//
|
||||
// #define RLIGHTS_IMPLEMENTATION
|
||||
// Generates the implementation of the library into the included file.
|
||||
// If not defined, the library is in header only mode and can be included
|
||||
// in other headers or source files without problems. But only ONE file should
|
||||
// hold the implementation.
|
||||
//
|
||||
// LICENSE: zlib/libpng
|
||||
//
|
||||
// Copyright (c) 2017-2020 Victor Fisac (@victorfisac) and Ramon Santamaria
|
||||
// (@raysan5)
|
||||
//
|
||||
// This software is provided "as-is", without any express or implied warranty.
|
||||
// In no event will the authors be held liable for any damages arising from the
|
||||
// use of this software.
|
||||
//
|
||||
// Permission is granted to anyone to use this software for any purpose,
|
||||
// including commercial applications, and to alter it and redistribute it freely,
|
||||
// subject to the following restrictions:
|
||||
//
|
||||
// 1. The origin of this software must not be misrepresented; you must not
|
||||
// claim that you wrote the original software. If you use this software in a
|
||||
// product, an acknowledgment in the product documentation would be appreciated
|
||||
// but is not required.
|
||||
//
|
||||
// 2. Altered source versions must be plainly marked as such, and must not
|
||||
// be misrepresented as being the original software.
|
||||
//
|
||||
// 3. This notice may not be removed or altered from any source
|
||||
// distribution.
|
||||
//
|
||||
// *********************************************************************************************/
|
||||
|
||||
const std = @import("std");
|
||||
usingnamespace @import("raylib");
|
||||
|
||||
const max_lights = 4;
|
||||
|
||||
pub const Light = struct {
|
||||
type: LightType,
|
||||
position: Vector3,
|
||||
target: Vector3,
|
||||
color: Color,
|
||||
enabled: bool,
|
||||
|
||||
// Shader locations
|
||||
enabledLoc: i32,
|
||||
typeLoc: i32,
|
||||
posLoc: i32,
|
||||
targetLoc: i32,
|
||||
colorLoc: i32,
|
||||
};
|
||||
|
||||
// Light type
|
||||
pub const LightType = enum { directional, point };
|
||||
|
||||
var lightsCount: u32 = 0;
|
||||
|
||||
fn getShaderLoc(shader: Shader, name: []const u8) !i32 {
|
||||
// TODO: Below code doesn't look good to me,
|
||||
// it assumes a specific shader naming and structure
|
||||
// Probably this implementation could be improved
|
||||
// (note from original C implementation, I don't have a better idea)
|
||||
var buf: [32]u8 = undefined;
|
||||
const key = try std.fmt.bufPrintZ(buf[0..], "lights[{}].{s}", .{ lightsCount, name });
|
||||
return GetShaderLocation(shader, key);
|
||||
}
|
||||
|
||||
// Create a light and get shader locations
|
||||
pub fn CreateLight(typ: LightType, position: Vector3, target: Vector3, color: Color, shader: Shader) !Light {
|
||||
if (lightsCount >= max_lights) {
|
||||
return error.TooManyLights;
|
||||
}
|
||||
|
||||
const light = Light{
|
||||
.enabled = true,
|
||||
.type = typ,
|
||||
.position = position,
|
||||
.target = target,
|
||||
.color = color,
|
||||
|
||||
.enabledLoc = try getShaderLoc(shader, "enabled"),
|
||||
.typeLoc = try getShaderLoc(shader, "type"),
|
||||
.posLoc = try getShaderLoc(shader, "position"),
|
||||
.targetLoc = try getShaderLoc(shader, "target"),
|
||||
.colorLoc = try getShaderLoc(shader, "color"),
|
||||
};
|
||||
UpdateLightValues(shader, light);
|
||||
|
||||
lightsCount += 1;
|
||||
|
||||
return light;
|
||||
}
|
||||
|
||||
// Send light properties to shader
|
||||
// NOTE: Light shader locations should be available
|
||||
pub fn UpdateLightValues(shader: Shader, light: Light) void {
|
||||
// Send to shader light enabled state and type
|
||||
SetShaderValue(shader, light.enabledLoc, &light.enabled, @enumToInt(ShaderUniformDataType.SHADER_UNIFORM_INT));
|
||||
SetShaderValue(shader, light.typeLoc, &light.type, @enumToInt(ShaderUniformDataType.SHADER_UNIFORM_INT));
|
||||
|
||||
// Send to shader light position values
|
||||
const position = [3]f32{ light.position.x, light.position.y, light.position.z };
|
||||
SetShaderValue(shader, light.posLoc, &position, @enumToInt(ShaderUniformDataType.SHADER_UNIFORM_VEC3));
|
||||
|
||||
// Send to shader light target position values
|
||||
const target = [3]f32{ light.target.x, light.target.y, light.target.z };
|
||||
SetShaderValue(shader, light.targetLoc, &target, @enumToInt(ShaderUniformDataType.SHADER_UNIFORM_VEC3));
|
||||
|
||||
// Send to shader light color values
|
||||
const color = [4]f32{
|
||||
@intToFloat(f32, light.color.r) / 255.0,
|
||||
@intToFloat(f32, light.color.g) / 255.0,
|
||||
@intToFloat(f32, light.color.b) / 255.0,
|
||||
@intToFloat(f32, light.color.a) / 255.0,
|
||||
};
|
||||
SetShaderValue(shader, light.colorLoc, &color, @enumToInt(ShaderUniformDataType.SHADER_UNIFORM_VEC4));
|
||||
}
|
@ -1,182 +0,0 @@
|
||||
//
|
||||
// shaders_basic_lighting
|
||||
// Zig version:
|
||||
// Author: Ryan Roden-Corrent
|
||||
// Date: 2021-07-24
|
||||
//
|
||||
// NOTE: This example requires raylib OpenGL 3.3 or ES2 versions for shaders
|
||||
// support,
|
||||
// OpenGL 1.1 does not support shaders, recompile raylib to OpenGL 3.3
|
||||
// version.
|
||||
//
|
||||
// NOTE: Shaders used in this example are #version 330 (OpenGL 3.3).
|
||||
usingnamespace @import("raylib");
|
||||
usingnamespace @import("rlights.zig");
|
||||
usingnamespace @import("raylib-math");
|
||||
|
||||
const resourceDir = "raylib/examples/shaders/resources/";
|
||||
|
||||
pub fn main() !void {
|
||||
// Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
const screenWidth = 800;
|
||||
const screenHeight = 450;
|
||||
|
||||
//SetConfigFlags(.FLAG_MSAA_4X_HINT); // Enable Multi Sampling Anti Aliasing 4x
|
||||
// (if available)
|
||||
InitWindow(screenWidth, screenHeight, "raylib [shaders] example - basic lighting");
|
||||
|
||||
// Define the camera to look into our 3d world
|
||||
const camera = Camera{
|
||||
.position = .{ .x = 2.0, .y = 2.0, .z = 6.0 }, // Camera position
|
||||
.target = .{ .x = 0.0, .y = 0.5, .z = 0.0 }, // Camera looking at point
|
||||
.up = .{ .x = 0.0, .y = 1.0, .z = 0.0 }, // Camera up vector (rotation towards target)
|
||||
.fovy = 45.0, // Camera field-of-view Y
|
||||
.projection = CameraProjection.CAMERA_PERSPECTIVE, // Camera mode type
|
||||
};
|
||||
|
||||
// Load models
|
||||
var modelA = LoadModelFromMesh(GenMeshTorus(0.4, 1.0, 16, 32));
|
||||
var modelB = LoadModelFromMesh(GenMeshCube(1.0, 1.0, 1.0));
|
||||
var modelC = LoadModelFromMesh(GenMeshSphere(0.5, 32, 32));
|
||||
|
||||
// Load models texture
|
||||
const texture = LoadTexture(resourceDir ++ "texel_checker.png");
|
||||
|
||||
// Assign texture to default model material
|
||||
modelA.materials[0].maps[@enumToInt(MAP_DIFFUSE)].texture = texture;
|
||||
modelB.materials[0].maps[@enumToInt(MAP_DIFFUSE)].texture = texture;
|
||||
modelC.materials[0].maps[@enumToInt(MAP_DIFFUSE)].texture = texture;
|
||||
|
||||
var shader = LoadShader(
|
||||
resourceDir ++ "/shaders/glsl330/base_lighting.vs",
|
||||
resourceDir ++ "/shaders/glsl330/lighting.fs",
|
||||
);
|
||||
|
||||
// Get some shader loactions
|
||||
shader.locs[@enumToInt(ShaderLocationIndex.SHADER_LOC_MATRIX_MODEL)] = GetShaderLocation(shader, "matModel");
|
||||
shader.locs[@enumToInt(ShaderLocationIndex.SHADER_LOC_VECTOR_VIEW)] = GetShaderLocation(shader, "viewPos");
|
||||
|
||||
// ambient light level
|
||||
const ambientLoc = GetShaderLocation(shader, "ambient");
|
||||
const ambientVals = [4]f32{ 0.2, 0.2, 0.2, 1.0 };
|
||||
SetShaderValue(shader, ambientLoc, &ambientVals, @enumToInt(ShaderUniformDataType.SHADER_UNIFORM_VEC4));
|
||||
|
||||
var angle: f32 = 6.282;
|
||||
|
||||
// All models use the same shader
|
||||
modelA.materials[0].shader = shader;
|
||||
modelB.materials[0].shader = shader;
|
||||
modelC.materials[0].shader = shader;
|
||||
|
||||
// Using 4 point lights, white, red, green and blue
|
||||
var lights = [_]Light{
|
||||
try CreateLight(LightType.point, .{ .x = 4, .y = 2, .z = 4 }, Vector3Zero(), WHITE, shader),
|
||||
try CreateLight(LightType.point, .{ .x = 4, .y = 2, .z = 4 }, Vector3Zero(), RED, shader),
|
||||
try CreateLight(LightType.point, .{ .x = 0, .y = 4, .z = 2 }, Vector3Zero(), GREEN, shader),
|
||||
try CreateLight(LightType.point, .{ .x = 0, .y = 4, .z = 2 }, Vector3Zero(), BLUE, shader),
|
||||
};
|
||||
|
||||
SetCameraMode(camera, CameraMode.CAMERA_ORBITAL); // Set an orbital camera mode
|
||||
|
||||
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
|
||||
//----------------------------------------------------------------------------------
|
||||
if (IsKeyPressed(KeyboardKey.KEY_W)) {
|
||||
lights[0].enabled = !lights[0].enabled;
|
||||
}
|
||||
if (IsKeyPressed(KeyboardKey.KEY_R)) {
|
||||
lights[1].enabled = !lights[1].enabled;
|
||||
}
|
||||
if (IsKeyPressed(KeyboardKey.KEY_G)) {
|
||||
lights[2].enabled = !lights[2].enabled;
|
||||
}
|
||||
if (IsKeyPressed(KeyboardKey.KEY_B)) {
|
||||
lights[3].enabled = !lights[3].enabled;
|
||||
}
|
||||
|
||||
//UpdateCamera(&camera); // Update camera
|
||||
|
||||
// Make the lights do differing orbits
|
||||
angle -= 0.02;
|
||||
lights[0].position.x = @cos(angle) * 4.0;
|
||||
lights[0].position.z = @sin(angle) * 4.0;
|
||||
lights[1].position.x = @cos(-angle * 0.6) * 4.0;
|
||||
lights[1].position.z = @sin(-angle * 0.6) * 4.0;
|
||||
lights[2].position.y = @cos(angle * 0.2) * 4.0;
|
||||
lights[2].position.z = @sin(angle * 0.2) * 4.0;
|
||||
lights[3].position.y = @cos(-angle * 0.35) * 4.0;
|
||||
lights[3].position.z = @sin(-angle * 0.35) * 4.0;
|
||||
|
||||
UpdateLightValues(shader, lights[0]);
|
||||
UpdateLightValues(shader, lights[1]);
|
||||
UpdateLightValues(shader, lights[2]);
|
||||
UpdateLightValues(shader, lights[3]);
|
||||
|
||||
// Rotate the torus
|
||||
modelA.transform =
|
||||
MatrixMultiply(modelA.transform, MatrixRotateX(-0.025));
|
||||
modelA.transform =
|
||||
MatrixMultiply(modelA.transform, MatrixRotateZ(0.012));
|
||||
|
||||
// Update the light shader with the camera view position
|
||||
const cameraPos = [3]f32{ camera.position.x, camera.position.y, camera.position.z };
|
||||
SetShaderValue(shader, shader.locs[@enumToInt(ShaderLocationIndex.SHADER_LOC_VECTOR_VIEW)], &cameraPos, @enumToInt(ShaderUniformDataType.SHADER_UNIFORM_VEC3));
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
//----------------------------------------------------------------------------------
|
||||
BeginDrawing();
|
||||
|
||||
ClearBackground(RAYWHITE);
|
||||
|
||||
BeginMode3D(camera);
|
||||
|
||||
// Draw the three models
|
||||
DrawModel(modelA, Vector3Zero(), 1.0, WHITE);
|
||||
DrawModel(modelB, .{ .x = -1.6, .y = 0, .z = 0 }, 1.0, WHITE);
|
||||
DrawModel(modelC, .{ .x = 1.6, .y = 0, .z = 0 }, 1.0, WHITE);
|
||||
|
||||
// Draw markers to show where the lights are
|
||||
if (lights[0].enabled) {
|
||||
DrawSphereEx(lights[0].position, 0.2, 8, 8, WHITE);
|
||||
}
|
||||
if (lights[1].enabled) {
|
||||
DrawSphereEx(lights[1].position, 0.2, 8, 8, RED);
|
||||
}
|
||||
if (lights[2].enabled) {
|
||||
DrawSphereEx(lights[2].position, 0.2, 8, 8, GREEN);
|
||||
}
|
||||
if (lights[3].enabled) {
|
||||
DrawSphereEx(lights[3].position, 0.2, 8, 8, BLUE);
|
||||
}
|
||||
|
||||
DrawGrid(10, 1.0);
|
||||
|
||||
EndMode3D();
|
||||
|
||||
DrawFPS(10, 10);
|
||||
|
||||
DrawText("Use keys RGBW to toggle lights", 10, 30, 20, DARKGRAY);
|
||||
|
||||
EndDrawing();
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
|
||||
// De-Initialization
|
||||
//--------------------------------------------------------------------------------------
|
||||
UnloadModel(modelA); // Unload the modelA
|
||||
UnloadModel(modelB); // Unload the modelB
|
||||
UnloadModel(modelC); // Unload the modelC
|
||||
|
||||
UnloadTexture(texture); // Unload the texture
|
||||
UnloadShader(shader); // Unload shader
|
||||
|
||||
CloseWindow(); // Close window and OpenGL context
|
||||
//--------------------------------------------------------------------------------------
|
||||
}
|
@ -23,7 +23,10 @@ pub fn main() anyerror!void {
|
||||
|
||||
var outlineSize: f32 = 2.0;
|
||||
const outlineColor = [4]f32{ 1.0, 0.0, 0.0, 1.0 }; // Normalized RED color
|
||||
const textureSize = rl.Vector2.init(@as(f32, @floatFromInt(texture.width)), @as(f32, @floatFromInt(texture.height)));
|
||||
const textureSize = rl.Vector2.init(
|
||||
@as(f32, @floatFromInt(texture.width)),
|
||||
@as(f32, @floatFromInt(texture.height)),
|
||||
);
|
||||
|
||||
// Get shader locations
|
||||
const outlineSizeLoc = rl.getShaderLocation(shdrOutline, "outlineSize");
|
||||
@ -31,9 +34,24 @@ pub fn main() anyerror!void {
|
||||
const textureSizeLoc = rl.getShaderLocation(shdrOutline, "textureSize");
|
||||
|
||||
// Set shader values (they can be changed later)
|
||||
rl.setShaderValue(shdrOutline, outlineSizeLoc, &outlineSize, @intFromEnum(rl.ShaderUniformDataType.shader_uniform_float));
|
||||
rl.setShaderValue(shdrOutline, outlineColorLoc, &outlineColor, @intFromEnum(rl.ShaderUniformDataType.shader_uniform_vec4));
|
||||
rl.setShaderValue(shdrOutline, textureSizeLoc, &textureSize, @intFromEnum(rl.ShaderUniformDataType.shader_uniform_vec2));
|
||||
rl.setShaderValue(
|
||||
shdrOutline,
|
||||
outlineSizeLoc,
|
||||
&outlineSize,
|
||||
@intFromEnum(rl.ShaderUniformDataType.shader_uniform_float),
|
||||
);
|
||||
rl.setShaderValue(
|
||||
shdrOutline,
|
||||
outlineColorLoc,
|
||||
&outlineColor,
|
||||
@intFromEnum(rl.ShaderUniformDataType.shader_uniform_vec4),
|
||||
);
|
||||
rl.setShaderValue(
|
||||
shdrOutline,
|
||||
textureSizeLoc,
|
||||
&textureSize,
|
||||
@intFromEnum(rl.ShaderUniformDataType.shader_uniform_vec2),
|
||||
);
|
||||
|
||||
rl.setTargetFPS(60); // Set our game to run at 60 frames-per-second
|
||||
//--------------------------------------------------------------------------------------
|
||||
@ -45,7 +63,12 @@ pub fn main() anyerror!void {
|
||||
outlineSize += rl.getMouseWheelMove();
|
||||
if (outlineSize < 1.0) outlineSize = 1.0;
|
||||
|
||||
rl.setShaderValue(shdrOutline, outlineSizeLoc, &outlineSize, @intFromEnum(rl.ShaderUniformDataType.shader_uniform_float));
|
||||
rl.setShaderValue(
|
||||
shdrOutline,
|
||||
outlineSizeLoc,
|
||||
&outlineSize,
|
||||
@intFromEnum(rl.ShaderUniformDataType.shader_uniform_float),
|
||||
);
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
// Draw
|
||||
@ -59,12 +82,22 @@ pub fn main() anyerror!void {
|
||||
rl.beginShaderMode(shdrOutline);
|
||||
defer rl.endShaderMode();
|
||||
|
||||
texture.draw(@divFloor(rl.getScreenWidth(), 2) - @divFloor(texture.width, 2), -30, rl.Color.white);
|
||||
texture.draw(
|
||||
@divFloor(rl.getScreenWidth(), 2) - @divFloor(texture.width, 2),
|
||||
-30,
|
||||
rl.Color.white,
|
||||
);
|
||||
}
|
||||
|
||||
rl.drawText("Shader-based\ntexture\noutline", 10, 10, 20, rl.Color.gray);
|
||||
|
||||
rl.drawText(rl.textFormat("Outline size: %i px", .{@as(i32, @intFromFloat(outlineSize))}), 10, 120, 20, rl.Color.maroon);
|
||||
rl.drawText(
|
||||
rl.textFormat("Outline size: %i px", .{@as(i32, @intFromFloat(outlineSize))}),
|
||||
10,
|
||||
120,
|
||||
20,
|
||||
rl.Color.maroon,
|
||||
);
|
||||
|
||||
rl.drawFPS(710, 10);
|
||||
//----------------------------------------------------------------------------------
|
||||
|
@ -21,7 +21,12 @@ pub fn main() anyerror!void {
|
||||
defer rl.unloadTexture(scarfy); // Texture unloading
|
||||
|
||||
const position = rl.Vector2.init(350.0, 280.0);
|
||||
var frameRec = rl.Rectangle.init(0, 0, @as(f32, @floatFromInt(@divFloor(scarfy.width, 6))), @as(f32, @floatFromInt(scarfy.height)));
|
||||
var frameRec = rl.Rectangle.init(
|
||||
0,
|
||||
0,
|
||||
@as(f32, @floatFromInt(@divFloor(scarfy.width, 6))),
|
||||
@as(f32, @floatFromInt(scarfy.height)),
|
||||
);
|
||||
var currentFrame: u8 = 0;
|
||||
|
||||
var framesCounter: u8 = 0;
|
||||
@ -69,7 +74,13 @@ pub fn main() anyerror!void {
|
||||
|
||||
rl.drawTexture(scarfy, 15, 40, rl.Color.white);
|
||||
rl.drawRectangleLines(15, 40, scarfy.width, scarfy.height, rl.Color.lime);
|
||||
rl.drawRectangleLines(15 + @as(i32, @intFromFloat(frameRec.x)), 40 + @as(i32, @intFromFloat(frameRec.y)), @as(i32, @intFromFloat(frameRec.width)), @as(i32, @intFromFloat(frameRec.height)), rl.Color.red);
|
||||
rl.drawRectangleLines(
|
||||
15 + @as(i32, @intFromFloat(frameRec.x)),
|
||||
40 + @as(i32, @intFromFloat(frameRec.y)),
|
||||
@as(i32, @intFromFloat(frameRec.width)),
|
||||
@as(i32, @intFromFloat(frameRec.height)),
|
||||
rl.Color.red,
|
||||
);
|
||||
|
||||
rl.drawText("FRAME SPEED: ", 165, 210, 10, rl.Color.dark_gray);
|
||||
rl.drawText(rl.textFormat("%02i FPS", .{framesSpeed}), 575, 210, 10, rl.Color.dark_gray);
|
||||
@ -84,7 +95,13 @@ pub fn main() anyerror!void {
|
||||
|
||||
scarfy.drawRec(frameRec, position, rl.Color.white); // Draw part of the texture
|
||||
|
||||
rl.drawText("(c) Scarfy sprite by Eiden Marsal", screenWidth - 200, screenHeight - 20, 10, rl.Color.gray);
|
||||
rl.drawText(
|
||||
"(c) Scarfy sprite by Eiden Marsal",
|
||||
screenWidth - 200,
|
||||
screenHeight - 20,
|
||||
10,
|
||||
rl.Color.gray,
|
||||
);
|
||||
//----------------------------------------------------------------------------------
|
||||
}
|
||||
}
|
||||
|
@ -22,8 +22,8 @@ ZIGGIFY = {
|
||||
}
|
||||
|
||||
|
||||
# Some c types have a different sizes on different systems
|
||||
# and zig knows that so we tell it to get the system specific size for us
|
||||
# Some C types have a different sizes on different systems and Zig
|
||||
# knows that so we tell it to get the system specific size for us.
|
||||
def c_to_zig_type(c: str) -> str:
|
||||
const = "const " if "const " in c else ""
|
||||
c = c.replace("const ", "")
|
||||
@ -38,16 +38,28 @@ def c_to_zig_type(c: str) -> str:
|
||||
def ziggify_type(name: str, t: str) -> str:
|
||||
NO_STRINGS = ["data", "fileData", "compData"]
|
||||
|
||||
single = ["value", "ptr", "bytesRead", "compDataSize", "dataSize", "outputSize", "camera", "collisionPoint", "frames", "image", "colorCount", "dst", "texture", "srcPtr", "dstPtr", "count", "codepointSize", "utf8Size", "position", "mesh", "materialCount", "material", "model", "animCount", "wave", "v1", "v2", "outAxis", "outAngle", "fileSize"]
|
||||
multi = ["data", "compData", "points", "fileData", "colors", "pixels", "fontChars", "chars", "recs", "codepoints", "textList", "transforms", "animations", "samples", "LoadImageColors", "LoadImagePalette", "LoadFontData", "LoadCodepoints", "TextSplit", "LoadMaterials", "LoadModelAnimations", "LoadWaveSamples", "images"]
|
||||
single = [
|
||||
"value", "ptr", "bytesRead", "compDataSize", "dataSize", "outputSize",
|
||||
"camera", "collisionPoint", "frames", "image", "colorCount", "dst",
|
||||
"texture", "srcPtr", "dstPtr", "count", "codepointSize", "utf8Size",
|
||||
"position", "mesh", "materialCount", "material", "model", "animCount",
|
||||
"wave", "v1", "v2", "outAxis", "outAngle", "fileSize"
|
||||
]
|
||||
multi = [
|
||||
"data", "compData", "points", "fileData", "colors", "pixels",
|
||||
"fontChars", "chars", "recs", "codepoints", "textList", "transforms",
|
||||
"animations", "samples", "LoadImageColors", "LoadImagePalette",
|
||||
"LoadFontData", "LoadCodepoints", "TextSplit", "LoadMaterials",
|
||||
"LoadModelAnimations", "LoadWaveSamples", "images"
|
||||
]
|
||||
string = False
|
||||
|
||||
if t.startswith("[*c]") and name not in single and name not in multi:
|
||||
if (t == "[*c]const u8" or t == "[*c]u8") and name not in NO_STRINGS: # strings are multis
|
||||
if (t == "[*c]const u8" or t == "[*c]u8") and name not in NO_STRINGS: # Strings are multis.
|
||||
string = True
|
||||
else:
|
||||
raise ValueError(f"{t} {name} not classified")
|
||||
|
||||
|
||||
pre = ""
|
||||
while t.startswith("[*c]"):
|
||||
t = t[4:]
|
||||
@ -57,7 +69,7 @@ def ziggify_type(name: str, t: str) -> str:
|
||||
pre += "*"
|
||||
else:
|
||||
pre += "[]"
|
||||
|
||||
|
||||
if t in ZIGGIFY:
|
||||
t = ZIGGIFY[t]
|
||||
|
||||
@ -69,14 +81,14 @@ def add_namespace_to_type(t: str) -> str:
|
||||
while t.startswith("[*c]"):
|
||||
t = t[4:]
|
||||
pre += "[*c]"
|
||||
|
||||
|
||||
if t.startswith("const "):
|
||||
t = t[6:]
|
||||
pre += "const "
|
||||
|
||||
if t[0].isupper():
|
||||
t = "rl." + t
|
||||
|
||||
|
||||
if t in ["float3", "float16"]:
|
||||
t = "rlm." + t
|
||||
|
||||
@ -88,12 +100,21 @@ def make_return_cast(source_type: str, dest_type: str, inner: str) -> str:
|
||||
return inner
|
||||
if source_type in ["[*c]const u8", "[*c]u8"]:
|
||||
return f"std.mem.span({inner})"
|
||||
|
||||
|
||||
if source_type in ZIGGIFY:
|
||||
return f"@as({dest_type}, {inner})"
|
||||
|
||||
# These all have to be done manually because their sizes depend on the function arguments
|
||||
if source_type in ["[*c]Color", "[*c]GlyphInfo", "[*c]c_int", "[*c][*c]const u8", "[*c]Material", "[*c]ModelAnimation", "[*c]f32"]:
|
||||
# These all have to be done manually because their sizes depend on the
|
||||
# function arguments.
|
||||
if source_type in [
|
||||
"[*c]Color",
|
||||
"[*c]GlyphInfo",
|
||||
"[*c]c_int",
|
||||
"[*c][*c]const u8",
|
||||
"[*c]Material",
|
||||
"[*c]ModelAnimation",
|
||||
"[*c]f32",
|
||||
]:
|
||||
return None
|
||||
else:
|
||||
raise ValueError(f"Don't know what to do {source_type} {dest_type} {inner}")
|
||||
@ -116,8 +137,8 @@ def fix_pointer(name: str, t: str):
|
||||
|
||||
|
||||
def fix_enums(arg_name, arg_type, func_name):
|
||||
# Hacking specific enums in here
|
||||
# Raylib doesn't use the enums but rather the resulting ints
|
||||
# Hacking specific enums in here.
|
||||
# Raylib doesn't use the enums but rather the resulting ints.
|
||||
if arg_type == "int" or arg_type == "unsigned int":
|
||||
if arg_name == "key":
|
||||
arg_type = "KeyboardKey"
|
||||
@ -130,7 +151,9 @@ def fix_enums(arg_name, arg_type, func_name):
|
||||
arg_type = "CameraMode"
|
||||
elif arg_name == "gesture":
|
||||
arg_type = "Gesture"
|
||||
elif arg_name == "flags" and func_name in ["SetWindowState", "ClearWindowState", "SetConfigFlags"]:
|
||||
elif arg_name == "flags" and func_name in [
|
||||
"SetWindowState", "ClearWindowState", "SetConfigFlags"
|
||||
]:
|
||||
arg_type = "ConfigFlags"
|
||||
elif arg_name == "logLevel":
|
||||
arg_type = "TraceLogLevel"
|
||||
@ -154,7 +177,7 @@ def parse_header(header_name: str, output_file: str, ext_file: str, prefix: str,
|
||||
if line.startswith("typedef struct"):
|
||||
zig_types.add(line.split(' ')[2])
|
||||
elif line.startswith("typedef enum"):
|
||||
# don't trip the general typedef case
|
||||
# Don't trip the general typedef case.
|
||||
pass
|
||||
elif line.startswith("typedef "):
|
||||
zig_types.add(line.split(' ')[2].replace(';', '').strip())
|
||||
@ -173,14 +196,17 @@ def parse_header(header_name: str, output_file: str, ext_file: str, prefix: str,
|
||||
line = line.replace(",", ", ")
|
||||
line = line.replace(" ", " ")
|
||||
|
||||
# each (.*) is some variable value
|
||||
result = re.search(prefix + "(.*) (.*)start_arg(.*)end_arg(.*)", line.replace("(", "start_arg").replace(")", "end_arg"))
|
||||
# Each (.*) is some variable value.
|
||||
result = re.search(
|
||||
prefix + "(.*) (.*)start_arg(.*)end_arg(.*)",
|
||||
line.replace("(", "start_arg").replace(")", "end_arg"),
|
||||
)
|
||||
|
||||
if result is None:
|
||||
leftover += line
|
||||
continue
|
||||
|
||||
# get whats in the (.*)'s
|
||||
# Get whats in the (.*)'s.
|
||||
return_type = result.group(1)
|
||||
func_name = result.group(2)
|
||||
arguments = result.group(3)
|
||||
@ -207,21 +233,20 @@ def parse_header(header_name: str, output_file: str, ext_file: str, prefix: str,
|
||||
if arg == "...":
|
||||
zig_c_arguments.append("...")
|
||||
continue
|
||||
# everything but the last element (for stuff like "const Vector3")
|
||||
# Everything but the last element (for stuff like "const Vector3").
|
||||
arg_type = " ".join(arg.split(" ")[0:-1])
|
||||
arg_name = arg.split(" ")[-1] # last element should be the name
|
||||
arg_name = arg.split(" ")[-1] # Last element should be the name.
|
||||
arg_type = fix_enums(arg_name, arg_type, func_name)
|
||||
|
||||
if arg_name == "type": arg_name = "ty"
|
||||
if arg_name == "type":
|
||||
arg_name = "ty"
|
||||
|
||||
arg_type = c_to_zig_type(arg_type)
|
||||
arg_name, arg_type = fix_pointer(arg_name, arg_type)
|
||||
zig_type = ziggify_type(arg_name, arg_type)
|
||||
|
||||
is_rl_type = arg_type[0].isupper()
|
||||
|
||||
zig_types.add(arg_type)
|
||||
zig_c_arguments.append(arg_name + ": " + add_namespace_to_type(arg_type)) # put everything together
|
||||
zig_c_arguments.append(arg_name + ": " + add_namespace_to_type(arg_type)) # Put everything together.
|
||||
zig_arguments.append(arg_name + ": " + zig_type)
|
||||
if arg_type == zig_type:
|
||||
zig_call_args.append(arg_name)
|
||||
@ -237,7 +262,7 @@ def parse_header(header_name: str, output_file: str, ext_file: str, prefix: str,
|
||||
|
||||
zig_name = convert_name_case(func_name)
|
||||
|
||||
# Todo: ziggify return type
|
||||
# TODO: Ziggify return type
|
||||
zig_arguments = ", ".join(zig_arguments)
|
||||
zig_call_args = ", ".join(zig_call_args)
|
||||
|
||||
@ -271,16 +296,18 @@ def parse_header(header_name: str, output_file: str, ext_file: str, prefix: str,
|
||||
|
||||
if func_name in manual or "FromMemory" in func_name:
|
||||
continue
|
||||
|
||||
|
||||
zig_return = ziggify_type(func_name, return_type)
|
||||
return_cast = make_return_cast(return_type, zig_return, f"cdef.{func_name}({zig_call_args})")
|
||||
|
||||
if return_cast:
|
||||
zig_funcs.append(f"pub fn {zig_name}({zig_arguments}) {zig_return}" +
|
||||
" {\n " +
|
||||
("return " if zig_return != "void" else "") +
|
||||
return_cast + ";"
|
||||
"\n}")
|
||||
zig_funcs.append(
|
||||
f"pub fn {zig_name}({zig_arguments}) {zig_return}" +
|
||||
" {\n " +
|
||||
("return " if zig_return != "void" else "") +
|
||||
return_cast + ";"
|
||||
"\n}"
|
||||
)
|
||||
|
||||
prelude = open(args[0], mode="r").read()
|
||||
ext_prelude = open(args[1], mode="r").read()
|
||||
@ -295,5 +322,19 @@ def parse_header(header_name: str, output_file: str, ext_file: str, prefix: str,
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
parse_header("raylib.h", "raylib-zig.zig", "raylib-zig-ext.zig", "RLAPI ", "preludes/raylib-zig-prelude.zig", "preludes/raylib-zig-ext-prelude.zig")
|
||||
parse_header("raymath.h", "raylib-zig-math.zig", "raylib-zig-math-ext.zig", "RMAPI ", "preludes/raylib-zig-math-prelude.zig", "preludes/raylib-zig-math-ext-prelude.zig")
|
||||
parse_header(
|
||||
"raylib.h",
|
||||
"raylib-zig.zig",
|
||||
"raylib-zig-ext.zig",
|
||||
"RLAPI ",
|
||||
"preludes/raylib-zig-prelude.zig",
|
||||
"preludes/raylib-zig-ext-prelude.zig"
|
||||
)
|
||||
parse_header(
|
||||
"raymath.h",
|
||||
"raylib-zig-math.zig",
|
||||
"raylib-zig-math-ext.zig",
|
||||
"RMAPI ",
|
||||
"preludes/raylib-zig-math-prelude.zig",
|
||||
"preludes/raylib-zig-math-ext-prelude.zig"
|
||||
)
|
||||
|
Loading…
x
Reference in New Issue
Block a user