2020-01-23 21:04:46 +01:00
|
|
|
// Copyright (c) 2019-2020 Alexander Medvednikov. All rights reserved.
|
2019-08-02 11:33:49 +02:00
|
|
|
// Use of this source code is governed by an MIT license
|
|
|
|
// that can be found in the LICENSE file.
|
|
|
|
|
|
|
|
module glfw
|
|
|
|
|
2019-09-23 12:42:20 +02:00
|
|
|
// note: we might need special case for this
|
|
|
|
// see TmpGlImportHack below (joe-c)
|
2019-08-02 11:33:49 +02:00
|
|
|
import gl
|
|
|
|
|
2019-08-22 23:00:31 +02:00
|
|
|
#flag -I @VROOT/thirdparty/glfw
|
|
|
|
#flag -L @VROOT/thirdparty/glfw
|
2019-08-02 11:33:49 +02:00
|
|
|
|
|
|
|
// Debugging a custom build
|
|
|
|
//-#flag darwin -L/var/tmp/glfw/src/
|
|
|
|
|
|
|
|
// MacPorts
|
|
|
|
#flag darwin -L/opt/local/lib
|
|
|
|
|
|
|
|
#flag darwin -lglfw
|
2019-09-28 13:18:04 +02:00
|
|
|
#flag freebsd -I/usr/local/include
|
|
|
|
#flag freebsd -Wl,-L/usr/local/lib,-lglfw
|
2020-03-21 09:48:02 +01:00
|
|
|
|
|
|
|
#flag solaris -I/opt/local/include
|
|
|
|
#flag solaris -L/opt/local/lib
|
|
|
|
#flag solaris -lglfw
|
|
|
|
|
2019-08-02 11:33:49 +02:00
|
|
|
#flag linux -lglfw
|
2019-12-27 09:27:19 +01:00
|
|
|
#flag windows -lgdi32 -lshell32 -lglfw3
|
2020-03-12 18:20:19 +01:00
|
|
|
#flag mingw -mwindows
|
2019-08-02 11:33:49 +02:00
|
|
|
#include <GLFW/glfw3.h>
|
|
|
|
// #flag darwin -framework Carbon
|
|
|
|
// #flag darwin -framework Cocoa
|
|
|
|
// #flag darwin -framework CoreVideo
|
|
|
|
// #flag darwin -framework IOKit
|
2019-10-27 08:13:40 +01:00
|
|
|
pub const (
|
2019-08-02 11:33:49 +02:00
|
|
|
RESIZABLE = 1
|
|
|
|
DECORATED = 2
|
|
|
|
)
|
|
|
|
|
2019-10-27 08:13:40 +01:00
|
|
|
pub const (
|
2020-04-16 12:30:33 +02:00
|
|
|
key_escape = 256
|
2020-03-25 13:44:21 +01:00
|
|
|
key_space = 32
|
2020-04-16 12:30:33 +02:00
|
|
|
key_left_super = 343
|
2019-08-02 11:33:49 +02:00
|
|
|
|
2020-04-16 12:30:33 +02:00
|
|
|
key_up = 265
|
|
|
|
key_left = 263
|
|
|
|
key_right = 262
|
|
|
|
key_down = 264
|
2019-08-02 11:33:49 +02:00
|
|
|
)
|
|
|
|
|
2020-04-02 01:45:22 +02:00
|
|
|
fn C.glfwGetWindowUserPointer() voidptr
|
|
|
|
fn C.glfwGetPrimaryMonitor() voidptr
|
|
|
|
fn C.glfwSetWindowUserPointer()
|
|
|
|
fn C.glfwSetCursor()
|
|
|
|
fn C.glfwGetCursorPos()
|
|
|
|
fn C.glfwSetClipboardString()
|
|
|
|
fn C.glfwGetWindowContentScale()
|
|
|
|
fn C.glfwGetClipboardString()
|
|
|
|
fn C.glfwGetKey()
|
2020-04-02 02:02:12 +02:00
|
|
|
fn C.glfwGetTime() f64
|
2020-04-02 01:45:22 +02:00
|
|
|
fn C.glfwSetCharModsCallback()
|
|
|
|
fn C.glfwSetKeyCallback()
|
|
|
|
fn C.glfwPostEmptyEvent()
|
|
|
|
fn C.glfwSetScrollCallback()
|
|
|
|
fn C.glfwSetWindowSizeCallback()
|
|
|
|
fn C.glfwSetMouseButtonCallback()
|
|
|
|
fn C.glfwSetCursorPosCallback()
|
|
|
|
fn C.glfwSwapBuffers()
|
2020-04-04 12:56:31 +02:00
|
|
|
fn C.glfwWindowShouldClose() bool
|
2020-04-02 02:02:12 +02:00
|
|
|
fn C.glfwSetWindowShouldClose()
|
|
|
|
fn C.glfwWaitEvents()
|
|
|
|
fn C.glfwPollEvents()
|
|
|
|
fn C.glfwSwapInterval()
|
|
|
|
fn C.glfwMakeContextCurrent()
|
|
|
|
fn C.glfwSetWindowTitle()
|
|
|
|
fn C.glfwTerminate()
|
2020-04-16 11:37:59 +02:00
|
|
|
fn C.glfwCreateWindow(w int, h int, title charptr, m voidptr, sh voidptr) voidptr
|
2020-04-02 02:02:12 +02:00
|
|
|
fn C.glfwWindowHint()
|
|
|
|
fn C.glfwDestroyWindow()
|
|
|
|
fn C.glfwInit()
|
|
|
|
fn C.glGetIntegerv()
|
2020-04-02 01:45:22 +02:00
|
|
|
|
2019-09-23 12:42:20 +02:00
|
|
|
// joe-c: fix & remove
|
|
|
|
struct TmpGlImportHack {
|
|
|
|
hack gl.TmpGlImportHack
|
|
|
|
}
|
|
|
|
|
2019-10-24 13:35:11 +02:00
|
|
|
pub struct WinCfg {
|
2020-03-15 01:16:55 +01:00
|
|
|
width int
|
|
|
|
height int
|
|
|
|
title string
|
|
|
|
ptr voidptr
|
|
|
|
borderless bool
|
|
|
|
is_modal int
|
|
|
|
is_browser bool
|
|
|
|
url string
|
2019-08-22 23:00:31 +02:00
|
|
|
always_on_top bool
|
2020-03-15 01:16:55 +01:00
|
|
|
scale_to_monitor bool = true
|
2019-08-02 11:33:49 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// data *C.GLFWwindow
|
|
|
|
// TODO change data to cobj
|
2019-10-24 13:35:11 +02:00
|
|
|
pub struct Window {
|
2020-03-15 01:16:55 +01:00
|
|
|
data voidptr
|
|
|
|
title string
|
|
|
|
mx int
|
|
|
|
my int
|
2020-03-16 15:44:26 +01:00
|
|
|
scale_ f32
|
2019-08-02 11:33:49 +02:00
|
|
|
}
|
|
|
|
|
2019-10-27 19:23:33 +01:00
|
|
|
pub struct Size {
|
2019-08-02 11:33:49 +02:00
|
|
|
pub:
|
|
|
|
width int
|
|
|
|
height int
|
|
|
|
}
|
|
|
|
|
2019-10-27 19:23:33 +01:00
|
|
|
pub struct Pos {
|
2019-09-01 06:09:18 +02:00
|
|
|
pub:
|
2019-08-02 11:33:49 +02:00
|
|
|
x int
|
|
|
|
y int
|
|
|
|
}
|
|
|
|
|
|
|
|
// type clickpub fn pub fn (window * GLFWwindow, button, action, mods int)
|
|
|
|
type clickpubfn fn (window voidptr, button, action, mods int)
|
|
|
|
|
2019-11-20 05:10:19 +01:00
|
|
|
/*
|
|
|
|
* TODO broken
|
|
|
|
fn init() {
|
|
|
|
init_glfw()
|
|
|
|
}
|
|
|
|
*/
|
|
|
|
|
2019-10-12 05:03:15 +02:00
|
|
|
pub fn init_glfw() {
|
2019-08-02 11:33:49 +02:00
|
|
|
C.glfwInit()
|
2019-08-22 23:00:31 +02:00
|
|
|
C.glfwWindowHint(C.GLFW_CONTEXT_VERSION_MAJOR, 3)
|
|
|
|
C.glfwWindowHint(C.GLFW_CONTEXT_VERSION_MINOR, 3)
|
|
|
|
C.glfwWindowHint(C.GLFW_OPENGL_FORWARD_COMPAT, C.GL_TRUE)
|
|
|
|
C.glfwWindowHint(C.GLFW_OPENGL_PROFILE, C.GLFW_OPENGL_CORE_PROFILE)
|
2019-08-02 11:33:49 +02:00
|
|
|
}
|
|
|
|
|
2020-04-01 23:49:11 +02:00
|
|
|
pub fn (w &Window) destroy() {
|
2019-08-02 11:33:49 +02:00
|
|
|
C.glfwDestroyWindow(w.data)
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn terminate() {
|
|
|
|
C.glfwTerminate()
|
|
|
|
}
|
|
|
|
|
|
|
|
// pub fn mouse_move(w * GLFWwindow, x, y double) {
|
|
|
|
pub fn mouse_move(w voidptr, x, y f64) {
|
|
|
|
// #printf("%f : %f => %d \n", x,y);
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn window_hint(key, val int) {
|
|
|
|
C.glfwWindowHint(key, val)
|
|
|
|
}
|
|
|
|
|
2020-04-01 23:49:11 +02:00
|
|
|
pub fn create_window(c WinCfg) &Window {
|
2019-08-02 11:33:49 +02:00
|
|
|
if c.borderless {
|
2019-08-22 23:00:31 +02:00
|
|
|
window_hint(C.GLFW_RESIZABLE, 0)
|
|
|
|
window_hint(C.GLFW_DECORATED, 0)
|
2019-08-02 11:33:49 +02:00
|
|
|
}
|
|
|
|
if c.always_on_top {
|
2019-08-22 23:00:31 +02:00
|
|
|
window_hint(C.GLFW_FLOATING, 1)
|
|
|
|
}
|
2020-03-15 01:16:55 +01:00
|
|
|
if c.scale_to_monitor {
|
|
|
|
$if windows {
|
|
|
|
window_hint(C.GLFW_SCALE_TO_MONITOR, 1)
|
|
|
|
}
|
|
|
|
}
|
2019-08-02 11:33:49 +02:00
|
|
|
cwindow := C.glfwCreateWindow(c.width, c.height, c.title.str, 0, 0)
|
2019-08-22 23:00:31 +02:00
|
|
|
if isnil(cwindow) {
|
2019-09-08 14:54:07 +02:00
|
|
|
println('failed to create a glfw window, make sure you have a GPU driver installed')
|
2019-08-02 11:33:49 +02:00
|
|
|
C.glfwTerminate()
|
|
|
|
}
|
2020-03-03 14:41:26 +01:00
|
|
|
// println('create window wnd=$cwindow ptr==$c.ptr')
|
2019-08-02 11:33:49 +02:00
|
|
|
C.glfwSetWindowUserPointer(cwindow, c.ptr)
|
2020-03-16 15:44:26 +01:00
|
|
|
|
2020-03-25 13:44:21 +01:00
|
|
|
mut scale := f32(1.0)
|
2020-03-15 01:16:55 +01:00
|
|
|
$if windows {
|
2020-03-16 15:44:26 +01:00
|
|
|
C.glfwGetWindowContentScale(cwindow, &scale, &scale)
|
2020-03-15 01:16:55 +01:00
|
|
|
}
|
2020-03-25 13:44:21 +01:00
|
|
|
$else {
|
|
|
|
scale = 1.0
|
|
|
|
}
|
2020-03-15 01:16:55 +01:00
|
|
|
|
2020-04-01 23:49:11 +02:00
|
|
|
window := &Window {
|
2019-08-02 11:33:49 +02:00
|
|
|
data: cwindow,
|
|
|
|
title: c.title,
|
2020-03-16 15:44:26 +01:00
|
|
|
scale_: scale
|
2019-08-02 11:33:49 +02:00
|
|
|
}
|
|
|
|
return window
|
|
|
|
}
|
|
|
|
|
2020-04-01 23:49:11 +02:00
|
|
|
pub fn (w &Window) set_title(title string) {
|
2019-08-02 11:33:49 +02:00
|
|
|
C.glfwSetWindowTitle(w.data, title.str)
|
|
|
|
}
|
|
|
|
|
2020-04-01 23:49:11 +02:00
|
|
|
pub fn (w &Window) make_context_current() {
|
2019-08-02 11:33:49 +02:00
|
|
|
C.glfwMakeContextCurrent(w.data)
|
|
|
|
}
|
|
|
|
|
2020-04-01 23:49:11 +02:00
|
|
|
pub fn (w &Window) scale() f32 {
|
2020-03-16 15:44:26 +01:00
|
|
|
return w.scale_
|
2020-03-15 01:16:55 +01:00
|
|
|
}
|
|
|
|
|
2019-08-02 11:33:49 +02:00
|
|
|
pub fn swap_interval(interval int) {
|
|
|
|
C.glfwSwapInterval(interval)
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn wait_events() {
|
|
|
|
C.glfwWaitEvents()
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn poll_events() {
|
|
|
|
C.glfwPollEvents()
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn set_should_close(w voidptr, close bool) {
|
|
|
|
C.glfwSetWindowShouldClose(w, close)
|
|
|
|
}
|
|
|
|
|
2020-04-01 23:49:11 +02:00
|
|
|
pub fn (w &Window) set_should_close(close bool) {
|
2020-01-26 23:33:12 +01:00
|
|
|
C.glfwSetWindowShouldClose(w.data, close)
|
|
|
|
}
|
|
|
|
|
2020-04-01 23:49:11 +02:00
|
|
|
pub fn (w &Window) should_close() bool {
|
2019-08-02 11:33:49 +02:00
|
|
|
return C.glfwWindowShouldClose(w.data)
|
|
|
|
}
|
|
|
|
|
2020-04-01 23:49:11 +02:00
|
|
|
pub fn (w &Window) swap_buffers() {
|
2019-08-02 11:33:49 +02:00
|
|
|
C.glfwSwapBuffers(w.data)
|
|
|
|
}
|
|
|
|
|
2020-04-01 23:49:11 +02:00
|
|
|
pub fn (w mut Window) onmousemove(cb voidptr) {
|
2019-08-02 11:33:49 +02:00
|
|
|
C.glfwSetCursorPosCallback(w.data, cb)
|
|
|
|
}
|
|
|
|
|
2020-04-01 23:49:11 +02:00
|
|
|
pub fn (w mut Window) set_mouse_button_callback(cb voidptr) {
|
2019-08-02 11:33:49 +02:00
|
|
|
C.glfwSetMouseButtonCallback(w.data, cb)
|
|
|
|
}
|
|
|
|
|
2020-04-01 23:49:11 +02:00
|
|
|
pub fn (w mut Window) on_resize(cb voidptr) {
|
2020-02-04 05:40:16 +01:00
|
|
|
C.glfwSetWindowSizeCallback(w.data, cb)
|
|
|
|
}
|
|
|
|
|
2020-04-01 23:49:11 +02:00
|
|
|
pub fn (w mut Window) on_click(cb voidptr) {
|
2019-08-02 11:33:49 +02:00
|
|
|
C.glfwSetMouseButtonCallback(w.data, cb)
|
|
|
|
}
|
|
|
|
|
2020-04-01 23:49:11 +02:00
|
|
|
pub fn (w &Window) set_scroll_callback(cb voidptr) {
|
2019-08-02 11:33:49 +02:00
|
|
|
C.glfwSetScrollCallback(w.data, cb)
|
|
|
|
}
|
|
|
|
|
2020-04-01 23:49:11 +02:00
|
|
|
pub fn (w &Window) on_scroll(cb voidptr) {
|
2019-08-02 11:33:49 +02:00
|
|
|
C.glfwSetScrollCallback(w.data, cb)
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn post_empty_event() {
|
|
|
|
C.glfwPostEmptyEvent()
|
|
|
|
}
|
|
|
|
|
2020-04-01 23:49:11 +02:00
|
|
|
pub fn (w mut Window) onkeydown(cb voidptr) {
|
2019-08-02 11:33:49 +02:00
|
|
|
C.glfwSetKeyCallback(w.data, cb)
|
|
|
|
}
|
|
|
|
|
2020-04-01 23:49:11 +02:00
|
|
|
pub fn (w mut Window) onchar(cb voidptr) {
|
2019-08-02 11:33:49 +02:00
|
|
|
C.glfwSetCharModsCallback(w.data, cb)
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn get_time() f64 {
|
|
|
|
return C.glfwGetTime()
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn key_pressed(wnd voidptr, key int) bool {
|
2019-08-22 23:00:31 +02:00
|
|
|
return int(C.glfwGetKey(wnd, key)) == C.GLFW_PRESS
|
2019-08-02 11:33:49 +02:00
|
|
|
}
|
|
|
|
|
2020-04-01 23:49:11 +02:00
|
|
|
pub fn (w &Window) get_clipboard_text() string {
|
2019-08-02 11:33:49 +02:00
|
|
|
return string(byteptr(C.glfwGetClipboardString(w.data)))
|
|
|
|
}
|
|
|
|
|
2020-04-01 23:49:11 +02:00
|
|
|
pub fn (w &Window) set_clipboard_text(s string) {
|
2019-08-02 11:33:49 +02:00
|
|
|
C.glfwSetClipboardString(w.data, s.str)
|
|
|
|
}
|
|
|
|
|
2020-03-16 15:44:26 +01:00
|
|
|
pub fn get_cursor_pos(cwindow voidptr) (f64, f64) {
|
2020-01-09 12:00:39 +01:00
|
|
|
x := f64(0)
|
|
|
|
y := f64(0)
|
2020-03-16 15:44:26 +01:00
|
|
|
C.glfwGetCursorPos(cwindow, &x, &y)
|
2020-03-15 01:16:55 +01:00
|
|
|
|
2020-03-25 13:44:21 +01:00
|
|
|
mut scale := f32(1.0)
|
2020-03-16 15:44:26 +01:00
|
|
|
$if windows {
|
|
|
|
C.glfwGetWindowContentScale(cwindow, &scale, &scale)
|
|
|
|
}
|
2020-03-25 13:44:21 +01:00
|
|
|
$else {
|
|
|
|
scale = 1.0
|
|
|
|
}
|
2020-03-16 15:44:26 +01:00
|
|
|
return x/scale, y/scale
|
2020-01-09 12:00:39 +01:00
|
|
|
}
|
|
|
|
|
2020-04-01 23:49:11 +02:00
|
|
|
pub fn (w &Window) get_cursor_pos() Pos {
|
2019-08-02 11:33:49 +02:00
|
|
|
x := f64(0)
|
|
|
|
y := f64(0)
|
|
|
|
C.glfwGetCursorPos(w.data, &x, &y)
|
2020-03-15 01:16:55 +01:00
|
|
|
|
2019-08-02 11:33:49 +02:00
|
|
|
return Pos {
|
2020-03-16 15:44:26 +01:00
|
|
|
x: int(x/w.scale_)
|
|
|
|
y: int(y/w.scale_)
|
2019-08-02 11:33:49 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-01-09 12:00:39 +01:00
|
|
|
enum Cursor {
|
|
|
|
arrow
|
|
|
|
ibeam
|
|
|
|
hand
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn set_cursor(c Cursor) {
|
|
|
|
C.glfwSetCursor(0, C.GLFW_IBEAM_CURSOR)
|
|
|
|
}
|
|
|
|
|
2020-04-01 23:49:11 +02:00
|
|
|
pub fn (w &Window) set_cursor(c Cursor) {
|
2020-01-09 12:00:39 +01:00
|
|
|
C.glfwSetCursor(w.data, C.GLFW_IBEAM_CURSOR)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2020-04-01 23:49:11 +02:00
|
|
|
pub fn (w &Window) user_ptr() voidptr {
|
2019-08-02 11:33:49 +02:00
|
|
|
return C.glfwGetWindowUserPointer(w.data)
|
|
|
|
}
|
|
|
|
|
2020-04-01 23:49:11 +02:00
|
|
|
pub fn (w &Window) set_user_ptr(ptr voidptr) {
|
2019-08-02 11:33:49 +02:00
|
|
|
C.glfwSetWindowUserPointer(w.data, ptr)
|
|
|
|
}
|
|
|
|
|
2019-08-13 13:50:19 +02:00
|
|
|
struct C.GLFWvidmode {
|
|
|
|
width int
|
2019-08-22 23:00:31 +02:00
|
|
|
height int
|
|
|
|
}
|
2019-08-13 13:50:19 +02:00
|
|
|
|
2019-09-03 08:04:11 +02:00
|
|
|
pub fn C.glfwGetVideoMode() &C.GLFWvidmode
|
2019-08-02 11:33:49 +02:00
|
|
|
|
|
|
|
pub fn get_monitor_size() Size {
|
2019-08-13 13:50:19 +02:00
|
|
|
//# GLFWvidmode* mode = glfwGetVideoMode(glfwGetPrimaryMonitor());
|
2019-08-22 23:00:31 +02:00
|
|
|
mode := C.glfwGetVideoMode(C.glfwGetPrimaryMonitor())
|
|
|
|
return Size{mode.width, mode.height}
|
2019-08-02 11:33:49 +02:00
|
|
|
}
|
|
|
|
|
2020-04-01 23:49:11 +02:00
|
|
|
fn C.glfwGetWindowSize(window &Window, width &int, height &int) // screen coordinates
|
|
|
|
fn C.glfwGetFramebufferSize(window &Window, width &int, height &int) // pixels
|
2020-01-12 19:35:06 +01:00
|
|
|
|
|
|
|
// get_window_size in screen coordinates
|
2020-04-01 23:49:11 +02:00
|
|
|
pub fn (w &Window) get_window_size() Size {
|
2020-03-16 15:44:26 +01:00
|
|
|
res := Size {0, 0}
|
|
|
|
C.glfwGetWindowSize(w.data, &res.width, &res.height)
|
2020-01-12 19:35:06 +01:00
|
|
|
return res
|
|
|
|
}
|
|
|
|
|
|
|
|
// get_framebuffer_size in pixels
|
2020-04-01 23:49:11 +02:00
|
|
|
pub fn (w &Window) get_framebuffer_size() Size {
|
2020-03-16 15:44:26 +01:00
|
|
|
res := Size {0, 0}
|
|
|
|
C.glfwGetFramebufferSize(w.data, &res.width, &res.height)
|
2020-01-12 19:35:06 +01:00
|
|
|
return res
|
|
|
|
}
|
|
|
|
|
2019-08-02 11:33:49 +02:00
|
|
|
pub fn (size Size) str() string {
|
|
|
|
return '{$size.width, $size.height}'
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn get_window_user_pointer(gwnd voidptr) voidptr {
|
|
|
|
return C.glfwGetWindowUserPointer(gwnd)
|
|
|
|
}
|