A Swift library that adds a more Swift-like interface to GLFW. As of pull request #5, cross-platform should be working now.
This package is based on CGLFW3, which is just the pure C bindings.
Me, kaixoo, am only maintaining this because the original maintainer, thepotatoking55, stopped maintaining the package.
In MacOS, this package could have some issues because originally we were setting a flag that disabled the use of Automatic Reference Counting, but since SwiftPM prohibts the use of .unsafeFlags to packages, we cannot set it.
I'm a linux Swift lover!
Adding this to your project is pretty standard for a Swift Package.
import PackageDescription
let package = Package(
name: "GLFWSample",
products: [
.executable(name: "GLFW Sample", targets: ["GLFWSample"])
],
dependencies: [
.package(url: "https://github.com/kaixoo12/SwiftGLFW.git", .from: "4.3.1")
...
],
targets: [
.executableTarget(
name: "GLFWSample",
// Silence deprecation warnings on Apple platforms if you're using OpenGL
cSettings: [
.define("GL_SILENCE_DEPRECATION",
.when(platforms: [.macOS])),
.define("GLES_SILENCE_DEPRECATION",
.when(platforms: [.iOS, .tvOS])),
],
dependencies: [
.product(name: "SwiftGLFW", package: "SwiftGLFW"),
...
]
)
]
)There's a work in progress adaptation of GLFW's C documentation on this repo, which should help show the differences (or serve as an introduction if you're new to GLFW). In-code documentation is also being worked on.
GLFW's Hello Window example, except in a much more Swift-idiomatic way:
import GLFW
import OpenGL // Or whatever other library you use
@MainActor
func main() {
do {
try GLFWSession.initialize()
/* macOS's OpenGL implementation requires some extra tweaking */
GLFWWindow.hints.contextVersion = (4, 1)
GLFWWindow.hints.openGLProfile = .core
GLFWWindow.hints.openGLCompatibility = .forward
/* Create a windowed mode window and its OpenGL context */
let window = try GLFWWindow(width: 640, height: 480, title: "Hello World")
/* Make the window's context current */
window.context.makeCurrent()
/* Loop until the user closes the window */
while !window.shouldClose {
/* Render here */
glClear(GLbitfield(GL_COLOR_BUFFER_BIT))
someRenderFunctionDefinedElsewhere()
/* Swap front and back buffers */
window.swapBuffers()
/* Poll for and process events */
GLFWSession.pollInputEvents()
}
} catch let error as GLFWError {
print(error.description ?? "Unknown error")
} catch {
print(error)
}
}Since they're fundamental to GLFW, GLFWSession.initialize and GLFWWindow.init can both throw errors. However, if you're expecting potential errors in other places, you can also call
try GLFWSession.checkForError()Or, you can assign an error handler to catch them as soon as they come up:
GLFWSession.onReceiveError = { error in
/* do something with it here */
}Like Swift, this package is built with readability and strong type-checking in mind. Rather than passing Int32s and OpaquePointers around, variables are represented with enums and so on.
import GLFW
try! GLFWSession.initialize()
guard let window = try? GLFWWindow(width: 640, height: 480, title: "Hello World") else {
GLFWSession.terminate()
return
}
window.resizable = false
window.maximize()
window.mouse.useRawMotionInput = true
window.mouse.cursorMode = .disabled
window.scrollInputHandler = { window, x, y in
...
}
let monitor = GLFWMonitor.primary
monitor.setGamma(1.0)Is equivalent to this:
#include <GLFW/glfw3.h>
GLFWwindow* window;
if !(glfwInit()) {
return -1;
}
window = glfwCreateWindow(640, 480, "Hello World", NULL, NULL);
if !(window) {
glfwTerminate();
return -1;
}
glfwSetWindowAttrib(window, GLFW_RESIZABLE, GLFW_FALSE);
glfwMaximizeWindow(window);
if (glfwRawMouseMotionSupported())
glfwSetInputMode(window, GLFW_RAW_MOUSE_MOTION, GLFW_TRUE);
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
void scroll_callback(GLFWwindow* window, double xoffset, double yoffset) {
...
}
glfwSetScrollCallback(window, scroll_callback);
GLFWmonitor* monitor = glfwGetPrimaryMonitor();
glfwSetGamma(monitor, 1.0);