1
0

clone raylib.zig into libs

This commit is contained in:
Rokas Puzonas 2024-01-10 23:45:31 +02:00
parent e3bed54ab7
commit 01f77a2e4b
25 changed files with 57634 additions and 0 deletions

3
.gitmodules vendored
View File

@ -1,3 +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

58
libs/raylib/.gitignore vendored Normal file
View File

@ -0,0 +1,58 @@
# Prerequisites
*.d
# Object files
*.o
*.ko
*.obj
*.elf
# Linker output
*.ilk
*.map
*.exp
# Precompiled Headers
*.gch
*.pch
# Libraries
*.lib
*.a
*.la
*.lo
# Shared objects (inc. Windows DLLs)
*.dll
*.so
*.so.*
*.dylib
# Executables
*.exe
*.out
*.app
*.i*86
*.x86_64
*.hex
# Debug files
*.dSYM/
*.su
*.idb
*.pdb
# Kernel Module Compile Results
*.mod*
*.cmd
.tmp_versions/
modules.order
Module.symvers
Mkfile.old
dkms.conf
zig-cache/
.vscode/settings.json
.DS_Store

21
libs/raylib/LICENSE Normal file
View 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.

116
libs/raylib/README.md Normal file
View File

@ -0,0 +1,116 @@
![logo](logo.png)
# raylib.zig
Idiomatic [raylib](https://www.raylib.com/) (5.1-dev) bindings for [Zig](https://ziglang.org/) (master).
[Example Usage](#usage)
Additional infos and WebGL examples [here](https://github.com/ryupold/examples-raylib.zig).
## supported platforms
- Windows
- macOS
- Linux
- HTML5/WebGL (emscripten)
## supported APIs
- [x] RLAPI (raylib.h)
- [x] RLAPI (rlgl.h)
- [x] RMAPI (raymath.h)
- [x] Constants
- [x] int, float, string
- [x] Colors
- [x] Versions
For [raygui](https://github.com/raysan5/raygui) bindings see: https://github.com/ryupold/raygui.zig
## <a id="usage">usage</a>
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/raylib.zig raylib
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");
pub fn build(b: *std.Build) !void {
const target = b.standardTargetOptions(.{});
const mode = b.standardOptimizeOption(.{});
const exe = ...;
raylib.addTo(b, exe, target, mode, .{});
}
```
and import in main.zig:
```zig
const raylib = @import("raylib");
pub fn main() void {
raylib.SetConfigFlags(raylib.ConfigFlags{ .FLAG_WINDOW_RESIZABLE = true });
raylib.InitWindow(800, 800, "hello world!");
raylib.SetTargetFPS(60);
defer raylib.CloseWindow();
while (!raylib.WindowShouldClose()) {
raylib.BeginDrawing();
defer raylib.EndDrawing();
raylib.ClearBackground(raylib.BLACK);
raylib.DrawFPS(10, 10);
raylib.DrawText("hello world!", 100, 100, 20, raylib.YELLOW);
}
}
```
### WebGL (emscripten) builds
For Webassembly builds see [examples-raylib.zig/build.zig](https://github.com/ryupold/examples-raylib.zig/blob/main/build.zig)
This weird workaround with `marshal.h/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 `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 `raylib.zig` feel free to [create an issue](https://github.com/ryupold/raylib.zig/issues) and I will look into it.
## memory
Some of the functions may return pointers to memory allocated within raylib.
Usually there will be a corresponding Unload/Free function to dispose it. You cannot use a Zig allocator to free that:
```zig
const data = LoadFileData("test.png");
defer UnloadFileData(data);
// using data...
```
## generate bindings
for current raylib 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 raylib repository I commit also the generated json files.
## build raylib_parser (executable)
If you want to build the raylib_parser executable without a C compiler.
```sh
zig build raylib_parser
```
you can then find the executable in `./zig-out/bin/`

17829
libs/raylib/bindings.json Normal file

File diff suppressed because it is too large Load Diff

144
libs/raylib/build.zig Normal file
View File

@ -0,0 +1,144 @@
const std = @import("std");
const generate = @import("generate.zig");
pub fn build(b: *std.Build) !void {
const raylibSrc = "raylib/src/";
const target = b.standardTargetOptions(.{});
//--- parse raylib and generate JSONs for all signatures --------------------------------------
const jsons = b.step("parse", "parse raylib headers and generate raylib jsons");
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/parser/raylib_parser.c" }, .flags = &.{} });
raylib_parser_build.linkLibC();
//raylib
const raylib_H = b.addRunArtifact(raylib_parser_build);
raylib_H.addArgs(&.{
"-i", raylibSrc ++ "raylib.h",
"-o", "raylib.json",
"-f", "JSON",
"-d", "RLAPI",
});
jsons.dependOn(&raylib_H.step);
//raymath
const raymath_H = b.addRunArtifact(raylib_parser_build);
raymath_H.addArgs(&.{
"-i", raylibSrc ++ "raymath.h",
"-o", "raymath.json",
"-f", "JSON",
"-d", "RMAPI",
});
jsons.dependOn(&raymath_H.step);
//rlgl
const rlgl_H = b.addRunArtifact(raylib_parser_build);
rlgl_H.addArgs(&.{
"-i", raylibSrc ++ "rlgl.h",
"-o", "rlgl.json",
"-f", "JSON",
"-d", "RLAPI",
});
jsons.dependOn(&rlgl_H.step);
//--- Generate intermediate -------------------------------------------------------------------
const intermediate = b.step("intermediate", "generate intermediate representation of the results from 'zig build parse' (keep custom=true)");
var intermediateZigStep = b.addRunArtifact(b.addExecutable(.{
.name = "intermediate",
.root_source_file = std.build.FileSource.relative("intermediate.zig"),
.target = target,
}));
intermediate.dependOn(&intermediateZigStep.step);
//--- Generate bindings -----------------------------------------------------------------------
const bindings = b.step("bindings", "generate bindings in from bindings.json");
var generateZigStep = 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(&generateZigStep.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_raylib = cwd ++ sep ++ "raylib/src";
const raylib_build = @import("raylib/src/build.zig");
fn linkThisLibrary(b: *std.Build, target: std.zig.CrossTarget, optimize: std.builtin.Mode) *std.build.LibExeObjStep {
const lib = b.addStaticLibrary(.{ .name = "raylib-zig", .target = target, .optimize = optimize });
lib.addIncludePath(.{ .path = dir_raylib });
lib.addIncludePath(.{ .path = cwd });
lib.linkLibC();
lib.addCSourceFile(.{ .file = .{ .path = cwd ++ sep ++ "marshal.c" }, .flags = &.{} });
return lib;
}
/// add this package to exe
pub fn addTo(b: *std.Build, exe: *std.build.Step.Compile, target: std.zig.CrossTarget, optimize: std.builtin.Mode, raylibOptions: raylib_build.Options) void {
exe.addAnonymousModule("raylib", .{ .source_file = .{ .path = cwd ++ sep ++ "raylib.zig" } });
exe.addIncludePath(.{ .path = dir_raylib });
exe.addIncludePath(.{ .path = cwd });
const lib = linkThisLibrary(b, target, optimize);
const lib_raylib = raylib_build.addRaylib(b, target, optimize, raylibOptions);
exe.linkLibrary(lib_raylib);
exe.linkLibrary(lib);
}
pub fn linkSystemDependencies(exe: *std.build.Step.Compile) void {
switch (exe.target.getOsTag()) {
.macos => {
exe.linkFramework("Foundation");
exe.linkFramework("Cocoa");
exe.linkFramework("OpenGL");
exe.linkFramework("CoreAudio");
exe.linkFramework("CoreVideo");
exe.linkFramework("IOKit");
},
.linux => {
exe.addLibraryPath(.{ .path = "/usr/lib" });
exe.addIncludePath(.{ .path = "/usr/include" });
exe.linkSystemLibrary("GL");
exe.linkSystemLibrary("rt");
exe.linkSystemLibrary("dl");
exe.linkSystemLibrary("m");
exe.linkSystemLibrary("X11");
},
.freebsd, .openbsd, .netbsd, .dragonfly => {
exe.linkSystemLibrary("GL");
exe.linkSystemLibrary("rt");
exe.linkSystemLibrary("dl");
exe.linkSystemLibrary("m");
exe.linkSystemLibrary("X11");
exe.linkSystemLibrary("Xrandr");
exe.linkSystemLibrary("Xinerama");
exe.linkSystemLibrary("Xi");
exe.linkSystemLibrary("Xxf86vm");
exe.linkSystemLibrary("Xcursor");
},
else => {},
}
exe.linkLibC();
}

View File

@ -0,0 +1,24 @@
#include <stdint.h>
#include <stdlib.h>
#include "emscripten/emscripten.h"
#include "raylib.h"
// Zig compiles C code with -fstack-protector-strong which requires the following two symbols
// which don't seem to be provided by the emscripten toolchain(?)
void *__stack_chk_guard = (void *)0xdeadbeef;
void __stack_chk_fail(void)
{
exit(1);
}
// emsc_main() is the Zig entry function in main.zig
extern int emsc_main(void);
extern void emsc_set_window_size(int width, int height);
int main()
{
return emsc_main();
}

View File

@ -0,0 +1,96 @@
<!DOCTYPE html>
<html lang="en-us">
<head>
<meta charset="utf-8" />
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<!--no caching for now, the game is still pretty small-->
<meta http-equiv="cache-control" content="no-cache" />
<meta http-equiv="expires" content="0" />
<title>demo</title>
<!-- Favicon -->
<link rel="shortcut icon" href="/assets/_favicon.ico" />
<style>
body {
background-color: rgb(42, 42, 42);
margin: 0px;
padding: 8px;
display: flex;
align-items: center;
/* Internet Explorer 10+ */
-ms-overflow-style: none;
/*Firefox*/
scrollbar-width: none;
}
body::-webkit-scrollbar {
/*Chrome and Safari*/
display: none;
}
canvas.emscripten {
border: 0px none;
background-color: transparent;
}
</style>
<script>
function setResizeInterval(delay, repetitions) {
let x = 0;
let intervalID = window.setInterval(function () {
Module.resizeWindow(document.documentElement.clientWidth - 16, document.documentElement.clientHeight - 16);
if (++x === repetitions) {
window.clearInterval(intervalID);
}
}, delay);
}
</script>
</head>
<body onload="setResizeInterval(300, 5)"
onresize="if(Module.resizeWindow) Module.resizeWindow(document.documentElement.clientWidth-16,document.documentElement.clientHeight-16)">
<canvas class="emscripten" id="canvas" oncontextmenu="event.preventDefault()"
tabindex="-1"></canvas>
<!-- <p id="output" /> -->
<script>
var Module = {
print: (function () {
var element = document.getElementById("output");
if (element) element.value = ""; // clear browser cache
return function (text) {
if (arguments.length > 1)
text = Array.prototype.slice.call(arguments).join(" ");
console.log(text);
if (element) {
element.value += text + "\n";
element.scrollTop = element.scrollHeight; // focus on bottom
}
};
})(),
canvas: (function () {
var canvas = document.getElementById("canvas");
return canvas;
})(),
};
Module.onRuntimeInitialized = function () {
Module.resizeWindow = function (w, h) {
Module.ccall(
"emsc_set_window_size",
null,
["number", "number"],
[w, h]
);
};
Module.resizeWindow(document.documentElement.clientWidth - 16, document.documentElement.clientHeight - 16);
};
</script>
{{{ SCRIPT }}}
</body>
</html>

View File

@ -0,0 +1,328 @@
<!doctype html>
<html lang="en-us">
<head>
<meta charset="utf-8">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>raylib web game</title>
<meta name="title" content="raylib web game">
<meta name="description" content="New raylib web videogame, developed using raylib videogames library">
<meta name="keywords" content="raylib, games, html5, programming, C, C++, library, learn, videogames">
<meta name="viewport" content="width=device-width">
<!-- Open Graph metatags for sharing -->
<meta property="og:title" content="raylib web game">
<meta property="og:image:type" content="image/png">
<meta property="og:image" content="https://www.raylib.com/common/img/raylib_logo.png">
<meta property="og:site_name" content="raylib.com">
<meta property="og:url" content="https://www.raylib.com/games.html">
<meta property="og:description" content="New raylib web videogame, developed using raylib videogames library">
<!-- Twitter metatags for sharing -->
<meta name="twitter:card" content="summary">
<meta name="twitter:site" content="@raysan5">
<meta name="twitter:title" content="raylib web game">
<meta name="twitter:image" content="https://www.raylib.com/common/raylib_logo.png">
<meta name="twitter:url" content="https://www.raylib.com/games.html">
<meta name="twitter:description" content="New raylib web game, developed using raylib videogames library">
<!-- Favicon -->
<link rel="shortcut icon" href="https://www.raylib.com/favicon.ico">
<style>
body {
font-family: arial;
margin: 0;
padding: none;
}
#header {
width: 100%;
height: 80px;
background-color: #888888;
}
/* NOTE: raylib logo is embedded in the page as base64 png image */
#logo {
width:64px;
height:64px;
float:left;
position:relative;
margin:10px;
background-image:url('data:image/png;base64,\
iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAIAAAAlC+aJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADs\
MAAA7DAcdvqGQAAAAadEVYdFNvZnR3YXJlAFBhaW50Lk5FVCB2My41LjExR/NCNwAAA7JJREFUaEPtk0FyWzEMQ+37X7fZhxX4\
YY3AD1OKF1nkzTRlSBCCLeVBnvl/AUdaELOunPno1kts1kixdtEZKVs+xIxebBkZsVknn/L5nFGDLR8T4zVC9fX19S/+tTFijr\
YK4jUjbPUtqBHpnEE6PkZD7jQZV8n5Recw1XQKciZuPaEtR6UjNs5ENVGMsBVqpPtER0ZMOhpyp8m4YL4OjD9yxsyZxnQycfMJ\
ETNSzsRE1+dihK3YMiJmpHTW3xpmXPC6BXlCHfqnBlsjY5hxf/6EVEOM2BTEi0fYCX4ONSI6Kq3Blg/prIOMq2CsRur4KQ0x64\
SdjOufEDEdHZGOhmz5RDHCVqhRuQ86YsVskbc+GXchLiHnFyYH+UigQDVGnImbT8hwFkgLg2qiM8JO6Ylx1FNLa3DmYwqCTsZd\
4BPqGJG7MwKzpeiWKTKxXkLMVE3MSOmsdwxLH6Rd/wCCLSNDx6djeKfJuArGeoYamRHpaEjnCBYZVy8hZqo2GI36qPjsiOiMsB\
XGcev4Mx9TLGTchbgEjN/uz6jGrBvDjg+LTNx8Qp2CbG2xMKgmOiPslJ4Yxx+eSnSkzlosZNwFPiHl7FRTkLNRJm4+IeVM0ymI\
H42wE/wcKalQI4MRl4EW3p6VcRWMua8F6WjIlqZDxvVPiHQ6CjVbYkV9ohhhp/Rk1wiYgpyJ78i4CsZbjkb8Qx+ihvzu3RPaKo\
gZkY6GlEeMsKdPSOFIC8VoOusg44L5c+T8ouOoGhWbdWJ8tMi4egkxo4hoh2yNTGf3iIyr5Lyic4bRENXo+lvDjAt4C1Hk/OKt\
UaAj0+n4dMSZ2D+hrYJsaYh2SClG2jV9kJKKzhlGQ1SsW299Mq6C8dYZHTExo8fzieI5ivipYnYy7nwJqGKmOYyRwfiUBXITfh\
5qSHRGWEkfqJqURgvsdHyWYv7Ko8DnYYegk3EB00cxprdrJRzFd7YQzawu8L1GMTYS/KpPaAFTkIn1EmJmspJSs5xBzSyGhlkB\
mlxfNFiP5mw4wlbMh4F5Ddxp5jNINBdCEz9zPOC1zD7Q0HBdmXndwv0TMtydEdzlWJT4VZ8Qt9Qn4/onxMIwa5ZYGJU5yufBiC\
jwE50AGjLCVuS8Yt4H7OgZLKK5EKOsLviEWJSL/+0uMi7gLUSBseYwqEbXvSHCec1CJvZPyHCmYQffaBBfOTCGHM2aEbZi1+gO\
1XTWVXMnzrhAn5DSOZVsiQlHnSITKzGj6DeTcZWc/3oy7h9//PF4PL4BlvsWrb6RE+oAAAAASUVORK5CYII=');
}
.emscripten { padding-right: 0; margin-left: auto; margin-right: auto; display: block; }
div.emscripten { text-align: center; }
div.emscripten_border { border: 1px solid black; }
/* NOTE: Canvas *must not* have any border or padding, or mouse coords will be wrong */
canvas.emscripten {
border: 0px none;
background: black;
width: 100%;
}
.spinner {
height: 30px;
width: 30px;
margin: 0;
margin-top: 20px;
margin-left: 20px;
display: inline-block;
vertical-align: top;
-webkit-animation: rotation .8s linear infinite;
-moz-animation: rotation .8s linear infinite;
-o-animation: rotation .8s linear infinite;
animation: rotation 0.8s linear infinite;
border-left: 5px solid black;
border-right: 5px solid black;
border-bottom: 5px solid black;
border-top: 5px solid red;
border-radius: 100%;
background-color: rgb(245, 245, 245);
}
@-webkit-keyframes rotation {
from {-webkit-transform: rotate(0deg);}
to {-webkit-transform: rotate(360deg);}
}
@-moz-keyframes rotation {
from {-moz-transform: rotate(0deg);}
to {-moz-transform: rotate(360deg);}
}
@-o-keyframes rotation {
from {-o-transform: rotate(0deg);}
to {-o-transform: rotate(360deg);}
}
@keyframes rotation {
from {transform: rotate(0deg);}
to {transform: rotate(360deg);}
}
#status {
display: inline-block;
vertical-align: top;
margin-top: 30px;
margin-left: 20px;
font-weight: bold;
color: rgb(40, 40, 40);
}
#progress {
height: 0px;
width: 0px;
}
#controls {
display: inline-block;
float: right;
vertical-align: top;
margin-top: 15px;
margin-right: 20px;
}
#output {
width: 100%;
height: 140px;
margin: 0 auto;
margin-top: 10px;
display: block;
background-color: black;
color: rgb(37, 174, 38);
font-family: 'Lucida Console', Monaco, monospace;
outline: none;
}
input[type=button] {
background-color: lightgray;
border: 4px solid darkgray;
color: black;
text-decoration: none;
cursor: pointer;
width: 140px;
height: 50px;
}
input[type=button]:hover {
background-color: #f5f5f5ff;
border-color: black;
}
</style>
</head>
<body>
<div id="header">
<a id="logo" href="https://www.raylib.com"></a>
<div class="spinner" id='spinner'></div>
<div class="emscripten" id="status">Downloading...</div>
<span id='controls'>
<span><input type="button" value="🖵 FULLSCREEN" onclick="Module.requestFullscreen(false, false)"></span>
<span><input type="button" id="btn-audio" value="🔇 SUSPEND" onclick="toggleAudio()"></span>
</span>
<div class="emscripten">
<progress value="0" max="100" id="progress" hidden=1></progress>
</div>
</div>
<div class="emscripten_border">
<canvas class="emscripten" id="canvas" oncontextmenu="event.preventDefault()" tabindex=-1></canvas>
</div>
<textarea id="output" rows="8"></textarea>
<script type='text/javascript' src="https://cdn.jsdelivr.net/gh/eligrey/FileSaver.js/dist/FileSaver.min.js"> </script>
<script type='text/javascript'>
function saveFileFromMEMFSToDisk(memoryFSname, localFSname) // This can be called by C/C++ code
{
var isSafari = false; // Not supported, navigator.userAgent access is being restricted
//var isSafari = /^((?!chrome|android).)*safari/i.test(navigator.userAgent);
var data = FS.readFile(memoryFSname);
var blob;
if (isSafari) blob = new Blob([data.buffer], { type: "application/octet-stream" });
else blob = new Blob([data.buffer], { type: "application/octet-binary" });
// NOTE: SaveAsDialog is a browser setting. For example, in Google Chrome,
// in Settings/Advanced/Downloads section you have a setting:
// 'Ask where to save each file before downloading' - which you can set true/false.
// If you enable this setting it would always ask you and bring the SaveAsDialog
saveAs(blob, localFSname);
}
</script>
<script type='text/javascript'>
var statusElement = document.querySelector('#status');
var progressElement = document.querySelector('#progress');
var spinnerElement = document.querySelector('#spinner');
var Module = {
preRun: [],
postRun: [],
print: (function() {
var element = document.querySelector('#output');
if (element) element.value = ''; // Clear browser cache
return function(text) {
if (arguments.length > 1) text = Array.prototype.slice.call(arguments).join(' ');
// These replacements are necessary if you render to raw HTML
//text = text.replace(/&/g, "&amp;");
//text = text.replace(/</g, "&lt;");
//text = text.replace(/>/g, "&gt;");
//text = text.replace('\n', '<br>', 'g');
console.log(text);
if (element) {
element.value += text + "\n";
element.scrollTop = element.scrollHeight; // focus on bottom
}
};
})(),
printErr: function(text) {
if (arguments.length > 1) text = Array.prototype.slice.call(arguments).join(' ');
console.error(text);
},
canvas: (function() {
var canvas = document.querySelector('#canvas');
// As a default initial behavior, pop up an alert when webgl context is lost.
// To make your application robust, you may want to override this behavior before shipping!
// See http://www.khronos.org/registry/webgl/specs/latest/1.0/#5.15.2
canvas.addEventListener("webglcontextlost", function(e) { alert('WebGL context lost. You will need to reload the page.'); e.preventDefault(); }, false);
return canvas;
})(),
setStatus: function(text) {
if (!Module.setStatus.last) Module.setStatus.last = { time: Date.now(), text: '' };
if (text === Module.setStatus.last.text) return;
var m = text.match(/([^(]+)\((\d+(\.\d+)?)\/(\d+)\)/);
var now = Date.now();
if (m && now - Module.setStatus.last.time < 30) return; // If this is a progress update, skip it if too soon
Module.setStatus.last.time = now;
Module.setStatus.last.text = text;
if (m) {
text = m[1];
progressElement.value = parseInt(m[2])*100;
progressElement.max = parseInt(m[4])*100;
progressElement.hidden = true;
spinnerElement.hidden = false;
} else {
progressElement.value = null;
progressElement.max = null;
progressElement.hidden = true;
if (!text) spinnerElement.style.display = 'none';
}
statusElement.innerHTML = text;
},
totalDependencies: 0,
monitorRunDependencies: function(left) {
this.totalDependencies = Math.max(this.totalDependencies, left);
Module.setStatus(left ? 'Preparing... (' + (this.totalDependencies-left) + '/' + this.totalDependencies + ')' : 'All downloads complete.');
},
//noInitialRun: true
};
Module.setStatus('Downloading...');
window.onerror = function() {
Module.setStatus('Exception thrown, see JavaScript console');
spinnerElement.style.display = 'none';
Module.setStatus = function(text) { if (text) Module.printErr('[post-exception status] ' + text); };
};
</script>
<!-- REF: https://developers.google.com/web/updates/2018/11/web-audio-autoplay -->
<script type='text/javascript'>
var audioBtn = document.querySelector('#btn-audio');
// An array of all contexts to resume on the page
const audioContexList = [];
(function() {
// A proxy object to intercept AudioContexts and
// add them to the array for tracking and resuming later
self.AudioContext = new Proxy(self.AudioContext, {
construct(target, args) {
const result = new target(...args);
audioContexList.push(result);
if (result.state == "suspended") audioBtn.value = "🔈 RESUME";
return result;
}
});
})();
function toggleAudio() {
var resumed = false;
audioContexList.forEach(ctx => {
if (ctx.state == "suspended") { ctx.resume(); resumed = true; }
else if (ctx.state == "running") ctx.suspend();
});
if (resumed) audioBtn.value = "🔇 SUSPEND";
else audioBtn.value = "🔈 RESUME";
}
</script>
{{{ SCRIPT }}}
</body>
</html>

529
libs/raylib/generate.zig Normal file
View File

@ -0,0 +1,529 @@
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 = "raylib.zig";
pub const injectFile = "inject.zig";
fn trim(s: []const u8) []const u8 {
return std.mem.trim(u8, s, &[_]u8{ ' ', '\t', '\n' });
}
pub fn main() !void {
std.log.info("generating raylib.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("marshal.h", .{});
defer h.close();
var c = try fs.cwd().createFile("marshal.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, " = packed struct(u32) {")) |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, "raylib.m{s}(\n", .{func.name}));
if (!isPrimitiveOrPointer(func.returnType)) {
if (bindings.containsStruct(stripType(func.returnType))) {
try file.writeAll(try allocPrint(allocator, "@ptrCast([*c]raylib.{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]raylib.{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]raylib.{s}, @ptrToInt(&{s})),\n", .{ stripType(param.typ), param.name }));
} else if (isPointer(param.typ)) {
if (std.mem.endsWith(u8, param.typ, "anyopaque")) {
try file.writeAll(try allocPrint(allocator, "{s},\n", .{param.name}));
} else if (isConst(param.typ)) {
try file.writeAll(try allocPrint(allocator, "@intToPtr([*c]const {s}, @ptrToInt({s})),\n", .{ stripType(param.typ), 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 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/raylib/gui_icons.h Normal file
View 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
};

5
libs/raylib/inject.c Normal file
View File

@ -0,0 +1,5 @@
#define GRAPHICS_API_OPENGL_11
// #define RLGL_IMPLEMENTATION
#include "raylib.h"
#include "rlgl.h"
#include "raymath.h"

12
libs/raylib/inject.h Normal file
View File

@ -0,0 +1,12 @@
//--- CORE ----------------------------------------------------------------------------------------
#define GRAPHICS_API_OPENGL_11
// #define RLGL_IMPLEMENTATION
#include "raylib.h"
#include "rlgl.h"
#include "raymath.h"
// Enable vertex state pointer
void rlEnableStatePointer(int vertexAttribType, void *buffer);
// Disable vertex state pointer
void rlDisableStatePointer(int vertexAttribType);

999
libs/raylib/inject.zig Normal file
View File

@ -0,0 +1,999 @@
const std = @import("std");
const raylib = @cImport({
@cInclude("raylib.h");
@cDefine("GRAPHICS_API_OPENGL_11", {});
// @cDefine("RLGL_IMPLEMENTATION", {});
@cInclude("rlgl.h");
@cDefine("RAYMATH_IMPLEMENTATION", {});
@cInclude("raymath.h");
@cInclude("marshal.h");
});
//--- structs -------------------------------------------------------------------------------------
/// System/Window config flags
pub const ConfigFlags = packed struct(u32) {
FLAG_UNKNOWN_1: bool = false, // 0x0001
/// Set to run program in fullscreen
FLAG_FULLSCREEN_MODE: bool = false, // 0x0002,
/// Set to allow resizable window
FLAG_WINDOW_RESIZABLE: bool = false, // 0x0004,
/// Set to disable window decoration (frame and buttons)
FLAG_WINDOW_UNDECORATED: bool = false, // 0x0008,
/// Set to allow transparent framebuffer
FLAG_WINDOW_TRANSPARENT: bool = false, // 0x0010,
/// Set to try enabling MSAA 4X
FLAG_MSAA_4X_HINT: bool = false, // 0x0020,
/// Set to try enabling V-Sync on GPU
FLAG_VSYNC_HINT: bool = false, // 0x0040,
/// Set to hide window
FLAG_WINDOW_HIDDEN: bool = false, // 0x0080,
/// Set to allow windows running while minimized
FLAG_WINDOW_ALWAYS_RUN: bool = false, // 0x0100,
/// Set to minimize window (iconify)
FLAG_WINDOW_MINIMIZED: bool = false, // 0x0200,
/// Set to maximize window (expanded to monitor)
FLAG_WINDOW_MAXIMIZED: bool = false, // 0x0400,
/// Set to window non focused
FLAG_WINDOW_UNFOCUSED: bool = false, // 0x0800,
/// Set to window always on top
FLAG_WINDOW_TOPMOST: bool = false, // 0x1000,
/// Set to support HighDPI
FLAG_WINDOW_HIGHDPI: bool = false, // 0x2000,
/// Set to support mouse passthrough, only supported when FLAG_WINDOW_UNDECORATED
FLAG_WINDOW_MOUSE_PASSTHROUGH: bool = false, // 0x4000,
FLAG_UNKNOWN_2: bool = false, // 0x8000
/// Set to try enabling interlaced video format (for V3D)
FLAG_INTERLACED_HINT: bool = false, // 0x10000
FLAG_PADDING: u15 = 0, // 0xFFFE0000
};
/// Transform, vectex transformation data
pub const Transform = extern struct {
/// Translation
translation: Vector3,
/// Rotation
rotation: Vector4,
/// Scale
scale: Vector3,
};
/// Matrix, 4x4 components, column major, OpenGL style, right handed
pub const Matrix = extern struct {
/// Matrix first row (4 components) [m0, m4, m8, m12]
m0: f32,
m4: f32,
m8: f32,
m12: f32,
/// Matrix second row (4 components) [m1, m5, m9, m13]
m1: f32,
m5: f32,
m9: f32,
m13: f32,
/// Matrix third row (4 components) [m2, m6, m10, m14]
m2: f32,
m6: f32,
m10: f32,
m14: f32,
/// Matrix fourth row (4 components) [m3, m7, m11, m15]
m3: f32,
m7: f32,
m11: f32,
m15: f32,
pub fn zero() @This() {
return @This(){
.m0 = 0,
.m1 = 0,
.m2 = 0,
.m3 = 0,
.m4 = 0,
.m5 = 0,
.m6 = 0,
.m7 = 0,
.m8 = 0,
.m9 = 0,
.m10 = 0,
.m11 = 0,
.m12 = 0,
.m13 = 0,
.m14 = 0,
.m15 = 0,
};
}
pub fn identity() @This() {
return MatrixIdentity();
}
};
pub const Rectangle = extern struct {
x: f32 = 0,
y: f32 = 0,
width: f32 = 0,
height: f32 = 0,
pub fn toI32(self: @This()) RectangleI {
return .{
.x = @as(i32, @intFromFloat(self.x)),
.y = @as(i32, @intFromFloat(self.y)),
.width = @as(i32, @intFromFloat(self.width)),
.height = @as(i32, @intFromFloat(self.height)),
};
}
pub fn pos(self: @This()) Vector2 {
return .{
.x = self.x,
.y = self.y,
};
}
pub fn size(self: @This()) Vector2 {
return .{
.x = self.width,
.y = self.height,
};
}
pub fn topLeft(self: @This()) Vector2 {
return .{
.x = self.x,
.y = self.y,
};
}
pub fn topCenter(self: @This()) Vector2 {
return .{
.x = self.x + self.width / 2,
.y = self.y,
};
}
pub fn topRight(self: @This()) Vector2 {
return .{
.x = self.x + self.width,
.y = self.y,
};
}
pub fn centerLeft(self: @This()) Vector2 {
return .{
.x = self.x,
.y = self.y + self.height / 2,
};
}
pub fn center(self: @This()) Vector2 {
return .{
.x = self.x + self.width / 2,
.y = self.y + self.height / 2,
};
}
pub fn centerRight(self: @This()) Vector2 {
return .{
.x = self.x + self.width,
.y = self.y + self.height / 2,
};
}
pub fn bottomLeft(self: @This()) Vector2 {
return .{
.x = self.x + 0,
.y = self.y + self.height,
};
}
pub fn bottomCenter(self: @This()) Vector2 {
return .{
.x = self.x + self.width / 2,
.y = self.y + self.height,
};
}
pub fn bottomRight(self: @This()) Vector2 {
return .{
.x = self.x + self.width,
.y = self.y + self.height,
};
}
pub fn area(self: @This()) f32 {
return self.width * self.height;
}
pub fn include(self: @This(), other: @This()) @This() {
return self.includePoint(other.topLeft()).includePoint(other.bottomRight());
}
pub fn includePoint(self: @This(), point: Vector2) @This() {
const minX = @min(self.x, point.x);
const minY = @min(self.y, point.y);
const maxX = @max(self.x + self.width, point.x);
const maxY = @max(self.y + self.height, point.y);
return .{
.x = minX,
.y = minY,
.width = maxX - minX,
.height = maxY - minY,
};
}
};
pub const RectangleI = extern struct {
x: i32 = 0,
y: i32 = 0,
width: i32 = 0,
height: i32 = 0,
pub fn toF32(self: @This()) Rectangle {
return .{
.x = @as(f32, @floatFromInt(self.x)),
.y = @as(f32, @floatFromInt(self.y)),
.width = @as(f32, @floatFromInt(self.width)),
.height = @as(f32, @floatFromInt(self.height)),
};
}
pub fn pos(self: @This()) Vector2i {
return .{
.x = self.x,
.y = self.y,
};
}
};
pub const Vector2 = extern struct {
x: f32 = 0,
y: f32 = 0,
pub fn zero() @This() {
return .{ .x = 0, .y = 0 };
}
pub fn setZero(self: *@This()) void {
self.x = 0;
self.y = 0;
}
pub fn one() @This() {
return @This(){ .x = 1, .y = 1 };
}
pub fn neg(self: @This()) @This() {
return @This(){ .x = -self.x, .y = -self.y };
}
pub fn length2(self: @This()) f32 {
var sum = self.x * self.x;
sum += self.y * self.y;
return sum;
}
pub fn length(self: @This()) f32 {
return std.math.sqrt(self.length2());
}
pub fn distanceTo(self: @This(), other: @This()) f32 {
return self.sub(other).length();
}
pub fn distanceToSquared(self: @This(), other: @This()) f32 {
return self.sub(other).length2();
}
pub fn normalize(self: @This()) @This() {
const l = self.length();
if (l == 0.0) return @This().zero();
return self.scale(1.0 / l);
}
pub fn scale(self: @This(), factor: f32) @This() {
return @This(){
.x = self.x * factor,
.y = self.y * factor,
};
}
pub fn add(self: @This(), other: @This()) @This() {
return @This(){
.x = self.x + other.x,
.y = self.y + other.y,
};
}
/// same as add but assign result directly to this
pub fn addSet(self: *@This(), other: @This()) void {
self.x += other.x;
self.y += other.y;
}
pub fn sub(self: @This(), other: @This()) @This() {
return @This(){
.x = self.x - other.x,
.y = self.y - other.y,
};
}
pub fn lerp(self: @This(), other: @This(), t: f32) @This() {
return self.scale(1 - t).add(other.scale(t));
}
pub fn randomInUnitCircle(rng: std.rand.Random) @This() {
return randomOnUnitCircle(rng).scale(randomF32(rng, 0, 1));
}
pub fn randomOnUnitCircle(rng: std.rand.Random) @This() {
return (Vector2{ .x = 1 }).rotate(randomF32(rng, -PI, PI));
}
pub fn clampX(self: @This(), minX: f32, maxX: f32) @This() {
return .{
.x = std.math.clamp(self.x, minX, maxX),
.y = self.y,
};
}
pub fn clampY(self: @This(), minY: f32, maxY: f32) @This() {
return .{
.x = self.x,
.y = std.math.clamp(self.y, minY, maxY),
};
}
pub fn int(self: @This()) Vector2i {
return .{ .x = @as(i32, @intFromFloat(self.x)), .y = @as(i32, @intFromFloat(self.y)) };
}
/// Cross product
pub fn cross(self: @This(), other: @This()) f32 {
return self.x * other.y - self.y * other.x;
}
/// Dot product.
pub fn dot(self: @This(), other: @This()) f32 {
return self.x * other.x + self.y * other.y;
}
pub fn rotate(self: @This(), a: f32) @This() {
return Vector2Rotate(self, a);
}
pub fn fromAngle(a: f32) @This() {
return Vector2Rotate(.{ .x = 1 }, a);
}
pub fn angle(this: @This()) f32 {
const zeroRotation: Vector2 = .{ .x = 1, .y = 0 };
if (this.x == zeroRotation.x and this.y == zeroRotation.y) return 0;
const c = zeroRotation.cross(this);
const d = zeroRotation.dot(this);
return std.math.atan2(f32, c, d);
}
pub fn xy0(self: @This()) Vector3 {
return .{ .x = self.x, .y = self.y };
}
pub fn x0z(self: @This()) Vector3 {
return .{ .x = self.x, .z = self.y };
}
pub fn set(self: @This(), setter: struct { x: ?f32 = null, y: ?f32 = null }) Vector2 {
var copy = self;
if (setter.x) |x| copy.x = x;
if (setter.y) |y| copy.y = y;
return copy;
}
};
pub const Vector2i = extern struct {
x: i32 = 0,
y: i32 = 0,
pub fn float(self: @This()) Vector2 {
return .{ .x = @as(f32, @floatFromInt(self.x)), .y = @as(f32, @floatFromInt(self.y)) };
}
};
pub const Vector3 = extern struct {
x: f32 = 0,
y: f32 = 0,
z: f32 = 0,
pub fn new(x: f32, y: f32, z: f32) @This() {
return @This(){ .x = x, .y = y, .z = z };
}
pub fn zero() @This() {
return @This(){ .x = 0, .y = 0, .z = 0 };
}
pub fn one() @This() {
return @This(){ .x = 1, .y = 1, .z = 1 };
}
pub fn length2(self: @This()) f32 {
var sum = self.x * self.x;
sum += self.y * self.y;
sum += self.z * self.z;
return sum;
}
pub fn length(self: @This()) f32 {
return std.math.sqrt(self.length2());
}
pub fn normalize(self: @This()) @This() {
const l = self.length();
if (l == 0.0) return @This().zero();
return self.scale(1.0 / l);
}
pub fn scale(self: @This(), factor: f32) @This() {
return @This(){
.x = self.x * factor,
.y = self.y * factor,
.z = self.z * factor,
};
}
pub fn add(self: @This(), other: @This()) @This() {
return @This(){
.x = self.x + other.x,
.y = self.y + other.y,
.z = self.z + other.z,
};
}
pub fn sub(self: @This(), other: @This()) @This() {
return @This(){
.x = self.x - other.x,
.y = self.y - other.y,
.z = self.z - other.z,
};
}
pub fn neg(this: @This()) @This() {
return .{
.x = -this.x,
.y = -this.y,
.z = -this.z,
};
}
pub fn lerp(self: @This(), other: @This(), t: f32) @This() {
return self.scale(1 - t).add(other.scale(t));
}
pub fn forward() @This() {
return @This().new(0, 0, 1);
}
pub fn rotate(self: @This(), quaternion: Vector4) @This() {
return Vector3RotateByQuaternion(self, quaternion);
}
pub fn angleBetween(self: @This(), other: Vector3) f32 {
return Vector3Angle(self, other);
// return std.math.acos(self.dot(other) / (self.length() * other.length()));
}
/// Dot product.
pub fn dot(self: @This(), other: @This()) f32 {
return self.x * other.x + self.y * other.y + self.z * other.z;
}
pub fn xy(self: @This()) Vector2 {
return .{ .x = self.x, .y = self.y };
}
pub fn set(self: @This(), setter: struct { x: ?f32 = null, y: ?f32 = null, z: ?f32 = null }) Vector3 {
var copy = self;
if (setter.x) |x| copy.x = x;
if (setter.y) |y| copy.y = y;
if (setter.z) |z| copy.z = z;
return copy;
}
};
pub const Vector4 = extern struct {
x: f32 = 0,
y: f32 = 0,
z: f32 = 0,
w: f32 = 0,
pub fn zero() @This() {
return @This(){ .x = 0, .y = 0, .z = 0 };
}
pub fn one() @This() {
return @This(){ .x = 1, .y = 1, .z = 1 };
}
pub fn length2(self: @This()) f32 {
var sum = self.x * self.x;
sum += self.y * self.y;
sum += self.z * self.z;
sum += self.w * self.w;
return sum;
}
pub fn length(self: @This()) f32 {
return std.math.sqrt(self.length2());
}
pub fn normalize(self: @This()) @This() {
const l = self.length();
if (l == 0.0) return @This().zero();
return self.scale(1.0 / l);
}
pub fn scale(self: @This(), factor: f32) @This() {
return @This(){
.x = self.x * factor,
.y = self.y * factor,
.z = self.z * factor,
.w = self.w * factor,
};
}
pub fn add(self: @This(), other: @This()) @This() {
return @This(){
.x = self.x + other.x,
.y = self.y + other.y,
.z = self.z + other.z,
.w = self.w + other.w,
};
}
pub fn sub(self: @This(), other: @This()) @This() {
return @This(){
.x = self.x - other.x,
.y = self.y - other.y,
.z = self.z - other.z,
.w = self.w - other.w,
};
}
pub fn lerp(self: @This(), other: @This(), t: f32) @This() {
return self.scale(1 - t).add(other.scale(t));
}
pub fn toColor(self: @This()) Color {
return .{
.r = @as(u8, @intFromFloat(std.math.clamp(self.x * 255, 0, 255))),
.g = @as(u8, @intFromFloat(std.math.clamp(self.y * 255, 0, 255))),
.b = @as(u8, @intFromFloat(std.math.clamp(self.z * 255, 0, 255))),
.a = @as(u8, @intFromFloat(std.math.clamp(self.w * 255, 0, 255))),
};
}
pub fn fromAngleAxis(axis: Vector3, angle: f32) @This() {
return QuaternionFromAxisAngle(axis, angle);
}
};
/// Color type, RGBA (32bit)
pub const Color = extern struct {
r: u8 = 0,
g: u8 = 0,
b: u8 = 0,
a: u8 = 255,
pub const ColorChangeConfig = struct {
r: ?u8 = null,
g: ?u8 = null,
b: ?u8 = null,
a: ?u8 = null,
};
pub fn set(self: @This(), c: ColorChangeConfig) Color {
return .{
.r = if (c.r) |_r| _r else self.r,
.g = if (c.g) |_g| _g else self.g,
.b = if (c.b) |_b| _b else self.b,
.a = if (c.a) |_a| _a else self.a,
};
}
pub fn lerp(self: @This(), other: @This(), t: f32) @This() {
return self.toVector4().lerp(other.toVector4(), t).toColor();
}
pub fn lerpA(self: @This(), targetAlpha: u8, t: f32) @This() {
var copy = self;
const a = @as(f32, @floatFromInt(self.a));
copy.a = @as(u8, @intFromFloat(a * (1 - t) + @as(f32, @floatFromInt(targetAlpha)) * t));
return copy;
}
pub fn toVector4(self: @This()) Vector4 {
return .{
.x = @as(f32, @floatFromInt(self.r)) / 255.0,
.y = @as(f32, @floatFromInt(self.g)) / 255.0,
.z = @as(f32, @floatFromInt(self.b)) / 255.0,
.w = @as(f32, @floatFromInt(self.a)) / 255.0,
};
}
/// negate color (keep alpha)
pub fn neg(self: @This()) @This() {
return .{
.r = 255 - self.r,
.g = 255 - self.g,
.b = 255 - self.b,
.a = self.a,
};
}
};
/// Camera2D, defines position/orientation in 2d space
pub const Camera2D = extern struct {
/// Camera offset (displacement from target)
offset: Vector2 = Vector2.zero(),
/// Camera target (rotation and zoom origin)
target: Vector2,
/// Camera rotation in degrees
rotation: f32 = 0,
/// Camera zoom (scaling), should be 1.0f by default
zoom: f32 = 1,
};
pub const MATERIAL_MAP_DIFFUSE = @as(usize, @intCast(@intFromEnum(MaterialMapIndex.MATERIAL_MAP_ALBEDO)));
pub const MATERIAL_MAP_SPECULAR = @as(usize, @intCast(@intFromEnum(MaterialMapIndex.MATERIAL_MAP_METALNESS)));
//--- callbacks -----------------------------------------------------------------------------------
/// Logging: Redirect trace log messages
pub const TraceLogCallback = *const fn (logLevel: c_int, text: [*c]const u8, args: ?*anyopaque) void;
/// FileIO: Load binary data
pub const LoadFileDataCallback = *const fn (fileName: [*c]const u8, bytesRead: [*c]c_uint) [*c]u8;
/// FileIO: Save binary data
pub const SaveFileDataCallback = *const fn (fileName: [*c]const u8, data: ?*anyopaque, bytesToWrite: c_uint) bool;
/// FileIO: Load text data
pub const LoadFileTextCallback = *const fn (fileName: [*c]const u8) [*c]u8;
/// FileIO: Save text data
pub const SaveFileTextCallback = *const fn (fileName: [*c]const u8, text: [*c]const u8) bool;
/// Audio Loading and Playing Functions (Module: audio)
pub const AudioCallback = *const fn (bufferData: ?*anyopaque, frames: u32) void;
//--- utils ---------------------------------------------------------------------------------------
// Camera global state context data [56 bytes]
pub const CameraData = extern struct {
/// Current camera mode
mode: u32,
/// Camera distance from position to target
targetDistance: f32,
/// Player eyes position from ground (in meters)
playerEyesPosition: f32,
/// Camera angle in plane XZ
angle: Vector2,
/// Previous mouse position
previousMousePosition: Vector2,
// Camera movement control keys
/// Move controls (CAMERA_FIRST_PERSON)
moveControl: i32[6],
/// Smooth zoom control key
smoothZoomControl: i32,
/// Alternative control key
altControl: i32,
/// Pan view control key
panControl: i32,
};
pub fn randomF32(rng: std.rand.Random, min: f32, max: f32) f32 {
return rng.float(f32) * (max - min) + min;
}
//--- functions -----------------------------------------------------------------------------------
/// Setup init configuration flags (view FLAGS)
pub fn SetConfigFlags(
flags: ConfigFlags,
) void {
raylib.SetConfigFlags(@as(c_uint, @bitCast(flags)));
}
/// Load file data as byte array (read)
pub fn LoadFileData(fileName: [*:0]const u8) ![]const u8 {
var bytesRead: u32 = undefined;
const data = raylib.LoadFileData(
@as([*c]const u8, @ptrFromInt(@intFromPtr(fileName))),
@as([*c]c_int, @ptrCast(&bytesRead)),
);
if (data == null) return error.FileNotFound;
return data[0..bytesRead];
}
/// Unload file data allocated by LoadFileData()
pub fn UnloadFileData(
data: []const u8,
) void {
raylib.UnloadFileData(
@as([*c]u8, @ptrFromInt(@intFromPtr(data.ptr))),
);
}
/// Set custom trace log
pub fn SetTraceLogCallback(
_: TraceLogCallback,
) void {
@panic("use log.zig for that");
}
/// Generate image font atlas using chars info
pub fn GenImageFontAtlas(
chars: [*]const GlyphInfo,
recs: [*]const [*]const Rectangle,
glyphCount: i32,
fontSize: i32,
padding: i32,
packMethod: i32,
) Image {
var out: Image = undefined;
mGenImageFontAtlas(
@as([*c]raylib.Image, @ptrCast(&out)),
@as([*c]raylib.GlyphInfo, @ptrCast(chars)),
@as([*c][*c]raylib.Rectangle, @ptrCast(recs)),
glyphCount,
fontSize,
padding,
packMethod,
);
return out;
}
export fn mGenImageFontAtlas(
out: [*c]raylib.Image,
chars: [*c]raylib.GlyphInfo,
recs: [*c][*c]raylib.Rectangle,
glyphCount: i32,
fontSize: i32,
padding: i32,
packMethod: i32,
) void {
out.* = raylib.GenImageFontAtlas(
chars,
recs,
glyphCount,
fontSize,
padding,
packMethod,
);
}
/// Get native window handle
pub fn GetWindowHandle() ?*anyopaque {
return raylib.GetWindowHandle();
}
/// Internal memory allocator
pub fn MemAlloc(
size: i32,
) ?*anyopaque {
return raylib.MemAlloc(size);
}
/// Internal memory reallocator
pub fn MemRealloc(
ptr: ?*anyopaque,
size: i32,
) ?*anyopaque {
return raylib.MemRealloc(ptr, size);
}
/// Internal memory free
pub fn MemFree(
ptr: ?*anyopaque,
) void {
raylib.MemFree(ptr);
}
/// Show trace log messages (LOG_DEBUG, LOG_INFO, LOG_WARNING, LOG_ERROR...)
pub fn TraceLog(
logLevel: i32,
text: [*:0]const u8,
) void {
raylib.TraceLog(logLevel, text);
}
/// Text formatting with variables (sprintf() style)
/// caller owns memory
pub fn TextFormat(allocator: std.mem.Allocator, comptime fmt: []const u8, args: anytype) std.fmt.AllocPrintError![*:0]const u8 {
return (try std.fmt.allocPrintZ(allocator, fmt, args)).ptr;
}
/// Split text into multiple strings
pub fn TextSplit(allocator: std.mem.Allocator, text: []const u8, delimiter: []const u8, count: i32) ![]const []const u8 {
var list = std.ArrayList([]const u8).init(allocator);
var it = std.mem.split(u8, text, delimiter);
var i = 0;
var n = 0;
while (it.next()) |slice| : (i += 1) {
if (i >= count) {
break;
}
try list.append(slice);
n += slice.len;
}
if (n < text.len) {
try list.append(text[n..]);
}
return list.toOwnedSlice();
}
/// Join text strings with delimiter
pub fn TextJoin(allocator: std.mem.Allocator, textList: []const []const u8, delimiter: []const u8) ![:0]const u8 {
return (try std.mem.joinZ(allocator, delimiter, textList)).ptr;
}
/// Append text at specific position and move cursor!
pub fn TextAppend(allocator: std.mem.Allocator, text: []const u8, append: []const u8, position: i32) std.fmt.AllocPrintError![:0]u8 {
return (try std.fmt.allocPrintZ(allocator, "{s}{s}{s}", .{
text[0..position],
append,
text[position..],
})).ptr;
}
//--- RLGL ----------------------------------------------------------------------------------------
pub const DEG2RAD: f32 = PI / 180;
pub const RAD2DEG: f32 = 180 / PI;
///
pub const rlglData = extern struct {
/// Current render batch
currentBatch: ?*rlRenderBatch,
/// Default internal render batch
defaultBatch: rlRenderBatch,
pub const State = extern struct {
/// Current active render batch vertex counter (generic, used for all batches)
vertexCounter: i32,
/// Current active texture coordinate X (added on glVertex*())
texcoordx: f32,
/// Current active texture coordinate Y (added on glVertex*())
texcoordy: f32,
/// Current active normal X (added on glVertex*())
normalx: f32,
/// Current active normal Y (added on glVertex*())
normaly: f32,
/// Current active normal Z (added on glVertex*())
normalz: f32,
/// Current active color R (added on glVertex*())
colorr: u8,
/// Current active color G (added on glVertex*())
colorg: u8,
/// Current active color B (added on glVertex*())
colorb: u8,
/// Current active color A (added on glVertex*())
colora: u8,
/// Current matrix mode
currentMatrixMode: i32,
/// Current matrix pointer
currentMatrix: ?*Matrix,
/// Default modelview matrix
modelview: Matrix,
/// Default projection matrix
projection: Matrix,
/// Transform matrix to be used with rlTranslate, rlRotate, rlScale
transform: Matrix,
/// Require transform matrix application to current draw-call vertex (if required)
transformRequired: bool,
/// Matrix stack for push/pop
stack: [RL_MAX_MATRIX_STACK_SIZE]Matrix,
/// Matrix stack counter
stackCounter: i32,
/// Default texture used on shapes/poly drawing (required by shader)
defaultTextureId: u32,
/// Active texture ids to be enabled on batch drawing (0 active by default)
activeTextureId: [RL_DEFAULT_BATCH_MAX_TEXTURE_UNITS]u32,
/// Default vertex shader id (used by default shader program)
defaultVShaderId: u32,
/// Default fragment shader id (used by default shader program)
defaultFShaderId: u32,
/// Default shader program id, supports vertex color and diffuse texture
defaultShaderId: u32,
/// Default shader locations pointer to be used on rendering
defaultShaderLocs: [*]i32,
/// Current shader id to be used on rendering (by default, defaultShaderId)
currentShaderId: u32,
/// Current shader locations pointer to be used on rendering (by default, defaultShaderLocs)
currentShaderLocs: [*]i32,
/// Stereo rendering flag
stereoRender: bool,
/// VR stereo rendering eyes projection matrices
projectionStereo: [2]Matrix,
/// VR stereo rendering eyes view offset matrices
viewOffsetStereo: [2]Matrix,
/// Blending mode active
currentBlendMode: i32,
/// Blending source factor
glBlendSrcFactor: i32,
/// Blending destination factor
glBlendDstFactor: i32,
/// Blending equation
glBlendEquation: i32,
/// Current framebuffer width
framebufferWidth: i32,
/// Current framebuffer height
framebufferHeight: i32,
};
pub const ExtSupported = extern struct {
/// VAO support (OpenGL ES2 could not support VAO extension) (GL_ARB_vertex_array_object)
vao: bool,
/// Instancing supported (GL_ANGLE_instanced_arrays, GL_EXT_draw_instanced + GL_EXT_instanced_arrays)
instancing: bool,
/// NPOT textures full support (GL_ARB_texture_non_power_of_two, GL_OES_texture_npot)
texNPOT: bool,
/// Depth textures supported (GL_ARB_depth_texture, GL_WEBGL_depth_texture, GL_OES_depth_texture)
texDepth: bool,
/// float textures support (32 bit per channel) (GL_OES_texture_float)
texFloat32: bool,
/// DDS texture compression support (GL_EXT_texture_compression_s3tc, GL_WEBGL_compressed_texture_s3tc, GL_WEBKIT_WEBGL_compressed_texture_s3tc)
texCompDXT: bool,
/// ETC1 texture compression support (GL_OES_compressed_ETC1_RGB8_texture, GL_WEBGL_compressed_texture_etc1)
texCompETC1: bool,
/// ETC2/EAC texture compression support (GL_ARB_ES3_compatibility)
texCompETC2: bool,
/// PVR texture compression support (GL_IMG_texture_compression_pvrtc)
texCompPVRT: bool,
/// ASTC texture compression support (GL_KHR_texture_compression_astc_hdr, GL_KHR_texture_compression_astc_ldr)
texCompASTC: bool,
/// Clamp mirror wrap mode supported (GL_EXT_texture_mirror_clamp)
texMirrorClamp: bool,
/// Anisotropic texture filtering support (GL_EXT_texture_filter_anisotropic)
texAnisoFilter: bool,
/// Compute shaders support (GL_ARB_compute_shader)
computeShader: bool,
/// Shader storage buffer object support (GL_ARB_shader_storage_buffer_object)
ssbo: bool,
/// Maximum anisotropy level supported (minimum is 2.0f)
maxAnisotropyLevel: f32,
/// Maximum bits for depth component
maxDepthBits: i32,
};
};
/// Enable attribute state pointer
pub fn rlEnableStatePointer(
vertexAttribType: i32,
buffer: *anyopaque,
) void {
raylib.rlEnableStatePointer(
vertexAttribType,
@as([*c]anyopaque, @ptrCast(buffer)),
);
}
/// Disable attribute state pointer
pub fn rlDisableStatePointer(
vertexAttribType: i32,
) void {
raylib.rlDisableStatePointer(
vertexAttribType,
);
}
/// Get the last gamepad button pressed
pub fn GetGamepadButtonPressed() ?GamepadButton {
if (raylib.GetGamepadButtonPressed() == -1) return null;
return @as(GamepadButton, @enumFromInt(raylib.GetGamepadButtonPressed()));
}

View File

@ -0,0 +1,48 @@
const std = @import("std");
const fs = std.fs;
const mapping = @import("type_mapping.zig");
const json = std.json;
pub const jsonFiles: []const []const u8 = &.{
"raylib.json",
"rlgl.json",
"raymath.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/raylib/logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

4035
libs/raylib/marshal.c Normal file

File diff suppressed because it is too large Load Diff

2429
libs/raylib/marshal.h Normal file

File diff suppressed because it is too large Load Diff

1
libs/raylib/raylib Submodule

@ -0,0 +1 @@
Subproject commit e46b6147fc30e69dd300bbda90ff0a62bf8a4df0

11660
libs/raylib/raylib.json Normal file

File diff suppressed because it is too large Load Diff

12171
libs/raylib/raylib.zig Normal file

File diff suppressed because it is too large Load Diff

View 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;

1954
libs/raylib/raymath.json Normal file

File diff suppressed because it is too large Load Diff

3928
libs/raylib/rlgl.json Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,691 @@
//! 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 pointeR = if (isPointer(c)) "?[*]" else "";
const stripped = stripType(c);
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);
}