SwiftGLFW

一个 Swift 库,为 GLFW 添加了一个更具 Swift 风格的接口。到目前为止,它只在 macOS 上进行了测试,但它应该可以在 Windows 和 Linux 上轻松编译和运行。自 pull request #5 起,跨平台应该可以工作了。

这个软件包基于 CGLFW3,它只是纯粹的 C 绑定。

设置

将其添加到您的项目中对于 Swift Package 来说非常标准。

import PackageDescription

let package = Package(
    name: "GLFWSample",
    products: [
        .executable(name: "GLFW Sample", targets: ["GLFWSample"])
    ],
    dependencies: [
        .package(url: "https://github.com/thepotatoking55/SwiftGLFW.git", .upToNextMajor(from: "4.2.0"))
        ...
    ],
    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"),
                ...
            ]
        )
    ]
)

用法

文档

此仓库上有一个 正在进行的 GLFW 的 C 文档的改编版,应该有助于展示差异(或者如果您是 GLFW 的新手,可以作为介绍)。代码内文档也在开发中。

示例代码

GLFW 的 Hello Window 示例,只是以一种更符合 Swift 习惯用法的方式

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)
    }
}

错误处理

由于它们是 GLFW 的基础,GLFWSession.initializeGLFWWindow.init 都可以抛出错误。但是,如果您期望在其他地方出现潜在错误,您也可以调用

try GLFWSession.checkForError()

或者,您可以分配一个错误处理程序,以便在错误出现时立即捕获它们

GLFWSession.onReceiveError = { error in
    /* do something with it here */
}

总结

与 Swift 一样,此软件包的设计考虑了可读性和强大的类型检查。变量使用枚举等表示,而不是传递 Int32OpaquePointer

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)

等同于这个

#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);