README: minimal README linking to new website
Helps hexops/mach#881 Signed-off-by: Stephen Gutekanst <stephen@hexops.com>
This commit is contained in:
parent
4d59b4d4e2
commit
fae6bfd3c4
1 changed files with 14 additions and 152 deletions
166
README.md
166
README.md
|
@ -1,164 +1,26 @@
|
||||||
# mach/glfw - Ziggified GLFW bindings [](https://github.com/hexops/mach-glfw/actions) <a href="https://hexops.com"><img align="right" alt="Hexops logo" src="https://raw.githubusercontent.com/hexops/media/main/readme.svg"></img></a>
|
<a href="https://machengine.org/pkg/mach-glfw">
|
||||||
|
<picture>
|
||||||
|
<source media="(prefers-color-scheme: dark)" srcset="https://machengine.org/next/assets/mach/glfw-full-dark.svg">
|
||||||
|
<img alt="mach-gpu" src="https://machengine.org/next/assets/mach/glfw-full-light.svg" height="150px">
|
||||||
|
</picture>
|
||||||
|
</a>
|
||||||
|
|
||||||
Ziggified GLFW bindings that [Mach engine](https://github.com/hexops/mach) uses, with 100% API coverage, zero-fuss installation, cross compilation, and more.
|
Perfected GLFW bindings for Zig
|
||||||
|
|
||||||
This repository is a separate copy of the same library in the [main Mach repository](https://github.com/hexops/mach), and is automatically kept in sync, so that anyone can use this library in their own project / engine if they like!
|
## Features
|
||||||
|
|
||||||
## Zero fuss installation, cross compilation, and more
|
* Zero-fuss installation, cross-compilation at the flip of a switch, and broad platform support.
|
||||||
|
* 100% API coverage. Every function, type, constant, etc. has been exposed in a ziggified API.
|
||||||
|
|
||||||
[Just as with Mach](https://github.com/hexops/mach#zero-fuss-installation--cross-compilation), you get zero fuss installation & cross compilation using these GLFW bindings. **only `zig` and `git` are needed to build from any OS and produce binaries for every OS.** No system dependencies at all.
|
See also: [What does a ziggified GLFW API offer?](https://machengine.org/pkg/mach-glfw/)
|
||||||
|
|
||||||
## 100% API coverage, 130+ tests, etc.
|
## Documentation
|
||||||
|
|
||||||
These bindings have 100% API coverage of GLFW v3.3.4. Every function, type, constant, etc. has been wrapped in a ziggified API.
|
[machengine.org/pkg/mach-glfw](https://machengine.org/pkg/mach-glfw)
|
||||||
|
|
||||||
There are 130+ tests, and CI tests on all major platforms as well as cross-compilation between platforms:
|
|
||||||
|
|
||||||
[platform support table](https://github.com/hexops/mach#supported-platforms)
|
|
||||||
|
|
||||||
## What does a ziggified GLFW API offer?
|
|
||||||
|
|
||||||
Why create a ziggified GLFW wrapper, instead of just using `@cImport` and interfacing with GLFW directly? You get:
|
|
||||||
|
|
||||||
- `true` and `false` instead of `c.GLFW_TRUE` and `c.GLFW_FALSE` constants.
|
|
||||||
- Generics, so you can just use `window.hint` instead of `glfwWindowHint`, `glfwWindowHintString`, etc.
|
|
||||||
- **Enums**, always know what value a GLFW function can accept as everything is strictly typed. And use the nice Zig syntax to access enums, like `window.getKey(.escape)` instead of `c.glfwGetKey(window, c.GLFW_KEY_ESCAPE)`
|
|
||||||
- Slices instead of C pointers and lengths.
|
|
||||||
- [packed structs](https://ziglang.org/documentation/master/#packed-struct) represent bit masks, so you can use `if (joystick.down and joystick.right)` instead of `if (joystick & c.GLFW_HAT_DOWN and joystick & c.GLFW_HAT_RIGHT)`, etc.
|
|
||||||
- Methods, e.g. `my_window.hint(...)` instead of `glfwWindowHint(my_window, ...)`
|
|
||||||
|
|
||||||
## How do I use OpenGL, Vulkan, WebGPU, etc. with this?
|
|
||||||
|
|
||||||
You'll need to bring your own library for this. Some are:
|
|
||||||
|
|
||||||
- (Vulkan) https://github.com/Snektron/vulkan-zig (also see https://github.com/Avokadoen/zig_vulkan)
|
|
||||||
- (OpenGL) https://github.com/ziglibs/zgl
|
|
||||||
|
|
||||||
## Examples
|
|
||||||
|
|
||||||
A minimal Vulkan example can be found in the [mach-glfw-vulkan-example](https://github.com/hexops/mach-glfw-vulkan-example) repository:
|
|
||||||
|
|
||||||
<img width="912" alt="image" src="https://user-images.githubusercontent.com/3173176/139573985-d862f35a-e78e-40c2-bc0c-9c4fb68d6ecd.png">
|
|
||||||
|
|
||||||
## Getting started
|
|
||||||
|
|
||||||
### Adding dependency
|
|
||||||
|
|
||||||
Create a `build.zig.zon` file in your project (replace `$LATEST_COMMIT` with the latest commit hash):
|
|
||||||
|
|
||||||
```
|
|
||||||
.{
|
|
||||||
.name = "mypkg",
|
|
||||||
.version = "0.1.0",
|
|
||||||
.dependencies = .{
|
|
||||||
.mach_glfw = .{
|
|
||||||
.url = "https://github.com/hexops/mach-glfw/archive/$LATEST_COMMIT.tar.gz",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
Run `zig build` in your project, and the compiler instruct you to add a `.hash = "..."` field next to `.url`.
|
|
||||||
|
|
||||||
Then use the dependency in your `build.zig`:
|
|
||||||
|
|
||||||
```zig
|
|
||||||
...
|
|
||||||
const glfw = @import("mach_glfw");
|
|
||||||
|
|
||||||
pub fn build(b: *Build) !void {
|
|
||||||
...
|
|
||||||
exe.addModule("glfw", glfw.module(b));
|
|
||||||
try glfw.link(b, exe, .{});
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
# Next steps
|
|
||||||
|
|
||||||
Now in your code you may import and use GLFW:
|
|
||||||
|
|
||||||
```zig
|
|
||||||
const glfw = @import("glfw");
|
|
||||||
|
|
||||||
/// Default GLFW error handling callback
|
|
||||||
fn errorCallback(error_code: glfw.ErrorCode, description: [:0]const u8) void {
|
|
||||||
std.log.err("glfw: {}: {s}\n", .{ error_code, description });
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn main() !void {
|
|
||||||
glfw.setErrorCallback(errorCallback);
|
|
||||||
if (!glfw.init(.{})) {
|
|
||||||
std.log.err("failed to initialize GLFW: {?s}", .{glfw.getErrorString()});
|
|
||||||
std.process.exit(1);
|
|
||||||
}
|
|
||||||
defer glfw.terminate();
|
|
||||||
|
|
||||||
// Create our window
|
|
||||||
const window = glfw.Window.create(640, 480, "Hello, mach-glfw!", null, null, .{}) orelse {
|
|
||||||
std.log.err("failed to create GLFW window: {?s}", .{glfw.getErrorString()});
|
|
||||||
std.process.exit(1);
|
|
||||||
};
|
|
||||||
defer window.destroy();
|
|
||||||
|
|
||||||
// Wait for the user to close the window.
|
|
||||||
while (!window.shouldClose()) {
|
|
||||||
glfw.pollEvents();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## A warning about error handling
|
|
||||||
|
|
||||||
Unless the action you're performing is truly critical to your application continuing further, you should avoid terminating on error.
|
|
||||||
|
|
||||||
This is because GLFW unfortunately must return errors for _a large portion_ of its functionality on some platforms, but especially for Wayland - so ideally your application is resiliant to such errors and merely e.g. logs failures that are not critical.
|
|
||||||
|
|
||||||
Here is a rough list of functionality Wayland does not support:
|
|
||||||
|
|
||||||
- `Window.setIcon`
|
|
||||||
- `Window.setPos`, `Window.getPos`
|
|
||||||
- `Window.iconify`, `Window.focus`
|
|
||||||
- `Monitor.setGamma`
|
|
||||||
- `Monitor.getGammaRamp`, `Monitor.setGammaRamp`
|
|
||||||
|
|
||||||
For example, `window.getPos()` will always return x=0, y=0 on Wayland due to lack of platform support.
|
|
||||||
Ignoring this error is a reasonable choice for most applications.
|
|
||||||
However, errors like this can still be caught and handled:
|
|
||||||
|
|
||||||
```zig
|
|
||||||
const pos = window.getPos();
|
|
||||||
|
|
||||||
// Option 1: convert a GLFW error into a Zig error.
|
|
||||||
glfw.getErrorCode() catch |err| {
|
|
||||||
std.log.err("failed to get window position: error={}", .{err});
|
|
||||||
return err; // Or fall back to an alternative implementation.
|
|
||||||
};
|
|
||||||
|
|
||||||
// Option 2: log a human-readable description of the error.
|
|
||||||
if (glfw.getErrorString()) |description| {
|
|
||||||
std.log.err("failed to get window position: {s}", .{description});
|
|
||||||
// ...
|
|
||||||
}
|
|
||||||
|
|
||||||
// Option 3: use a combination of the above approaches.
|
|
||||||
if (glfw.getError()) |err| {
|
|
||||||
const error_code = err.error_code; // Zig error
|
|
||||||
const description = err.description; // Human-readable description
|
|
||||||
std.log.err("failed to get window position: error={}: {s}", .{error_code, description});
|
|
||||||
// ...
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
Note that the above example relies on GLFW's saved error being empty; otherwise, previously emitted errors may be mistaken for an error caused by `window.getPos()`.
|
|
||||||
If your application frequently ignores errors, it may be necessary to call `glfw.clearError()` or `defer glfw.clearError()` to ensure a clean slate for future error handling.
|
|
||||||
|
|
||||||
## GLFW version
|
|
||||||
|
|
||||||
For now mach/glfw tracks the latest `master` revision of GLFW, as recorded [in this file](https://github.com/hexops-graveyard/glfw/blob/main/VERSION), as this version has critical undefined behavior fixes required for GLFW to work with Zig. We will switch to stable releases of GLFW once GLFW 3.4 is tagged.
|
|
||||||
|
|
||||||
## Join the community
|
## Join the community
|
||||||
|
|
||||||
Join the Mach engine community [on Discord](https://discord.gg/XNG3NZgCqp) to discuss this project, ask questions, get help, etc.
|
Join the [Mach community on Discord](https://discord.gg/XNG3NZgCqp) to discuss this project, ask questions, get help, etc.
|
||||||
|
|
||||||
## Issues
|
## Issues
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue