zig-glfw/README.md

116 lines
5.1 KiB
Markdown
Raw Normal View History

# mach/glfw - Ziggified GLFW bindings [![CI](https://github.com/hexops/mach-glfw/workflows/CI/badge.svg)](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>
2021-07-10 01:11:39 -07:00
Ziggified GLFW bindings that [Mach engine](https://github.com/hexops/mach) uses, with 100% API coverage, zero-fuss installation, cross compilation, and more.
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!
## Zero fuss installation, cross compilation, and more
2021-10-24 05:50:56 -07:00
[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.
## 100% API coverage, 130+ tests, etc.
These bindings have 100% API coverage of GLFW v3.3.4. Every function, type, constant, etc. has been wrapped in a ziggified API.
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:
* Errors as [zig errors](https://ziglang.org/documentation/master/#Errors) instead of via a callback function.
* `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
In a `libs` subdirectory of the root of your project:
```sg
git clone https://github.com/hexops/mach-glfw
```
Then in your `build.zig` add:
```zig
const glfw = @import("libs/mach-glfw/build.zig");
pub fn build(b: *Builder) void {
...
exe.addPackagePath("glfw", "libs/mach-glfw/src/main.zig");
glfw.link(b, exe, .{});
}
```
Now in your code you may import and use GLFW:
```zig
const glfw = @import("glfw");
pub fn main() !void {
try glfw.init(.{});
defer glfw.terminate();
// Create our window
glfw: window hints rework (#71) * glfw: make comments into doc comments * glfw: Publicize Window.CursorPos, Window.Size, Window.Pos, and Window.FrameSize * glfw: Make enum value name the same format as other enum value names * glfw: Window hints rework patch * glfw: Relegate `Window.hint` to testing; move it down to just above the tests to reflect this, add doc comment line * glfw: handle error `Error.InvalidEnum` explicitly, for clear error message in this unlikely edge case * glfw: instate `Hint.context_no_error` as a hint, as it actually is specified to be a Window creation hint by the docs, and affirm removal of `Hint.context_revision`, which isn't. The docs don't seem to specify a default value for `Hints.context_no_error` to take on, so we could set it based on `std.debug.runtime_safety` like this. * glfw: default `context_no_error` to `false`, and added a note of caution about its usage as suggested. * glfw: Inline enum values of `ClientApi`, `ContextCreationApi`, `ContextRobustness`, `ContextReleaseBehavior`, and `OpenGlProfile` from consts.zig, and remove the now unused constants (replaced by aformentioned enum values). * glfw: Reference `Window.Hint` enum instead of `Window.Hints` struct to ensure fields are the same * glfw: add comment explaining default values of `Window.Hints` * glfw: change `OpenGlProfile` to `OpenGLProfile` based on established naming convention * glfw: Update actual declaration of `OpenGLProfile` * glfw: call `Window.defaultHints` after window creation, not before * glfw: remove 'consts.zig', and move `dont_care` directly into 'main.zig'; fix anything referencing it. * glfw: put `Window.defaultHints` into defer statement to handle cleanup in all paths * glfw: move `Hint.focused` to match position of `Hints.focused` * glfw: do 'zig fmt glfw/src' * glfw: Cull `Window.Hint` comments, polish remaining; match order entirely according to current GLFW docs * glfw: Change `Window.Hints.*Api` to `Window.Hints.*API` Co-authored-by: Stephen Gutekanst <stephen@hexops.com>
2021-11-16 02:41:16 +01:00
const window = try glfw.Window.create(640, 480, "Hello, mach-glfw!", null, null, .{});
defer window.destroy();
// Wait for the user to close the window.
while (!window.shouldClose()) {
2021-11-15 14:45:05 +03:30
try glfw.pollEvents();
}
}
```
## A warning about error handling
Unless the action you're performing is truly critical to your application continuing further, you should avoid using `try`.
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.
Instead of `try window.getPos()` for example, you may use:
```zig
const pos = window.getPos() catch |err| {
2021-11-04 05:13:39 +02:00
std.log.err("failed to get window position: error={}\n", .{err});
return;
2021-11-04 05:13:39 +02:00
};
```
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`
## Issues
Issues are tracked in the [main Mach repository](https://github.com/hexops/mach/issues?q=is%3Aissue+is%3Aopen+label%3Aglfw).
## Contributing
Contributions are very welcome, but pull requests must be sent to [the main repository](https://github.com/hexops/mach/tree/main/glfw) to avoid some complex merge conflicts we'd get by accepting contributions in both repositories. Once the changes are merged there, they'll get sync'd to this repository automatically.
We track the latest stable release of GLFW, if you need a newer version we can start a development branch / figure that out - just open an issue.