Compare commits
9 Commits
c4c28f3b7a
...
3e5c51d838
Author | SHA1 | Date | |
---|---|---|---|
3e5c51d838 | |||
10d00e73f7 | |||
e03a5925f8 | |||
4c2cc5135e | |||
7446790256 | |||
01436636d5 | |||
193316f9ee | |||
d4bc5f7f10 | |||
3fb9ea38eb |
6
.gitmodules
vendored
6
.gitmodules
vendored
@ -1,6 +1,6 @@
|
||||
[submodule "libs/zgltf"]
|
||||
path = libs/zgltf
|
||||
url = https://github.com/kooparse/zgltf.git
|
||||
[submodule "libs/raylib/raylib"]
|
||||
path = libs/raylib/raylib
|
||||
url = git@github.com:raysan5/raylib.git
|
||||
[submodule "libs/raygui/raygui"]
|
||||
path = libs/raygui/raygui
|
||||
url = https://github.com/raysan5/raygui
|
||||
|
22
build.zig
22
build.zig
@ -1,5 +1,6 @@
|
||||
const std = @import("std");
|
||||
const raylib = @import("libs/raylib/build.zig");
|
||||
const raygui = @import("libs/raygui/build.zig");
|
||||
|
||||
pub fn build(b: *std.Build) !void {
|
||||
const target = b.standardTargetOptions(.{});
|
||||
@ -15,10 +16,6 @@ pub fn build(b: *std.Build) !void {
|
||||
.target = target
|
||||
});
|
||||
|
||||
exe.addModule("zgltf", b.createModule(.{
|
||||
.source_file = .{ .path = "libs/zgltf/src/main.zig" },
|
||||
}));
|
||||
|
||||
// Provide filenames of all files in 'src/ROMs' to program as options
|
||||
{
|
||||
var files = std.ArrayList([]const u8).init(b.allocator);
|
||||
@ -37,21 +34,8 @@ pub fn build(b: *std.Build) !void {
|
||||
exe.addOptions("options", options);
|
||||
}
|
||||
|
||||
raylib.addTo(b, exe, target, optimize, .{});
|
||||
|
||||
{
|
||||
var build_models_step = b.step("models", "Export .blend files");
|
||||
var build_models = b.addSystemCommand(&[_][]const u8{ "blender" });
|
||||
build_models.addFileArg(.{ .path = "src/assets/models/emulator.blend" });
|
||||
build_models.addArg("--background");
|
||||
build_models.addArg("--python");
|
||||
build_models.addFileArg(.{ .path = "src/assets/models/export.py" });
|
||||
build_models.addArg("--");
|
||||
build_models.addArg("src/assets/models/emulator.glb");
|
||||
|
||||
build_models_step.dependOn(&build_models.step);
|
||||
exe.step.dependOn(build_models_step);
|
||||
}
|
||||
raylib.addTo(b, exe, target, optimize, .{ });
|
||||
raygui.addTo(b, exe, target, optimize);
|
||||
|
||||
const run_cmd = b.addRunArtifact(exe);
|
||||
|
||||
|
21
libs/raygui/LICENSE
Normal file
21
libs/raygui/LICENSE
Normal file
@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2022 Michael Scherbakow
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
81
libs/raygui/README.md
Normal file
81
libs/raygui/README.md
Normal file
@ -0,0 +1,81 @@
|
||||

|
||||
|
||||
# raygui.zig
|
||||
Idiomatic [raygui](https://github.com/raysan5/raygui) **RAYGUIAPI** (raygui.h) bindings for [Zig](https://ziglang.org/) (master).
|
||||
|
||||
## usage
|
||||
|
||||
The easy way would be adding this as submodule directly in your source folder.
|
||||
Thats what I do until there is an official package manager for Zig.
|
||||
|
||||
```sh
|
||||
cd $YOUR_SRC_FOLDER
|
||||
git submodule add https://github.com/ryupold/raygui.zig raygui
|
||||
git submodule update --init --recursive
|
||||
```
|
||||
|
||||
The bindings have been prebuilt so you just need to add raylib as module
|
||||
|
||||
build.zig:
|
||||
```zig
|
||||
const raylib = @import("path/to/raylib.zig/build.zig");
|
||||
const raygui = @import("path/to/raygui.zig/build.zig");
|
||||
|
||||
pub fn build(b: *std.Build) !void {
|
||||
const target = b.standardTargetOptions(.{});
|
||||
const mode = b.standardOptimizeOption(.{});
|
||||
const exe = ...;
|
||||
raylib.addTo(b, exe, target, mode);
|
||||
raygui.addTo(b, exe, target, mode);
|
||||
}
|
||||
```
|
||||
|
||||
and import in main.zig:
|
||||
```zig
|
||||
const raylib = @import("raylib");
|
||||
const raygui = @import("raygui");
|
||||
|
||||
pub fn main() void {
|
||||
raylib.InitWindow(800, 800, "hello world!");
|
||||
raylib.SetConfigFlags(.FLAG_WINDOW_RESIZABLE);
|
||||
raylib.SetTargetFPS(60);
|
||||
|
||||
defer raylib.CloseWindow();
|
||||
|
||||
while (!raylib.WindowShouldClose()) {
|
||||
raylib.BeginDrawing();
|
||||
defer raylib.EndDrawing();
|
||||
|
||||
raylib.ClearBackground(raylib.BLACK);
|
||||
raylib.DrawFPS(10, 10);
|
||||
|
||||
if (raygui.GuiButton(.{ .x = 100, .y = 100, .width = 200, .height = 100 }, "press me!")) {
|
||||
std.debug.print("pressed\n", .{});
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
> See `build.zig` in [examples-raylib.zig](https://github.com/ryupold/examples-raylib.zig) for how to build.
|
||||
|
||||
> Note: you only need the files `raygui.zig`, `raygui_marshal.h` and `raygui_marshal.c` for this to work
|
||||
>
|
||||
This weird workaround with `raygui_marshal.h/raygui_marshal.c` I actually had to make for Webassembly builds to work, because passing structs as function parameters or returning them cannot be done on the Zig side somehow. If I try it, I get a runtime error "index out of bounds". This happens only in WebAssembly builds. So `raygui_marshal.c` must be compiled with `emcc`. See [build.zig](https://github.com/ryupold/examples-raylib.zig/blob/main/build.zig) in the examples.
|
||||
|
||||
## custom definitions
|
||||
An easy way to fix binding mistakes is to edit them in `bindings.json` and setting the custom flag to true. This way the binding will not be overriden when calling `zig build intermediate`.
|
||||
Additionally you can add custom definitions into `inject.zig, inject.h, inject.c` these files will be prepended accordingly.
|
||||
|
||||
## disclaimer
|
||||
I have NOT tested most of the generated functions, so there might be bugs. Especially when it comes to pointers as it is not decidable (for the generator) what a pointer to C means. Could be single item, array, sentinel terminated and/or nullable. If you run into crashes using one of the functions or types in `raygui.zig` feel free to [create an issue](https://github.com/ryupold/raygui.zig/issues) and I will look into it.
|
||||
|
||||
## generate bindings
|
||||
for current raygui source (submodule)
|
||||
|
||||
```sh
|
||||
zig build parse # create JSON files with raylib_parser
|
||||
zig build intermediate # generate bindings.json (keeps definitions with custom=true)
|
||||
zig build bindings # write all intermediate bindings to raylib.zig
|
||||
```
|
||||
|
||||
For easier diffing and to follow changes to the raygui repository I commit also the generated json files.
|
3419
libs/raygui/bindings.json
Normal file
3419
libs/raygui/bindings.json
Normal file
File diff suppressed because it is too large
Load Diff
87
libs/raygui/build.zig
Normal file
87
libs/raygui/build.zig
Normal file
@ -0,0 +1,87 @@
|
||||
const std = @import("std");
|
||||
const generate = @import("generate.zig");
|
||||
|
||||
const rayguiSrc = "raygui/src/";
|
||||
|
||||
pub fn build(b: *std.Build) !void {
|
||||
const target = b.standardTargetOptions(.{});
|
||||
|
||||
//--- parse raygui and generate JSONs for all signatures --------------------------------------
|
||||
const jsons = b.step("parse", "parse raygui headers and generate raylib parser output as json");
|
||||
const raylib_parser_build = b.addExecutable(.{
|
||||
.name = "raylib_parser",
|
||||
.root_source_file = std.build.FileSource.relative("raylib_parser.zig"),
|
||||
.target = target,
|
||||
.optimize = .ReleaseFast,
|
||||
});
|
||||
raylib_parser_build.addCSourceFile(.{ .file = .{ .path = "../raylib/raylib/parser/raylib_parser.c" }, .flags = &.{} });
|
||||
raylib_parser_build.linkLibC();
|
||||
|
||||
//raygui
|
||||
const raygui_H = b.addRunArtifact(raylib_parser_build);
|
||||
raygui_H.addArgs(&.{
|
||||
"-i", "raygui/src/raygui.h",
|
||||
"-o", "raygui.json",
|
||||
"-f", "JSON",
|
||||
"-d", "RAYGUIAPI",
|
||||
});
|
||||
jsons.dependOn(&raygui_H.step);
|
||||
|
||||
//--- Generate intermediate -------------------------------------------------------------------
|
||||
const intermediate = b.step("intermediate", "generate intermediate representation of the results from 'zig build parse' (keep custom=true)");
|
||||
var intermediateZig = b.addRunArtifact(b.addExecutable(.{
|
||||
.name = "intermediate",
|
||||
.root_source_file = std.build.FileSource.relative("intermediate.zig"),
|
||||
.target = target,
|
||||
}));
|
||||
intermediate.dependOn(&intermediateZig.step);
|
||||
|
||||
//--- Generate bindings -----------------------------------------------------------------------
|
||||
const bindings = b.step("bindings", "generate bindings in from bindings.json");
|
||||
var generateZig = b.addRunArtifact(b.addExecutable(.{
|
||||
.name = "generate",
|
||||
.root_source_file = std.build.FileSource.relative("generate.zig"),
|
||||
.target = target,
|
||||
}));
|
||||
const fmt = b.addFmt(.{ .paths = &.{generate.outputFile} });
|
||||
fmt.step.dependOn(&generateZig.step);
|
||||
bindings.dependOn(&fmt.step);
|
||||
|
||||
//--- just build raylib_parser.exe ------------------------------------------------------------
|
||||
const raylib_parser_install = b.step("raylib_parser", "build ./zig-out/bin/raylib_parser.exe");
|
||||
const generateBindings_install = b.addInstallArtifact(raylib_parser_build, .{});
|
||||
raylib_parser_install.dependOn(&generateBindings_install.step);
|
||||
}
|
||||
|
||||
// above: generate library
|
||||
// below: linking (use as dependency)
|
||||
|
||||
fn current_file() []const u8 {
|
||||
return @src().file;
|
||||
}
|
||||
|
||||
const cwd = std.fs.path.dirname(current_file()).?;
|
||||
const sep = std.fs.path.sep_str;
|
||||
const dir_raygui = cwd ++ sep ++ "raygui/src";
|
||||
|
||||
/// add this package to lib
|
||||
pub fn addTo(b: *std.Build, lib: *std.build.LibExeObjStep, target: std.zig.CrossTarget, optimize: std.builtin.Mode) void {
|
||||
_ = b;
|
||||
_ = optimize;
|
||||
_ = target;
|
||||
|
||||
if (lib.modules.get("raylib") orelse lib.modules.get("raylib.zig") orelse lib.modules.get("raylib-zig")) |raylib| {
|
||||
lib.addAnonymousModule("raygui", .{
|
||||
.source_file = .{ .path = cwd ++ sep ++ "raygui.zig" },
|
||||
.dependencies = &.{
|
||||
.{ .name = "raylib", .module = raylib },
|
||||
},
|
||||
});
|
||||
lib.addIncludePath(.{ .path = dir_raygui });
|
||||
lib.addIncludePath(.{ .path = cwd });
|
||||
lib.linkLibC();
|
||||
lib.addCSourceFile(.{ .file = .{ .path = cwd ++ sep ++ "raygui_marshal.c" }, .flags = &.{"-DRAYGUI_IMPLEMENTATION"} });
|
||||
} else {
|
||||
std.debug.panic("lib needs to have 'raylib', 'raylib.zig' or 'raylib-zig' as module dependency", .{});
|
||||
}
|
||||
}
|
533
libs/raygui/generate.zig
Normal file
533
libs/raygui/generate.zig
Normal file
@ -0,0 +1,533 @@
|
||||
const std = @import("std");
|
||||
const fs = std.fs;
|
||||
const json = std.json;
|
||||
const allocPrint = std.fmt.allocPrint;
|
||||
const mapping = @import("type_mapping.zig");
|
||||
const intermediate = @import("intermediate.zig");
|
||||
|
||||
pub const outputFile = "raygui.zig";
|
||||
pub const injectFile = "inject.zig";
|
||||
pub const marshalFilePrefix = "raygui_marshal";
|
||||
|
||||
fn trim(s: []const u8) []const u8 {
|
||||
return std.mem.trim(u8, s, &[_]u8{ ' ', '\t', '\n' });
|
||||
}
|
||||
|
||||
pub fn main() !void {
|
||||
std.log.info("generating raygui.zig ...", .{});
|
||||
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
|
||||
defer {
|
||||
if (gpa.deinit() == .leak) {
|
||||
std.log.err("memory leak detected", .{});
|
||||
}
|
||||
}
|
||||
const allocator = gpa.allocator();
|
||||
var arena = std.heap.ArenaAllocator.init(allocator);
|
||||
defer arena.deinit();
|
||||
|
||||
const bindingsData = try fs.cwd().readFileAlloc(arena.allocator(), intermediate.bindingsJSON, std.math.maxInt(usize));
|
||||
|
||||
const bindings = try json.parseFromSliceLeaky(mapping.Intermediate, arena.allocator(), bindingsData, .{
|
||||
.ignore_unknown_fields = true,
|
||||
});
|
||||
|
||||
var file = try fs.cwd().createFile(outputFile, .{});
|
||||
defer file.close();
|
||||
|
||||
try file.writeAll("\n\n");
|
||||
|
||||
const inject = try Injections.load(arena.allocator());
|
||||
try writeInjections(arena.allocator(), &file, inject);
|
||||
|
||||
try writeFunctions(arena.allocator(), &file, bindings, inject);
|
||||
var h = try fs.cwd().createFile(marshalFilePrefix ++ ".h", .{});
|
||||
defer h.close();
|
||||
var c = try fs.cwd().createFile(marshalFilePrefix ++ ".c", .{});
|
||||
defer c.close();
|
||||
const raylib: mapping.CombinedRaylib = try mapping.CombinedRaylib.load(arena.allocator(), intermediate.jsonFiles);
|
||||
try writeCFunctions(arena.allocator(), &h, &c, inject, raylib);
|
||||
|
||||
try writeStructs(arena.allocator(), &file, bindings, inject);
|
||||
try writeEnums(arena.allocator(), &file, bindings, inject);
|
||||
try writeDefines(arena.allocator(), &file, bindings, inject);
|
||||
|
||||
std.log.info("... done", .{});
|
||||
}
|
||||
|
||||
const Injections = struct {
|
||||
lines: []const []const u8,
|
||||
symbols: []const []const u8,
|
||||
|
||||
pub fn load(allocator: std.mem.Allocator) !@This() {
|
||||
var injectZigLines = std.ArrayList([]const u8).init(allocator);
|
||||
var symbols = std.ArrayList([]const u8).init(allocator);
|
||||
|
||||
var file = try fs.cwd().openFile(injectFile, .{});
|
||||
var reader = file.reader();
|
||||
while (try reader.readUntilDelimiterOrEofAlloc(allocator, '\n', std.math.maxInt(usize))) |line| {
|
||||
if (std.mem.indexOf(u8, line, "pub const ")) |startIndex| {
|
||||
if (std.mem.indexOf(u8, line, " = extern struct {")) |endIndex| {
|
||||
const s = line["pub const ".len + startIndex .. endIndex];
|
||||
try symbols.append(s);
|
||||
std.log.debug("inject symbol: {s}", .{s});
|
||||
} else if (std.mem.indexOf(u8, line, " = raylib.")) |endIndex| {
|
||||
const s = line["pub const ".len + startIndex .. endIndex];
|
||||
try symbols.append(s);
|
||||
std.log.debug("inject symbol: {s}", .{s});
|
||||
}
|
||||
}
|
||||
if (std.mem.indexOf(u8, line, "pub fn ")) |startIndex| {
|
||||
if (std.mem.indexOf(u8, line, "(")) |endIndex| {
|
||||
const s = line["pub fn ".len + startIndex .. endIndex];
|
||||
try symbols.append(s);
|
||||
std.log.debug("inject symbol: {s}", .{s});
|
||||
}
|
||||
}
|
||||
try injectZigLines.append(line);
|
||||
}
|
||||
|
||||
return @This(){
|
||||
.lines = try injectZigLines.toOwnedSlice(),
|
||||
.symbols = try symbols.toOwnedSlice(),
|
||||
};
|
||||
}
|
||||
|
||||
pub fn containsSymbol(self: @This(), name: []const u8) bool {
|
||||
for (self.symbols) |s| {
|
||||
if (eql(s, name)) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
fn writeFunctions(
|
||||
allocator: std.mem.Allocator,
|
||||
file: *fs.File,
|
||||
bindings: mapping.Intermediate,
|
||||
inject: Injections,
|
||||
) !void {
|
||||
var buf: [51200]u8 = undefined;
|
||||
var fba = std.heap.FixedBufferAllocator.init(&buf);
|
||||
|
||||
for (bindings.functions) |func| {
|
||||
if (inject.containsSymbol(func.name)) continue;
|
||||
defer fba.reset();
|
||||
|
||||
//--- signature -------------------------
|
||||
const funcDescription: []const u8 = func.description orelse "";
|
||||
try file.writeAll(
|
||||
try allocPrint(
|
||||
allocator,
|
||||
"\n/// {s}\npub fn {s} (\n",
|
||||
.{ funcDescription, func.name },
|
||||
),
|
||||
);
|
||||
|
||||
for (func.params) |param| {
|
||||
if (param.description) |description| {
|
||||
try file.writeAll(try allocPrint(
|
||||
allocator,
|
||||
"/// {s}\n",
|
||||
.{description},
|
||||
));
|
||||
}
|
||||
try file.writeAll(try allocPrint(
|
||||
allocator,
|
||||
"{s}: {s},\n",
|
||||
.{ param.name, param.typ },
|
||||
));
|
||||
}
|
||||
|
||||
if (func.custom) {
|
||||
try file.writeAll(
|
||||
try allocPrint(
|
||||
allocator,
|
||||
") {s} {{\n",
|
||||
.{func.returnType},
|
||||
),
|
||||
);
|
||||
} else if (isPointer(func.returnType)) {
|
||||
if (eql("u8", (stripType(func.returnType)))) {
|
||||
try file.writeAll(
|
||||
try allocPrint(
|
||||
allocator,
|
||||
") [*:0]const {s} {{\n",
|
||||
.{stripType(func.returnType)},
|
||||
),
|
||||
);
|
||||
} else {
|
||||
try file.writeAll(
|
||||
try allocPrint(
|
||||
allocator,
|
||||
") {s} {{\n",
|
||||
.{func.returnType},
|
||||
),
|
||||
);
|
||||
}
|
||||
} else {
|
||||
try file.writeAll(
|
||||
try allocPrint(
|
||||
allocator,
|
||||
") {s} {{\n",
|
||||
.{func.returnType},
|
||||
),
|
||||
);
|
||||
}
|
||||
const returnTypeIsVoid = eql(func.returnType, "void");
|
||||
|
||||
//--- body ------------------------------
|
||||
if (isPointer(func.returnType)) {
|
||||
try file.writeAll(try allocPrint(allocator, "return @ptrCast({s},\n", .{func.returnType}));
|
||||
} else if (isPrimitiveOrPointer(func.returnType)) {
|
||||
try file.writeAll("return ");
|
||||
} else if (!returnTypeIsVoid) {
|
||||
try file.writeAll(try allocPrint(allocator, "var out: {s} = undefined;\n", .{func.returnType}));
|
||||
}
|
||||
try file.writeAll(try allocPrint(allocator, "raygui.m{s}(\n", .{func.name}));
|
||||
|
||||
if (!isPrimitiveOrPointer(func.returnType)) {
|
||||
if (bindings.containsStruct(stripType(func.returnType))) {
|
||||
try file.writeAll(try allocPrint(allocator, "@ptrCast([*c]raygui.{s}, &out),\n", .{func.returnType}));
|
||||
} else if (!returnTypeIsVoid) {
|
||||
try file.writeAll(try allocPrint(allocator, "@ptrCast([*c]{s}, &out),\n", .{func.returnType}));
|
||||
}
|
||||
}
|
||||
|
||||
for (func.params) |param| {
|
||||
if (isFunctionPointer(param.typ)) {
|
||||
try file.writeAll(try allocPrint(allocator, "@ptrCast({s}),\n", .{param.name}));
|
||||
} else if (bindings.containsStruct(stripType(param.typ)) and isPointer(param.typ)) {
|
||||
try file.writeAll(try allocPrint(allocator, "@intToPtr([*c]raygui.{s}, @ptrToInt({s})),\n", .{ stripType(param.typ), param.name }));
|
||||
} else if (bindings.containsEnum(param.typ)) {
|
||||
try file.writeAll(try allocPrint(allocator, "@enumToInt({s}),\n", .{param.name}));
|
||||
} else if (bindings.containsStruct(stripType(param.typ))) {
|
||||
try file.writeAll(try allocPrint(allocator, "@intToPtr([*c]raygui.{s}, @ptrToInt(&{s})),\n", .{ stripType(param.typ), param.name }));
|
||||
} else if (isPointer(param.typ)) {
|
||||
if (isConst(param.typ)) {
|
||||
const stripped = stripType(param.typ);
|
||||
if (isPointer(stripped) and isConst(stripped)) {
|
||||
try file.writeAll(try allocPrint(allocator, "@intToPtr([*c][*c]const {s}, @ptrToInt({s})),\n", .{ stripType(stripped), param.name }));
|
||||
} else {
|
||||
try file.writeAll(try allocPrint(allocator, "@intToPtr([*c]const {s}, @ptrToInt({s})),\n", .{ stripped, param.name }));
|
||||
}
|
||||
} else {
|
||||
try file.writeAll(try allocPrint(allocator, "@ptrCast([*c]{s}, {s}),\n", .{ stripType(param.typ), param.name }));
|
||||
}
|
||||
} else {
|
||||
try file.writeAll(try allocPrint(allocator, "{s},\n", .{param.name}));
|
||||
}
|
||||
}
|
||||
|
||||
if (isPointer(func.returnType)) {
|
||||
try file.writeAll("),\n);\n");
|
||||
} else {
|
||||
try file.writeAll(");\n");
|
||||
}
|
||||
|
||||
if (!isPrimitiveOrPointer(func.returnType) and !returnTypeIsVoid) {
|
||||
try file.writeAll("return out;\n");
|
||||
}
|
||||
|
||||
try file.writeAll("}\n");
|
||||
}
|
||||
|
||||
std.log.info("generated functions", .{});
|
||||
}
|
||||
|
||||
/// write: RETURN NAME(PARAMS...)
|
||||
/// or: void NAME(RETURN*, PARAMS...)
|
||||
fn writeCSignature(
|
||||
allocator: std.mem.Allocator,
|
||||
file: *fs.File,
|
||||
func: mapping.RaylibFunction,
|
||||
) !void {
|
||||
const returnType = func.returnType;
|
||||
|
||||
//return directly
|
||||
if (mapping.isPrimitiveOrPointer(returnType)) {
|
||||
try file.writeAll(try allocPrint(allocator, "{s} m{s}(", .{ returnType, func.name }));
|
||||
if (func.params == null or func.params.?.len == 0) {
|
||||
try file.writeAll("void");
|
||||
}
|
||||
}
|
||||
//wrap return type and put as first function parameter
|
||||
else {
|
||||
try file.writeAll(try allocPrint(allocator, "void m{s}({s} *out", .{ func.name, returnType }));
|
||||
if (func.params != null and func.params.?.len > 0) {
|
||||
try file.writeAll(", ");
|
||||
}
|
||||
}
|
||||
|
||||
if (func.params) |params| {
|
||||
for (params, 0..) |param, i| {
|
||||
const paramType = param.type;
|
||||
if (mapping.isPrimitiveOrPointer(paramType) or isFunctionPointer(paramType)) {
|
||||
try file.writeAll(try allocPrint(allocator, "{s} {s}", .{ paramType, param.name }));
|
||||
} else {
|
||||
try file.writeAll(try allocPrint(allocator, "{s} *{s}", .{ paramType, param.name }));
|
||||
}
|
||||
|
||||
if (i < params.len - 1) {
|
||||
try file.writeAll(", ");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
try file.writeAll(")");
|
||||
}
|
||||
|
||||
fn writeCFunctions(
|
||||
allocator: std.mem.Allocator,
|
||||
h: *fs.File,
|
||||
c: *fs.File,
|
||||
inject: Injections,
|
||||
rl: mapping.CombinedRaylib,
|
||||
) !void {
|
||||
var hInject = try fs.cwd().openFile("inject.h", .{});
|
||||
defer hInject.close();
|
||||
try h.writeFileAll(hInject, .{});
|
||||
var cInject = try fs.cwd().openFile("inject.c", .{});
|
||||
defer cInject.close();
|
||||
try c.writeFileAll(cInject, .{});
|
||||
|
||||
for (rl.functions.values()) |func| {
|
||||
if (inject.containsSymbol(func.name)) continue;
|
||||
|
||||
//--- C-HEADER -----------------------------
|
||||
|
||||
try h.writeAll(try allocPrint(allocator, "// {s}\n", .{func.description}));
|
||||
try writeCSignature(allocator, h, func);
|
||||
try h.writeAll(";\n\n");
|
||||
|
||||
try writeCSignature(allocator, c, func);
|
||||
try c.writeAll("\n{\n");
|
||||
|
||||
//--- C-IMPLEMENT -----------------------------
|
||||
|
||||
if (eql(func.returnType, "void")) {
|
||||
try c.writeAll("\t");
|
||||
} else if (mapping.isPrimitiveOrPointer(func.returnType)) {
|
||||
try c.writeAll("\treturn ");
|
||||
} else {
|
||||
try c.writeAll("\t*out = ");
|
||||
}
|
||||
|
||||
try c.writeAll(
|
||||
try allocPrint(
|
||||
allocator,
|
||||
"{s}(",
|
||||
.{func.name},
|
||||
),
|
||||
);
|
||||
|
||||
if (func.params) |params| {
|
||||
for (params, 0..) |param, i| {
|
||||
if (mapping.isPrimitiveOrPointer(param.type) or isFunctionPointer(param.type)) {
|
||||
try c.writeAll(
|
||||
try allocPrint(
|
||||
allocator,
|
||||
"{s}",
|
||||
.{param.name},
|
||||
),
|
||||
);
|
||||
} else {
|
||||
try c.writeAll(
|
||||
try allocPrint(
|
||||
allocator,
|
||||
"*{s}",
|
||||
.{param.name},
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
if (i < params.len - 1) {
|
||||
try c.writeAll(", ");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
try c.writeAll(");\n}\n\n");
|
||||
}
|
||||
}
|
||||
|
||||
fn writeStructs(
|
||||
allocator: std.mem.Allocator,
|
||||
file: *fs.File,
|
||||
bindings: mapping.Intermediate,
|
||||
inject: Injections,
|
||||
) !void {
|
||||
var buf: [51200]u8 = undefined;
|
||||
var fba = std.heap.FixedBufferAllocator.init(&buf);
|
||||
|
||||
for (bindings.structs) |s| {
|
||||
if (inject.containsSymbol(s.name)) continue;
|
||||
defer fba.reset();
|
||||
|
||||
try file.writeAll(
|
||||
try allocPrint(
|
||||
allocator,
|
||||
"\n/// {?s}\npub const {s} = extern struct {{\n",
|
||||
.{ s.description, s.name },
|
||||
),
|
||||
);
|
||||
|
||||
for (s.fields) |field| {
|
||||
try file.writeAll(try allocPrint(allocator, "/// {?s}\n\t{s}: {s},\n", .{
|
||||
field.description,
|
||||
field.name,
|
||||
field.typ,
|
||||
}));
|
||||
}
|
||||
|
||||
try file.writeAll("\n};\n");
|
||||
}
|
||||
|
||||
std.log.info("generated structs", .{});
|
||||
}
|
||||
|
||||
fn writeEnums(
|
||||
allocator: std.mem.Allocator,
|
||||
file: *fs.File,
|
||||
bindings: mapping.Intermediate,
|
||||
inject: Injections,
|
||||
) !void {
|
||||
var buf: [51200]u8 = undefined;
|
||||
var fba = std.heap.FixedBufferAllocator.init(&buf);
|
||||
|
||||
for (bindings.enums) |e| {
|
||||
if (inject.containsSymbol(e.name)) continue;
|
||||
defer fba.reset();
|
||||
|
||||
try file.writeAll(
|
||||
try allocPrint(
|
||||
allocator,
|
||||
"\n/// {?s}\npub const {s} = enum(i32) {{\n",
|
||||
.{ e.description, e.name },
|
||||
),
|
||||
);
|
||||
|
||||
for (e.values) |value| {
|
||||
try file.writeAll(try allocPrint(allocator, "/// {?s}\n{s} = {d},\n", .{
|
||||
value.description,
|
||||
value.name,
|
||||
value.value,
|
||||
}));
|
||||
}
|
||||
|
||||
try file.writeAll("\n};\n");
|
||||
}
|
||||
|
||||
std.log.info("generated enums", .{});
|
||||
}
|
||||
|
||||
fn writeDefines(
|
||||
allocator: std.mem.Allocator,
|
||||
file: *fs.File,
|
||||
bindings: mapping.Intermediate,
|
||||
inject: Injections,
|
||||
) !void {
|
||||
var buf: [51200]u8 = undefined;
|
||||
var fba = std.heap.FixedBufferAllocator.init(&buf);
|
||||
|
||||
for (bindings.defines) |d| {
|
||||
if (inject.containsSymbol(d.name)) continue;
|
||||
defer fba.reset();
|
||||
|
||||
try file.writeAll(
|
||||
try allocPrint(
|
||||
allocator,
|
||||
"\n/// {?s}\npub const {s}: {s} = {s};\n",
|
||||
.{ d.description, d.name, d.typ, d.value },
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
std.log.info("generated defines", .{});
|
||||
}
|
||||
|
||||
fn writeInjections(
|
||||
_: std.mem.Allocator,
|
||||
file: *fs.File,
|
||||
inject: Injections,
|
||||
) !void {
|
||||
var buf: [51200]u8 = undefined;
|
||||
var fba = std.heap.FixedBufferAllocator.init(&buf);
|
||||
|
||||
for (inject.lines) |line| {
|
||||
defer fba.reset();
|
||||
|
||||
try file.writeAll(try allocPrint(fba.allocator(), "{s}\n", .{line}));
|
||||
}
|
||||
|
||||
std.log.info("written inject.zig", .{});
|
||||
}
|
||||
|
||||
fn eql(a: []const u8, b: []const u8) bool {
|
||||
return std.mem.eql(u8, a, b);
|
||||
}
|
||||
|
||||
fn startsWith(haystack: []const u8, needle: []const u8) bool {
|
||||
return std.mem.startsWith(u8, haystack, needle);
|
||||
}
|
||||
|
||||
fn endsWith(haystack: []const u8, needle: []const u8) bool {
|
||||
return std.mem.endsWith(u8, haystack, needle);
|
||||
}
|
||||
|
||||
/// is c pointer type
|
||||
fn isPointer(z: []const u8) bool {
|
||||
return pointerOffset(z) > 0;
|
||||
}
|
||||
|
||||
fn isFunctionPointer(z: []const u8) bool {
|
||||
return std.mem.indexOf(u8, z, "fn(") != null or std.mem.endsWith(u8, z, "Callback");
|
||||
}
|
||||
|
||||
fn pointerOffset(z: []const u8) usize {
|
||||
if (startsWith(z, "*")) return 1;
|
||||
if (startsWith(z, "?*")) return 2;
|
||||
if (startsWith(z, "[*]")) return 3;
|
||||
if (startsWith(z, "?[*]")) return 4;
|
||||
if (startsWith(z, "[*c]")) return 4;
|
||||
if (startsWith(z, "[*:0]")) return 5;
|
||||
if (startsWith(z, "?[*:0]")) return 6;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
fn isConst(z: []const u8) bool {
|
||||
return startsWith(z[pointerOffset(z)..], "const ");
|
||||
}
|
||||
|
||||
fn isVoid(z: []const u8) bool {
|
||||
return eql(stripType(z), "void");
|
||||
}
|
||||
|
||||
/// strips const and pointer annotations
|
||||
/// *const TName -> TName
|
||||
fn stripType(z: []const u8) []const u8 {
|
||||
var name = z[pointerOffset(z)..];
|
||||
name = if (startsWith(name, "const ")) name["const ".len..] else name;
|
||||
|
||||
return std.mem.trim(u8, name, " \t\n");
|
||||
}
|
||||
|
||||
/// true if Zig type is primitive or a pointer to anything
|
||||
/// this means we don't need to wrap it in a pointer
|
||||
pub fn isPrimitiveOrPointer(z: []const u8) bool {
|
||||
const primitiveTypes = std.ComptimeStringMap(void, .{
|
||||
// .{ "void", {} }, // zig void is zero sized while C void is >= 1 byte
|
||||
.{ "bool", {} },
|
||||
.{ "u8", {} },
|
||||
.{ "i8", {} },
|
||||
.{ "i16", {} },
|
||||
.{ "u16", {} },
|
||||
.{ "i32", {} },
|
||||
.{ "u32", {} },
|
||||
.{ "i64", {} },
|
||||
.{ "u64", {} },
|
||||
.{ "f32", {} },
|
||||
.{ "f64", {} },
|
||||
});
|
||||
return primitiveTypes.has(stripType(z)) or pointerOffset(z) > 0;
|
||||
}
|
547
libs/raygui/gui_icons.h
Normal file
547
libs/raygui/gui_icons.h
Normal file
@ -0,0 +1,547 @@
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// raygui Icons exporter v1.1 - Icons data exported as a values array //
|
||||
// //
|
||||
// more info and bugs-report: github.com/raysan5/raygui //
|
||||
// feedback and support: ray[at]raylibtech.com //
|
||||
// //
|
||||
// Copyright (c) 2019-2021 raylib technologies (@raylibtech) //
|
||||
// //
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
// Defines and Macros
|
||||
//----------------------------------------------------------------------------------
|
||||
#define RAYGUI_ICON_SIZE 16 // Size of icons (squared)
|
||||
#define RAYGUI_ICON_MAX_ICONS 256 // Maximum number of icons
|
||||
#define RAYGUI_ICON_MAX_NAME_LENGTH 32 // Maximum length of icon name id
|
||||
|
||||
// Icons data is defined by bit array (every bit represents one pixel)
|
||||
// Those arrays are stored as unsigned int data arrays, so every array
|
||||
// element defines 32 pixels (bits) of information
|
||||
// Number of elemens depend on RAYGUI_ICON_SIZE (by default 16x16 pixels)
|
||||
#define RAYGUI_ICON_DATA_ELEMENTS (RAYGUI_ICON_SIZE*RAYGUI_ICON_SIZE/32)
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
// Icons enumeration
|
||||
//----------------------------------------------------------------------------------
|
||||
typedef enum {
|
||||
RAYGUI_ICON_NONE = 0,
|
||||
RAYGUI_ICON_FOLDER_FILE_OPEN = 1,
|
||||
RAYGUI_ICON_FILE_SAVE_CLASSIC = 2,
|
||||
RAYGUI_ICON_FOLDER_OPEN = 3,
|
||||
RAYGUI_ICON_FOLDER_SAVE = 4,
|
||||
RAYGUI_ICON_FILE_OPEN = 5,
|
||||
RAYGUI_ICON_FILE_SAVE = 6,
|
||||
RAYGUI_ICON_FILE_EXPORT = 7,
|
||||
RAYGUI_ICON_FILE_NEW = 8,
|
||||
RAYGUI_ICON_FILE_DELETE = 9,
|
||||
RAYGUI_ICON_FILETYPE_TEXT = 10,
|
||||
RAYGUI_ICON_FILETYPE_AUDIO = 11,
|
||||
RAYGUI_ICON_FILETYPE_IMAGE = 12,
|
||||
RAYGUI_ICON_FILETYPE_PLAY = 13,
|
||||
RAYGUI_ICON_FILETYPE_VIDEO = 14,
|
||||
RAYGUI_ICON_FILETYPE_INFO = 15,
|
||||
RAYGUI_ICON_FILE_COPY = 16,
|
||||
RAYGUI_ICON_FILE_CUT = 17,
|
||||
RAYGUI_ICON_FILE_PASTE = 18,
|
||||
RAYGUI_ICON_CURSOR_HAND = 19,
|
||||
RAYGUI_ICON_CURSOR_POINTER = 20,
|
||||
RAYGUI_ICON_CURSOR_CLASSIC = 21,
|
||||
RAYGUI_ICON_PENCIL = 22,
|
||||
RAYGUI_ICON_PENCIL_BIG = 23,
|
||||
RAYGUI_ICON_BRUSH_CLASSIC = 24,
|
||||
RAYGUI_ICON_BRUSH_PAINTER = 25,
|
||||
RAYGUI_ICON_WATER_DROP = 26,
|
||||
RAYGUI_ICON_COLOR_PICKER = 27,
|
||||
RAYGUI_ICON_RUBBER = 28,
|
||||
RAYGUI_ICON_COLOR_BUCKET = 29,
|
||||
RAYGUI_ICON_TEXT_T = 30,
|
||||
RAYGUI_ICON_TEXT_A = 31,
|
||||
RAYGUI_ICON_SCALE = 32,
|
||||
RAYGUI_ICON_RESIZE = 33,
|
||||
RAYGUI_ICON_FILTER_POINT = 34,
|
||||
RAYGUI_ICON_FILTER_BILINEAR = 35,
|
||||
RAYGUI_ICON_CROP = 36,
|
||||
RAYGUI_ICON_CROP_ALPHA = 37,
|
||||
RAYGUI_ICON_SQUARE_TOGGLE = 38,
|
||||
RAYGUI_ICON_SIMMETRY = 39,
|
||||
RAYGUI_ICON_SIMMETRY_HORIZONTAL = 40,
|
||||
RAYGUI_ICON_SIMMETRY_VERTICAL = 41,
|
||||
RAYGUI_ICON_LENS = 42,
|
||||
RAYGUI_ICON_LENS_BIG = 43,
|
||||
RAYGUI_ICON_EYE_ON = 44,
|
||||
RAYGUI_ICON_EYE_OFF = 45,
|
||||
RAYGUI_ICON_FILTER_TOP = 46,
|
||||
RAYGUI_ICON_FILTER = 47,
|
||||
RAYGUI_ICON_TARGET_POINT = 48,
|
||||
RAYGUI_ICON_TARGET_SMALL = 49,
|
||||
RAYGUI_ICON_TARGET_BIG = 50,
|
||||
RAYGUI_ICON_TARGET_MOVE = 51,
|
||||
RAYGUI_ICON_CURSOR_MOVE = 52,
|
||||
RAYGUI_ICON_CURSOR_SCALE = 53,
|
||||
RAYGUI_ICON_CURSOR_SCALE_RIGHT = 54,
|
||||
RAYGUI_ICON_CURSOR_SCALE_LEFT = 55,
|
||||
RAYGUI_ICON_UNDO = 56,
|
||||
RAYGUI_ICON_REDO = 57,
|
||||
RAYGUI_ICON_REREDO = 58,
|
||||
RAYGUI_ICON_MUTATE = 59,
|
||||
RAYGUI_ICON_ROTATE = 60,
|
||||
RAYGUI_ICON_REPEAT = 61,
|
||||
RAYGUI_ICON_SHUFFLE = 62,
|
||||
RAYGUI_ICON_EMPTYBOX = 63,
|
||||
RAYGUI_ICON_TARGET = 64,
|
||||
RAYGUI_ICON_TARGET_SMALL_FILL = 65,
|
||||
RAYGUI_ICON_TARGET_BIG_FILL = 66,
|
||||
RAYGUI_ICON_TARGET_MOVE_FILL = 67,
|
||||
RAYGUI_ICON_CURSOR_MOVE_FILL = 68,
|
||||
RAYGUI_ICON_CURSOR_SCALE_FILL = 69,
|
||||
RAYGUI_ICON_CURSOR_SCALE_RIGHT_FILL = 70,
|
||||
RAYGUI_ICON_CURSOR_SCALE_LEFT_FILL = 71,
|
||||
RAYGUI_ICON_UNDO_FILL = 72,
|
||||
RAYGUI_ICON_REDO_FILL = 73,
|
||||
RAYGUI_ICON_REREDO_FILL = 74,
|
||||
RAYGUI_ICON_MUTATE_FILL = 75,
|
||||
RAYGUI_ICON_ROTATE_FILL = 76,
|
||||
RAYGUI_ICON_REPEAT_FILL = 77,
|
||||
RAYGUI_ICON_SHUFFLE_FILL = 78,
|
||||
RAYGUI_ICON_EMPTYBOX_SMALL = 79,
|
||||
RAYGUI_ICON_BOX = 80,
|
||||
RAYGUI_ICON_BOX_TOP = 81,
|
||||
RAYGUI_ICON_BOX_TOP_RIGHT = 82,
|
||||
RAYGUI_ICON_BOX_RIGHT = 83,
|
||||
RAYGUI_ICON_BOX_BOTTOM_RIGHT = 84,
|
||||
RAYGUI_ICON_BOX_BOTTOM = 85,
|
||||
RAYGUI_ICON_BOX_BOTTOM_LEFT = 86,
|
||||
RAYGUI_ICON_BOX_LEFT = 87,
|
||||
RAYGUI_ICON_BOX_TOP_LEFT = 88,
|
||||
RAYGUI_ICON_BOX_CENTER = 89,
|
||||
RAYGUI_ICON_BOX_CIRCLE_MASK = 90,
|
||||
RAYGUI_ICON_POT = 91,
|
||||
RAYGUI_ICON_ALPHA_MULTIPLY = 92,
|
||||
RAYGUI_ICON_ALPHA_CLEAR = 93,
|
||||
RAYGUI_ICON_DITHERING = 94,
|
||||
RAYGUI_ICON_MIPMAPS = 95,
|
||||
RAYGUI_ICON_BOX_GRID = 96,
|
||||
RAYGUI_ICON_GRID = 97,
|
||||
RAYGUI_ICON_BOX_CORNERS_SMALL = 98,
|
||||
RAYGUI_ICON_BOX_CORNERS_BIG = 99,
|
||||
RAYGUI_ICON_FOUR_BOXES = 100,
|
||||
RAYGUI_ICON_GRID_FILL = 101,
|
||||
RAYGUI_ICON_BOX_MULTISIZE = 102,
|
||||
RAYGUI_ICON_ZOOM_SMALL = 103,
|
||||
RAYGUI_ICON_ZOOM_MEDIUM = 104,
|
||||
RAYGUI_ICON_ZOOM_BIG = 105,
|
||||
RAYGUI_ICON_ZOOM_ALL = 106,
|
||||
RAYGUI_ICON_ZOOM_CENTER = 107,
|
||||
RAYGUI_ICON_BOX_DOTS_SMALL = 108,
|
||||
RAYGUI_ICON_BOX_DOTS_BIG = 109,
|
||||
RAYGUI_ICON_BOX_CONCENTRIC = 110,
|
||||
RAYGUI_ICON_BOX_GRID_BIG = 111,
|
||||
RAYGUI_ICON_OK_TICK = 112,
|
||||
RAYGUI_ICON_CROSS = 113,
|
||||
RAYGUI_ICON_ARROW_LEFT = 114,
|
||||
RAYGUI_ICON_ARROW_RIGHT = 115,
|
||||
RAYGUI_ICON_ARROW_BOTTOM = 116,
|
||||
RAYGUI_ICON_ARROW_TOP = 117,
|
||||
RAYGUI_ICON_ARROW_LEFT_FILL = 118,
|
||||
RAYGUI_ICON_ARROW_RIGHT_FILL = 119,
|
||||
RAYGUI_ICON_ARROW_BOTTOM_FILL = 120,
|
||||
RAYGUI_ICON_ARROW_TOP_FILL = 121,
|
||||
RAYGUI_ICON_AUDIO = 122,
|
||||
RAYGUI_ICON_FX = 123,
|
||||
RAYGUI_ICON_WAVE = 124,
|
||||
RAYGUI_ICON_WAVE_SINUS = 125,
|
||||
RAYGUI_ICON_WAVE_SQUARE = 126,
|
||||
RAYGUI_ICON_WAVE_TRIANGULAR = 127,
|
||||
RAYGUI_ICON_CROSS_SMALL = 128,
|
||||
RAYGUI_ICON_PLAYER_PREVIOUS = 129,
|
||||
RAYGUI_ICON_PLAYER_PLAY_BACK = 130,
|
||||
RAYGUI_ICON_PLAYER_PLAY = 131,
|
||||
RAYGUI_ICON_PLAYER_PAUSE = 132,
|
||||
RAYGUI_ICON_PLAYER_STOP = 133,
|
||||
RAYGUI_ICON_PLAYER_NEXT = 134,
|
||||
RAYGUI_ICON_PLAYER_RECORD = 135,
|
||||
RAYGUI_ICON_MAGNET = 136,
|
||||
RAYGUI_ICON_LOCK_CLOSE = 137,
|
||||
RAYGUI_ICON_LOCK_OPEN = 138,
|
||||
RAYGUI_ICON_CLOCK = 139,
|
||||
RAYGUI_ICON_TOOLS = 140,
|
||||
RAYGUI_ICON_GEAR = 141,
|
||||
RAYGUI_ICON_GEAR_BIG = 142,
|
||||
RAYGUI_ICON_BIN = 143,
|
||||
RAYGUI_ICON_HAND_POINTER = 144,
|
||||
RAYGUI_ICON_LASER = 145,
|
||||
RAYGUI_ICON_COIN = 146,
|
||||
RAYGUI_ICON_EXPLOSION = 147,
|
||||
RAYGUI_ICON_1UP = 148,
|
||||
RAYGUI_ICON_PLAYER = 149,
|
||||
RAYGUI_ICON_PLAYER_JUMP = 150,
|
||||
RAYGUI_ICON_KEY = 151,
|
||||
RAYGUI_ICON_DEMON = 152,
|
||||
RAYGUI_ICON_TEXT_POPUP = 153,
|
||||
RAYGUI_ICON_GEAR_EX = 154,
|
||||
RAYGUI_ICON_CRACK = 155,
|
||||
RAYGUI_ICON_CRACK_POINTS = 156,
|
||||
RAYGUI_ICON_STAR = 157,
|
||||
RAYGUI_ICON_DOOR = 158,
|
||||
RAYGUI_ICON_EXIT = 159,
|
||||
RAYGUI_ICON_MODE_2D = 160,
|
||||
RAYGUI_ICON_MODE_3D = 161,
|
||||
RAYGUI_ICON_CUBE = 162,
|
||||
RAYGUI_ICON_CUBE_FACE_TOP = 163,
|
||||
RAYGUI_ICON_CUBE_FACE_LEFT = 164,
|
||||
RAYGUI_ICON_CUBE_FACE_FRONT = 165,
|
||||
RAYGUI_ICON_CUBE_FACE_BOTTOM = 166,
|
||||
RAYGUI_ICON_CUBE_FACE_RIGHT = 167,
|
||||
RAYGUI_ICON_CUBE_FACE_BACK = 168,
|
||||
RAYGUI_ICON_CAMERA = 169,
|
||||
RAYGUI_ICON_SPECIAL = 170,
|
||||
RAYGUI_ICON_LINK_NET = 171,
|
||||
RAYGUI_ICON_LINK_BOXES = 172,
|
||||
RAYGUI_ICON_LINK_MULTI = 173,
|
||||
RAYGUI_ICON_LINK = 174,
|
||||
RAYGUI_ICON_LINK_BROKE = 175,
|
||||
RAYGUI_ICON_TEXT_NOTES = 176,
|
||||
RAYGUI_ICON_NOTEBOOK = 177,
|
||||
RAYGUI_ICON_SUITCASE = 178,
|
||||
RAYGUI_ICON_SUITCASE_ZIP = 179,
|
||||
RAYGUI_ICON_MAILBOX = 180,
|
||||
RAYGUI_ICON_MONITOR = 181,
|
||||
RAYGUI_ICON_PRINTER = 182,
|
||||
RAYGUI_ICON_PHOTO_CAMERA = 183,
|
||||
RAYGUI_ICON_PHOTO_CAMERA_FLASH = 184,
|
||||
RAYGUI_ICON_HOUSE = 185,
|
||||
RAYGUI_ICON_HEART = 186,
|
||||
RAYGUI_ICON_CORNER = 187,
|
||||
RAYGUI_ICON_VERTICAL_BARS = 188,
|
||||
RAYGUI_ICON_VERTICAL_BARS_FILL = 189,
|
||||
RAYGUI_ICON_LIFE_BARS = 190,
|
||||
RAYGUI_ICON_INFO = 191,
|
||||
RAYGUI_ICON_CROSSLINE = 192,
|
||||
RAYGUI_ICON_HELP = 193,
|
||||
RAYGUI_ICON_FILETYPE_ALPHA = 194,
|
||||
RAYGUI_ICON_FILETYPE_HOME = 195,
|
||||
RAYGUI_ICON_LAYERS_VISIBLE = 196,
|
||||
RAYGUI_ICON_LAYERS = 197,
|
||||
RAYGUI_ICON_WINDOW = 198,
|
||||
RAYGUI_ICON_199 = 199,
|
||||
RAYGUI_ICON_200 = 200,
|
||||
RAYGUI_ICON_201 = 201,
|
||||
RAYGUI_ICON_202 = 202,
|
||||
RAYGUI_ICON_203 = 203,
|
||||
RAYGUI_ICON_204 = 204,
|
||||
RAYGUI_ICON_205 = 205,
|
||||
RAYGUI_ICON_206 = 206,
|
||||
RAYGUI_ICON_207 = 207,
|
||||
RAYGUI_ICON_208 = 208,
|
||||
RAYGUI_ICON_209 = 209,
|
||||
RAYGUI_ICON_210 = 210,
|
||||
RAYGUI_ICON_211 = 211,
|
||||
RAYGUI_ICON_212 = 212,
|
||||
RAYGUI_ICON_213 = 213,
|
||||
RAYGUI_ICON_214 = 214,
|
||||
RAYGUI_ICON_215 = 215,
|
||||
RAYGUI_ICON_216 = 216,
|
||||
RAYGUI_ICON_217 = 217,
|
||||
RAYGUI_ICON_218 = 218,
|
||||
RAYGUI_ICON_219 = 219,
|
||||
RAYGUI_ICON_220 = 220,
|
||||
RAYGUI_ICON_221 = 221,
|
||||
RAYGUI_ICON_222 = 222,
|
||||
RAYGUI_ICON_223 = 223,
|
||||
RAYGUI_ICON_224 = 224,
|
||||
RAYGUI_ICON_225 = 225,
|
||||
RAYGUI_ICON_226 = 226,
|
||||
RAYGUI_ICON_227 = 227,
|
||||
RAYGUI_ICON_228 = 228,
|
||||
RAYGUI_ICON_229 = 229,
|
||||
RAYGUI_ICON_230 = 230,
|
||||
RAYGUI_ICON_231 = 231,
|
||||
RAYGUI_ICON_232 = 232,
|
||||
RAYGUI_ICON_233 = 233,
|
||||
RAYGUI_ICON_234 = 234,
|
||||
RAYGUI_ICON_235 = 235,
|
||||
RAYGUI_ICON_236 = 236,
|
||||
RAYGUI_ICON_237 = 237,
|
||||
RAYGUI_ICON_238 = 238,
|
||||
RAYGUI_ICON_239 = 239,
|
||||
RAYGUI_ICON_240 = 240,
|
||||
RAYGUI_ICON_241 = 241,
|
||||
RAYGUI_ICON_242 = 242,
|
||||
RAYGUI_ICON_243 = 243,
|
||||
RAYGUI_ICON_244 = 244,
|
||||
RAYGUI_ICON_245 = 245,
|
||||
RAYGUI_ICON_246 = 246,
|
||||
RAYGUI_ICON_247 = 247,
|
||||
RAYGUI_ICON_248 = 248,
|
||||
RAYGUI_ICON_249 = 249,
|
||||
RAYGUI_ICON_250 = 250,
|
||||
RAYGUI_ICON_251 = 251,
|
||||
RAYGUI_ICON_252 = 252,
|
||||
RAYGUI_ICON_253 = 253,
|
||||
RAYGUI_ICON_254 = 254,
|
||||
RAYGUI_ICON_255 = 255,
|
||||
} guiIconName;
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
// Icons data
|
||||
//----------------------------------------------------------------------------------
|
||||
static unsigned int guiIcons[RAYGUI_ICON_MAX_ICONS*RAYGUI_ICON_DATA_ELEMENTS] = {
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // RAYGUI_ICON_NONE
|
||||
0x3ff80000, 0x2f082008, 0x2042207e, 0x40027fc2, 0x40024002, 0x40024002, 0x40024002, 0x00007ffe, // RAYGUI_ICON_FOLDER_FILE_OPEN
|
||||
0x3ffe0000, 0x44226422, 0x400247e2, 0x5ffa4002, 0x57ea500a, 0x500a500a, 0x40025ffa, 0x00007ffe, // RAYGUI_ICON_FILE_SAVE_CLASSIC
|
||||
0x00000000, 0x0042007e, 0x40027fc2, 0x40024002, 0x41024002, 0x44424282, 0x793e4102, 0x00000100, // RAYGUI_ICON_FOLDER_OPEN
|
||||
0x00000000, 0x0042007e, 0x40027fc2, 0x40024002, 0x41024102, 0x44424102, 0x793e4282, 0x00000000, // RAYGUI_ICON_FOLDER_SAVE
|
||||
0x3ff00000, 0x201c2010, 0x20042004, 0x21042004, 0x24442284, 0x21042104, 0x20042104, 0x00003ffc, // RAYGUI_ICON_FILE_OPEN
|
||||
0x3ff00000, 0x201c2010, 0x20042004, 0x21042004, 0x21042104, 0x22842444, 0x20042104, 0x00003ffc, // RAYGUI_ICON_FILE_SAVE
|
||||
0x3ff00000, 0x201c2010, 0x00042004, 0x20041004, 0x20844784, 0x00841384, 0x20042784, 0x00003ffc, // RAYGUI_ICON_FILE_EXPORT
|
||||
0x3ff00000, 0x201c2010, 0x20042004, 0x20042004, 0x22042204, 0x22042f84, 0x20042204, 0x00003ffc, // RAYGUI_ICON_FILE_NEW
|
||||
0x3ff00000, 0x201c2010, 0x20042004, 0x20042004, 0x25042884, 0x25042204, 0x20042884, 0x00003ffc, // RAYGUI_ICON_FILE_DELETE
|
||||
0x3ff00000, 0x201c2010, 0x20042004, 0x20042ff4, 0x20042ff4, 0x20042ff4, 0x20042004, 0x00003ffc, // RAYGUI_ICON_FILETYPE_TEXT
|
||||
0x3ff00000, 0x201c2010, 0x27042004, 0x244424c4, 0x26442444, 0x20642664, 0x20042004, 0x00003ffc, // RAYGUI_ICON_FILETYPE_AUDIO
|
||||
0x3ff00000, 0x201c2010, 0x26042604, 0x20042004, 0x35442884, 0x2414222c, 0x20042004, 0x00003ffc, // RAYGUI_ICON_FILETYPE_IMAGE
|
||||
0x3ff00000, 0x201c2010, 0x20c42004, 0x22442144, 0x22442444, 0x20c42144, 0x20042004, 0x00003ffc, // RAYGUI_ICON_FILETYPE_PLAY
|
||||
0x3ff00000, 0x3ffc2ff0, 0x3f3c2ff4, 0x3dbc2eb4, 0x3dbc2bb4, 0x3f3c2eb4, 0x3ffc2ff4, 0x00002ff4, // RAYGUI_ICON_FILETYPE_VIDEO
|
||||
0x3ff00000, 0x201c2010, 0x21842184, 0x21842004, 0x21842184, 0x21842184, 0x20042184, 0x00003ffc, // RAYGUI_ICON_FILETYPE_INFO
|
||||
0x0ff00000, 0x381c0810, 0x28042804, 0x28042804, 0x28042804, 0x28042804, 0x20102ffc, 0x00003ff0, // RAYGUI_ICON_FILE_COPY
|
||||
0x00000000, 0x701c0000, 0x079c1e14, 0x55a000f0, 0x079c00f0, 0x701c1e14, 0x00000000, 0x00000000, // RAYGUI_ICON_FILE_CUT
|
||||
0x01c00000, 0x13e41bec, 0x3f841004, 0x204420c4, 0x20442044, 0x20442044, 0x207c2044, 0x00003fc0, // RAYGUI_ICON_FILE_PASTE
|
||||
0x00000000, 0x3aa00fe0, 0x2abc2aa0, 0x2aa42aa4, 0x20042aa4, 0x20042004, 0x3ffc2004, 0x00000000, // RAYGUI_ICON_CURSOR_HAND
|
||||
0x00000000, 0x003c000c, 0x030800c8, 0x30100c10, 0x10202020, 0x04400840, 0x01800280, 0x00000000, // RAYGUI_ICON_CURSOR_POINTER
|
||||
0x00000000, 0x00180000, 0x01f00078, 0x03e007f0, 0x07c003e0, 0x04000e40, 0x00000000, 0x00000000, // RAYGUI_ICON_CURSOR_CLASSIC
|
||||
0x00000000, 0x04000000, 0x11000a00, 0x04400a80, 0x01100220, 0x00580088, 0x00000038, 0x00000000, // RAYGUI_ICON_PENCIL
|
||||
0x04000000, 0x15000a00, 0x50402880, 0x14102820, 0x05040a08, 0x015c028c, 0x007c00bc, 0x00000000, // RAYGUI_ICON_PENCIL_BIG
|
||||
0x01c00000, 0x01400140, 0x01400140, 0x0ff80140, 0x0ff80808, 0x0aa80808, 0x0aa80aa8, 0x00000ff8, // RAYGUI_ICON_BRUSH_CLASSIC
|
||||
0x1ffc0000, 0x5ffc7ffe, 0x40004000, 0x00807f80, 0x01c001c0, 0x01c001c0, 0x01c001c0, 0x00000080, // RAYGUI_ICON_BRUSH_PAINTER
|
||||
0x00000000, 0x00800000, 0x01c00080, 0x03e001c0, 0x07f003e0, 0x036006f0, 0x000001c0, 0x00000000, // RAYGUI_ICON_WATER_DROP
|
||||
0x00000000, 0x3e003800, 0x1f803f80, 0x0c201e40, 0x02080c10, 0x00840104, 0x00380044, 0x00000000, // RAYGUI_ICON_COLOR_PICKER
|
||||
0x00000000, 0x07800300, 0x1fe00fc0, 0x3f883fd0, 0x0e021f04, 0x02040402, 0x00f00108, 0x00000000, // RAYGUI_ICON_RUBBER
|
||||
0x00c00000, 0x02800140, 0x08200440, 0x20081010, 0x2ffe3004, 0x03f807fc, 0x00e001f0, 0x00000040, // RAYGUI_ICON_COLOR_BUCKET
|
||||
0x00000000, 0x21843ffc, 0x01800180, 0x01800180, 0x01800180, 0x01800180, 0x03c00180, 0x00000000, // RAYGUI_ICON_TEXT_T
|
||||
0x00800000, 0x01400180, 0x06200340, 0x0c100620, 0x1ff80c10, 0x380c1808, 0x70067004, 0x0000f80f, // RAYGUI_ICON_TEXT_A
|
||||
0x78000000, 0x50004000, 0x00004800, 0x03c003c0, 0x03c003c0, 0x00100000, 0x0002000a, 0x0000000e, // RAYGUI_ICON_SCALE
|
||||
0x75560000, 0x5e004002, 0x54001002, 0x41001202, 0x408200fe, 0x40820082, 0x40820082, 0x00006afe, // RAYGUI_ICON_RESIZE
|
||||
0x00000000, 0x3f003f00, 0x3f003f00, 0x3f003f00, 0x00400080, 0x001c0020, 0x001c001c, 0x00000000, // RAYGUI_ICON_FILTER_POINT
|
||||
0x6d800000, 0x00004080, 0x40804080, 0x40800000, 0x00406d80, 0x001c0020, 0x001c001c, 0x00000000, // RAYGUI_ICON_FILTER_BILINEAR
|
||||
0x40080000, 0x1ffe2008, 0x14081008, 0x11081208, 0x10481088, 0x10081028, 0x10047ff8, 0x00001002, // RAYGUI_ICON_CROP
|
||||
0x00100000, 0x3ffc0010, 0x2ab03550, 0x22b02550, 0x20b02150, 0x20302050, 0x2000fff0, 0x00002000, // RAYGUI_ICON_CROP_ALPHA
|
||||
0x40000000, 0x1ff82000, 0x04082808, 0x01082208, 0x00482088, 0x00182028, 0x35542008, 0x00000002, // RAYGUI_ICON_SQUARE_TOGGLE
|
||||
0x00000000, 0x02800280, 0x06c006c0, 0x0ea00ee0, 0x1e901eb0, 0x3e883e98, 0x7efc7e8c, 0x00000000, // RAYGUI_ICON_SIMMETRY
|
||||
0x01000000, 0x05600100, 0x1d480d50, 0x7d423d44, 0x3d447d42, 0x0d501d48, 0x01000560, 0x00000100, // RAYGUI_ICON_SIMMETRY_HORIZONTAL
|
||||
0x01800000, 0x04200240, 0x10080810, 0x00001ff8, 0x00007ffe, 0x0ff01ff8, 0x03c007e0, 0x00000180, // RAYGUI_ICON_SIMMETRY_VERTICAL
|
||||
0x00000000, 0x010800f0, 0x02040204, 0x02040204, 0x07f00308, 0x1c000e00, 0x30003800, 0x00000000, // RAYGUI_ICON_LENS
|
||||
0x00000000, 0x061803f0, 0x08240c0c, 0x08040814, 0x0c0c0804, 0x23f01618, 0x18002400, 0x00000000, // RAYGUI_ICON_LENS_BIG
|
||||
0x00000000, 0x00000000, 0x1c7007c0, 0x638e3398, 0x1c703398, 0x000007c0, 0x00000000, 0x00000000, // RAYGUI_ICON_EYE_ON
|
||||
0x00000000, 0x10002000, 0x04700fc0, 0x610e3218, 0x1c703098, 0x001007a0, 0x00000008, 0x00000000, // RAYGUI_ICON_EYE_OFF
|
||||
0x00000000, 0x00007ffc, 0x40047ffc, 0x10102008, 0x04400820, 0x02800280, 0x02800280, 0x00000100, // RAYGUI_ICON_FILTER_TOP
|
||||
0x00000000, 0x40027ffe, 0x10082004, 0x04200810, 0x02400240, 0x02400240, 0x01400240, 0x000000c0, // RAYGUI_ICON_FILTER
|
||||
0x00800000, 0x00800080, 0x00000080, 0x3c9e0000, 0x00000000, 0x00800080, 0x00800080, 0x00000000, // RAYGUI_ICON_TARGET_POINT
|
||||
0x00800000, 0x00800080, 0x00800080, 0x3f7e01c0, 0x008001c0, 0x00800080, 0x00800080, 0x00000000, // RAYGUI_ICON_TARGET_SMALL
|
||||
0x00800000, 0x00800080, 0x03e00080, 0x3e3e0220, 0x03e00220, 0x00800080, 0x00800080, 0x00000000, // RAYGUI_ICON_TARGET_BIG
|
||||
0x01000000, 0x04400280, 0x01000100, 0x43842008, 0x43849ab2, 0x01002008, 0x04400100, 0x01000280, // RAYGUI_ICON_TARGET_MOVE
|
||||
0x01000000, 0x04400280, 0x01000100, 0x41042108, 0x41049ff2, 0x01002108, 0x04400100, 0x01000280, // RAYGUI_ICON_CURSOR_MOVE
|
||||
0x781e0000, 0x500a4002, 0x04204812, 0x00000240, 0x02400000, 0x48120420, 0x4002500a, 0x0000781e, // RAYGUI_ICON_CURSOR_SCALE
|
||||
0x00000000, 0x20003c00, 0x24002800, 0x01000200, 0x00400080, 0x00140024, 0x003c0004, 0x00000000, // RAYGUI_ICON_CURSOR_SCALE_RIGHT
|
||||
0x00000000, 0x0004003c, 0x00240014, 0x00800040, 0x02000100, 0x28002400, 0x3c002000, 0x00000000, // RAYGUI_ICON_CURSOR_SCALE_LEFT
|
||||
0x00000000, 0x00100020, 0x10101fc8, 0x10001020, 0x10001000, 0x10001000, 0x00001fc0, 0x00000000, // RAYGUI_ICON_UNDO
|
||||
0x00000000, 0x08000400, 0x080813f8, 0x00080408, 0x00080008, 0x00080008, 0x000003f8, 0x00000000, // RAYGUI_ICON_REDO
|
||||
0x00000000, 0x3ffc0000, 0x20042004, 0x20002000, 0x20402000, 0x3f902020, 0x00400020, 0x00000000, // RAYGUI_ICON_REREDO
|
||||
0x00000000, 0x3ffc0000, 0x20042004, 0x27fc2004, 0x20202000, 0x3fc82010, 0x00200010, 0x00000000, // RAYGUI_ICON_MUTATE
|
||||
0x00000000, 0x0ff00000, 0x10081818, 0x11801008, 0x10001180, 0x18101020, 0x00100fc8, 0x00000020, // RAYGUI_ICON_ROTATE
|
||||
0x00000000, 0x04000200, 0x240429fc, 0x20042204, 0x20442004, 0x3f942024, 0x00400020, 0x00000000, // RAYGUI_ICON_REPEAT
|
||||
0x00000000, 0x20001000, 0x22104c0e, 0x00801120, 0x11200040, 0x4c0e2210, 0x10002000, 0x00000000, // RAYGUI_ICON_SHUFFLE
|
||||
0x7ffe0000, 0x50024002, 0x44024802, 0x41024202, 0x40424082, 0x40124022, 0x4002400a, 0x00007ffe, // RAYGUI_ICON_EMPTYBOX
|
||||
0x00800000, 0x03e00080, 0x08080490, 0x3c9e0808, 0x08080808, 0x03e00490, 0x00800080, 0x00000000, // RAYGUI_ICON_TARGET
|
||||
0x00800000, 0x00800080, 0x00800080, 0x3ffe01c0, 0x008001c0, 0x00800080, 0x00800080, 0x00000000, // RAYGUI_ICON_TARGET_SMALL_FILL
|
||||
0x00800000, 0x00800080, 0x03e00080, 0x3ffe03e0, 0x03e003e0, 0x00800080, 0x00800080, 0x00000000, // RAYGUI_ICON_TARGET_BIG_FILL
|
||||
0x01000000, 0x07c00380, 0x01000100, 0x638c2008, 0x638cfbbe, 0x01002008, 0x07c00100, 0x01000380, // RAYGUI_ICON_TARGET_MOVE_FILL
|
||||
0x01000000, 0x07c00380, 0x01000100, 0x610c2108, 0x610cfffe, 0x01002108, 0x07c00100, 0x01000380, // RAYGUI_ICON_CURSOR_MOVE_FILL
|
||||
0x781e0000, 0x6006700e, 0x04204812, 0x00000240, 0x02400000, 0x48120420, 0x700e6006, 0x0000781e, // RAYGUI_ICON_CURSOR_SCALE_FILL
|
||||
0x00000000, 0x38003c00, 0x24003000, 0x01000200, 0x00400080, 0x000c0024, 0x003c001c, 0x00000000, // RAYGUI_ICON_CURSOR_SCALE_RIGHT_FILL
|
||||
0x00000000, 0x001c003c, 0x0024000c, 0x00800040, 0x02000100, 0x30002400, 0x3c003800, 0x00000000, // RAYGUI_ICON_CURSOR_SCALE_LEFT_FILL
|
||||
0x00000000, 0x00300020, 0x10301ff8, 0x10001020, 0x10001000, 0x10001000, 0x00001fc0, 0x00000000, // RAYGUI_ICON_UNDO_FILL
|
||||
0x00000000, 0x0c000400, 0x0c081ff8, 0x00080408, 0x00080008, 0x00080008, 0x000003f8, 0x00000000, // RAYGUI_ICON_REDO_FILL
|
||||
0x00000000, 0x3ffc0000, 0x20042004, 0x20002000, 0x20402000, 0x3ff02060, 0x00400060, 0x00000000, // RAYGUI_ICON_REREDO_FILL
|
||||
0x00000000, 0x3ffc0000, 0x20042004, 0x27fc2004, 0x20202000, 0x3ff82030, 0x00200030, 0x00000000, // RAYGUI_ICON_MUTATE_FILL
|
||||
0x00000000, 0x0ff00000, 0x10081818, 0x11801008, 0x10001180, 0x18301020, 0x00300ff8, 0x00000020, // RAYGUI_ICON_ROTATE_FILL
|
||||
0x00000000, 0x06000200, 0x26042ffc, 0x20042204, 0x20442004, 0x3ff42064, 0x00400060, 0x00000000, // RAYGUI_ICON_REPEAT_FILL
|
||||
0x00000000, 0x30001000, 0x32107c0e, 0x00801120, 0x11200040, 0x7c0e3210, 0x10003000, 0x00000000, // RAYGUI_ICON_SHUFFLE_FILL
|
||||
0x00000000, 0x30043ffc, 0x24042804, 0x21042204, 0x20442084, 0x20142024, 0x3ffc200c, 0x00000000, // RAYGUI_ICON_EMPTYBOX_SMALL
|
||||
0x00000000, 0x20043ffc, 0x20042004, 0x20042004, 0x20042004, 0x20042004, 0x3ffc2004, 0x00000000, // RAYGUI_ICON_BOX
|
||||
0x00000000, 0x23c43ffc, 0x23c423c4, 0x200423c4, 0x20042004, 0x20042004, 0x3ffc2004, 0x00000000, // RAYGUI_ICON_BOX_TOP
|
||||
0x00000000, 0x3e043ffc, 0x3e043e04, 0x20043e04, 0x20042004, 0x20042004, 0x3ffc2004, 0x00000000, // RAYGUI_ICON_BOX_TOP_RIGHT
|
||||
0x00000000, 0x20043ffc, 0x20042004, 0x3e043e04, 0x3e043e04, 0x20042004, 0x3ffc2004, 0x00000000, // RAYGUI_ICON_BOX_RIGHT
|
||||
0x00000000, 0x20043ffc, 0x20042004, 0x20042004, 0x3e042004, 0x3e043e04, 0x3ffc3e04, 0x00000000, // RAYGUI_ICON_BOX_BOTTOM_RIGHT
|
||||
0x00000000, 0x20043ffc, 0x20042004, 0x20042004, 0x23c42004, 0x23c423c4, 0x3ffc23c4, 0x00000000, // RAYGUI_ICON_BOX_BOTTOM
|
||||
0x00000000, 0x20043ffc, 0x20042004, 0x20042004, 0x207c2004, 0x207c207c, 0x3ffc207c, 0x00000000, // RAYGUI_ICON_BOX_BOTTOM_LEFT
|
||||
0x00000000, 0x20043ffc, 0x20042004, 0x207c207c, 0x207c207c, 0x20042004, 0x3ffc2004, 0x00000000, // RAYGUI_ICON_BOX_LEFT
|
||||
0x00000000, 0x207c3ffc, 0x207c207c, 0x2004207c, 0x20042004, 0x20042004, 0x3ffc2004, 0x00000000, // RAYGUI_ICON_BOX_TOP_LEFT
|
||||
0x00000000, 0x20043ffc, 0x20042004, 0x23c423c4, 0x23c423c4, 0x20042004, 0x3ffc2004, 0x00000000, // RAYGUI_ICON_BOX_CENTER
|
||||
0x7ffe0000, 0x40024002, 0x47e24182, 0x4ff247e2, 0x47e24ff2, 0x418247e2, 0x40024002, 0x00007ffe, // RAYGUI_ICON_BOX_CIRCLE_MASK
|
||||
0x7fff0000, 0x40014001, 0x40014001, 0x49555ddd, 0x4945495d, 0x400149c5, 0x40014001, 0x00007fff, // RAYGUI_ICON_POT
|
||||
0x7ffe0000, 0x53327332, 0x44ce4cce, 0x41324332, 0x404e40ce, 0x48125432, 0x4006540e, 0x00007ffe, // RAYGUI_ICON_ALPHA_MULTIPLY
|
||||
0x7ffe0000, 0x53327332, 0x44ce4cce, 0x41324332, 0x5c4e40ce, 0x44124432, 0x40065c0e, 0x00007ffe, // RAYGUI_ICON_ALPHA_CLEAR
|
||||
0x7ffe0000, 0x42fe417e, 0x42fe417e, 0x42fe417e, 0x42fe417e, 0x42fe417e, 0x42fe417e, 0x00007ffe, // RAYGUI_ICON_DITHERING
|
||||
0x07fe0000, 0x1ffa0002, 0x7fea000a, 0x402a402a, 0x5b2a512a, 0x5128552a, 0x40205128, 0x00007fe0, // RAYGUI_ICON_MIPMAPS
|
||||
0x00000000, 0x1ff80000, 0x12481248, 0x12481ff8, 0x1ff81248, 0x12481248, 0x00001ff8, 0x00000000, // RAYGUI_ICON_BOX_GRID
|
||||
0x12480000, 0x7ffe1248, 0x12481248, 0x12487ffe, 0x7ffe1248, 0x12481248, 0x12487ffe, 0x00001248, // RAYGUI_ICON_GRID
|
||||
0x00000000, 0x1c380000, 0x1c3817e8, 0x08100810, 0x08100810, 0x17e81c38, 0x00001c38, 0x00000000, // RAYGUI_ICON_BOX_CORNERS_SMALL
|
||||
0x700e0000, 0x700e5ffa, 0x20042004, 0x20042004, 0x20042004, 0x20042004, 0x5ffa700e, 0x0000700e, // RAYGUI_ICON_BOX_CORNERS_BIG
|
||||
0x3f7e0000, 0x21422142, 0x21422142, 0x00003f7e, 0x21423f7e, 0x21422142, 0x3f7e2142, 0x00000000, // RAYGUI_ICON_FOUR_BOXES
|
||||
0x00000000, 0x3bb80000, 0x3bb83bb8, 0x3bb80000, 0x3bb83bb8, 0x3bb80000, 0x3bb83bb8, 0x00000000, // RAYGUI_ICON_GRID_FILL
|
||||
0x7ffe0000, 0x7ffe7ffe, 0x77fe7000, 0x77fe77fe, 0x777e7700, 0x777e777e, 0x777e777e, 0x0000777e, // RAYGUI_ICON_BOX_MULTISIZE
|
||||
0x781e0000, 0x40024002, 0x00004002, 0x01800000, 0x00000180, 0x40020000, 0x40024002, 0x0000781e, // RAYGUI_ICON_ZOOM_SMALL
|
||||
0x781e0000, 0x40024002, 0x00004002, 0x03c003c0, 0x03c003c0, 0x40020000, 0x40024002, 0x0000781e, // RAYGUI_ICON_ZOOM_MEDIUM
|
||||
0x781e0000, 0x40024002, 0x07e04002, 0x07e007e0, 0x07e007e0, 0x400207e0, 0x40024002, 0x0000781e, // RAYGUI_ICON_ZOOM_BIG
|
||||
0x781e0000, 0x5ffa4002, 0x1ff85ffa, 0x1ff81ff8, 0x1ff81ff8, 0x5ffa1ff8, 0x40025ffa, 0x0000781e, // RAYGUI_ICON_ZOOM_ALL
|
||||
0x00000000, 0x2004381c, 0x00002004, 0x00000000, 0x00000000, 0x20040000, 0x381c2004, 0x00000000, // RAYGUI_ICON_ZOOM_CENTER
|
||||
0x00000000, 0x1db80000, 0x10081008, 0x10080000, 0x00001008, 0x10081008, 0x00001db8, 0x00000000, // RAYGUI_ICON_BOX_DOTS_SMALL
|
||||
0x35560000, 0x00002002, 0x00002002, 0x00002002, 0x00002002, 0x00002002, 0x35562002, 0x00000000, // RAYGUI_ICON_BOX_DOTS_BIG
|
||||
0x7ffe0000, 0x40024002, 0x48124ff2, 0x49924812, 0x48124992, 0x4ff24812, 0x40024002, 0x00007ffe, // RAYGUI_ICON_BOX_CONCENTRIC
|
||||
0x00000000, 0x10841ffc, 0x10841084, 0x1ffc1084, 0x10841084, 0x10841084, 0x00001ffc, 0x00000000, // RAYGUI_ICON_BOX_GRID_BIG
|
||||
0x00000000, 0x00000000, 0x10000000, 0x04000800, 0x01040200, 0x00500088, 0x00000020, 0x00000000, // RAYGUI_ICON_OK_TICK
|
||||
0x00000000, 0x10080000, 0x04200810, 0x01800240, 0x02400180, 0x08100420, 0x00001008, 0x00000000, // RAYGUI_ICON_CROSS
|
||||
0x00000000, 0x02000000, 0x00800100, 0x00200040, 0x00200010, 0x00800040, 0x02000100, 0x00000000, // RAYGUI_ICON_ARROW_LEFT
|
||||
0x00000000, 0x00400000, 0x01000080, 0x04000200, 0x04000800, 0x01000200, 0x00400080, 0x00000000, // RAYGUI_ICON_ARROW_RIGHT
|
||||
0x00000000, 0x00000000, 0x00000000, 0x08081004, 0x02200410, 0x00800140, 0x00000000, 0x00000000, // RAYGUI_ICON_ARROW_BOTTOM
|
||||
0x00000000, 0x00000000, 0x01400080, 0x04100220, 0x10040808, 0x00000000, 0x00000000, 0x00000000, // RAYGUI_ICON_ARROW_TOP
|
||||
0x00000000, 0x02000000, 0x03800300, 0x03e003c0, 0x03e003f0, 0x038003c0, 0x02000300, 0x00000000, // RAYGUI_ICON_ARROW_LEFT_FILL
|
||||
0x00000000, 0x00400000, 0x01c000c0, 0x07c003c0, 0x07c00fc0, 0x01c003c0, 0x004000c0, 0x00000000, // RAYGUI_ICON_ARROW_RIGHT_FILL
|
||||
0x00000000, 0x00000000, 0x00000000, 0x0ff81ffc, 0x03e007f0, 0x008001c0, 0x00000000, 0x00000000, // RAYGUI_ICON_ARROW_BOTTOM_FILL
|
||||
0x00000000, 0x00000000, 0x01c00080, 0x07f003e0, 0x1ffc0ff8, 0x00000000, 0x00000000, 0x00000000, // RAYGUI_ICON_ARROW_TOP_FILL
|
||||
0x00000000, 0x18a008c0, 0x32881290, 0x24822686, 0x26862482, 0x12903288, 0x08c018a0, 0x00000000, // RAYGUI_ICON_AUDIO
|
||||
0x00000000, 0x04800780, 0x004000c0, 0x662000f0, 0x08103c30, 0x130a0e18, 0x0000318e, 0x00000000, // RAYGUI_ICON_FX
|
||||
0x00000000, 0x00800000, 0x08880888, 0x2aaa0a8a, 0x0a8a2aaa, 0x08880888, 0x00000080, 0x00000000, // RAYGUI_ICON_WAVE
|
||||
0x00000000, 0x00600000, 0x01080090, 0x02040108, 0x42044204, 0x24022402, 0x00001800, 0x00000000, // RAYGUI_ICON_WAVE_SINUS
|
||||
0x00000000, 0x07f80000, 0x04080408, 0x04080408, 0x04080408, 0x7c0e0408, 0x00000000, 0x00000000, // RAYGUI_ICON_WAVE_SQUARE
|
||||
0x00000000, 0x00000000, 0x00a00040, 0x22084110, 0x08021404, 0x00000000, 0x00000000, 0x00000000, // RAYGUI_ICON_WAVE_TRIANGULAR
|
||||
0x00000000, 0x00000000, 0x04200000, 0x01800240, 0x02400180, 0x00000420, 0x00000000, 0x00000000, // RAYGUI_ICON_CROSS_SMALL
|
||||
0x00000000, 0x18380000, 0x12281428, 0x10a81128, 0x112810a8, 0x14281228, 0x00001838, 0x00000000, // RAYGUI_ICON_PLAYER_PREVIOUS
|
||||
0x00000000, 0x18000000, 0x11801600, 0x10181060, 0x10601018, 0x16001180, 0x00001800, 0x00000000, // RAYGUI_ICON_PLAYER_PLAY_BACK
|
||||
0x00000000, 0x00180000, 0x01880068, 0x18080608, 0x06081808, 0x00680188, 0x00000018, 0x00000000, // RAYGUI_ICON_PLAYER_PLAY
|
||||
0x00000000, 0x1e780000, 0x12481248, 0x12481248, 0x12481248, 0x12481248, 0x00001e78, 0x00000000, // RAYGUI_ICON_PLAYER_PAUSE
|
||||
0x00000000, 0x1ff80000, 0x10081008, 0x10081008, 0x10081008, 0x10081008, 0x00001ff8, 0x00000000, // RAYGUI_ICON_PLAYER_STOP
|
||||
0x00000000, 0x1c180000, 0x14481428, 0x15081488, 0x14881508, 0x14281448, 0x00001c18, 0x00000000, // RAYGUI_ICON_PLAYER_NEXT
|
||||
0x00000000, 0x03c00000, 0x08100420, 0x10081008, 0x10081008, 0x04200810, 0x000003c0, 0x00000000, // RAYGUI_ICON_PLAYER_RECORD
|
||||
0x00000000, 0x0c3007e0, 0x13c81818, 0x14281668, 0x14281428, 0x1c381c38, 0x08102244, 0x00000000, // RAYGUI_ICON_MAGNET
|
||||
0x07c00000, 0x08200820, 0x3ff80820, 0x23882008, 0x21082388, 0x20082108, 0x1ff02008, 0x00000000, // RAYGUI_ICON_LOCK_CLOSE
|
||||
0x07c00000, 0x08000800, 0x3ff80800, 0x23882008, 0x21082388, 0x20082108, 0x1ff02008, 0x00000000, // RAYGUI_ICON_LOCK_OPEN
|
||||
0x01c00000, 0x0c180770, 0x3086188c, 0x60832082, 0x60034781, 0x30062002, 0x0c18180c, 0x01c00770, // RAYGUI_ICON_CLOCK
|
||||
0x0a200000, 0x1b201b20, 0x04200e20, 0x04200420, 0x04700420, 0x0e700e70, 0x0e700e70, 0x04200e70, // RAYGUI_ICON_TOOLS
|
||||
0x01800000, 0x3bdc318c, 0x0ff01ff8, 0x7c3e1e78, 0x1e787c3e, 0x1ff80ff0, 0x318c3bdc, 0x00000180, // RAYGUI_ICON_GEAR
|
||||
0x01800000, 0x3ffc318c, 0x1c381ff8, 0x781e1818, 0x1818781e, 0x1ff81c38, 0x318c3ffc, 0x00000180, // RAYGUI_ICON_GEAR_BIG
|
||||
0x00000000, 0x08080ff8, 0x08081ffc, 0x0aa80aa8, 0x0aa80aa8, 0x0aa80aa8, 0x08080aa8, 0x00000ff8, // RAYGUI_ICON_BIN
|
||||
0x00000000, 0x00000000, 0x20043ffc, 0x08043f84, 0x04040f84, 0x04040784, 0x000007fc, 0x00000000, // RAYGUI_ICON_HAND_POINTER
|
||||
0x00000000, 0x24400400, 0x00001480, 0x6efe0e00, 0x00000e00, 0x24401480, 0x00000400, 0x00000000, // RAYGUI_ICON_LASER
|
||||
0x00000000, 0x03c00000, 0x08300460, 0x11181118, 0x11181118, 0x04600830, 0x000003c0, 0x00000000, // RAYGUI_ICON_COIN
|
||||
0x00000000, 0x10880080, 0x06c00810, 0x366c07e0, 0x07e00240, 0x00001768, 0x04200240, 0x00000000, // RAYGUI_ICON_EXPLOSION
|
||||
0x00000000, 0x3d280000, 0x2528252c, 0x3d282528, 0x05280528, 0x05e80528, 0x00000000, 0x00000000, // RAYGUI_ICON_1UP
|
||||
0x01800000, 0x03c003c0, 0x018003c0, 0x0ff007e0, 0x0bd00bd0, 0x0a500bd0, 0x02400240, 0x02400240, // RAYGUI_ICON_PLAYER
|
||||
0x01800000, 0x03c003c0, 0x118013c0, 0x03c81ff8, 0x07c003c8, 0x04400440, 0x0c080478, 0x00000000, // RAYGUI_ICON_PLAYER_JUMP
|
||||
0x3ff80000, 0x30183ff8, 0x30183018, 0x3ff83ff8, 0x03000300, 0x03c003c0, 0x03e00300, 0x000003e0, // RAYGUI_ICON_KEY
|
||||
0x3ff80000, 0x3ff83ff8, 0x33983ff8, 0x3ff83398, 0x3ff83ff8, 0x00000540, 0x0fe00aa0, 0x00000fe0, // RAYGUI_ICON_DEMON
|
||||
0x00000000, 0x0ff00000, 0x20041008, 0x25442004, 0x10082004, 0x06000bf0, 0x00000300, 0x00000000, // RAYGUI_ICON_TEXT_POPUP
|
||||
0x00000000, 0x11440000, 0x07f00be8, 0x1c1c0e38, 0x1c1c0c18, 0x07f00e38, 0x11440be8, 0x00000000, // RAYGUI_ICON_GEAR_EX
|
||||
0x00000000, 0x20080000, 0x0c601010, 0x07c00fe0, 0x07c007c0, 0x0c600fe0, 0x20081010, 0x00000000, // RAYGUI_ICON_CRACK
|
||||
0x00000000, 0x20080000, 0x0c601010, 0x04400fe0, 0x04405554, 0x0c600fe0, 0x20081010, 0x00000000, // RAYGUI_ICON_CRACK_POINTS
|
||||
0x00000000, 0x00800080, 0x01c001c0, 0x1ffc3ffe, 0x03e007f0, 0x07f003e0, 0x0c180770, 0x00000808, // RAYGUI_ICON_STAR
|
||||
0x0ff00000, 0x08180810, 0x08100818, 0x0a100810, 0x08180810, 0x08100818, 0x08100810, 0x00001ff8, // RAYGUI_ICON_DOOR
|
||||
0x0ff00000, 0x08100810, 0x08100810, 0x10100010, 0x4f902010, 0x10102010, 0x08100010, 0x00000ff0, // RAYGUI_ICON_EXIT
|
||||
0x00040000, 0x001f000e, 0x0ef40004, 0x12f41284, 0x0ef41214, 0x10040004, 0x7ffc3004, 0x10003000, // RAYGUI_ICON_MODE_2D
|
||||
0x78040000, 0x501f600e, 0x0ef44004, 0x12f41284, 0x0ef41284, 0x10140004, 0x7ffc300c, 0x10003000, // RAYGUI_ICON_MODE_3D
|
||||
0x7fe00000, 0x50286030, 0x47fe4804, 0x44224402, 0x44224422, 0x241275e2, 0x0c06140a, 0x000007fe, // RAYGUI_ICON_CUBE
|
||||
0x7fe00000, 0x5ff87ff0, 0x47fe4ffc, 0x44224402, 0x44224422, 0x241275e2, 0x0c06140a, 0x000007fe, // RAYGUI_ICON_CUBE_FACE_TOP
|
||||
0x7fe00000, 0x50386030, 0x47fe483c, 0x443e443e, 0x443e443e, 0x241e75fe, 0x0c06140e, 0x000007fe, // RAYGUI_ICON_CUBE_FACE_LEFT
|
||||
0x7fe00000, 0x50286030, 0x47fe4804, 0x47fe47fe, 0x47fe47fe, 0x27fe77fe, 0x0ffe17fe, 0x000007fe, // RAYGUI_ICON_CUBE_FACE_FRONT
|
||||
0x7fe00000, 0x50286030, 0x47fe4804, 0x44224402, 0x44224422, 0x3ff27fe2, 0x0ffe1ffa, 0x000007fe, // RAYGUI_ICON_CUBE_FACE_BOTTOM
|
||||
0x7fe00000, 0x70286030, 0x7ffe7804, 0x7c227c02, 0x7c227c22, 0x3c127de2, 0x0c061c0a, 0x000007fe, // RAYGUI_ICON_CUBE_FACE_RIGHT
|
||||
0x7fe00000, 0x7fe87ff0, 0x7ffe7fe4, 0x7fe27fe2, 0x7fe27fe2, 0x24127fe2, 0x0c06140a, 0x000007fe, // RAYGUI_ICON_CUBE_FACE_BACK
|
||||
0x00000000, 0x2a0233fe, 0x22022602, 0x22022202, 0x2a022602, 0x00a033fe, 0x02080110, 0x00000000, // RAYGUI_ICON_CAMERA
|
||||
0x00000000, 0x200c3ffc, 0x000c000c, 0x3ffc000c, 0x30003000, 0x30003000, 0x3ffc3004, 0x00000000, // RAYGUI_ICON_SPECIAL
|
||||
0x00000000, 0x0022003e, 0x012201e2, 0x0100013e, 0x01000100, 0x79000100, 0x4f004900, 0x00007800, // RAYGUI_ICON_LINK_NET
|
||||
0x00000000, 0x44007c00, 0x45004600, 0x00627cbe, 0x00620022, 0x45007cbe, 0x44004600, 0x00007c00, // RAYGUI_ICON_LINK_BOXES
|
||||
0x00000000, 0x0044007c, 0x0010007c, 0x3f100010, 0x3f1021f0, 0x3f100010, 0x3f0021f0, 0x00000000, // RAYGUI_ICON_LINK_MULTI
|
||||
0x00000000, 0x0044007c, 0x00440044, 0x0010007c, 0x00100010, 0x44107c10, 0x440047f0, 0x00007c00, // RAYGUI_ICON_LINK
|
||||
0x00000000, 0x0044007c, 0x00440044, 0x0000007c, 0x00000010, 0x44007c10, 0x44004550, 0x00007c00, // RAYGUI_ICON_LINK_BROKE
|
||||
0x02a00000, 0x22a43ffc, 0x20042004, 0x20042ff4, 0x20042ff4, 0x20042ff4, 0x20042004, 0x00003ffc, // RAYGUI_ICON_TEXT_NOTES
|
||||
0x3ffc0000, 0x20042004, 0x245e27c4, 0x27c42444, 0x2004201e, 0x201e2004, 0x20042004, 0x00003ffc, // RAYGUI_ICON_NOTEBOOK
|
||||
0x00000000, 0x07e00000, 0x04200420, 0x24243ffc, 0x24242424, 0x24242424, 0x3ffc2424, 0x00000000, // RAYGUI_ICON_SUITCASE
|
||||
0x00000000, 0x0fe00000, 0x08200820, 0x40047ffc, 0x7ffc5554, 0x40045554, 0x7ffc4004, 0x00000000, // RAYGUI_ICON_SUITCASE_ZIP
|
||||
0x00000000, 0x20043ffc, 0x3ffc2004, 0x13c81008, 0x100813c8, 0x10081008, 0x1ff81008, 0x00000000, // RAYGUI_ICON_MAILBOX
|
||||
0x00000000, 0x40027ffe, 0x5ffa5ffa, 0x5ffa5ffa, 0x40025ffa, 0x03c07ffe, 0x1ff81ff8, 0x00000000, // RAYGUI_ICON_MONITOR
|
||||
0x0ff00000, 0x6bfe7ffe, 0x7ffe7ffe, 0x68167ffe, 0x08106816, 0x08100810, 0x0ff00810, 0x00000000, // RAYGUI_ICON_PRINTER
|
||||
0x3ff80000, 0xfffe2008, 0x870a8002, 0x904a888a, 0x904a904a, 0x870a888a, 0xfffe8002, 0x00000000, // RAYGUI_ICON_PHOTO_CAMERA
|
||||
0x0fc00000, 0xfcfe0cd8, 0x8002fffe, 0x84428382, 0x84428442, 0x80028382, 0xfffe8002, 0x00000000, // RAYGUI_ICON_PHOTO_CAMERA_FLASH
|
||||
0x00000000, 0x02400180, 0x08100420, 0x20041008, 0x23c42004, 0x22442244, 0x3ffc2244, 0x00000000, // RAYGUI_ICON_HOUSE
|
||||
0x00000000, 0x1c700000, 0x3ff83ef8, 0x3ff83ff8, 0x0fe01ff0, 0x038007c0, 0x00000100, 0x00000000, // RAYGUI_ICON_HEART
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x80000000, 0xe000c000, // RAYGUI_ICON_CORNER
|
||||
0x00000000, 0x14001c00, 0x15c01400, 0x15401540, 0x155c1540, 0x15541554, 0x1ddc1554, 0x00000000, // RAYGUI_ICON_VERTICAL_BARS
|
||||
0x00000000, 0x03000300, 0x1b001b00, 0x1b601b60, 0x1b6c1b60, 0x1b6c1b6c, 0x1b6c1b6c, 0x00000000, // RAYGUI_ICON_VERTICAL_BARS_FILL
|
||||
0x00000000, 0x00000000, 0x403e7ffe, 0x7ffe403e, 0x7ffe0000, 0x43fe43fe, 0x00007ffe, 0x00000000, // RAYGUI_ICON_LIFE_BARS
|
||||
0x7ffc0000, 0x43844004, 0x43844284, 0x43844004, 0x42844284, 0x42844284, 0x40044384, 0x00007ffc, // RAYGUI_ICON_INFO
|
||||
0x40008000, 0x10002000, 0x04000800, 0x01000200, 0x00400080, 0x00100020, 0x00040008, 0x00010002, // RAYGUI_ICON_CROSSLINE
|
||||
0x00000000, 0x1ff01ff0, 0x18301830, 0x1f001830, 0x03001f00, 0x00000300, 0x03000300, 0x00000000, // RAYGUI_ICON_HELP
|
||||
0x3ff00000, 0x2abc3550, 0x2aac3554, 0x2aac3554, 0x2aac3554, 0x2aac3554, 0x2aac3554, 0x00003ffc, // RAYGUI_ICON_FILETYPE_ALPHA
|
||||
0x3ff00000, 0x201c2010, 0x22442184, 0x28142424, 0x29942814, 0x2ff42994, 0x20042004, 0x00003ffc, // RAYGUI_ICON_FILETYPE_HOME
|
||||
0x07fe0000, 0x04020402, 0x7fe20402, 0x44224422, 0x44224422, 0x402047fe, 0x40204020, 0x00007fe0, // RAYGUI_ICON_LAYERS_VISIBLE
|
||||
0x07fe0000, 0x04020402, 0x7c020402, 0x44024402, 0x44024402, 0x402047fe, 0x40204020, 0x00007fe0, // RAYGUI_ICON_LAYERS
|
||||
0x00000000, 0x40027ffe, 0x7ffe4002, 0x40024002, 0x40024002, 0x40024002, 0x7ffe4002, 0x00000000, // RAYGUI_ICON_WINDOW
|
||||
0x09100000, 0x09f00910, 0x09100910, 0x00000910, 0x24a2779e, 0x27a224a2, 0x709e20a2, 0x00000000, // RAYGUI_ICON_199
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // RAYGUI_ICON_200
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // RAYGUI_ICON_201
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // RAYGUI_ICON_202
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // RAYGUI_ICON_203
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // RAYGUI_ICON_204
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // RAYGUI_ICON_205
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // RAYGUI_ICON_206
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // RAYGUI_ICON_207
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // RAYGUI_ICON_208
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // RAYGUI_ICON_209
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // RAYGUI_ICON_210
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // RAYGUI_ICON_211
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // RAYGUI_ICON_212
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // RAYGUI_ICON_213
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // RAYGUI_ICON_214
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // RAYGUI_ICON_215
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // RAYGUI_ICON_216
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // RAYGUI_ICON_217
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // RAYGUI_ICON_218
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // RAYGUI_ICON_219
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // RAYGUI_ICON_220
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // RAYGUI_ICON_221
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // RAYGUI_ICON_222
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // RAYGUI_ICON_223
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // RAYGUI_ICON_224
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // RAYGUI_ICON_225
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // RAYGUI_ICON_226
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // RAYGUI_ICON_227
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // RAYGUI_ICON_228
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // RAYGUI_ICON_229
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // RAYGUI_ICON_230
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // RAYGUI_ICON_231
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // RAYGUI_ICON_232
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // RAYGUI_ICON_233
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // RAYGUI_ICON_234
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // RAYGUI_ICON_235
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // RAYGUI_ICON_236
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // RAYGUI_ICON_237
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // RAYGUI_ICON_238
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // RAYGUI_ICON_239
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // RAYGUI_ICON_240
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // RAYGUI_ICON_241
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // RAYGUI_ICON_242
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // RAYGUI_ICON_243
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // RAYGUI_ICON_244
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // RAYGUI_ICON_245
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // RAYGUI_ICON_246
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // RAYGUI_ICON_247
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // RAYGUI_ICON_248
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // RAYGUI_ICON_249
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // RAYGUI_ICON_250
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // RAYGUI_ICON_251
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // RAYGUI_ICON_252
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // RAYGUI_ICON_253
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // RAYGUI_ICON_254
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, // RAYGUI_ICON_255
|
||||
};
|
2
libs/raygui/inject.c
Normal file
2
libs/raygui/inject.c
Normal file
@ -0,0 +1,2 @@
|
||||
#include "raygui.h"
|
||||
|
2
libs/raygui/inject.h
Normal file
2
libs/raygui/inject.h
Normal file
@ -0,0 +1,2 @@
|
||||
#include "raygui.h"
|
||||
|
66
libs/raygui/inject.zig
Normal file
66
libs/raygui/inject.zig
Normal file
@ -0,0 +1,66 @@
|
||||
const std = @import("std");
|
||||
const raygui = @cImport({
|
||||
@cInclude("raygui.h");
|
||||
@cInclude("raygui_marshal.h");
|
||||
});
|
||||
const raylib = @import("raylib");
|
||||
|
||||
pub const Rectangle = raylib.Rectangle;
|
||||
pub const Vector2 = raylib.Vector2;
|
||||
pub const Color = raylib.Color;
|
||||
pub const RICON_SIZE = 32;
|
||||
pub const RICON_DATA_ELEMENTS = 255;
|
||||
|
||||
pub fn textAlignPixelOffset(h: i32) i32 {
|
||||
return h % 2;
|
||||
}
|
||||
|
||||
fn bitCheck(a: u32, b: u32) bool {
|
||||
const r = @shlWithOverflow(1, @as(u5, @truncate(b)));
|
||||
return (a & (r[0])) != 0;
|
||||
}
|
||||
|
||||
/// Draw selected icon using rectangles pixel-by-pixel
|
||||
pub fn GuiDrawIcon(
|
||||
icon: raygui.GuiIconName,
|
||||
posX: i32,
|
||||
posY: i32,
|
||||
pixelSize: i32,
|
||||
color: raylib.Color,
|
||||
) void {
|
||||
const iconId = @intFromEnum(icon);
|
||||
|
||||
var i: i32 = 0;
|
||||
var y: i32 = 0;
|
||||
while (i < RICON_SIZE * RICON_SIZE / 32) : (i += 1) {
|
||||
var k: u32 = 0;
|
||||
while (k < 32) : (k += 1) {
|
||||
if (bitCheck(raygui.guiIcons[@as(usize, @intCast(iconId * RICON_DATA_ELEMENTS + i))], k)) {
|
||||
_ = raylib.DrawRectangle(
|
||||
posX + @as(i32, @intCast(k % RICON_SIZE)) * pixelSize,
|
||||
posY + y * pixelSize,
|
||||
pixelSize,
|
||||
pixelSize,
|
||||
color,
|
||||
);
|
||||
}
|
||||
|
||||
if ((k == 15) or (k == 31)) {
|
||||
y += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Draw button with icon centered
|
||||
pub fn GuiDrawIconButton(bounds: raylib.Rectangle, icon: GuiIconName, iconTint: raylib.Color) bool {
|
||||
const pressed = GuiButton(bounds, "");
|
||||
GuiDrawIcon(
|
||||
icon,
|
||||
@as(i32, @intFromFloat(bounds.x + bounds.width / 2 - @as(f32, @floatFromInt(RICON_SIZE)) / 2)),
|
||||
@as(i32, @intFromFloat(bounds.y + (bounds.height / 2) - @as(f32, @floatFromInt(RICON_SIZE)) / 2)),
|
||||
1,
|
||||
iconTint,
|
||||
);
|
||||
return pressed;
|
||||
}
|
46
libs/raygui/intermediate.zig
Normal file
46
libs/raygui/intermediate.zig
Normal file
@ -0,0 +1,46 @@
|
||||
const std = @import("std");
|
||||
const fs = std.fs;
|
||||
const mapping = @import("type_mapping.zig");
|
||||
const json = std.json;
|
||||
|
||||
pub const jsonFiles: []const []const u8 = &.{
|
||||
"raygui.json",
|
||||
};
|
||||
pub const bindingsJSON = "bindings.json";
|
||||
|
||||
pub fn main() !void {
|
||||
std.log.info("updating bindings.json ...", .{});
|
||||
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
|
||||
defer {
|
||||
if (gpa.deinit() == .leak) {
|
||||
std.log.err("memory leak detected", .{});
|
||||
}
|
||||
}
|
||||
const allocator = gpa.allocator();
|
||||
var arena = std.heap.ArenaAllocator.init(allocator);
|
||||
defer arena.deinit();
|
||||
|
||||
const raylib: mapping.CombinedRaylib = try mapping.CombinedRaylib.load(arena.allocator(), jsonFiles);
|
||||
|
||||
var bindings: mapping.Intermediate = mapping.Intermediate.loadCustoms(arena.allocator(), bindingsJSON) catch |err| Catch: {
|
||||
std.log.warn("could not open {s}: {?}\n", .{ bindingsJSON, err });
|
||||
break :Catch mapping.Intermediate{
|
||||
.enums = &[_]mapping.Enum{},
|
||||
.structs = &[_]mapping.Struct{},
|
||||
.functions = &[_]mapping.Function{},
|
||||
.defines = &[_]mapping.Define{},
|
||||
};
|
||||
};
|
||||
|
||||
try bindings.addNonCustom(arena.allocator(), raylib);
|
||||
|
||||
var file = try fs.cwd().createFile(bindingsJSON, .{});
|
||||
defer file.close();
|
||||
|
||||
try json.stringify(bindings, .{
|
||||
.emit_null_optional_fields = false,
|
||||
.whitespace = .indent_2,
|
||||
}, file.writer());
|
||||
|
||||
std.log.info("... done", .{});
|
||||
}
|
BIN
libs/raygui/logo.png
Normal file
BIN
libs/raygui/logo.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.1 KiB |
1
libs/raygui/raygui
Submodule
1
libs/raygui/raygui
Submodule
@ -0,0 +1 @@
|
||||
Subproject commit e30a826909cefbce39bae4ceaee76da6b163e2b1
|
3355
libs/raygui/raygui.json
Normal file
3355
libs/raygui/raygui.json
Normal file
File diff suppressed because it is too large
Load Diff
1694
libs/raygui/raygui.zig
Normal file
1694
libs/raygui/raygui.zig
Normal file
File diff suppressed because it is too large
Load Diff
277
libs/raygui/raygui_marshal.c
Normal file
277
libs/raygui/raygui_marshal.c
Normal file
@ -0,0 +1,277 @@
|
||||
#include "raygui.h"
|
||||
|
||||
void mGuiEnable(void)
|
||||
{
|
||||
GuiEnable();
|
||||
}
|
||||
|
||||
void mGuiDisable(void)
|
||||
{
|
||||
GuiDisable();
|
||||
}
|
||||
|
||||
void mGuiLock(void)
|
||||
{
|
||||
GuiLock();
|
||||
}
|
||||
|
||||
void mGuiUnlock(void)
|
||||
{
|
||||
GuiUnlock();
|
||||
}
|
||||
|
||||
bool mGuiIsLocked(void)
|
||||
{
|
||||
return GuiIsLocked();
|
||||
}
|
||||
|
||||
void mGuiSetAlpha(float alpha)
|
||||
{
|
||||
GuiSetAlpha(alpha);
|
||||
}
|
||||
|
||||
void mGuiSetState(int state)
|
||||
{
|
||||
GuiSetState(state);
|
||||
}
|
||||
|
||||
int mGuiGetState(void)
|
||||
{
|
||||
return GuiGetState();
|
||||
}
|
||||
|
||||
void mGuiSetFont(Font *font)
|
||||
{
|
||||
GuiSetFont(*font);
|
||||
}
|
||||
|
||||
void mGuiGetFont(Font *out)
|
||||
{
|
||||
*out = GuiGetFont();
|
||||
}
|
||||
|
||||
void mGuiSetStyle(int control, int property, int value)
|
||||
{
|
||||
GuiSetStyle(control, property, value);
|
||||
}
|
||||
|
||||
int mGuiGetStyle(int control, int property)
|
||||
{
|
||||
return GuiGetStyle(control, property);
|
||||
}
|
||||
|
||||
void mGuiLoadStyle(const char * fileName)
|
||||
{
|
||||
GuiLoadStyle(fileName);
|
||||
}
|
||||
|
||||
void mGuiLoadStyleDefault(void)
|
||||
{
|
||||
GuiLoadStyleDefault();
|
||||
}
|
||||
|
||||
void mGuiEnableTooltip(void)
|
||||
{
|
||||
GuiEnableTooltip();
|
||||
}
|
||||
|
||||
void mGuiDisableTooltip(void)
|
||||
{
|
||||
GuiDisableTooltip();
|
||||
}
|
||||
|
||||
void mGuiSetTooltip(const char * tooltip)
|
||||
{
|
||||
GuiSetTooltip(tooltip);
|
||||
}
|
||||
|
||||
const char * mGuiIconText(int iconId, const char * text)
|
||||
{
|
||||
return GuiIconText(iconId, text);
|
||||
}
|
||||
|
||||
void mGuiSetIconScale(int scale)
|
||||
{
|
||||
GuiSetIconScale(scale);
|
||||
}
|
||||
|
||||
unsigned int * mGuiGetIcons(void)
|
||||
{
|
||||
return GuiGetIcons();
|
||||
}
|
||||
|
||||
char ** mGuiLoadIcons(const char * fileName, bool loadIconsName)
|
||||
{
|
||||
return GuiLoadIcons(fileName, loadIconsName);
|
||||
}
|
||||
|
||||
int mGuiWindowBox(Rectangle *bounds, const char * title)
|
||||
{
|
||||
return GuiWindowBox(*bounds, title);
|
||||
}
|
||||
|
||||
int mGuiGroupBox(Rectangle *bounds, const char * text)
|
||||
{
|
||||
return GuiGroupBox(*bounds, text);
|
||||
}
|
||||
|
||||
int mGuiLine(Rectangle *bounds, const char * text)
|
||||
{
|
||||
return GuiLine(*bounds, text);
|
||||
}
|
||||
|
||||
int mGuiPanel(Rectangle *bounds, const char * text)
|
||||
{
|
||||
return GuiPanel(*bounds, text);
|
||||
}
|
||||
|
||||
int mGuiTabBar(Rectangle *bounds, const char ** text, int count, int * active)
|
||||
{
|
||||
return GuiTabBar(*bounds, text, count, active);
|
||||
}
|
||||
|
||||
int mGuiScrollPanel(Rectangle *bounds, const char * text, Rectangle *content, Vector2 * scroll, Rectangle * view)
|
||||
{
|
||||
return GuiScrollPanel(*bounds, text, *content, scroll, view);
|
||||
}
|
||||
|
||||
int mGuiLabel(Rectangle *bounds, const char * text)
|
||||
{
|
||||
return GuiLabel(*bounds, text);
|
||||
}
|
||||
|
||||
int mGuiButton(Rectangle *bounds, const char * text)
|
||||
{
|
||||
return GuiButton(*bounds, text);
|
||||
}
|
||||
|
||||
int mGuiLabelButton(Rectangle *bounds, const char * text)
|
||||
{
|
||||
return GuiLabelButton(*bounds, text);
|
||||
}
|
||||
|
||||
int mGuiToggle(Rectangle *bounds, const char * text, bool * active)
|
||||
{
|
||||
return GuiToggle(*bounds, text, active);
|
||||
}
|
||||
|
||||
int mGuiToggleGroup(Rectangle *bounds, const char * text, int * active)
|
||||
{
|
||||
return GuiToggleGroup(*bounds, text, active);
|
||||
}
|
||||
|
||||
int mGuiToggleSlider(Rectangle *bounds, const char * text, int * active)
|
||||
{
|
||||
return GuiToggleSlider(*bounds, text, active);
|
||||
}
|
||||
|
||||
int mGuiCheckBox(Rectangle *bounds, const char * text, bool * checked)
|
||||
{
|
||||
return GuiCheckBox(*bounds, text, checked);
|
||||
}
|
||||
|
||||
int mGuiComboBox(Rectangle *bounds, const char * text, int * active)
|
||||
{
|
||||
return GuiComboBox(*bounds, text, active);
|
||||
}
|
||||
|
||||
int mGuiDropdownBox(Rectangle *bounds, const char * text, int * active, bool editMode)
|
||||
{
|
||||
return GuiDropdownBox(*bounds, text, active, editMode);
|
||||
}
|
||||
|
||||
int mGuiSpinner(Rectangle *bounds, const char * text, int * value, int minValue, int maxValue, bool editMode)
|
||||
{
|
||||
return GuiSpinner(*bounds, text, value, minValue, maxValue, editMode);
|
||||
}
|
||||
|
||||
int mGuiValueBox(Rectangle *bounds, const char * text, int * value, int minValue, int maxValue, bool editMode)
|
||||
{
|
||||
return GuiValueBox(*bounds, text, value, minValue, maxValue, editMode);
|
||||
}
|
||||
|
||||
int mGuiTextBox(Rectangle *bounds, char * text, int textSize, bool editMode)
|
||||
{
|
||||
return GuiTextBox(*bounds, text, textSize, editMode);
|
||||
}
|
||||
|
||||
int mGuiSlider(Rectangle *bounds, const char * textLeft, const char * textRight, float * value, float minValue, float maxValue)
|
||||
{
|
||||
return GuiSlider(*bounds, textLeft, textRight, value, minValue, maxValue);
|
||||
}
|
||||
|
||||
int mGuiSliderBar(Rectangle *bounds, const char * textLeft, const char * textRight, float * value, float minValue, float maxValue)
|
||||
{
|
||||
return GuiSliderBar(*bounds, textLeft, textRight, value, minValue, maxValue);
|
||||
}
|
||||
|
||||
int mGuiProgressBar(Rectangle *bounds, const char * textLeft, const char * textRight, float * value, float minValue, float maxValue)
|
||||
{
|
||||
return GuiProgressBar(*bounds, textLeft, textRight, value, minValue, maxValue);
|
||||
}
|
||||
|
||||
int mGuiStatusBar(Rectangle *bounds, const char * text)
|
||||
{
|
||||
return GuiStatusBar(*bounds, text);
|
||||
}
|
||||
|
||||
int mGuiDummyRec(Rectangle *bounds, const char * text)
|
||||
{
|
||||
return GuiDummyRec(*bounds, text);
|
||||
}
|
||||
|
||||
int mGuiGrid(Rectangle *bounds, const char * text, float spacing, int subdivs, Vector2 * mouseCell)
|
||||
{
|
||||
return GuiGrid(*bounds, text, spacing, subdivs, mouseCell);
|
||||
}
|
||||
|
||||
int mGuiListView(Rectangle *bounds, const char * text, int * scrollIndex, int * active)
|
||||
{
|
||||
return GuiListView(*bounds, text, scrollIndex, active);
|
||||
}
|
||||
|
||||
int mGuiListViewEx(Rectangle *bounds, const char ** text, int count, int * scrollIndex, int * active, int * focus)
|
||||
{
|
||||
return GuiListViewEx(*bounds, text, count, scrollIndex, active, focus);
|
||||
}
|
||||
|
||||
int mGuiMessageBox(Rectangle *bounds, const char * title, const char * message, const char * buttons)
|
||||
{
|
||||
return GuiMessageBox(*bounds, title, message, buttons);
|
||||
}
|
||||
|
||||
int mGuiTextInputBox(Rectangle *bounds, const char * title, const char * message, const char * buttons, char * text, int textMaxSize, bool * secretViewActive)
|
||||
{
|
||||
return GuiTextInputBox(*bounds, title, message, buttons, text, textMaxSize, secretViewActive);
|
||||
}
|
||||
|
||||
int mGuiColorPicker(Rectangle *bounds, const char * text, Color * color)
|
||||
{
|
||||
return GuiColorPicker(*bounds, text, color);
|
||||
}
|
||||
|
||||
int mGuiColorPanel(Rectangle *bounds, const char * text, Color * color)
|
||||
{
|
||||
return GuiColorPanel(*bounds, text, color);
|
||||
}
|
||||
|
||||
int mGuiColorBarAlpha(Rectangle *bounds, const char * text, float * alpha)
|
||||
{
|
||||
return GuiColorBarAlpha(*bounds, text, alpha);
|
||||
}
|
||||
|
||||
int mGuiColorBarHue(Rectangle *bounds, const char * text, float * value)
|
||||
{
|
||||
return GuiColorBarHue(*bounds, text, value);
|
||||
}
|
||||
|
||||
int mGuiColorPickerHSV(Rectangle *bounds, const char * text, Vector3 * colorHsv)
|
||||
{
|
||||
return GuiColorPickerHSV(*bounds, text, colorHsv);
|
||||
}
|
||||
|
||||
int mGuiColorPanelHSV(Rectangle *bounds, const char * text, Vector3 * colorHsv)
|
||||
{
|
||||
return GuiColorPanelHSV(*bounds, text, colorHsv);
|
||||
}
|
||||
|
167
libs/raygui/raygui_marshal.h
Normal file
167
libs/raygui/raygui_marshal.h
Normal file
@ -0,0 +1,167 @@
|
||||
#include "raygui.h"
|
||||
|
||||
// Enable gui controls (global state)
|
||||
void mGuiEnable(void);
|
||||
|
||||
// Disable gui controls (global state)
|
||||
void mGuiDisable(void);
|
||||
|
||||
// Lock gui controls (global state)
|
||||
void mGuiLock(void);
|
||||
|
||||
// Unlock gui controls (global state)
|
||||
void mGuiUnlock(void);
|
||||
|
||||
// Check if gui is locked (global state)
|
||||
bool mGuiIsLocked(void);
|
||||
|
||||
// Set gui controls alpha (global state), alpha goes from 0.0f to 1.0f
|
||||
void mGuiSetAlpha(float alpha);
|
||||
|
||||
// Set gui state (global state)
|
||||
void mGuiSetState(int state);
|
||||
|
||||
// Get gui state (global state)
|
||||
int mGuiGetState(void);
|
||||
|
||||
// Set gui custom font (global state)
|
||||
void mGuiSetFont(Font *font);
|
||||
|
||||
// Get gui custom font (global state)
|
||||
void mGuiGetFont(Font *out);
|
||||
|
||||
// Set one style property
|
||||
void mGuiSetStyle(int control, int property, int value);
|
||||
|
||||
// Get one style property
|
||||
int mGuiGetStyle(int control, int property);
|
||||
|
||||
// Load style file over global style variable (.rgs)
|
||||
void mGuiLoadStyle(const char * fileName);
|
||||
|
||||
// Load style default over global style
|
||||
void mGuiLoadStyleDefault(void);
|
||||
|
||||
// Enable gui tooltips (global state)
|
||||
void mGuiEnableTooltip(void);
|
||||
|
||||
// Disable gui tooltips (global state)
|
||||
void mGuiDisableTooltip(void);
|
||||
|
||||
// Set tooltip string
|
||||
void mGuiSetTooltip(const char * tooltip);
|
||||
|
||||
// Get text with icon id prepended (if supported)
|
||||
const char * mGuiIconText(int iconId, const char * text);
|
||||
|
||||
// Set default icon drawing size
|
||||
void mGuiSetIconScale(int scale);
|
||||
|
||||
// Get raygui icons data pointer
|
||||
unsigned int * mGuiGetIcons(void);
|
||||
|
||||
// Load raygui icons file (.rgi) into internal icons data
|
||||
char ** mGuiLoadIcons(const char * fileName, bool loadIconsName);
|
||||
|
||||
// Window Box control, shows a window that can be closed
|
||||
int mGuiWindowBox(Rectangle *bounds, const char * title);
|
||||
|
||||
// Group Box control with text name
|
||||
int mGuiGroupBox(Rectangle *bounds, const char * text);
|
||||
|
||||
// Line separator control, could contain text
|
||||
int mGuiLine(Rectangle *bounds, const char * text);
|
||||
|
||||
// Panel control, useful to group controls
|
||||
int mGuiPanel(Rectangle *bounds, const char * text);
|
||||
|
||||
// Tab Bar control, returns TAB to be closed or -1
|
||||
int mGuiTabBar(Rectangle *bounds, const char ** text, int count, int * active);
|
||||
|
||||
// Scroll Panel control
|
||||
int mGuiScrollPanel(Rectangle *bounds, const char * text, Rectangle *content, Vector2 * scroll, Rectangle * view);
|
||||
|
||||
// Label control, shows text
|
||||
int mGuiLabel(Rectangle *bounds, const char * text);
|
||||
|
||||
// Button control, returns true when clicked
|
||||
int mGuiButton(Rectangle *bounds, const char * text);
|
||||
|
||||
// Label button control, show true when clicked
|
||||
int mGuiLabelButton(Rectangle *bounds, const char * text);
|
||||
|
||||
// Toggle Button control, returns true when active
|
||||
int mGuiToggle(Rectangle *bounds, const char * text, bool * active);
|
||||
|
||||
// Toggle Group control, returns active toggle index
|
||||
int mGuiToggleGroup(Rectangle *bounds, const char * text, int * active);
|
||||
|
||||
// Toggle Slider control, returns true when clicked
|
||||
int mGuiToggleSlider(Rectangle *bounds, const char * text, int * active);
|
||||
|
||||
// Check Box control, returns true when active
|
||||
int mGuiCheckBox(Rectangle *bounds, const char * text, bool * checked);
|
||||
|
||||
// Combo Box control, returns selected item index
|
||||
int mGuiComboBox(Rectangle *bounds, const char * text, int * active);
|
||||
|
||||
// Dropdown Box control, returns selected item
|
||||
int mGuiDropdownBox(Rectangle *bounds, const char * text, int * active, bool editMode);
|
||||
|
||||
// Spinner control, returns selected value
|
||||
int mGuiSpinner(Rectangle *bounds, const char * text, int * value, int minValue, int maxValue, bool editMode);
|
||||
|
||||
// Value Box control, updates input text with numbers
|
||||
int mGuiValueBox(Rectangle *bounds, const char * text, int * value, int minValue, int maxValue, bool editMode);
|
||||
|
||||
// Text Box control, updates input text
|
||||
int mGuiTextBox(Rectangle *bounds, char * text, int textSize, bool editMode);
|
||||
|
||||
// Slider control, returns selected value
|
||||
int mGuiSlider(Rectangle *bounds, const char * textLeft, const char * textRight, float * value, float minValue, float maxValue);
|
||||
|
||||
// Slider Bar control, returns selected value
|
||||
int mGuiSliderBar(Rectangle *bounds, const char * textLeft, const char * textRight, float * value, float minValue, float maxValue);
|
||||
|
||||
// Progress Bar control, shows current progress value
|
||||
int mGuiProgressBar(Rectangle *bounds, const char * textLeft, const char * textRight, float * value, float minValue, float maxValue);
|
||||
|
||||
// Status Bar control, shows info text
|
||||
int mGuiStatusBar(Rectangle *bounds, const char * text);
|
||||
|
||||
// Dummy control for placeholders
|
||||
int mGuiDummyRec(Rectangle *bounds, const char * text);
|
||||
|
||||
// Grid control, returns mouse cell position
|
||||
int mGuiGrid(Rectangle *bounds, const char * text, float spacing, int subdivs, Vector2 * mouseCell);
|
||||
|
||||
// List View control, returns selected list item index
|
||||
int mGuiListView(Rectangle *bounds, const char * text, int * scrollIndex, int * active);
|
||||
|
||||
// List View with extended parameters
|
||||
int mGuiListViewEx(Rectangle *bounds, const char ** text, int count, int * scrollIndex, int * active, int * focus);
|
||||
|
||||
// Message Box control, displays a message
|
||||
int mGuiMessageBox(Rectangle *bounds, const char * title, const char * message, const char * buttons);
|
||||
|
||||
// Text Input Box control, ask for text, supports secret
|
||||
int mGuiTextInputBox(Rectangle *bounds, const char * title, const char * message, const char * buttons, char * text, int textMaxSize, bool * secretViewActive);
|
||||
|
||||
// Color Picker control (multiple color controls)
|
||||
int mGuiColorPicker(Rectangle *bounds, const char * text, Color * color);
|
||||
|
||||
// Color Panel control
|
||||
int mGuiColorPanel(Rectangle *bounds, const char * text, Color * color);
|
||||
|
||||
// Color Bar Alpha control
|
||||
int mGuiColorBarAlpha(Rectangle *bounds, const char * text, float * alpha);
|
||||
|
||||
// Color Bar Hue control
|
||||
int mGuiColorBarHue(Rectangle *bounds, const char * text, float * value);
|
||||
|
||||
// Color Picker control that avoids conversion to RGB on each call (multiple color controls)
|
||||
int mGuiColorPickerHSV(Rectangle *bounds, const char * text, Vector3 * colorHsv);
|
||||
|
||||
// Color Panel control that returns HSV color value, used by GuiColorPickerHSV()
|
||||
int mGuiColorPanelHSV(Rectangle *bounds, const char * text, Vector3 * colorHsv);
|
||||
|
6
libs/raygui/raylib_parser.zig
Normal file
6
libs/raygui/raylib_parser.zig
Normal file
@ -0,0 +1,6 @@
|
||||
//! run 'zig build jsons' to generate bindings for raylib
|
||||
//! run 'zig build raylib_parser' to build the raylib_parser.exe
|
||||
|
||||
/// this needs to be here so the zig compiler won't complain that there is no entry point
|
||||
/// but actually we are using main() of 'raylib/src/parser/raylib_parser.c'
|
||||
pub extern fn main() c_int;
|
694
libs/raygui/type_mapping.zig
Normal file
694
libs/raygui/type_mapping.zig
Normal file
@ -0,0 +1,694 @@
|
||||
//! Strategy:
|
||||
//! 1. generate raylib JSONs
|
||||
//! 2. combine in a union RaylibJson
|
||||
//! 3. convert to intermediate representation
|
||||
//! 4. read adjusted intermediate JSONs
|
||||
//! 5. generate raylib.zig // wrap paramters and pass them to marshall versions of the raylib functions
|
||||
//! 6. generate marshall.c // unwrap parameters from zig function and call the actual raylib function
|
||||
//! 7. generate marshall.h // C signatures for all marshalled functions
|
||||
|
||||
const std = @import("std");
|
||||
const json = std.json;
|
||||
const memoryConstrain: usize = 1024 * 1024 * 1024; // 1 GiB
|
||||
const Allocator = std.mem.Allocator;
|
||||
const fmt = std.fmt.allocPrint;
|
||||
const talloc = std.testing.allocator;
|
||||
const expect = std.testing.expect;
|
||||
const expectEqualStrings = std.testing.expectEqualStrings;
|
||||
|
||||
//--- Intermediate Format -------------------------------------------------------------------------
|
||||
|
||||
pub const Intermediate = struct {
|
||||
functions: []Function,
|
||||
enums: []Enum,
|
||||
structs: []Struct,
|
||||
defines: []Define,
|
||||
|
||||
pub fn loadCustoms(allocator: Allocator, jsonFile: []const u8) !@This() {
|
||||
var enums = std.ArrayList(Enum).init(allocator);
|
||||
var structs = std.ArrayList(Struct).init(allocator);
|
||||
var functions = std.ArrayList(Function).init(allocator);
|
||||
var defines = std.ArrayList(Define).init(allocator);
|
||||
|
||||
const jsonData = try std.fs.cwd().readFileAlloc(allocator, jsonFile, memoryConstrain);
|
||||
|
||||
const bindingJson = try json.parseFromSliceLeaky(Intermediate, allocator, jsonData, .{
|
||||
.ignore_unknown_fields = true,
|
||||
});
|
||||
|
||||
for (bindingJson.enums) |t| {
|
||||
if (t.custom) {
|
||||
try enums.append(t);
|
||||
}
|
||||
}
|
||||
|
||||
for (bindingJson.structs) |t| {
|
||||
if (t.custom) {
|
||||
try structs.append(t);
|
||||
}
|
||||
}
|
||||
|
||||
for (bindingJson.functions) |f| {
|
||||
if (f.custom) {
|
||||
try functions.append(f);
|
||||
}
|
||||
}
|
||||
|
||||
for (bindingJson.defines) |f| {
|
||||
if (f.custom) {
|
||||
try defines.append(f);
|
||||
}
|
||||
}
|
||||
|
||||
return @This(){
|
||||
.enums = try enums.toOwnedSlice(),
|
||||
.structs = try structs.toOwnedSlice(),
|
||||
.functions = try functions.toOwnedSlice(),
|
||||
.defines = try defines.toOwnedSlice(),
|
||||
};
|
||||
}
|
||||
|
||||
pub fn addNonCustom(self: *@This(), allocator: Allocator, rlJson: CombinedRaylib) !void {
|
||||
var enums = std.ArrayList(Enum).init(allocator);
|
||||
try enums.appendSlice(self.enums);
|
||||
var structs = std.ArrayList(Struct).init(allocator);
|
||||
try structs.appendSlice(self.structs);
|
||||
var functions = std.ArrayList(Function).init(allocator);
|
||||
try functions.appendSlice(self.functions);
|
||||
var defines = std.ArrayList(Define).init(allocator);
|
||||
try defines.appendSlice(self.defines);
|
||||
|
||||
outer: for (rlJson.defines.values(), 0..) |d, i| {
|
||||
for (defines.items) |added| {
|
||||
if (eql(added.name, d.name)) {
|
||||
std.log.debug("{s} is customized", .{d.name});
|
||||
continue :outer;
|
||||
}
|
||||
}
|
||||
const define = parseRaylibDefine(allocator, d) orelse continue :outer;
|
||||
|
||||
if (i < defines.items.len) {
|
||||
try defines.insert(i, define);
|
||||
} else {
|
||||
try defines.append(define);
|
||||
}
|
||||
}
|
||||
outer: for (rlJson.enums.values(), 0..) |e, i| {
|
||||
const name = if (alias.get(e.name)) |n| n else e.name;
|
||||
for (enums.items) |added| {
|
||||
if (eql(added.name, name)) {
|
||||
std.log.debug("{s} is customized", .{name});
|
||||
continue :outer;
|
||||
}
|
||||
}
|
||||
|
||||
if (i < enums.items.len) {
|
||||
try enums.insert(i, try parseRaylibEnum(allocator, e));
|
||||
} else {
|
||||
try enums.append(try parseRaylibEnum(allocator, e));
|
||||
}
|
||||
}
|
||||
outer: for (rlJson.structs.values(), 0..) |s, i| {
|
||||
const name = if (alias.get(s.name)) |n| n else s.name;
|
||||
for (structs.items) |added| {
|
||||
if (eql(added.name, name)) {
|
||||
std.log.debug("{s} is customized", .{name});
|
||||
continue :outer;
|
||||
}
|
||||
}
|
||||
if (i < structs.items.len) {
|
||||
try structs.insert(i, try parseRaylibStruct(allocator, s));
|
||||
} else {
|
||||
try structs.append(try parseRaylibStruct(allocator, s));
|
||||
}
|
||||
}
|
||||
for (rlJson.defines.values()) |_| {}
|
||||
|
||||
outer: for (rlJson.functions.values(), 0..) |f, i| {
|
||||
for (functions.items) |added| {
|
||||
if (eql(added.name, f.name)) {
|
||||
std.log.debug("{s} is customized", .{f.name});
|
||||
continue :outer;
|
||||
}
|
||||
}
|
||||
if (i < functions.items.len) {
|
||||
try functions.insert(i, try parseRaylibFunction(allocator, f));
|
||||
} else {
|
||||
try functions.append(try parseRaylibFunction(allocator, f));
|
||||
}
|
||||
}
|
||||
|
||||
self.enums = try enums.toOwnedSlice();
|
||||
self.structs = try structs.toOwnedSlice();
|
||||
self.functions = try functions.toOwnedSlice();
|
||||
self.defines = try defines.toOwnedSlice();
|
||||
}
|
||||
|
||||
pub fn containsStruct(self: @This(), name: []const u8) bool {
|
||||
for (self.structs) |s| {
|
||||
if (eql(s.name, name)) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
pub fn containsEnum(self: @This(), name: []const u8) bool {
|
||||
for (self.enums) |e| {
|
||||
if (eql(e.name, name)) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
pub fn containsDefine(self: @This(), name: []const u8) bool {
|
||||
for (self.defines) |d| {
|
||||
if (eql(d.name, name)) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
pub const Function = struct {
|
||||
name: []const u8,
|
||||
params: []FunctionParameter,
|
||||
returnType: []const u8,
|
||||
description: ?[]const u8 = null,
|
||||
custom: bool = false,
|
||||
};
|
||||
|
||||
pub const FunctionParameter = struct {
|
||||
name: []const u8,
|
||||
typ: []const u8,
|
||||
description: ?[]const u8 = null,
|
||||
};
|
||||
|
||||
pub fn parseRaylibFunction(allocator: Allocator, func: RaylibFunction) !Function {
|
||||
var args = std.ArrayList(FunctionParameter).init(allocator);
|
||||
if (func.params) |params| {
|
||||
for (params) |p| {
|
||||
const t = try toZig(allocator, p.type);
|
||||
|
||||
try args.append(.{
|
||||
.name = p.name,
|
||||
.typ = t,
|
||||
.description = p.description,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
const returnType = try toZig(allocator, func.returnType);
|
||||
|
||||
return Function{
|
||||
.name = func.name,
|
||||
.params = try args.toOwnedSlice(),
|
||||
.returnType = returnType,
|
||||
.description = func.description,
|
||||
};
|
||||
}
|
||||
|
||||
pub const Struct = struct {
|
||||
name: []const u8,
|
||||
fields: []const StructField,
|
||||
description: ?[]const u8 = null,
|
||||
custom: bool = false,
|
||||
};
|
||||
|
||||
pub const StructField = struct {
|
||||
name: []const u8,
|
||||
typ: []const u8,
|
||||
description: ?[]const u8 = null,
|
||||
};
|
||||
|
||||
pub fn parseRaylibStruct(allocator: Allocator, s: RaylibStruct) !Struct {
|
||||
var fields = std.ArrayList(StructField).init(allocator);
|
||||
for (s.fields) |field| {
|
||||
var typ = try toZig(allocator, getTypeWithoutArrayNotation(field.type));
|
||||
|
||||
if (getArraySize(field.type)) |size| {
|
||||
typ = try std.fmt.allocPrint(allocator, "[{d}]{s}", .{ size, typ });
|
||||
}
|
||||
|
||||
try fields.append(.{
|
||||
.name = field.name,
|
||||
.typ = typ,
|
||||
.description = field.description,
|
||||
});
|
||||
}
|
||||
|
||||
return Struct{
|
||||
.name = if (alias.get(s.name)) |a| a else s.name,
|
||||
.fields = try fields.toOwnedSlice(),
|
||||
.description = s.description,
|
||||
};
|
||||
}
|
||||
|
||||
pub const Define = struct {
|
||||
name: []const u8,
|
||||
typ: []const u8,
|
||||
value: []const u8,
|
||||
description: ?[]const u8 = null,
|
||||
custom: bool = false,
|
||||
};
|
||||
|
||||
pub fn parseRaylibDefine(allocator: Allocator, s: RaylibDefine) ?Define {
|
||||
var typ: []const u8 = undefined;
|
||||
var value: []const u8 = undefined;
|
||||
|
||||
if (eql("INT", s.type)) {
|
||||
typ = "i32";
|
||||
value = std.fmt.allocPrint(allocator, "{s}", .{s.value}) catch return null;
|
||||
} else if (eql("LONG", s.type)) {
|
||||
typ = "i64";
|
||||
value = std.fmt.allocPrint(allocator, "{s}", .{s.value}) catch return null;
|
||||
} else if (eql("FLOAT", s.type)) {
|
||||
typ = "f32";
|
||||
value = std.fmt.allocPrint(allocator, "{s}", .{s.value}) catch return null;
|
||||
} else if (eql("DOUBLE", s.type)) {
|
||||
typ = "f64";
|
||||
value = std.fmt.allocPrint(allocator, "{s}", .{s.value}) catch return null;
|
||||
} else if (eql("STRING", s.type)) {
|
||||
typ = "[]const u8";
|
||||
value = std.fmt.allocPrint(allocator, "\"{s}\"", .{s.value}) catch return null;
|
||||
} else if (eql("COLOR", s.type)) {
|
||||
typ = "Color";
|
||||
std.debug.assert(startsWith(s.value, "CLITERAL(Color){"));
|
||||
std.debug.assert(endsWith(s.value, "}"));
|
||||
|
||||
const componentString = s.value["CLITERAL(Color){".len .. s.value.len - 1];
|
||||
var spliterator = std.mem.split(u8, componentString, ",");
|
||||
var r = spliterator.next() orelse return null;
|
||||
r = std.mem.trim(u8, r, " \t\r\n");
|
||||
var g = spliterator.next() orelse return null;
|
||||
g = std.mem.trim(u8, g, " \t\r\n");
|
||||
var b = spliterator.next() orelse return null;
|
||||
b = std.mem.trim(u8, b, " \t\r\n");
|
||||
var a = spliterator.next() orelse return null;
|
||||
a = std.mem.trim(u8, a, " \t\r\n");
|
||||
value = std.fmt.allocPrint(allocator, ".{{.r={s}, .g={s}, .b={s}, .a={s}}}", .{ r, g, b, a }) catch return null;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
|
||||
return Define{
|
||||
.name = s.name,
|
||||
.typ = typ,
|
||||
.value = value,
|
||||
.description = s.description,
|
||||
};
|
||||
}
|
||||
|
||||
pub const Enum = struct {
|
||||
name: []const u8,
|
||||
values: []const EnumValue,
|
||||
description: ?[]const u8 = null,
|
||||
custom: bool = false,
|
||||
};
|
||||
|
||||
pub const EnumValue = struct {
|
||||
name: []const u8,
|
||||
value: c_int,
|
||||
description: ?[]const u8 = null,
|
||||
};
|
||||
|
||||
pub fn parseRaylibEnum(allocator: Allocator, e: RaylibEnum) !Enum {
|
||||
var values = std.ArrayList(EnumValue).init(allocator);
|
||||
for (e.values) |value| {
|
||||
try values.append(.{
|
||||
.name = value.name,
|
||||
.value = value.value,
|
||||
.description = value.description,
|
||||
});
|
||||
}
|
||||
|
||||
return Enum{
|
||||
.name = e.name,
|
||||
.values = try values.toOwnedSlice(),
|
||||
.description = e.description,
|
||||
};
|
||||
}
|
||||
|
||||
/// is c const type
|
||||
pub fn isConst(c: []const u8) bool {
|
||||
return startsWith(c, "const ");
|
||||
}
|
||||
test "isConst" {
|
||||
try expect(!isConst("char *"));
|
||||
try expect(!isConst("unsigned char *"));
|
||||
try expect(isConst("const unsigned char *"));
|
||||
try expect(isConst("const unsigned int *"));
|
||||
try expect(isConst("const void *"));
|
||||
try expect(!isConst("Vector2 *"));
|
||||
try expect(!isConst("Vector2"));
|
||||
try expect(!isConst("int"));
|
||||
}
|
||||
|
||||
/// is c pointer type
|
||||
pub fn isPointer(c: []const u8) bool {
|
||||
return endsWith(c, "*");
|
||||
}
|
||||
test "isPointer" {
|
||||
try expect(isPointer("char *"));
|
||||
try expect(isPointer("unsigned char *"));
|
||||
try expect(isPointer("const unsigned char *"));
|
||||
try expect(isPointer("const unsigned int *"));
|
||||
try expect(isPointer("Vector2 *"));
|
||||
try expect(!isPointer("Vector2"));
|
||||
try expect(!isPointer("int"));
|
||||
}
|
||||
|
||||
pub fn isPointerToPointer(c: []const u8) bool {
|
||||
return endsWith(c, "**");
|
||||
}
|
||||
test "isPointerToPointer" {
|
||||
try expect(!isPointerToPointer("char *"));
|
||||
try expect(!isPointerToPointer("unsigned char *"));
|
||||
try expect(isPointerToPointer("const unsigned char **"));
|
||||
try expect(isPointerToPointer("const unsigned int **"));
|
||||
try expect(isPointerToPointer("Vector2 **"));
|
||||
try expect(!isPointerToPointer("Vector2*"));
|
||||
try expect(!isPointerToPointer("int"));
|
||||
}
|
||||
|
||||
pub fn isVoid(c: []const u8) bool {
|
||||
return eql(stripType(c), "void");
|
||||
}
|
||||
test "isVoid" {
|
||||
try expect(!isVoid("char *"));
|
||||
try expect(!isVoid("unsigned char *"));
|
||||
try expect(!isVoid("const unsigned char *"));
|
||||
try expect(isVoid("const void *"));
|
||||
try expect(isVoid("void *"));
|
||||
try expect(isVoid("void"));
|
||||
try expect(isVoid("void **"));
|
||||
}
|
||||
|
||||
/// strips const and pointer annotations
|
||||
/// const TName * -> TName
|
||||
pub fn stripType(c: []const u8) []const u8 {
|
||||
var name = if (isConst(c)) c["const ".len..] else c;
|
||||
name = if (isPointer(name)) name[0 .. name.len - 1] else name;
|
||||
// double pointer?
|
||||
name = if (isPointer(name)) name[0 .. name.len - 1] else name;
|
||||
name = std.mem.trim(u8, name, " \t\n");
|
||||
if (alias.get(name)) |ali| {
|
||||
name = ali;
|
||||
}
|
||||
return name;
|
||||
}
|
||||
test "stripType" {
|
||||
try expectEqualStrings("void", stripType("const void *"));
|
||||
try expectEqualStrings("unsinged int", stripType("unsinged int *"));
|
||||
try expectEqualStrings("Vector2", stripType("const Vector2 *"));
|
||||
}
|
||||
|
||||
pub fn getArraySize(typ: []const u8) ?usize {
|
||||
if (std.mem.indexOf(u8, typ, "[")) |open| {
|
||||
if (std.mem.indexOf(u8, typ, "]")) |close| {
|
||||
return std.fmt.parseInt(usize, typ[open + 1 .. close], 10) catch null;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
test "getArraySize" {
|
||||
const expectEqual = std.testing.expectEqual;
|
||||
|
||||
try expectEqual(@as(?usize, 4), getArraySize("float[4]"));
|
||||
try expectEqual(@as(?usize, 44), getArraySize("int[44]"));
|
||||
try expectEqual(@as(?usize, 123456), getArraySize("a[123456]"));
|
||||
try expectEqual(@as(?usize, 1), getArraySize("test[1] "));
|
||||
try expectEqual(@as(?usize, null), getArraySize("foo[]"));
|
||||
try expectEqual(@as(?usize, null), getArraySize("bar"));
|
||||
try expectEqual(@as(?usize, null), getArraySize("foo["));
|
||||
try expectEqual(@as(?usize, null), getArraySize("bar]"));
|
||||
try expectEqual(@as(?usize, 42), getArraySize(" lol this is ok[42] "));
|
||||
}
|
||||
|
||||
pub fn getTypeWithoutArrayNotation(typ: []const u8) []const u8 {
|
||||
if (std.mem.indexOf(u8, typ, "[")) |open| {
|
||||
return typ[0..open];
|
||||
}
|
||||
return typ;
|
||||
}
|
||||
|
||||
fn toZig(allocator: Allocator, c: []const u8) ![]const u8 {
|
||||
if (fixedMapping.get(c)) |fixed| {
|
||||
return fixed;
|
||||
}
|
||||
|
||||
const consT = if (isConst(c)) "const " else "";
|
||||
const stripped = stripType(c);
|
||||
const pointeR = if (isPointer(c))
|
||||
if (eql(stripped, "unsigned char") or eql(stripped, "char")) "?[*:0]" else "*"
|
||||
else
|
||||
"";
|
||||
|
||||
const name = if (raylibToZigType.get(stripped)) |primitive| primitive else stripped;
|
||||
|
||||
if (isPointer(c)) {
|
||||
return try fmt(allocator, "{s}{s}{s}", .{ pointeR, consT, name });
|
||||
}
|
||||
return name;
|
||||
}
|
||||
test "toZig" {
|
||||
var arena = std.heap.ArenaAllocator.init(talloc);
|
||||
defer arena.deinit();
|
||||
const a = arena.allocator();
|
||||
|
||||
try expectEqualStrings("i32", try toZig(a, "int"));
|
||||
try expectEqualStrings("const i32", try toZig(a, "const int"));
|
||||
try expectEqualStrings("?[*]Vector2", try toZig(a, "Vector2 *"));
|
||||
}
|
||||
|
||||
const raylibToZigType = std.ComptimeStringMap([]const u8, .{
|
||||
.{ "void", "void" },
|
||||
.{ "bool", "bool" },
|
||||
.{ "char", "u8" },
|
||||
.{ "unsigned char", "u8" },
|
||||
.{ "short", "i16" },
|
||||
.{ "unsigned short", "u16" },
|
||||
.{ "int", "i32" },
|
||||
.{ "unsigned int", "u32" },
|
||||
.{ "long", "i64" },
|
||||
.{ "unsigned long", "u64" },
|
||||
.{ "unsigned long long", "u64" },
|
||||
.{ "float", "f32" },
|
||||
.{ "double", "f64" },
|
||||
});
|
||||
|
||||
const fixedMapping = std.ComptimeStringMap([]const u8, .{
|
||||
.{ "void *", "*anyopaque" },
|
||||
.{ "const void *", "*const anyopaque" },
|
||||
.{ "const unsigned char *", "[*:0]const u8" },
|
||||
.{ "const char *", "[*:0]const u8" },
|
||||
.{ "const char **", "[*]const [*:0]const u8" },
|
||||
.{ "char **", "[*][*:0]u8" },
|
||||
.{ "rAudioBuffer *", "*anyopaque" },
|
||||
.{ "rAudioProcessor *", "*anyopaque" },
|
||||
.{ "Image *", "*Image" },
|
||||
});
|
||||
|
||||
//--- Raylib parser JSONs -------------------------------------------------------------------------
|
||||
|
||||
const alias = std.ComptimeStringMap([]const u8, .{
|
||||
.{ "Camera", "Camera3D" },
|
||||
.{ "Texture", "Texture2D" },
|
||||
.{ "TextureCubemap", "Texture2D" },
|
||||
.{ "RenderTexture", "RenderTexture2D" },
|
||||
.{ "GuiStyle", "u32" },
|
||||
.{ "Quaternion", "Vector4" },
|
||||
.{ "PhysicsBody", "*PhysicsBodyData" },
|
||||
});
|
||||
|
||||
const cAlias = std.ComptimeStringMap([]const u8, .{
|
||||
.{ "Camera", "Camera3D" },
|
||||
.{ "Texture", "Texture2D" },
|
||||
.{ "TextureCubemap", "Texture2D" },
|
||||
.{ "RenderTexture", "RenderTexture2D" },
|
||||
.{ "Quaternion", "Vector4" },
|
||||
.{ "PhysicsBody", "PhysicsBodyData *" },
|
||||
});
|
||||
|
||||
pub const CombinedRaylib = struct {
|
||||
structs: std.StringArrayHashMap(RaylibStruct),
|
||||
enums: std.StringArrayHashMap(RaylibEnum),
|
||||
defines: std.StringArrayHashMap(RaylibDefine),
|
||||
functions: std.StringArrayHashMap(RaylibFunction),
|
||||
|
||||
pub fn load(allocator: Allocator, jsonFiles: []const []const u8) !@This() {
|
||||
var structs = std.StringArrayHashMap(RaylibStruct).init(allocator);
|
||||
var enums = std.StringArrayHashMap(RaylibEnum).init(allocator);
|
||||
var defines = std.StringArrayHashMap(RaylibDefine).init(allocator);
|
||||
var functions = std.StringArrayHashMap(RaylibFunction).init(allocator);
|
||||
|
||||
for (jsonFiles) |jsonFile| {
|
||||
std.log.info("parsing {s}", .{jsonFile});
|
||||
const jsonData = try std.fs.cwd().readFileAlloc(allocator, jsonFile, memoryConstrain);
|
||||
|
||||
const bindingJson = try json.parseFromSliceLeaky(RaylibJson, allocator, jsonData, .{
|
||||
.ignore_unknown_fields = true,
|
||||
.duplicate_field_behavior = .use_last,
|
||||
});
|
||||
|
||||
for (bindingJson.structs) |*s| {
|
||||
for (s.fields) |*f| {
|
||||
f.type = cAlias.get(f.type) orelse f.type;
|
||||
}
|
||||
try structs.put(s.name, s.*);
|
||||
}
|
||||
|
||||
for (bindingJson.enums) |e| {
|
||||
try enums.put(e.name, e);
|
||||
}
|
||||
|
||||
for (bindingJson.defines) |d| {
|
||||
try defines.put(d.name, d);
|
||||
}
|
||||
|
||||
for (bindingJson.functions) |*f| {
|
||||
f.returnType = cAlias.get(f.returnType) orelse f.returnType;
|
||||
if (f.params) |params| {
|
||||
for (params) |*p| {
|
||||
p.type = cAlias.get(p.type) orelse p.type;
|
||||
}
|
||||
}
|
||||
try functions.put(f.name, f.*);
|
||||
}
|
||||
}
|
||||
|
||||
return @This(){
|
||||
.structs = structs,
|
||||
.enums = enums,
|
||||
.defines = defines,
|
||||
.functions = functions,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn toIntermediate(self: @This(), allocator: Allocator, customs: Intermediate) !Intermediate {
|
||||
var functions = std.ArrayList(Function).init(allocator);
|
||||
var enums = std.ArrayList(Enum).init(allocator);
|
||||
var structs = std.ArrayList(Struct).init(allocator);
|
||||
|
||||
enums: for (self.enums.values()) |e| {
|
||||
for (customs.enums) |tt| {
|
||||
if (eql(tt.name, e.name)) break :enums;
|
||||
}
|
||||
try enums.append(try parseRaylibEnum(allocator, e));
|
||||
}
|
||||
structs: for (self.structs.values()) |s| {
|
||||
for (customs.structs) |tt| {
|
||||
if (eql(tt.name, s.name)) break :structs;
|
||||
}
|
||||
try structs.append(try parseRaylibStruct(allocator, s, customs));
|
||||
}
|
||||
for (self.defines.values()) |_| {}
|
||||
|
||||
funcs: for (self.functions.values()) |f| {
|
||||
for (customs.functions) |ff| {
|
||||
if (eql(ff.name, f.name)) break :funcs;
|
||||
}
|
||||
try functions.append(try parseRaylibFunction(allocator, f, customs.types));
|
||||
}
|
||||
|
||||
return Intermediate{
|
||||
.functions = try functions.toOwnedSlice(),
|
||||
.enums = try enums.toOwnedSlice(),
|
||||
.structs = try structs.toOwnedSlice(),
|
||||
};
|
||||
}
|
||||
|
||||
fn containsStruct(self: @This(), name: []const u8) bool {
|
||||
return self.structs.contains(name);
|
||||
}
|
||||
|
||||
fn containsEnum(self: @This(), name: []const u8) bool {
|
||||
return self.enums.contains(name);
|
||||
}
|
||||
|
||||
fn containsFunction(self: @This(), name: []const u8) bool {
|
||||
return self.functions.contains(name);
|
||||
}
|
||||
};
|
||||
|
||||
const RaylibJson = struct {
|
||||
structs: []RaylibStruct,
|
||||
enums: []RaylibEnum,
|
||||
defines: []RaylibDefine,
|
||||
functions: []RaylibFunction,
|
||||
};
|
||||
|
||||
pub const RaylibStruct = struct {
|
||||
name: []const u8,
|
||||
description: []const u8,
|
||||
fields: []RaylibField,
|
||||
};
|
||||
|
||||
pub const RaylibField = struct {
|
||||
name: []const u8,
|
||||
description: []const u8,
|
||||
type: []const u8,
|
||||
};
|
||||
|
||||
pub const RaylibEnum = struct {
|
||||
name: []const u8,
|
||||
description: []const u8,
|
||||
values: []RaylibEnumValue,
|
||||
};
|
||||
|
||||
pub const RaylibEnumValue = struct {
|
||||
name: []const u8,
|
||||
description: []const u8,
|
||||
value: c_int,
|
||||
};
|
||||
|
||||
pub const RaylibFunction = struct {
|
||||
name: []const u8,
|
||||
description: []const u8,
|
||||
returnType: []const u8,
|
||||
params: ?[]RaylibFunctionParam = null,
|
||||
};
|
||||
|
||||
pub const RaylibFunctionParam = struct {
|
||||
name: []const u8,
|
||||
type: []const u8,
|
||||
description: ?[]const u8 = null,
|
||||
};
|
||||
|
||||
pub const RaylibDefine = struct {
|
||||
name: []const u8,
|
||||
type: []const u8,
|
||||
value: []const u8,
|
||||
description: ?[]const u8 = null,
|
||||
};
|
||||
|
||||
//--- Helpers -------------------------------------------------------------------------------------
|
||||
|
||||
/// true if C type is primitive or a pointer to anything
|
||||
/// this means we don't need to wrap it in a pointer
|
||||
pub fn isPrimitiveOrPointer(c: []const u8) bool {
|
||||
const primitiveTypes = std.ComptimeStringMap(void, .{
|
||||
.{ "void", {} },
|
||||
.{ "bool", {} },
|
||||
.{ "char", {} },
|
||||
.{ "unsigned char", {} },
|
||||
.{ "short", {} },
|
||||
.{ "unsigned short", {} },
|
||||
.{ "int", {} },
|
||||
.{ "unsigned int", {} },
|
||||
.{ "long", {} },
|
||||
.{ "unsigned long", {} },
|
||||
.{ "unsigned long long", {} },
|
||||
.{ "float", {} },
|
||||
.{ "double", {} },
|
||||
});
|
||||
return primitiveTypes.has(stripType(c)) or endsWith(c, "*");
|
||||
}
|
||||
|
||||
fn eql(a: []const u8, b: []const u8) bool {
|
||||
return std.mem.eql(u8, a, b);
|
||||
}
|
||||
|
||||
fn startsWith(haystack: []const u8, needle: []const u8) bool {
|
||||
return std.mem.startsWith(u8, haystack, needle);
|
||||
}
|
||||
|
||||
fn endsWith(haystack: []const u8, needle: []const u8) bool {
|
||||
return std.mem.endsWith(u8, haystack, needle);
|
||||
}
|
@ -1 +0,0 @@
|
||||
Subproject commit f9ed05023db75484333b6c7125a8c02a99cf3a14
|
Binary file not shown.
Binary file not shown.
Before Width: | Height: | Size: 504 KiB |
Binary file not shown.
@ -1,13 +0,0 @@
|
||||
import bpy
|
||||
import sys
|
||||
|
||||
argv = sys.argv
|
||||
argv = argv[argv.index("--") + 1:]
|
||||
assert len(argv) >= 1
|
||||
|
||||
output_path = argv[0]
|
||||
assert output_path.endswith(".gltf") or output_path.endswith(".glb")
|
||||
bpy.ops.export_scene.gltf(
|
||||
filepath=output_path,
|
||||
use_visible=True,
|
||||
)
|
Binary file not shown.
Before Width: | Height: | Size: 311 B |
@ -1,523 +0,0 @@
|
||||
const Self = @This();
|
||||
const Gltf = @import("zgltf");
|
||||
const rl = @import("raylib");
|
||||
const std = @import("std");
|
||||
const RaylibChip = @import("raylib-chip.zig");
|
||||
const Light = @import("./light.zig");
|
||||
|
||||
const assert = std.debug.assert;
|
||||
const Allocator = std.mem.Allocator;
|
||||
|
||||
allocator: Allocator,
|
||||
|
||||
materials: []rl.Material,
|
||||
|
||||
models: std.ArrayList(rl.Model),
|
||||
static_models: std.ArrayList(*rl.Model),
|
||||
buttons: [16]*rl.Model,
|
||||
power_switch: *rl.Model,
|
||||
power_light_position: rl.Vector3,
|
||||
|
||||
bbox: rl.BoundingBox,
|
||||
position: rl.Vector3,
|
||||
|
||||
button_state: *[16]bool,
|
||||
powered: *bool,
|
||||
|
||||
fn getExtensionByMimeType(mime_type: []const u8) ?[:0]const u8 {
|
||||
if (std.mem.eql(u8, mime_type, "image/png")) {
|
||||
return ".png\x00";
|
||||
} else if (std.mem.eql(u8, mime_type, "image/jpg")) {
|
||||
return ".jpg\x00";
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
fn loadGltfImage(image: Gltf.Image) !rl.Image {
|
||||
assert(image.uri == null);
|
||||
assert(image.data != null);
|
||||
assert(image.mime_type != null);
|
||||
|
||||
const image_data = image.data.?;
|
||||
const mime_type = image.mime_type.?;
|
||||
|
||||
const file_type = getExtensionByMimeType(mime_type);
|
||||
assert(file_type != null);
|
||||
|
||||
const rl_image = rl.LoadImageFromMemory(file_type.?, @ptrCast(image_data.ptr), @intCast(image_data.len));
|
||||
if (@as(?*anyopaque, @ptrCast(rl_image.data)) == null) {
|
||||
return error.Failed;
|
||||
}
|
||||
return rl_image;
|
||||
}
|
||||
|
||||
fn loadGltfMaterial(data: Gltf.Data, material: Gltf.Material) !rl.Material {
|
||||
var rl_material = rl.LoadMaterialDefault();
|
||||
errdefer rl.UnloadMaterial(rl_material);
|
||||
|
||||
var albedo_map: *rl.MaterialMap = &rl_material.maps.?[@intFromEnum(rl.MaterialMapIndex.MATERIAL_MAP_ALBEDO)];
|
||||
if (material.metallic_roughness.base_color_texture) |base_color_texture| {
|
||||
const texture = data.textures.items[base_color_texture.index];
|
||||
const image = data.images.items[texture.source.?];
|
||||
|
||||
const rl_image = try loadGltfImage(image);
|
||||
defer rl.UnloadImage(rl_image);
|
||||
albedo_map.texture = rl.LoadTextureFromImage(rl_image);
|
||||
}
|
||||
|
||||
albedo_map.color.r = @intFromFloat(material.metallic_roughness.base_color_factor[0]*255);
|
||||
albedo_map.color.g = @intFromFloat(material.metallic_roughness.base_color_factor[1]*255);
|
||||
albedo_map.color.b = @intFromFloat(material.metallic_roughness.base_color_factor[2]*255);
|
||||
albedo_map.color.a = @intFromFloat(material.metallic_roughness.base_color_factor[3]*255);
|
||||
|
||||
return rl_material;
|
||||
}
|
||||
|
||||
fn loadGltfPrimitive(gltf: Gltf, primitive: Gltf.Primitive) !rl.Mesh {
|
||||
var allocator = std.heap.c_allocator;
|
||||
|
||||
assert(primitive.mode == .triangles);
|
||||
var rl_mesh = std.mem.zeroes(rl.Mesh);
|
||||
errdefer rl.UnloadMesh(rl_mesh);
|
||||
|
||||
var bin = gltf.glb_binary.?;
|
||||
var f32_buffer = std.ArrayList(f32).init(allocator);
|
||||
defer f32_buffer.deinit();
|
||||
|
||||
for (primitive.attributes.items) |attribute| {
|
||||
switch (attribute) {
|
||||
.position => |accessor_index| {
|
||||
const accessor = gltf.data.accessors.items[accessor_index];
|
||||
assert(accessor.component_type == .float);
|
||||
assert(accessor.type == .vec3);
|
||||
f32_buffer.clearAndFree();
|
||||
gltf.getDataFromBufferView(f32, &f32_buffer, accessor, bin);
|
||||
|
||||
var vertices = try allocator.dupe(f32, f32_buffer.items);
|
||||
rl_mesh.vertexCount = @intCast(accessor.count);
|
||||
rl_mesh.vertices = @ptrCast(vertices);
|
||||
},
|
||||
.normal => |accessor_index| {
|
||||
const accessor = gltf.data.accessors.items[accessor_index];
|
||||
assert(accessor.component_type == .float);
|
||||
assert(accessor.type == .vec3);
|
||||
f32_buffer.clearRetainingCapacity();
|
||||
gltf.getDataFromBufferView(f32, &f32_buffer, accessor, bin);
|
||||
|
||||
var normals = try allocator.dupe(f32, f32_buffer.items);
|
||||
rl_mesh.normals = @ptrCast(normals);
|
||||
},
|
||||
.tangent => |accessor_index| {
|
||||
const accessor = gltf.data.accessors.items[accessor_index];
|
||||
assert(accessor.component_type == .float);
|
||||
assert(accessor.type == .vec4);
|
||||
f32_buffer.clearRetainingCapacity();
|
||||
gltf.getDataFromBufferView(f32, &f32_buffer, accessor, bin);
|
||||
|
||||
var tangents = try allocator.dupe(f32, f32_buffer.items);
|
||||
rl_mesh.tangents = @ptrCast(tangents);
|
||||
},
|
||||
.texcoord => |accessor_index| {
|
||||
const accessor = gltf.data.accessors.items[accessor_index];
|
||||
assert(accessor.component_type == .float);
|
||||
assert(accessor.type == .vec2);
|
||||
f32_buffer.clearRetainingCapacity();
|
||||
gltf.getDataFromBufferView(f32, &f32_buffer, accessor, bin);
|
||||
|
||||
var texcoords = try allocator.dupe(f32, f32_buffer.items);
|
||||
rl_mesh.texcoords = @ptrCast(texcoords);
|
||||
},
|
||||
else => {}
|
||||
}
|
||||
}
|
||||
|
||||
if (primitive.indices) |accessor_index| {
|
||||
const accessor = gltf.data.accessors.items[accessor_index];
|
||||
rl_mesh.triangleCount = @divExact(accessor.count, 3);
|
||||
const accessor_count: usize = @intCast(accessor.count);
|
||||
|
||||
var indices = try allocator.alloc(u16, accessor_count);
|
||||
rl_mesh.indices = @ptrCast(indices);
|
||||
|
||||
if (accessor.component_type == Gltf.ComponentType.unsigned_short) {
|
||||
var u16_buffer = std.ArrayList(u16).init(allocator);
|
||||
defer u16_buffer.deinit();
|
||||
gltf.getDataFromBufferView(u16, &u16_buffer, accessor, bin);
|
||||
|
||||
@memcpy(indices, u16_buffer.items);
|
||||
} else if (accessor.component_type == Gltf.ComponentType.unsigned_integer) {
|
||||
var u32_buffer = std.ArrayList(u32).init(allocator);
|
||||
defer u32_buffer.deinit();
|
||||
gltf.getDataFromBufferView(u32, &u32_buffer, accessor, bin);
|
||||
|
||||
for (0..accessor_count) |i| {
|
||||
indices[i] = @truncate(u32_buffer.items[i]);
|
||||
}
|
||||
rl.TraceLog(@intFromEnum(rl.TraceLogLevel.LOG_WARNING), "MODEL: Indices data converted from u32 to u16, possible loss of data");
|
||||
} else {
|
||||
@panic("Unknown GLTF primitives indices component type. Use u16 or u32");
|
||||
}
|
||||
} else {
|
||||
rl_mesh.triangleCount = @divExact(rl_mesh.vertexCount, 3);
|
||||
}
|
||||
|
||||
rl.UploadMesh(@ptrCast(&rl_mesh), false);
|
||||
return rl_mesh;
|
||||
}
|
||||
|
||||
fn loadGltfMesh(materials: []rl.Material, gltf: Gltf, node: Gltf.Node) !rl.Model {
|
||||
const allocator = std.heap.c_allocator;
|
||||
const transform = Gltf.getGlobalTransform(&gltf.data, node);
|
||||
|
||||
var model = std.mem.zeroes(rl.Model);
|
||||
errdefer rl.UnloadModel(model);
|
||||
|
||||
model.transform = rl.Matrix{
|
||||
.m0 = transform[0][0],
|
||||
.m4 = transform[1][0],
|
||||
.m8 = transform[2][0],
|
||||
.m12 = transform[3][0],
|
||||
|
||||
.m1 = transform[0][1],
|
||||
.m5 = transform[1][1],
|
||||
.m9 = transform[2][1],
|
||||
.m13 = transform[3][1],
|
||||
|
||||
.m2 = transform[0][2],
|
||||
.m6 = transform[1][2],
|
||||
.m10 = transform[2][2],
|
||||
.m14 = transform[3][2],
|
||||
|
||||
.m3 = transform[0][3],
|
||||
.m7 = transform[1][3],
|
||||
.m11 = transform[2][3],
|
||||
.m15 = transform[3][3]
|
||||
};
|
||||
|
||||
if (node.mesh) |mesh_idx| {
|
||||
const mesh = gltf.data.meshes.items[mesh_idx];
|
||||
const primitives: []Gltf.Primitive = mesh.primitives.items;
|
||||
|
||||
var meshes = try allocator.alloc(rl.Mesh, primitives.len);
|
||||
model.meshCount = @intCast(primitives.len);
|
||||
model.meshes = @ptrCast(meshes.ptr);
|
||||
|
||||
var mesh_material = try allocator.alloc(i32, primitives.len);
|
||||
model.meshMaterial = @ptrCast(mesh_material.ptr);
|
||||
@memset(mesh_material, 0);
|
||||
|
||||
var used_material_ids = try allocator.alloc(usize, materials.len);
|
||||
var used_materials_count: usize = 0;
|
||||
defer allocator.free(used_material_ids);
|
||||
|
||||
for (0.., primitives) |j, primitive| {
|
||||
meshes[j] = try loadGltfPrimitive(gltf, primitive);
|
||||
|
||||
var mtl: usize = 0;
|
||||
if (primitive.material) |material| {
|
||||
mtl = material + 1;
|
||||
}
|
||||
|
||||
var mtl_index = std.mem.indexOfScalar(usize, used_material_ids[0..used_materials_count], mtl);
|
||||
if (mtl_index == null) {
|
||||
mtl_index = used_materials_count;
|
||||
used_material_ids[used_materials_count] = mtl;
|
||||
used_materials_count += 1;
|
||||
}
|
||||
|
||||
mesh_material[j] = @intCast(mtl_index.?);
|
||||
}
|
||||
|
||||
var used_materials = try allocator.alloc(rl.Material, used_materials_count+1);
|
||||
model.materials = @ptrCast(used_materials);
|
||||
model.materialCount = 0;
|
||||
for (0..used_materials_count) |i| {
|
||||
used_materials[i] = materials[used_material_ids[i]];
|
||||
|
||||
const max_material_maps = 12;
|
||||
const maps = try allocator.dupe(rl.MaterialMap, used_materials[i].maps.?[0..max_material_maps]);
|
||||
used_materials[i].maps = @ptrCast(maps);
|
||||
model.materialCount += 1;
|
||||
}
|
||||
}
|
||||
|
||||
return model;
|
||||
}
|
||||
|
||||
pub fn init(allocator: Allocator, powered: *bool, button_state: *[16]bool, screen_texture: rl.RenderTexture2D) !Self {
|
||||
var gltf = Gltf.init(allocator);
|
||||
defer gltf.deinit();
|
||||
try gltf.parse(@embedFile("assets/models/emulator.glb"));
|
||||
|
||||
const scene = gltf.data.scenes.items[gltf.data.scene.?];
|
||||
const scene_nodes: std.ArrayList(Gltf.Index) = scene.nodes.?;
|
||||
|
||||
const material_count: usize = @intCast(gltf.data.materials.items.len);
|
||||
var materials = try allocator.alloc(rl.Material, material_count+1);
|
||||
@memset(materials, std.mem.zeroes(rl.Material));
|
||||
errdefer allocator.free(materials);
|
||||
|
||||
materials[0] = rl.LoadMaterialDefault();
|
||||
errdefer {
|
||||
for (materials) |mtl| {
|
||||
rl.UnloadMaterial(mtl);
|
||||
}
|
||||
}
|
||||
|
||||
for (0..material_count, gltf.data.materials.items) |i, material| {
|
||||
materials[i+1] = try loadGltfMaterial(gltf.data, material);
|
||||
}
|
||||
|
||||
var models = try std.ArrayList(rl.Model).initCapacity(allocator, scene_nodes.items.len);
|
||||
errdefer models.deinit();
|
||||
errdefer {
|
||||
for (models.items) |model| {
|
||||
rl.UnloadModel(model);
|
||||
}
|
||||
}
|
||||
|
||||
var static_models = std.ArrayList(*rl.Model).init(allocator);
|
||||
errdefer static_models.deinit();
|
||||
|
||||
|
||||
var buttons: [16]*rl.Model = undefined;
|
||||
var power_switch: *rl.Model = undefined;
|
||||
var power_light: ?*rl.Model = null;
|
||||
|
||||
for (scene_nodes.items) |node_index| {
|
||||
const node = gltf.data.nodes.items[node_index];
|
||||
if (node.mesh == null) continue;
|
||||
|
||||
models.appendAssumeCapacity(try loadGltfMesh(materials, gltf, node));
|
||||
var model: *rl.Model = &models.items[models.items.len-1];
|
||||
|
||||
const name = node.name;
|
||||
if (std.mem.eql(u8, name, "Power switch")) {
|
||||
power_switch = model;
|
||||
} else if (std.mem.startsWith(u8, name, "Buttons ")) {
|
||||
var space = std.mem.indexOfScalar(u8, name, ' ').?;
|
||||
const button_idx = try std.fmt.parseInt(usize, name[space+1..], 16);
|
||||
buttons[button_idx] = model;
|
||||
} else {
|
||||
try static_models.append(model);
|
||||
}
|
||||
|
||||
if (std.mem.eql(u8, name, "Screen")) {
|
||||
const screen_material = &model.materials.?[0];
|
||||
rl.SetMaterialTexture(@ptrCast(screen_material), rl.MATERIAL_MAP_DIFFUSE, screen_texture.texture);
|
||||
} else if (std.mem.eql(u8, name, "Power indicator")) {
|
||||
power_light = model;
|
||||
}
|
||||
}
|
||||
|
||||
var power_light_position = rl.Vector3.zero();
|
||||
if (power_light) |model| {
|
||||
power_light_position = matrixGetTranslation(model.transform);
|
||||
}
|
||||
|
||||
return Self{
|
||||
.allocator = allocator,
|
||||
|
||||
.materials = materials,
|
||||
|
||||
.static_models = static_models,
|
||||
.models = models,
|
||||
.buttons = buttons,
|
||||
.power_switch = power_switch,
|
||||
.powered = powered,
|
||||
.button_state = button_state,
|
||||
|
||||
.power_light_position = power_light_position,
|
||||
.bbox = rl.GetModelBoundingBox(static_models.items[0].*),
|
||||
.position = rl.Vector3{ .x = 0, .y = 0, .z = 0 },
|
||||
};
|
||||
}
|
||||
|
||||
pub fn setShader(self: *Self, shader: rl.Shader) void {
|
||||
for (self.models.items) |*model| {
|
||||
if (model.materials == null) continue;
|
||||
|
||||
for (0..@intCast(model.materialCount)) |i| {
|
||||
model.materials.?[i].shader = shader;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn deinit(self: *Self) void {
|
||||
for (self.models.items) |model| {
|
||||
rl.UnloadModel(model);
|
||||
}
|
||||
for (self.materials) |mtl| {
|
||||
rl.UnloadMaterial(mtl);
|
||||
}
|
||||
self.allocator.free(self.materials);
|
||||
self.static_models.deinit();
|
||||
self.models.deinit();
|
||||
}
|
||||
|
||||
fn getRayCollisionModel(ray: rl.Ray, model: rl.Model, position: rl.Vector3) rl.RayCollision {
|
||||
var closest_hit_info = std.mem.zeroes(rl.RayCollision);
|
||||
const transform = rl.MatrixMultiply(model.transform, rl.MatrixTranslate(position.x, position.y, position.z));
|
||||
|
||||
for (0..@intCast(model.meshCount)) |i| {
|
||||
if (model.meshes == null) break;
|
||||
const mesh = model.meshes.?[i];
|
||||
|
||||
const hit_info = rl.GetRayCollisionMesh(ray, mesh, transform);
|
||||
if (!hit_info.hit) continue;
|
||||
|
||||
if ((!closest_hit_info.hit) or (closest_hit_info.distance > hit_info.distance)) {
|
||||
closest_hit_info = hit_info;
|
||||
}
|
||||
}
|
||||
|
||||
return closest_hit_info;
|
||||
}
|
||||
|
||||
const ModelCollision = struct { collision: rl.RayCollision, model: *rl.Model };
|
||||
fn getRayCollisionModels(ray: rl.Ray, models: []rl.Model, position: rl.Vector3) ?ModelCollision {
|
||||
var closest_hit_info: ?rl.RayCollision = null;
|
||||
var closest_model: ?*rl.Model = null;
|
||||
|
||||
for (models) |*model| {
|
||||
const hit_info = getRayCollisionModel(ray, model.*, position);
|
||||
if (!hit_info.hit) continue;
|
||||
|
||||
if ((closest_hit_info == null) or (closest_hit_info.?.distance > hit_info.distance)) {
|
||||
closest_hit_info = hit_info;
|
||||
closest_model = model;
|
||||
}
|
||||
}
|
||||
|
||||
if (closest_hit_info == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return ModelCollision{
|
||||
.collision = closest_hit_info.?,
|
||||
.model = closest_model.?
|
||||
};
|
||||
}
|
||||
|
||||
pub fn isOverPowerSwitch(self: *const Self, ray: rl.Ray) bool {
|
||||
const collision = getRayCollisionModels(ray, self.models.items, self.position);
|
||||
if (collision) |c| {
|
||||
return c.model == self.power_switch;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
fn matrixGetTranslation(mat: rl.Matrix) rl.Vector3 {
|
||||
return rl.Vector3{
|
||||
.x = mat.m12,
|
||||
.y = mat.m13,
|
||||
.z = mat.m14,
|
||||
};
|
||||
}
|
||||
|
||||
fn matrixGetScale(mat: rl.Matrix) rl.Vector3 {
|
||||
return rl.Vector3{
|
||||
.x = rl.Vector3Length(rl.Vector3{ .x = mat.m0, .y = mat.m1, .z = mat.m2 }),
|
||||
.y = rl.Vector3Length(rl.Vector3{ .x = mat.m4, .y = mat.m5, .z = mat.m6 }),
|
||||
.z = rl.Vector3Length(rl.Vector3{ .x = mat.m8, .y = mat.m9, .z = mat.m10 }),
|
||||
};
|
||||
}
|
||||
|
||||
// https://stackoverflow.com/a/64336115
|
||||
fn matrixGetRotation(mat: rl.Matrix) rl.Vector3 {
|
||||
const scale = matrixGetScale(mat);
|
||||
const R11 = mat.m0 / scale.x;
|
||||
const R12 = mat.m1 / scale.x;
|
||||
const R13 = mat.m2 / scale.x;
|
||||
|
||||
const R21 = mat.m4 / scale.y;
|
||||
// const R22 = mat.m5 / scale.y;
|
||||
// const R23 = mat.m6 / scale.y;
|
||||
|
||||
const R31 = mat.m8 / scale.z;
|
||||
const R32 = mat.m9 / scale.z;
|
||||
const R33 = mat.m10 / scale.z;
|
||||
|
||||
const asin = std.math.asin;
|
||||
const cos = std.math.cos;
|
||||
const atan2 = std.math.atan2;
|
||||
const pi = rl.PI;
|
||||
|
||||
var roll: f32 = undefined;
|
||||
var pitch: f32 = undefined;
|
||||
var yaw: f32 = undefined;
|
||||
if (R31 != 1 and R31 != -1) {
|
||||
const pitch_1 = -1 * asin(R31);
|
||||
// const pitch_2 = pi - pitch_1;
|
||||
const roll_1 = atan2(f32, R32 / cos(pitch_1), R33 / cos(pitch_1));
|
||||
// const roll_2 = atan2( R32 / cos(pitch_2) , R33 / cos(pitch_2));
|
||||
const yaw_1 = atan2(f32, R21 / cos(pitch_1), R11 / cos(pitch_1));
|
||||
// const yaw_2 = atan2( R21 / cos(pitch_2) , R11 / cos(pitch_2));
|
||||
|
||||
// IMPORTANT NOTE here, there is more than one solution but we choose the first for this case for simplicity !
|
||||
// You can insert your own domain logic here on how to handle both solutions appropriately (see the reference publication link for more info).
|
||||
pitch = pitch_1;
|
||||
roll = roll_1;
|
||||
yaw = yaw_1;
|
||||
} else {
|
||||
yaw = 0; // anything (we default this to zero)
|
||||
if (R31 == -1) {
|
||||
pitch = pi / 2;
|
||||
roll = yaw + atan2(f32, R12, R13);
|
||||
} else {
|
||||
pitch = -pi / 2;
|
||||
roll = -1*yaw + atan2(f32, -1*R12, -1*R13);
|
||||
}
|
||||
}
|
||||
|
||||
// convert from radians to degrees
|
||||
roll = roll * rl.RAD2DEG;
|
||||
pitch = pitch * rl.RAD2DEG;
|
||||
yaw = yaw * rl.RAD2DEG;
|
||||
|
||||
return rl.Vector3{
|
||||
.x = roll,
|
||||
.y = pitch,
|
||||
.z = yaw,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn draw(self: *Self) void {
|
||||
for (self.buttons, 0..) |button, i| {
|
||||
var position = self.position;
|
||||
if (self.button_state[i]) {
|
||||
position.z += 0.035;
|
||||
}
|
||||
rl.DrawModel(button.*, position, 1.0, rl.WHITE);
|
||||
}
|
||||
|
||||
for (self.static_models.items) |model| {
|
||||
rl.DrawModel(model.*, self.position, 1.0, rl.WHITE);
|
||||
}
|
||||
|
||||
{ // Power switch
|
||||
const on_angle: f32 = 45;
|
||||
const off_angle: f32 = -45;
|
||||
const target_angle = if (self.powered.*) on_angle else off_angle;
|
||||
|
||||
var transform = self.power_switch.transform;
|
||||
const rotation = matrixGetRotation(transform);
|
||||
const dt = rl.GetFrameTime();
|
||||
const delta_angle = rotation.z - target_angle;
|
||||
transform = rl.MatrixMultiply(rl.MatrixRotateZ((delta_angle * dt * 0.2)), transform);
|
||||
|
||||
self.power_switch.transform = transform;
|
||||
rl.DrawModel(self.power_switch.*, self.position, 1.0, rl.WHITE);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_power_light_position(self: *Self) rl.Vector3 {
|
||||
return self.power_light_position.add(self.position);
|
||||
}
|
||||
|
||||
pub fn get_power_light_color(self: *Self) rl.Color {
|
||||
_ = self;
|
||||
return rl.GREEN;
|
||||
}
|
70
src/gui-layout.zig
Normal file
70
src/gui-layout.zig
Normal file
@ -0,0 +1,70 @@
|
||||
const Self = @This();
|
||||
const rl = @import("raylib");
|
||||
const std = @import("std");
|
||||
|
||||
const LayoutFrame = struct {
|
||||
ox: f32,
|
||||
oy: f32,
|
||||
sx: f32,
|
||||
sy: f32,
|
||||
};
|
||||
|
||||
const LayoutStack = std.BoundedArray(LayoutFrame, 16);
|
||||
|
||||
stack: LayoutStack,
|
||||
|
||||
pub fn init() Self {
|
||||
var stack = LayoutStack.init(0) catch unreachable;
|
||||
stack.append(.{
|
||||
.ox = 0,
|
||||
.oy = 0,
|
||||
.sx = 1,
|
||||
.sy = 1,
|
||||
}) catch unreachable;
|
||||
|
||||
return Self { .stack = stack };
|
||||
}
|
||||
|
||||
pub fn deinit(self: *Self) void {
|
||||
if (self.stack.len > 1) {
|
||||
@panic(".push() was called more times than .pop()");
|
||||
}
|
||||
}
|
||||
|
||||
pub fn top(self: *Self) *LayoutFrame {
|
||||
return &self.stack.buffer[self.stack.len-1];
|
||||
}
|
||||
|
||||
pub fn push(self: *Self) void {
|
||||
const top_frame = self.top();
|
||||
self.stack.append(top_frame.*) catch @panic("LayoutStack is too small, increase hard-coded limit");
|
||||
}
|
||||
|
||||
pub fn pop(self: *Self) void {
|
||||
if (self.stack.len == 1) {
|
||||
@panic(".pop() was called more times than .push()");
|
||||
}
|
||||
_ = self.stack.pop();
|
||||
}
|
||||
|
||||
pub fn translate(self: *Self, x: f32, y: f32) void {
|
||||
const top_frame = self.top();
|
||||
top_frame.ox += x * top_frame.sx;
|
||||
top_frame.oy += y * top_frame.sy;
|
||||
}
|
||||
|
||||
pub fn scale(self: *Self, x: f32, y: f32) void {
|
||||
const top_frame = self.top();
|
||||
top_frame.sx *= x;
|
||||
top_frame.sy *= y;
|
||||
}
|
||||
|
||||
pub fn rect(self: *Self, x: f32, y: f32, width: f32, height: f32) rl.Rectangle {
|
||||
const top_frame = self.top();
|
||||
return rl.Rectangle {
|
||||
.x = x * top_frame.sx + top_frame.ox,
|
||||
.y = y * top_frame.sy + top_frame.oy,
|
||||
.width = width * top_frame.sx,
|
||||
.height = height * top_frame.sy
|
||||
};
|
||||
}
|
@ -1,88 +0,0 @@
|
||||
const Self = @This();
|
||||
const rl = @import("raylib");
|
||||
const std = @import("std");
|
||||
|
||||
pub const LightType = enum(i32) {
|
||||
DIRECTIONAL = 0,
|
||||
POINT = 1,
|
||||
};
|
||||
|
||||
shader: rl.Shader,
|
||||
|
||||
enabledLoc: i32,
|
||||
typeLoc: i32,
|
||||
positionLoc: i32,
|
||||
targetLoc: i32,
|
||||
colorLoc: i32,
|
||||
intensityLoc: i32,
|
||||
|
||||
fn getLightShaderLocation(shader: rl.Shader, idx: usize, comptime name: []const u8) i32 {
|
||||
var buf: [128]u8 = undefined;
|
||||
var fba = std.heap.FixedBufferAllocator.init(&buf);
|
||||
const prop_name = std.fmt.allocPrintZ(fba.allocator(), "lights[{d}]." ++ name, .{idx}) catch unreachable;
|
||||
return rl.GetShaderLocation(shader, prop_name);
|
||||
}
|
||||
|
||||
pub fn init(shader: rl.Shader, idx: usize) Self {
|
||||
return Self{
|
||||
.shader = shader,
|
||||
|
||||
.enabledLoc = getLightShaderLocation(shader, idx, "enabled"),
|
||||
.typeLoc = getLightShaderLocation(shader, idx, "type"),
|
||||
.positionLoc = getLightShaderLocation(shader, idx, "position"),
|
||||
.targetLoc = getLightShaderLocation(shader, idx, "target"),
|
||||
.colorLoc = getLightShaderLocation(shader, idx, "color"),
|
||||
.intensityLoc = getLightShaderLocation(shader, idx, "intensity"),
|
||||
};
|
||||
}
|
||||
|
||||
pub fn set_directional(self: *const Self, color: rl.Color, position: rl.Vector3, intensity: f32, target: rl.Vector3) void {
|
||||
self.set_type(.DIRECTIONAL);
|
||||
self.set_intensity(intensity);
|
||||
self.set_enabled(true);
|
||||
self.set_position(position);
|
||||
self.set_color(color);
|
||||
self.set_target(target);
|
||||
}
|
||||
|
||||
pub fn set_point(self: *const Self, color: rl.Color, position: rl.Vector3, intensity: f32) void {
|
||||
self.set_type(.POINT);
|
||||
self.set_intensity(intensity);
|
||||
self.set_enabled(true);
|
||||
self.set_color(color);
|
||||
self.set_position(position);
|
||||
}
|
||||
|
||||
pub fn set_enabled(self: *const Self, enabled: bool) void {
|
||||
const enabled_i32: i32 = @intFromBool(enabled);
|
||||
rl.SetShaderValue(self.shader, self.enabledLoc, &enabled_i32, .SHADER_UNIFORM_INT);
|
||||
}
|
||||
|
||||
pub fn set_type(self: *const Self, light_type: LightType) void {
|
||||
const light_type_i32: i32 = @intFromEnum(light_type);
|
||||
rl.SetShaderValue(self.shader, self.typeLoc, &light_type_i32, .SHADER_UNIFORM_INT);
|
||||
}
|
||||
|
||||
pub fn set_intensity(self: *const Self, intensity: f32) void {
|
||||
rl.SetShaderValue(self.shader, self.intensityLoc, &intensity, .SHADER_UNIFORM_FLOAT);
|
||||
}
|
||||
|
||||
pub fn set_position(self: *const Self, pos: rl.Vector3) void {
|
||||
const position = [3]f32{ pos.x, pos.y, pos.z };
|
||||
rl.SetShaderValue(self.shader, self.positionLoc, &position, .SHADER_UNIFORM_VEC3);
|
||||
}
|
||||
|
||||
pub fn set_target(self: *const Self, target: rl.Vector3) void {
|
||||
const target_f32 = [3]f32{ target.x, target.y, target.z };
|
||||
rl.SetShaderValue(self.shader, self.targetLoc, &target_f32, .SHADER_UNIFORM_VEC3);
|
||||
}
|
||||
|
||||
pub fn set_color(self: *const Self, color: rl.Color) void {
|
||||
const color_f32 = [4]f32{
|
||||
@as(f32, @floatFromInt(color.r)) / 255.0,
|
||||
@as(f32, @floatFromInt(color.g)) / 255.0,
|
||||
@as(f32, @floatFromInt(color.b)) / 255.0,
|
||||
@as(f32, @floatFromInt(color.a)) / 255.0,
|
||||
};
|
||||
rl.SetShaderValue(self.shader, self.colorLoc, &color_f32, .SHADER_UNIFORM_VEC4);
|
||||
}
|
@ -1,11 +1,11 @@
|
||||
const Self = @This();
|
||||
const rl = @import("raylib");
|
||||
const gui = @import("raygui");
|
||||
const std = @import("std");
|
||||
const Gltf = @import("zgltf");
|
||||
const EmulatorModel = @import("./emulator-model.zig");
|
||||
const ROM = @import("./roms.zig").ROM;
|
||||
const Light = @import("./light.zig");
|
||||
const ShaderCode = @import("./shader-code.zig");
|
||||
const roms = @import("./roms.zig");
|
||||
const GUILayout = @import("./gui-layout.zig");
|
||||
const VerticalLayout = @import("./vertical-layout.zig");
|
||||
const ROM = roms.ROM;
|
||||
|
||||
const ChipContext = @import("chip.zig");
|
||||
const RaylibChip = @import("raylib-chip.zig");
|
||||
@ -14,26 +14,17 @@ const assert = std.debug.assert;
|
||||
const Allocator = std.mem.Allocator;
|
||||
const StringList = std.ArrayList([]const u8);
|
||||
|
||||
const max_lights: u32 = 2;
|
||||
const rom_list = roms.listROMs();
|
||||
|
||||
allocator: Allocator,
|
||||
|
||||
emulator: EmulatorModel,
|
||||
|
||||
camera_turn_vel: rl.Vector3 = rl.Vector3{ .x = 0, .y = 0, .z = 0 },
|
||||
camera_target_orientation: ?rl.Vector3 = null,
|
||||
previous_click_time: f64 = 0.0,
|
||||
|
||||
shader: rl.Shader,
|
||||
lights: [max_lights]Light,
|
||||
|
||||
powered: *bool,
|
||||
chip: *ChipContext,
|
||||
raylib_chip: *RaylibChip,
|
||||
chip_sound: rl.Sound,
|
||||
screen_texture: rl.RenderTexture2D,
|
||||
rom: ?ROM = null,
|
||||
camera: rl.Camera3D,
|
||||
|
||||
is_gui_open: bool = true,
|
||||
selected_rom_index: i32 = 3,
|
||||
rom_list_scroll_index: i32 = 0,
|
||||
|
||||
pub fn genSinWave(wave: *rl.Wave, frequency: f32) void {
|
||||
assert(wave.sampleSize == 16); // Only 16 bits are supported
|
||||
@ -50,83 +41,7 @@ pub fn genSinWave(wave: *rl.Wave, frequency: f32) void {
|
||||
}
|
||||
}
|
||||
|
||||
fn getCameraProjection(camera: *const rl.Camera3D) rl.Matrix {
|
||||
const screen_width: f32 = @floatFromInt(rl.GetScreenWidth());
|
||||
const screen_height: f32 = @floatFromInt(rl.GetScreenHeight());
|
||||
|
||||
if (camera.projection == .CAMERA_PERSPECTIVE) {
|
||||
return rl.MatrixPerspective(camera.fovy*rl.DEG2RAD, screen_width/screen_height, rl.RL_CULL_DISTANCE_NEAR, rl.RL_CULL_DISTANCE_FAR);
|
||||
} else if (camera.projection == .CAMERA_ORTHOGRAPHIC) {
|
||||
const aspect = screen_width/screen_height;
|
||||
const top = camera.fovy/2.0;
|
||||
const right = top*aspect;
|
||||
|
||||
return rl.MatrixOrtho(-right, right, -top, top, rl.RL_CULL_DISTANCE_NEAR, rl.RL_CULL_DISTANCE_FAR);
|
||||
} else {
|
||||
unreachable;
|
||||
}
|
||||
}
|
||||
|
||||
fn getScreenDirectionFromCamera(mat_proj: *const rl.Matrix, mat_view: *const rl.Matrix, point: rl.Vector2) rl.Vector3 {
|
||||
const screen_width: f32 = @floatFromInt(rl.GetScreenWidth());
|
||||
const screen_height: f32 = @floatFromInt(rl.GetScreenHeight());
|
||||
|
||||
const ndc_x = (2.0*point.x) / screen_width - 1.0;
|
||||
const ndc_y = 1.0 - (2.0*point.y) / screen_height;
|
||||
|
||||
var near_point = rl.Vector3Unproject(.{ .x = ndc_x, .y = ndc_y, .z = 0.0 }, mat_proj.*, mat_view.*);
|
||||
var far_point = rl.Vector3Unproject(.{ .x = ndc_x, .y = ndc_y, .z = 1.0 }, mat_proj.*, mat_view.*);
|
||||
|
||||
return rl.Vector3Subtract(far_point, near_point).normalize();
|
||||
}
|
||||
|
||||
fn getPrefferedDistanceToBox(camera: *const rl.Camera3D, box: rl.BoundingBox) f32 {
|
||||
const screen_width: f32 = @floatFromInt(rl.GetScreenWidth());
|
||||
const screen_height: f32 = @floatFromInt(rl.GetScreenHeight());
|
||||
const margin = @min(screen_width, screen_height)*0.1;
|
||||
|
||||
const box_size = box.max.sub(box.min);
|
||||
|
||||
const max_model_scale = @min((screen_width-2*margin)/box_size.x, (screen_height-2*margin)/box_size.y);
|
||||
// const model_screen_width = box_size.x * max_model_scale;
|
||||
const model_screen_height = box_size.y * max_model_scale;
|
||||
|
||||
const mat_proj = getCameraProjection(camera);
|
||||
const mat_view = rl.MatrixIdentity(); // rl.MatrixLookAt(camera.position, camera.target, camera.up);
|
||||
|
||||
const screen_middle = rl.Vector2{ .x = screen_width/2, .y = screen_height/2 };
|
||||
const box_top_middle = screen_middle.add(.{ .y = -model_screen_height/2 });
|
||||
|
||||
const middle_dir = getScreenDirectionFromCamera(&mat_proj, &mat_view, screen_middle);
|
||||
const top_middle_dir = getScreenDirectionFromCamera(&mat_proj, &mat_view, box_top_middle);
|
||||
const angle = top_middle_dir.angleBetween(middle_dir);
|
||||
const distance = 1/@tan(angle) * (box_size.y/2) + box_size.z/4;
|
||||
return distance;
|
||||
}
|
||||
|
||||
pub fn init(allocator: Allocator) !Self {
|
||||
const shader_code = try ShaderCode.init(allocator, max_lights);
|
||||
defer shader_code.deinit();
|
||||
const shader = rl.LoadShaderFromMemory(shader_code.vertex, shader_code.fragment);
|
||||
errdefer rl.UnloadShader(shader);
|
||||
|
||||
if (shader.id == rl.rlGetShaderIdDefault()) {
|
||||
return error.CompileShader;
|
||||
}
|
||||
|
||||
shader.locs.?[@intFromEnum(rl.ShaderLocationIndex.SHADER_LOC_VECTOR_VIEW)] = rl.GetShaderLocation(shader, "viewPos");
|
||||
|
||||
const ambientLoc = rl.GetShaderLocation(shader, "ambient");
|
||||
rl.SetShaderValue(shader, ambientLoc, &[4]f32{ 0.6, 0.6, 1, 1.0 }, .SHADER_UNIFORM_VEC4);
|
||||
|
||||
var lights: [max_lights]Light = undefined;
|
||||
for (0..max_lights) |i| {
|
||||
lights[i] = Light.init(shader, i);
|
||||
}
|
||||
|
||||
lights[0].set_directional(rl.WHITE, rl.Vector3.new(0.2, 0, -0.2), 1, rl.Vector3.zero());
|
||||
lights[1].set_directional(rl.WHITE, rl.Vector3.new(0.2, 0, 0.2), 1, rl.Vector3.zero());
|
||||
|
||||
var chip = try allocator.create(ChipContext);
|
||||
chip.* = try ChipContext.init(allocator);
|
||||
|
||||
@ -148,231 +63,208 @@ pub fn init(allocator: Allocator) !Self {
|
||||
var raylib_chip = try allocator.create(RaylibChip);
|
||||
raylib_chip.* = RaylibChip.init(chip, chip_sound);
|
||||
|
||||
const screen_texture = rl.LoadRenderTexture(raylib_chip.chip.display_width, raylib_chip.chip.display_height);
|
||||
errdefer rl.UnloadRenderTexture(screen_texture);
|
||||
|
||||
const powered = try allocator.create(bool);
|
||||
errdefer allocator.destroy(powered);
|
||||
|
||||
var emulator = try EmulatorModel.init(allocator, powered, &chip.input, screen_texture);
|
||||
errdefer emulator.deinit();
|
||||
emulator.setShader(shader);
|
||||
|
||||
return Self {
|
||||
var self = Self {
|
||||
.allocator = allocator,
|
||||
.emulator = emulator,
|
||||
.shader = shader,
|
||||
.lights = lights,
|
||||
|
||||
.chip = chip,
|
||||
.raylib_chip = raylib_chip,
|
||||
.chip_sound = chip_sound,
|
||||
.screen_texture = screen_texture,
|
||||
.powered = powered,
|
||||
.camera = rl.Camera3D{
|
||||
.position = rl.Vector3.new(0, 0, -10),
|
||||
.target = rl.Vector3.new(0.0, 0.0, 0.0),
|
||||
.up = rl.Vector3.new(0.0, 1.0, 0.0),
|
||||
.fovy = 45.0,
|
||||
.projection = rl.CameraProjection.CAMERA_PERSPECTIVE,
|
||||
},
|
||||
};
|
||||
|
||||
self.set_rom(3);
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
pub fn deinit(self: *Self) void {
|
||||
self.emulator.deinit();
|
||||
rl.UnloadShader(self.shader);
|
||||
rl.UnloadSound(self.chip_sound);
|
||||
rl.UnloadRenderTexture(self.screen_texture);
|
||||
|
||||
self.chip.deinit();
|
||||
self.allocator.destroy(self.powered);
|
||||
self.allocator.destroy(self.raylib_chip);
|
||||
self.allocator.destroy(self.chip);
|
||||
}
|
||||
|
||||
pub fn set_rom(self: *Self, rom: ROM) void {
|
||||
self.rom = rom;
|
||||
pub fn set_rom(self: *Self, index: i32) void {
|
||||
self.selected_rom_index = index;
|
||||
self.reset_rom();
|
||||
}
|
||||
|
||||
pub fn reset_rom(self: *Self) void {
|
||||
const rom = rom_list[@intCast(self.selected_rom_index)];
|
||||
self.chip.reset();
|
||||
self.chip.set_memory(0x200, rom.data);
|
||||
}
|
||||
|
||||
pub fn turn_on(self: *Self) void {
|
||||
self.powered.* = true;
|
||||
}
|
||||
|
||||
pub fn turn_off(self: *Self) void {
|
||||
self.powered.* = false;
|
||||
self.chip.reset();
|
||||
if (self.rom) |rom| {
|
||||
self.chip.set_memory(0x200, rom.data);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn toggle_power(self: *Self) void {
|
||||
if (self.powered.*) {
|
||||
self.turn_off();
|
||||
} else {
|
||||
self.turn_on();
|
||||
}
|
||||
}
|
||||
|
||||
fn updateCamera(self: *Self, dt: f32) void {
|
||||
const mouse_delta = rl.GetMouseDelta();
|
||||
const camera = &self.camera;
|
||||
const emulator = &self.emulator;
|
||||
|
||||
if (rl.IsWindowResized()) {
|
||||
const distance = getPrefferedDistanceToBox(camera, emulator.bbox);
|
||||
const direction = camera.position.sub(emulator.position).normalize();
|
||||
camera.position = emulator.position.add(direction.scale(distance));
|
||||
}
|
||||
|
||||
if (rl.Vector3Equals(camera.position, rl.Vector3Zero()) == 1) {
|
||||
const distance = getPrefferedDistanceToBox(camera, self.emulator.bbox);
|
||||
camera.target = emulator.position;
|
||||
camera.position = emulator.position.sub(rl.Vector3.new(0, 0, 1).scale(distance));
|
||||
}
|
||||
|
||||
var camera_turn_acc = rl.Vector3Zero();
|
||||
if (rl.IsMouseButtonDown(rl.MouseButton.MOUSE_BUTTON_LEFT)) {
|
||||
if (@fabs(mouse_delta.x) > 5) {
|
||||
const rotation_speed = 2; // Radians/second
|
||||
camera_turn_acc.x = -rotation_speed*mouse_delta.x;
|
||||
}
|
||||
if (@fabs(mouse_delta.x) < 5) {
|
||||
self.camera_turn_vel = self.camera_turn_vel.scale(0.90); // Holding drag
|
||||
}
|
||||
}
|
||||
|
||||
if (rl.IsMouseButtonPressed(rl.MouseButton.MOUSE_BUTTON_LEFT)) {
|
||||
self.camera_target_orientation = null;
|
||||
|
||||
const now = rl.GetTime();
|
||||
const duration_between_clicks = now - self.previous_click_time;
|
||||
if (duration_between_clicks < 0.3) {
|
||||
const ray = rl.GetMouseRay(rl.GetMousePosition(), camera.*);
|
||||
const collision = rl.GetRayCollisionBox(ray, self.emulator.bbox);
|
||||
if (collision.hit) {
|
||||
const front_face_normal = rl.Vector3.new(0, 0, -1);
|
||||
const back_face_normal = rl.Vector3.new(0, 0, 1);
|
||||
if (rl.Vector3Equals(collision.normal, front_face_normal) == 1) {
|
||||
self.camera_target_orientation = front_face_normal;
|
||||
} else if (rl.Vector3Equals(collision.normal, back_face_normal) == 1) {
|
||||
self.camera_target_orientation = back_face_normal;
|
||||
}
|
||||
}
|
||||
}
|
||||
self.previous_click_time = now;
|
||||
}
|
||||
|
||||
if (self.camera_target_orientation) |target| {
|
||||
const current_direction = camera.position.sub(emulator.position).normalize();
|
||||
const current_angle = std.math.atan2(f32, current_direction.z, current_direction.x);
|
||||
const target_angle = std.math.atan2(f32, target.z, target.x);
|
||||
const diff_angle = std.math.pi - @mod((target_angle - current_angle) + 3*std.math.pi, 2*std.math.pi);
|
||||
if (@fabs(diff_angle) < 0.001) {
|
||||
self.camera_turn_vel.x = 0;
|
||||
self.camera_target_orientation = null;
|
||||
} else {
|
||||
self.camera_turn_vel.x = diff_angle*3;
|
||||
}
|
||||
}
|
||||
|
||||
self.camera_turn_vel = self.camera_turn_vel.scale(0.95); // Ambient drag
|
||||
self.camera_turn_vel = self.camera_turn_vel.add(camera_turn_acc.scale(dt));
|
||||
|
||||
const camera_min_vel = 0;
|
||||
if (self.camera_turn_vel.length() > camera_min_vel) {
|
||||
const rotation = rl.MatrixRotate(camera.up.normalize(), self.camera_turn_vel.x*dt);
|
||||
var view = rl.Vector3Subtract(camera.position, camera.target);
|
||||
view = rl.Vector3Transform(view, rotation);
|
||||
camera.position = rl.Vector3Add(camera.target, view);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn update(self: *Self, dt: f32) void {
|
||||
self.updateCamera(dt);
|
||||
|
||||
const camera = &self.camera;
|
||||
const cameraPos = [3]f32{ camera.position.x, camera.position.y, camera.position.z };
|
||||
rl.SetShaderValue(self.shader, self.shader.locs.?[@intFromEnum(rl.ShaderLocationIndex.SHADER_LOC_VECTOR_VIEW)], &cameraPos, .SHADER_UNIFORM_VEC3);
|
||||
|
||||
const ray = rl.GetMouseRay(rl.GetMousePosition(), self.camera);
|
||||
if (self.emulator.isOverPowerSwitch(ray)) {
|
||||
if (rl.IsMouseButtonPressed(rl.MouseButton.MOUSE_BUTTON_LEFT)) {
|
||||
self.toggle_power();
|
||||
}
|
||||
}
|
||||
|
||||
self.raylib_chip.update_input();
|
||||
if (self.powered.*) {
|
||||
if (!self.is_gui_open) {
|
||||
rl.ResumeSound(self.chip_sound);
|
||||
self.raylib_chip.update(dt);
|
||||
} else {
|
||||
rl.PauseSound(self.chip_sound);
|
||||
}
|
||||
|
||||
rl.BeginTextureMode(self.screen_texture);
|
||||
{
|
||||
self.raylib_chip.render();
|
||||
}
|
||||
rl.EndTextureMode();
|
||||
|
||||
// {
|
||||
// var matProj = rl.MatrixIdentity();
|
||||
// // projection = CAMERA_PERSPECTIVE
|
||||
// matProj = rl.MatrixPerspective(camera.fovy*rl.DEG2RAD, (screen_width/screen_height), rl.RL_CULL_DISTANCE_NEAR, rl.RL_CULL_DISTANCE_FAR);
|
||||
//
|
||||
// var matView = rl.MatrixLookAt(camera.position, camera.target, camera.up);
|
||||
// // Convert world position vector to quaternion
|
||||
// var worldPos = rl.Vector4{ .x = position.x, .y = position.y, .z = position.z, .w = 1.0 };
|
||||
//
|
||||
// std.debug.print("worldPos {}\n", .{worldPos});
|
||||
// // Transform world position to view
|
||||
// worldPos = rl.QuaternionTransform(worldPos, matView);
|
||||
//
|
||||
// // Transform result to projection (clip space position)
|
||||
// worldPos = rl.QuaternionTransform(worldPos, matProj);
|
||||
//
|
||||
// // Calculate normalized device coordinates (inverted y)
|
||||
// var ndcPos = rl.Vector3.new( worldPos.x/worldPos.w, -worldPos.y/worldPos.w, worldPos.z/worldPos.w );
|
||||
//
|
||||
// // Calculate 2d screen position vector
|
||||
// screen_position = rl.Vector2{ .x = (ndcPos.x + 1.0)/2.0*screen_width, .y = (ndcPos.y + 1.0)/2.0*screen_height };
|
||||
// }
|
||||
|
||||
// const target_screen_position = rl.Vector2{ .x = screen_width/2, .y = screen_height*0.1 };
|
||||
// {
|
||||
// var matProj = get_camera_projection(&camera);
|
||||
// var matView = rl.MatrixLookAt(camera.position, camera.target, camera.up);
|
||||
//
|
||||
// const ndc_x = (2.0*target_screen_position.x) / screen_width - 1.0;
|
||||
// const ndc_y = 1.0 - (2.0*target_screen_position.y) / screen_height;
|
||||
//
|
||||
// var near_point = rl.Vector3Unproject(.{ .x = ndc_x, .y = ndc_y, .z = 0.0 }, matProj, matView);
|
||||
// var far_point = rl.Vector3Unproject(.{ .x = ndc_x, .y = ndc_y, .z = 1.0 }, matProj, matView);
|
||||
//
|
||||
// var direction = rl.Vector3Subtract(far_point, near_point).normalize();
|
||||
//
|
||||
// var origin: rl.Vector3 = undefined;
|
||||
// if (camera.projection == .CAMERA_PERSPECTIVE) {
|
||||
// origin = camera.position;
|
||||
// } else {
|
||||
// origin = rl.Vector3Unproject(.{ .x = ndc_x, .y = ndc_y, .z = -1.0 }, matProj, matView);
|
||||
// }
|
||||
//
|
||||
// var world_pos = origin.add(direction.scale(3));
|
||||
//
|
||||
// model_position = world_pos;
|
||||
// }
|
||||
}
|
||||
|
||||
pub fn draw(self: *Self) void {
|
||||
rl.ClearBackground(rl.Color{ .r = 33, .g = 33, .b = 33 });
|
||||
|
||||
rl.BeginShaderMode(self.shader);
|
||||
{
|
||||
rl.BeginMode3D(self.camera);
|
||||
self.emulator.draw();
|
||||
rl.EndMode3D();
|
||||
}
|
||||
rl.EndShaderMode();
|
||||
const display_width = self.chip.display_width;
|
||||
const display_height = self.chip.display_height;
|
||||
const screen_width = rl.GetScreenWidth();
|
||||
const screen_height = rl.GetScreenHeight();
|
||||
|
||||
const x_scale = @as(f32, @floatFromInt(screen_width)) / @as(f32, @floatFromInt(display_width));
|
||||
const y_scale = @as(f32, @floatFromInt(screen_height)) / @as(f32, @floatFromInt(display_height));
|
||||
const max_scale = @min(x_scale, y_scale);
|
||||
|
||||
const render_width: i32 = @intFromFloat(@as(f32, @floatFromInt(display_width)) * max_scale);
|
||||
const render_height: i32 = @intFromFloat(@as(f32, @floatFromInt(display_height)) * max_scale);
|
||||
|
||||
self.raylib_chip.render(
|
||||
@divTrunc(screen_width - render_width, 2),
|
||||
@divTrunc(screen_height - render_height, 2),
|
||||
render_width,
|
||||
render_height
|
||||
);
|
||||
|
||||
self.drawGui(self.allocator) catch @panic("GUI OOM");
|
||||
}
|
||||
|
||||
fn GuiListView(
|
||||
allocator: Allocator,
|
||||
bounds: rl.Rectangle,
|
||||
items: []const []const u8,
|
||||
scroll_index: *i32,
|
||||
active: *i32,
|
||||
) !i32 {
|
||||
var allocated_count: usize = 0;
|
||||
var items_z = try allocator.alloc([:0]const u8, items.len);
|
||||
var items_zn = try allocator.alloc([*:0]const u8, items.len);
|
||||
defer {
|
||||
for (0..allocated_count) |i| {
|
||||
allocator.free(items_z[i]);
|
||||
}
|
||||
allocator.free(items_z);
|
||||
allocator.free(items_zn);
|
||||
}
|
||||
|
||||
for (0.., items) |i, item| {
|
||||
items_z[i] = try allocator.dupeZ(u8, item);
|
||||
items_zn[i] = items_z[i].ptr;
|
||||
allocated_count += 1;
|
||||
}
|
||||
|
||||
return gui.GuiListViewEx(bounds, items_zn.ptr, @intCast(items_z.len), scroll_index, active, null);
|
||||
}
|
||||
|
||||
fn GuiListViewMinWidth(allocator: Allocator, height: i32, items: []const []const u8) !i32 {
|
||||
const border_width = gui.GuiGetStyle(.DEFAULT , @intFromEnum(gui.GuiControlProperty.BORDER_WIDTH));
|
||||
const item_spacing = gui.GuiGetStyle(.LISTVIEW, @intFromEnum(gui.GuiListViewProperty.LIST_ITEMS_SPACING));
|
||||
const item_height = gui.GuiGetStyle(.LISTVIEW, @intFromEnum(gui.GuiListViewProperty.LIST_ITEMS_HEIGHT));
|
||||
const font_size = gui.GuiGetStyle(.DEFAULT , @intFromEnum(gui.GuiDefaultProperty.TEXT_SIZE));
|
||||
const scrollbar_width = gui.GuiGetStyle(.LISTVIEW, @intFromEnum(gui.GuiListViewProperty.SCROLLBAR_WIDTH));
|
||||
|
||||
var max_item_width: i32 = 0;
|
||||
for (items) |item| {
|
||||
const item_z = try allocator.dupeZ(u8, item);
|
||||
defer allocator.free(item_z);
|
||||
const item_width = rl.MeasureText(item_z, font_size);
|
||||
|
||||
max_item_width = @max(max_item_width, item_width);
|
||||
}
|
||||
|
||||
const item_count: i32 = @intCast(items.len);
|
||||
const need_scrollbar = ((item_height + item_spacing)*item_count > height);
|
||||
|
||||
var min_width = max_item_width + 2*item_spacing + border_width;
|
||||
if (need_scrollbar) {
|
||||
min_width += scrollbar_width;
|
||||
}
|
||||
|
||||
return min_width;
|
||||
}
|
||||
|
||||
pub fn getWindowBodyBounds(bounds: rl.Rectangle) rl.Rectangle {
|
||||
const status_bar_height = 24; // defined as RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT in raygui.h
|
||||
const margin = 8;
|
||||
|
||||
return rl.Rectangle {
|
||||
.x = bounds.x + margin,
|
||||
.y = bounds.y + margin + status_bar_height,
|
||||
.width = bounds.width - 2*margin,
|
||||
.height = bounds.height - 2*margin - status_bar_height,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn pushGuiWindowBox(layout: *GUILayout, bounds: rl.Rectangle, title: [*:0]const u8) bool {
|
||||
const body = getWindowBodyBounds(bounds);
|
||||
layout.push();
|
||||
layout.translate(body.x, body.y);
|
||||
|
||||
return gui.GuiWindowBox(bounds, title) != 0;
|
||||
}
|
||||
|
||||
pub fn drawGui(self: *Self, allocator: Allocator) !void {
|
||||
if (rl.IsKeyPressed(.KEY_TAB)) {
|
||||
self.is_gui_open = !self.is_gui_open;
|
||||
}
|
||||
|
||||
if (!self.is_gui_open) return;
|
||||
|
||||
var window_layout = GUILayout.init();
|
||||
defer window_layout.deinit();
|
||||
|
||||
// Draw overlay, to indicate that emulator is paused
|
||||
rl.DrawRectangle(0, 0, rl.GetScreenWidth(), rl.GetScreenHeight(), .{
|
||||
.r = 22,
|
||||
.g = 22,
|
||||
.b = 22,
|
||||
.a = 128,
|
||||
});
|
||||
|
||||
const window_width: f32 = 400;
|
||||
const window_height: f32 = 200;
|
||||
const screen_width: f32 = @floatFromInt(rl.GetScreenWidth());
|
||||
const screen_height: f32 = @floatFromInt(rl.GetScreenHeight());
|
||||
const window = rl.Rectangle{
|
||||
.x = @trunc((screen_width-window_width)/2),
|
||||
.y = @trunc((screen_height-window_height)/2),
|
||||
.width = window_width,
|
||||
.height = window_height
|
||||
};
|
||||
if (pushGuiWindowBox(&window_layout, window, "CHIP-8 Settings")) {
|
||||
self.is_gui_open = false;
|
||||
}
|
||||
|
||||
var vertical_layout = VerticalLayout.init(4, getWindowBodyBounds(window));
|
||||
|
||||
if (gui.GuiButton(vertical_layout.row_sized(100, 24), "Reset") == 1) {
|
||||
self.reset_rom();
|
||||
}
|
||||
|
||||
_ = gui.GuiLabel(vertical_layout.row(16), "Current ROM:");
|
||||
{ // ROM list view
|
||||
const rom_list_names = try allocator.alloc([]const u8, rom_list.len);
|
||||
defer allocator.free(rom_list_names);
|
||||
|
||||
for (0.., rom_list) |i, rom| {
|
||||
rom_list_names[i] = rom.name;
|
||||
}
|
||||
|
||||
const list_height = 100;
|
||||
const list_width = try GuiListViewMinWidth(allocator, list_height, rom_list_names) + 20;
|
||||
var selected_rom = self.selected_rom_index;
|
||||
_ = try GuiListView(
|
||||
allocator,
|
||||
vertical_layout.row_sized(@floatFromInt(list_width), list_height),
|
||||
rom_list_names,
|
||||
&self.rom_list_scroll_index,
|
||||
&selected_rom
|
||||
);
|
||||
|
||||
if (selected_rom != self.selected_rom_index) {
|
||||
self.set_rom(selected_rom);
|
||||
}
|
||||
}
|
||||
|
||||
window_layout.pop();
|
||||
}
|
||||
|
@ -31,14 +31,6 @@ pub fn main() anyerror!void {
|
||||
var scene = try MainScene.init(allocator);
|
||||
defer scene.deinit();
|
||||
|
||||
const roms = comptime listROMs();
|
||||
scene.set_rom(roms[3]);
|
||||
|
||||
const font_size = 24;
|
||||
const font_ttf_default_numchars = 95; // TTF font generation default charset: 95 glyphs (ASCII 32..126)
|
||||
const font = rl.LoadFontEx("src/assets/fonts/generic-mono.otf", font_size, null, font_ttf_default_numchars);
|
||||
defer rl.UnloadFont(font);
|
||||
|
||||
while (!rl.WindowShouldClose()) {
|
||||
var dt = rl.GetFrameTime();
|
||||
scene.update(dt);
|
||||
|
@ -64,6 +64,10 @@ pub fn update(self: *Self, dt: f32) void {
|
||||
self.tick_time -= 1/self.tick_speed;
|
||||
}
|
||||
|
||||
self.update_timers(dt);
|
||||
}
|
||||
|
||||
pub fn update_timers(self: *Self, dt: f32) void {
|
||||
self.timer_time += dt;
|
||||
while (self.timer_time > 1/self.timer_speed) {
|
||||
self.chip.update_timer();
|
||||
@ -83,14 +87,25 @@ pub fn update(self: *Self, dt: f32) void {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn render(self: *const Self) void {
|
||||
rl.DrawRectangle(0, 0, self.chip.display_width, self.chip.display_height, self.off_color);
|
||||
pub fn render(self: *const Self, x: i32, y: i32, width: i32, height: i32) void {
|
||||
const display_width = self.chip.display_width;
|
||||
const display_height = self.chip.display_height;
|
||||
const x_scale = @as(f32,@floatFromInt(width)) / @as(f32, @floatFromInt(display_width));
|
||||
const y_scale = @as(f32,@floatFromInt(height)) / @as(f32, @floatFromInt(display_height));
|
||||
|
||||
for (0..self.chip.display_height) |y| {
|
||||
for (0..self.chip.display_width) |x| {
|
||||
if (self.chip.display_get(@intCast(x), @intCast(y))) {
|
||||
rl.DrawRectangle(@intCast(x), @intCast(y), 1, 1, self.on_color);
|
||||
rl.rlPushMatrix();
|
||||
rl.rlTranslatef(@floatFromInt(x), @floatFromInt(y), 0);
|
||||
rl.rlScalef(x_scale, y_scale, 1);
|
||||
|
||||
rl.DrawRectangle(0, 0, display_width, display_height, self.off_color);
|
||||
|
||||
for (0..display_height) |iy| {
|
||||
for (0..display_width) |ix| {
|
||||
if (self.chip.display_get(@intCast(ix), @intCast(iy))) {
|
||||
rl.DrawRectangle(@intCast(ix), @intCast(iy), 1, 1, self.on_color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
rl.rlPopMatrix();
|
||||
}
|
||||
|
@ -1,3 +1,4 @@
|
||||
const std = @import("std");
|
||||
const options = @import("options");
|
||||
const rom_count = options.roms.len;
|
||||
|
||||
@ -10,8 +11,12 @@ pub fn listROMs() [options.roms.len]ROM {
|
||||
var roms: [options.roms.len]ROM = undefined;
|
||||
|
||||
for (0.., options.roms) |i, file| {
|
||||
const extension = std.mem.lastIndexOfScalar(u8, file, '.') orelse file.len;
|
||||
const slash = std.mem.lastIndexOfScalar(u8, file, '/') orelse -1;
|
||||
|
||||
const name = file[(slash+1)..extension];
|
||||
roms[i] = ROM{
|
||||
.name = file,
|
||||
.name = name,
|
||||
.data = @embedFile(file)
|
||||
};
|
||||
}
|
||||
|
@ -1,36 +0,0 @@
|
||||
const Self = @This();
|
||||
const std = @import("std");
|
||||
const Allocator = std.mem.Allocator;
|
||||
|
||||
allocator: Allocator,
|
||||
vertex: [:0]u8,
|
||||
fragment: [:0]u8,
|
||||
|
||||
pub fn init(allocator: Allocator, max_lights_count: u32) !Self {
|
||||
const base_vertex_code = @embedFile("shaders/main_vs.glsl");
|
||||
const base_fragment_code = @embedFile("shaders/main_fs.glsl");
|
||||
|
||||
const vertex = try allocator.dupeZ(u8, base_vertex_code);
|
||||
errdefer allocator.free(vertex);
|
||||
|
||||
const newline = std.mem.indexOfScalar(u8, base_fragment_code, '\n') orelse unreachable;
|
||||
const first_line = base_fragment_code[0..newline];
|
||||
const after_first_line = base_fragment_code[(newline+1)..];
|
||||
const fragment = try std.fmt.allocPrintZ(allocator,
|
||||
\\{s}
|
||||
\\#define MAX_LIGHTS {}
|
||||
\\{s}
|
||||
, .{ first_line, max_lights_count, after_first_line });
|
||||
errdefer allocator.free(fragment);
|
||||
|
||||
return Self {
|
||||
.allocator = allocator,
|
||||
.vertex = vertex,
|
||||
.fragment = fragment
|
||||
};
|
||||
}
|
||||
|
||||
pub fn deinit(self: Self) void {
|
||||
self.allocator.free(self.vertex);
|
||||
self.allocator.free(self.fragment);
|
||||
}
|
@ -1,78 +0,0 @@
|
||||
#version 330
|
||||
|
||||
// Input vertex attributes (from vertex shader)
|
||||
in vec3 fragPosition;
|
||||
in vec2 fragTexCoord;
|
||||
in vec4 fragColor;
|
||||
in vec3 fragNormal;
|
||||
|
||||
// Input uniform values
|
||||
uniform sampler2D texture0;
|
||||
uniform vec4 colDiffuse;
|
||||
|
||||
// Output fragment color
|
||||
layout (location = 0) out vec4 finalColor;
|
||||
layout (location = 1) out vec4 bloomColor;
|
||||
|
||||
struct MaterialProperty {
|
||||
vec3 color;
|
||||
int useSampler;
|
||||
sampler2D sampler;
|
||||
};
|
||||
|
||||
#define LIGHT_DIRECTIONAL 0
|
||||
#define LIGHT_POINT 1
|
||||
|
||||
struct Light {
|
||||
int type;
|
||||
bool enabled;
|
||||
float intensity;
|
||||
vec3 position;
|
||||
vec4 color;
|
||||
|
||||
// Directional light arguments:
|
||||
vec3 target;
|
||||
};
|
||||
|
||||
// Input lighting values
|
||||
uniform Light lights[MAX_LIGHTS];
|
||||
uniform vec4 ambient;
|
||||
uniform vec3 viewPos;
|
||||
|
||||
void main() {
|
||||
// Texel color fetching from texture sampler
|
||||
vec4 texelColor = texture(texture0, fragTexCoord);
|
||||
|
||||
finalColor = fragColor * texelColor;
|
||||
|
||||
{ // Apply lights
|
||||
vec3 lightDot = vec3(0.0);
|
||||
vec3 normal = normalize(fragNormal);
|
||||
vec3 viewD = normalize(viewPos - fragPosition);
|
||||
vec3 specular = vec3(0.0);
|
||||
|
||||
for (int i = 0; i < MAX_LIGHTS; i++) {
|
||||
if (!lights[i].enabled) continue;
|
||||
|
||||
vec3 light = vec3(0.0);
|
||||
if (lights[i].type == LIGHT_DIRECTIONAL) {
|
||||
light = -normalize(lights[i].target - lights[i].position);
|
||||
} else if (lights[i].type == LIGHT_POINT) {
|
||||
light = normalize(lights[i].position - fragPosition);
|
||||
}
|
||||
|
||||
float NdotL = max(dot(normal, light), 0.0);
|
||||
lightDot += lights[i].color.rgb * NdotL * lights[i].intensity;
|
||||
|
||||
float specCo = 0.0;
|
||||
if (NdotL > 0.0) specCo = pow(max(0.0, dot(viewD, reflect(-(light), normal))), 16.0); // 16 refers to shine
|
||||
specular += specCo;
|
||||
}
|
||||
|
||||
finalColor *= ((colDiffuse + vec4(specular, 1.0))*vec4(lightDot, 1.0) + (ambient/10.0)*colDiffuse);
|
||||
}
|
||||
|
||||
// Gamma correction
|
||||
finalColor = pow(finalColor, vec4(1.0/1.9));
|
||||
}
|
||||
|
@ -1,31 +0,0 @@
|
||||
#version 330
|
||||
|
||||
// Input vertex attributes
|
||||
in vec3 vertexPosition;
|
||||
in vec2 vertexTexCoord;
|
||||
in vec3 vertexNormal;
|
||||
in vec4 vertexColor;
|
||||
|
||||
// Input uniform values
|
||||
uniform mat4 mvp;
|
||||
uniform mat4 matModel;
|
||||
uniform mat4 matNormal;
|
||||
|
||||
// Output vertex attributes (to fragment shader)
|
||||
out vec3 fragPosition;
|
||||
out vec2 fragTexCoord;
|
||||
out vec4 fragColor;
|
||||
out vec3 fragNormal;
|
||||
|
||||
// NOTE: Add here your custom variables
|
||||
|
||||
void main() {
|
||||
// Send vertex attributes to fragment shader
|
||||
fragPosition = vec3(matModel*vec4(vertexPosition, 1.0));
|
||||
fragTexCoord = vertexTexCoord;
|
||||
fragColor = vertexColor;
|
||||
fragNormal = normalize(vec3(matNormal*vec4(vertexNormal, 1.0)));
|
||||
|
||||
// Calculate final vertex position
|
||||
gl_Position = mvp*vec4(vertexPosition, 1.0);
|
||||
}
|
29
src/vertical-layout.zig
Normal file
29
src/vertical-layout.zig
Normal file
@ -0,0 +1,29 @@
|
||||
const Self = @This();
|
||||
const rl = @import("raylib");
|
||||
|
||||
bounds: rl.Rectangle,
|
||||
gap: f32,
|
||||
used: f32,
|
||||
|
||||
pub fn init(gap: f32, bounds: rl.Rectangle) Self {
|
||||
return Self{
|
||||
.bounds = bounds,
|
||||
.gap = gap,
|
||||
.used = 0
|
||||
};
|
||||
}
|
||||
|
||||
pub fn row_sized(self: *Self, width: f32, height: f32) rl.Rectangle {
|
||||
const rect = rl.Rectangle{
|
||||
.x = self.bounds.x,
|
||||
.y = self.bounds.y + self.used,
|
||||
.width = width,
|
||||
.height = height,
|
||||
};
|
||||
self.used += height + self.gap;
|
||||
return rect;
|
||||
}
|
||||
|
||||
pub fn row(self: *Self, height: f32) rl.Rectangle {
|
||||
return self.row_sized(self.bounds.width, height);
|
||||
}
|
Loading…
Reference in New Issue
Block a user