diff --git a/cl-glfw3-examples.asd b/cl-glfw3-examples.asd index 0795e73..ff2dd18 100644 --- a/cl-glfw3-examples.asd +++ b/cl-glfw3-examples.asd @@ -11,4 +11,5 @@ (:file "basic-window") (:file "fragment-shader") (:file "particles-basic") - (:file "events"))) + (:file "events") + (:file "icons"))) diff --git a/cl-glfw3.lisp b/cl-glfw3.lisp index de0a800..17e5245 100644 --- a/cl-glfw3.lisp +++ b/cl-glfw3.lisp @@ -18,15 +18,18 @@ set-error-callback initialize with-init + get-monitor-work-area def-monitor-callback *window* + window-hint create-window destroy-window - with-window + with-windows with-init-window window-should-close-p set-window-should-close set-window-title + set-window-icon get-window-opacity set-window-opacity get-window-position @@ -35,15 +38,20 @@ set-window-size set-window-size-limits set-window-aspect-ratio + get-window-frame-size set-window-monitor get-window-content-scale get-framebuffer-size iconify-window restore-window + maximize-window show-window hide-window +focus-window + request-window-attention get-window-monitor get-window-attribute + set-window-attribute get-context-version def-window-position-callback def-window-size-callback @@ -51,32 +59,43 @@ def-window-refresh-callback def-window-focus-callback def-window-iconify-callback +def-window-maximize-callback def-framebuffer-size-callback +def-window-content-scale-callback set-window-position-callback set-window-size-callback set-window-close-callback set-window-refresh-callback set-window-focus-callback set-window-iconify-callback +set-window-maximize-callback set-framebuffer-size-callback +set-window-content-scale-callback get-input-mode set-input-mode get-key get-mouse-button get-cursor-position set-cursor-position +create-cursor +set-cursor def-key-callback def-char-callback +def-char-mods-callback def-mouse-button-callback def-cursor-pos-callback def-cursor-enter-callback def-scroll-callback + def-drop-callback set-key-callback set-char-callback +set-char-mods-callback set-mouse-button-callback set-cursor-position-callback set-cursor-enter-callback set-scroll-callback + set-drop-callback +def-joystick-callback set-clipboard-string get-clipboard-string make-context-current @@ -89,6 +108,78 @@ (when (/= major 3) (error "Local GLFW is ~a.~a.~a, should be above 3.x" major minor rev))) +(defmacro with-image-pointer ((&rest bind*) &body body) + "Internal function" + (let ((gensym-pixels-vars (mapcar (lambda (x) + (gensym (format nil "~a" x))) + (mapcar #'first bind*)));マクロ中で使う変数sをリストにまとめて保管 + (img-binding-list (gensym "IMG-BINDING-LIST")));画像の評価を束縛する変数 + ;;画像の評価を1度だけにするため,letで束縛。上は束縛するための変数sをリストで保存している + `(let ((,img-binding-list (list ,@(mapcar (lambda (x) + (cadr x)) + bind*)))) + (mapc (lambda (img) + (assert (typep img '(simple-array (unsigned-byte 8) (* * 4))))) + ,img-binding-list) + ;;画像のピクセルデータの大きさの配列をallocしてgensym変数sに束縛 + (destructuring-bind ,gensym-pixels-vars + (mapcar (lambda (img-array) + (cffi:foreign-alloc :unsigned-char :count (array-total-size img-array))) + ,img-binding-list) + (unwind-protect + (progn + ;;画像のピクセルデータの中身を詰める + (mapc (lambda (img-array pixel-array-ptr) + (let ((height (array-dimension img-array 0)) + (width (array-dimension img-array 1))) + (loop for i from 0 below width do + (loop for j from 0 below height do + (loop for k from 0 below (array-dimension img-array 2) do + (setf (cffi:mem-ref pixel-array-ptr :unsigned-char (+ k (* i 4) + (* j (* width 4)))) + (aref img-array j i k))))))) + ,img-binding-list + (list ,@gensym-pixels-vars)) + ;;画像ストラクチャをallocしてbind*で示された変数に束縛 + (destructuring-bind ,(mapcar #'first bind*) + (loop for i from 0 below ,(length bind*) collect (cffi:foreign-alloc :int :count 3)) + (unwind-protect + (progn + ;;画像ストラクチャに中身を詰める + (mapc (lambda (img-structure-ptr image-array pixel-array-ptr) + (setf (cffi:mem-ref img-structure-ptr :int) (array-dimension image-array 1);width + (cffi:mem-ref img-structure-ptr :int 4) (array-dimension image-array 0);height + (cffi:mem-ref img-structure-ptr :pointer 8) pixel-array-ptr)) + (list ,@(mapcar #'first bind*)) + ,img-binding-list + (list ,@gensym-pixels-vars)) + ,@body) + (mapc #'cffi:foreign-free (list ,@(mapcar #'first bind*)))))) + (mapc #'cffi:foreign-free (list ,@gensym-pixels-vars))))))) + +#| +(defmacro with-image-pointer ((var image) &body body) + "Internal function" + ;;マクロの準備 + (alexandria:with-gensyms (width height pixels image-ptr) + (alexandria:once-only (image) + `(let ((,width (image-width ,image)) + (,height (image-height ,image))) + ;;ポインタを取得し中身をalloc + (cffi:with-foreign-pointer (,image-ptr ,(* 2 3));int*2+pointer=int*3=2*3 bytes + ;;中身を詰める + (cffi:with-foreign-pointer (,pixels (* 1 ,width ,height 4));4=rgba + (loop for i from 0 below (* ,width ,height 4) do + (setf (cffi:mem-ref ,pixels :uchar i) + (aref (image-pixels ,image) i))) + (setf (cffi:mem-ref ,image-ptr :int) ,width + (cffi:mem-ref ,image-ptr :int 4) ,height + (cffi:mem-ref ,image-ptr :pointer 8) ,pixels) + ;;ポインタを変数に束縛しbody展開 + (let ((,var ,image-ptr)) + ,@body))))))) +|# + ;;;; ## Window and monitor functions (defmacro import-export (&rest symbols) `(eval-when (:compile-toplevel :load-toplevel :execute) @@ -108,42 +199,169 @@ (defun set-error-callback (callback-name) (%glfw:set-error-callback (cffi:get-callback callback-name))) -(defun initialize () +(defun initialize (&key (joystick-hat-buttons t) + (cocoa-chdid-resources t) + (cocoa-menubar t)) "Start GLFW" + (%glfw:init-hint :joystick-hat-buttons joystick-hat-buttons) + (%glfw:init-hint :cocoa-chdid-resources cocoa-chdid-resources) + (%glfw:init-hint :cocoa-menubar cocoa-menubar) (let ((result (%glfw:init))) (unless result (error "Error initializing glfw.")) result)) -(defmacro with-init (&body body) +(defmacro with-init ((&rest init-keys) &body body) "Wrap BODY with an initialized GLFW instance, ensuring proper termination. If no error callback is set when this is called, a default error callback is set." `(progn (let ((prev-error-fun (set-error-callback 'default-error-fun))) (unless (cffi:null-pointer-p prev-error-fun) (%glfw:set-error-callback prev-error-fun))) - (initialize) + (initialize ,@init-keys) (unwind-protect (progn ,@body) (%glfw:terminate)))) -(import-export %glfw:get-monitors %glfw:get-primary-monitor %glfw:get-monitor-position %glfw:get-monitor-work-area %glfw:get-monitor-physical-size %glfw:get-monitor-content-scale %glfw:get-monitor-name %glfw:set-monitor-callback %glfw:get-video-modes %glfw:get-video-mode %glfw:set-gamma %glfw:get-gamma-ramp %glfw:set-gamma-ramp %glfw:terminate) +(import-export %glfw:default-window-hints %glfw:get-monitors %glfw:get-primary-monitor %glfw:get-monitor-position + %glfw:get-monitor-workarea %glfw:get-monitor-physical-size %glfw:get-monitor-content-scale + %glfw:get-monitor-name %glfw:set-monitor-callback %glfw:get-video-modes %glfw:get-video-mode + %glfw:set-gamma %glfw:get-gamma-ramp %glfw:set-gamma-ramp %glfw:terminate) + +(defun get-monitor-work-area (monitor) + "Inconsistent name of get-monitor-workarea. old-version used this name" + (warn "get-monitor-work-area is inconsistent name of foreign function.~% get-monitor-workarea is recommended") + (%glfw:get-monitor-workarea monitor)) (defmacro def-monitor-callback (name (monitor event) &body body) `(%glfw:define-glfw-callback ,name - ((,monitor :pointer) (,event %glfw::monitor-event)) + ((,monitor :pointer) (,event %glfw::connection-event)) ,@body)) (defvar *window* nil "The window that is currently the default for this library. Can be set through MAKE-CONTEXT-CURRENT.") +(deftype window-hint-boolean-input () + '(member :resizable :visible :decorated :focused :auto-iconify :floating :maximized + :center-cursor :transparent-framebuffer focus-on-show scale-to-monitor + :stereo :srgb-capable :double-buffer :opengl-forward-compat :opengl-debug-context + :cocoa-retina-framebuffer :graphics-switching)) +(deftype window-hint-integer-input () + '(member :red-bits :green-bits :blue-bits :alpha-bits :depth-bits :stencil-bits + :accum-red-bits :accum-green-bits :accum-blue-bits :accum-alpha-bits + :aux-buffers :samples :refresh-rate)) +(deftype window-hint-string-input () + '(member :cocoa-frame-name :x11-class-name :x11-instance-name)) +(deftype window-hint-other-input () + '(member :context-version-major :context-version-minor + :client-api + :context-creation-api + :context-robustness + :context-release-behavior + :opengl-profile)) + +(defun window-hint-default (target) + (ecase target + ((:resizable :visible :decorated :focused :auto-iconify :center-cursor :focus-on-show + :doublebuffer :cocoa-retina-framebuffer) t) + ((:floating :maximized :transparent-framebuffer :scale-to-monitor :stereo :srgb-capable + :opengl-forward-compat :opengl-debug-context :cocoa-graphics-switching) nil) + ((:red-bits :green-bits :blue-bits :alpha-bits :stencil-bits) 8) + (:depth-bits 24) + ((:accum-red-bits :accum-green-bits :accum-blue-bits :accum-alpha-bits :aux-buffers + :samples :context-version-minor) 0) + ((:refresh-rate) :dont-care) + (:client-api :opengl-api) + (:context-creation-api :native-context-api) + (:context-version-major 1) + (:context-robustness :no-robustness) + (:context-release-behavior :any-release-behavior) + (:opengl-profile :opengl-any-profile) + ((:cocoa-frame-name :x11-class-name :x11-instance-name) ""))) + +(defun window-hint (target value) + (when (eq value :default) (setf value (window-hint-default target))) + (typecase target + (window-hint-boolean-input + (%glfw:window-hint target + (cffi:convert-to-foreign (the boolean value) + :boolean))) + (window-hint-integer-input + (%glfw:window-hint target + (if (eq :dont-care value) + (cffi:convert-to-foreign -1 + :int) + (cffi:convert-to-foreign (the (integer 0) value) + :int)))) + (window-hint-string-input + (%glfw:window-hint-string target + (cffi:convert-to-foreign (the string value) + :string))) + (window-hint-other-input + (%glfw:window-hint target + (cffi:convert-to-foreign value + (case (the window-hint-other-input target) + (:client-api '%glfw::opengl-api) + (:context-creation-api '%glfw::context-creation) + (:context-robustness '%glfw::robustness) + (:context-release-behavior '%glfw::release-behavior) + (:opengl-profile '%glfw::opengl-profile) + ((:context-version-major :context-version-minor) :int))))) + (t (error "~a is not supported for window hint." target))) + value) + +(defmacro create-window (&rest init-bindings + &key (width 0) (height 0) (title "") + (monitor (cffi:null-pointer)) (shared (cffi:null-pointer)) + resizable visible decorated focused auto-iconify floating + maximized center-cursor transparent-framebuffer focus-on-show scale-to-monitor + red-bits green-bits blue-bits alpha-bits depth-bits stencil-bits + accum-red-bits accum-green-bits accum-blue-bits accum-alpha-bits aux-buffers + samples refresh-rate stereo srgb-capable doublebuffer client-api + context-creation-api context-version-major context-version-minor + context-robustness context-release-behavior opengl-forward-compat + opengl-debug-context opengl-profile + cocoa-retina-framebuffer cocoa-frame-name cocoa-graphics-switching + x11-class-name x11-instance-name) + (declare (ignorable + monitor shared + resizable visible decorated focused auto-iconify floating + maximized center-cursor transparent-framebuffer focus-on-show scale-to-monitor + red-bits green-bits blue-bits alpha-bits depth-bits stencil-bits + accum-red-bits accum-green-bits accum-blue-bits accum-alpha-bits aux-buffers + samples refresh-rate stereo srgb-capable doublebuffer client-api + context-creation-api context-version-major context-version-minor + context-robustness context-release-behavior opengl-forward-compat + opengl-debug-context opengl-profile + cocoa-retina-framebuffer cocoa-frame-name cocoa-graphics-switching + x11-class-name x11-instance-name)) + `(progn + ,@(loop :for (target value) :on init-bindings :by #'cddr + :unless (member target '(:width :height :title :monitor :shared)) + :collect `(window-hint ,(intern (string-upcase (symbol-name target)) :keyword) + ,value)) + (let ((win (%glfw:create-window ,width ,height ,title + ,monitor ,shared))) + (when (cffi:null-pointer-p win) + (error "Error: Can't create window.")) + win))) + +#| (defun create-window (&key (width 0) (height 0) - title + (title "") (monitor (cffi:null-pointer)) (shared (cffi:null-pointer)) ;; Hints (resizable t) (visible t) (decorated t) + (focused t) + (auto-iconify t) + (floating nil) + (maximized nil) + (center-cursor t) + (transparent-framebuffer nil) + (focus-on-show t) + (scale-to-monitor nil) (red-bits 8) (green-bits 8) (blue-bits 8) (alpha-bits 8) (depth-bits 24) (stencil-bits 8) (accum-red-bits 0) (accum-green-bits 0) (accum-blue-bits 0) @@ -153,56 +371,89 @@ (refresh-rate 0) (stereo nil) (srgb-capable nil) + (doublebuffer t) (client-api :opengl-api) + (context-creation-api :native-context-api) (context-version-major 1) (context-version-minor 0) (context-robustness :no-robustness) + (context-release-behavior :any-release-behavior) (opengl-forward-compat nil) (opengl-debug-context nil) - (opengl-profile :opengl-any-profile)) + (opengl-profile :opengl-any-profile) + (cocoa-retina-framebuffer t) + (cocoa-frame-name "") + (cocoa-graphics-switching nil) + (x11-class-name "") + (x11-instance-name "") + ) "This function handles all window hints. MONITOR: The monitor on which the window should be full-screen. SHARED: The window whose context to share resources with." (macrolet ((output-hints (&rest hints) - `(progn - ,@(loop for (name type) in hints collect - `(%glfw:window-hint - ,(intern (string-upcase - (symbol-name name)) :keyword) - (cffi:convert-to-foreign ,name ,type)))))) - (output-hints - (resizable :boolean) - (visible :boolean) - (decorated :boolean) - (red-bits :int) (green-bits :int) (blue-bits :int) (alpha-bits :int) - (depth-bits :int) (stencil-bits :int) - (accum-red-bits :int) (accum-green-bits :int) (accum-blue-bits :int) - (accum-alpha-bits :int) - (aux-buffers :int) - (samples :int) - (refresh-rate :int) - (stereo :boolean) - (srgb-capable :boolean) - (client-api '%glfw::opengl-api) - (context-version-major :int) - (context-version-minor :int) - (context-robustness '%glfw::robustness) - (opengl-forward-compat :boolean) - (opengl-debug-context :boolean) - (opengl-profile '%glfw::opengl-profile))) + (flet ((stringhint-p (hintname) + (member hintname '(cocoa-frame-name x11-class-name x11-instance-name)))) + `(progn + ,@(loop for (name type) in hints collect + `(,(if (stringhint-p (intern (string-upcase + (symbol-name name)))) + '%glfw:window-hint-string + '%glfw:window-hint) + ,(intern (string-upcase + (symbol-name name)) :keyword) + (cffi:convert-to-foreign ,name ,type))))))) + (output-hints + (resizable :boolean) + (visible :boolean) + (decorated :boolean) + (focused :boolean) + (auto-iconify :boolean) + (floating :boolean) + (maximized :boolean) + (center-cursor :boolean) + (transparent-framebuffer :boolean) + (focus-on-show :boolean) + (scale-to-monitor :boolean) + (red-bits :int) (green-bits :int) (blue-bits :int) (alpha-bits :int) + (depth-bits :int) (stencil-bits :int) + (accum-red-bits :int) (accum-green-bits :int) (accum-blue-bits :int) + (accum-alpha-bits :int) + (aux-buffers :int) + (samples :int) + (refresh-rate :int) + (stereo :boolean) + (srgb-capable :boolean) + (doublebuffer :boolean) + (client-api '%glfw::opengl-api) + (context-creation-api '%glfw::context-creation) + (context-version-major :int) + (context-version-minor :int) + (context-robustness '%glfw::robustness) + (context-release-behavior '%glfw::release-behavior) + (opengl-forward-compat :boolean) + (opengl-debug-context :boolean) + (opengl-profile '%glfw::opengl-profile) + (cocoa-retina-framebuffer :boolean) + (cocoa-frame-name :string) + (cocoa-graphics-switching :boolean) + (x11-class-name :string) + (x11-instance-name :string) + )) (let ((window (%glfw:create-window width height title monitor shared))) (if (cffi:null-pointer-p window) - (error "Error creating window.") - (if (eq client-api :no-api) + (error "Error creating window.") + (if (eq client-api :no-api) (setf *window* window) (make-context-current window))))) +|# (defun destroy-window (&optional (window *window*)) (when window (%glfw:destroy-window window)) (when (eq window *window*) (setf *window* nil))) +#| (defmacro with-window ((&rest window-keys) &body body) "Convenience macro for using windows." `(unwind-protect @@ -210,11 +461,25 @@ SHARED: The window whose context to share resources with." (create-window ,@window-keys) ,@body) (destroy-window))) +|# + +(defmacro with-windows ((&rest bindings) &body body) + "make windows (with-windows ((w0 ~~hints~~) (w1 ~~hints~~)) body)" + `(destructuring-bind ,(mapcar #'first bindings) + (list ,@(mapcar (lambda (bind) + `(create-window ,@bind)) + (mapcar #'cdr bindings))) + (unwind-protect + (progn ,@body) + (progn ,@(mapcar (lambda (window) + `(destroy-window ,window)) + (mapcar #'car bindings)))))) + (defmacro with-init-window ((&rest window-keys) &body body) "Convenience macro for setting up GLFW and opening a window." - `(with-init - (with-window ,window-keys ,@body))) + `(with-init () + (with-windows ((*window* ,@window-keys)) ,@body))) (defun window-should-close-p (&optional (window *window*)) (%glfw:window-should-close-p window)) @@ -249,6 +514,9 @@ SHARED: The window whose context to share resources with." (defun set-window-aspect-ratio (width height &optional (window *window*)) (%glfw:set-window-aspect-ratio window width height)) +(defun get-window-frame-size (&optional (window *window*)) + (%glfw:get-window-frame-size window)) + (defun get-window-content-scale (&optional (window *window*)) (%glfw:get-window-content-scale window)) @@ -264,15 +532,29 @@ SHARED: The window whose context to share resources with." (defun iconify-window (&optional (window *window*)) (%glfw:iconify-window window)) +(defun set-window-icon (image &optional (window *window*)) + (cond ((null image) (%glfw:set-window-icon window 0 (cffi:null-pointer))) + (t (with-image-pointer ((pointer image)) + (%glfw:set-window-icon window 1 pointer))))) + (defun restore-window (&optional (window *window*)) (%glfw:restore-window window)) +(defun maximize-window (&optional (window *window*)) + (%glfw:maximize-window window)) + (defun show-window (&optional (window *window*)) (%glfw:show-window window)) (defun hide-window (&optional (window *window*)) (%glfw:hide-window window)) +(defun focus-window (&optional (window *window*)) + (%glfw:focus-window window)) + +(defun request-window-attention (&optional (window *window*)) + (%glfw:request-window-attention window)) + (defun get-window-monitor (&optional (window *window*)) (let ((monitor (%glfw:get-window-monitor window))) (unless (cffi:null-pointer-p monitor) @@ -281,13 +563,18 @@ SHARED: The window whose context to share resources with." (defun get-window-attribute (attribute &optional (window *window*)) (let ((value (%glfw:get-window-attribute window attribute))) (ccase attribute - ((:focused :iconified :resizable :visible :decorated :opengl-forward-compat :opengl-debug-context) + ((:focused :iconified :maximized :hovered :visible :resizable :decorated :auto-iconify :floating :transparent-framebuffer :focus-on-show :opengl-forward-compat :opengl-debug-context :context-no-error) (cffi:convert-from-foreign value :boolean)) (:client-api (cffi:foreign-enum-keyword '%glfw::opengl-api value)) + (:context-creation-api (cffi:foreign-enum-keyword '%glfw::context-creation value)) ((:context-version-major :context-version-minor :context-revision) value) (:opengl-profile (cffi:foreign-enum-keyword '%glfw::opengl-profile value)) + (:context-release-behavior (cffi:foreign-enum-keyword '%glfw::release-behavior value)) (:context-robustness (cffi:foreign-enum-keyword '%glfw::robustness value))))) +(defun set-window-attribute (attribute value &optional (window *window*)) + (%glfw:set-window-attribute window attribute value)) + (defun get-context-version (&optional (window *window*)) "Convenience function returning (opengl-context-major-version opengl-context-minor-version opengl-context-revision)." (list (get-window-attribute :context-version-major window) @@ -324,11 +611,21 @@ SHARED: The window whose context to share resources with." ((,window :pointer) (,iconifiedp :boolean)) ,@body)) +(defmacro def-window-maximize-callback (name (window maximizedp) &body body) + `(%glfw:define-glfw-callback ,name + ((,window :pointer) (,maximizedp :boolean)) + ,@body)) + (defmacro def-framebuffer-size-callback (name (window w h) &body body) `(%glfw:define-glfw-callback ,name ((,window :pointer) (,w :int) (,h :int)) ,@body)) +(defmacro def-window-content-scale-callback (name (window xscale yscale) &body body) + `(%glfw:define-glfw-callback ,name + ((,window :pointer) (,xscale :float) (,yscale ,:float)) + ,@body)) + (defun set-window-position-callback (callback-name &optional (window *window*)) (%glfw:set-window-position-callback window (cffi:get-callback callback-name))) @@ -347,11 +644,17 @@ SHARED: The window whose context to share resources with." (defun set-window-iconify-callback (callback-name &optional (window *window*)) (%glfw:set-window-iconify-callback window (cffi:get-callback callback-name))) +(defun set-window-maximize-callback (callback-name &optional (window *window*)) + (%glfw:set-window-maximize-callback window (cffi:get-callback callback-name))) + (defun set-framebuffer-size-callback (callback-name &optional (window *window*)) (%glfw:set-framebuffer-size-callback window (cffi:get-callback callback-name))) +(defun set-window-content-scale-callback (callback-name &optional (window *window*)) + (%glfw:set-window-content-scale-callback window (cffi:get-callback callback-name))) + ;;;; ## Events and input -(import-export %glfw:poll-events %glfw:wait-events %glfw:post-empty-event) +(import-export %glfw:poll-events %glfw:wait-events %glfw:wait-events-timeout %glfw:post-empty-event) (defun get-input-mode (mode &optional (window *window*)) "Mode is one of :CURSOR :STICKY-KEYS or :STICKY-MOUSE-BUTTONS." @@ -382,6 +685,15 @@ SHARED: The window whose context to share resources with." (defun set-cursor-position (x y &optional (window *window*)) (%glfw:set-cursor-position window x y)) +(defun create-cursor (image xhot yhot) + (with-image-pointer ((pointer image)) (%glfw:create-cursor pointer xhot yhot))) + +(defun set-cursor (cursor &optional (window *window*)) + (%glfw:set-cursor window + (if (null cursor) + (cffi:null-pointer) + cursor))) + (defmacro def-key-callback (name (window key scancode action mod-keys) &body body) `(%glfw:define-glfw-callback ,name ((,window :pointer) (,key %glfw::key) (,scancode :int) @@ -395,6 +707,13 @@ SHARED: The window whose context to share resources with." (let ((,char (code-char ,char-code))) ,@body)))) +(defmacro def-char-mods-callback (name (window char mod-keys) &body body) + (let ((char-code (gensym "char"))) + `(%glfw:define-glfw-callback ,name + ((,window :pointer) (,char-code :unsigned-int) (,mod-keys %glfw::mod-keys)) + (let ((,char (code-char ,char-code))) + ,@body)))) + (defmacro def-mouse-button-callback (name (window button action mod-keys) &body body) `(%glfw:define-glfw-callback ,name ((,window :pointer) (,button %glfw::mouse) @@ -416,12 +735,26 @@ SHARED: The window whose context to share resources with." ((,window :pointer) (,x :double) (,y :double)) ,@body)) +;;must: support function +(defmacro def-drop-callback (name (window number-of-pathes pathes) &body body) + `(%glfw::define-glfw-drop-callback ,name + ((,window :pointer) (,number-of-pathes :int) (,pathes (:pointer :string))) + ,@body)) + +(defmacro def-joystick-callback (name (joystick event) &body body) + `(%glfw:define-glfw-callback ,name + ((,joystick int) (,event %glfw::connection-event)) + ,@body)) + (defun set-key-callback (callback-name &optional (window *window*)) (%glfw:set-key-callback window (cffi:get-callback callback-name))) (defun set-char-callback (callback-name &optional (window *window*)) (%glfw:set-char-callback window (cffi:get-callback callback-name))) +(defun set-char-mods-callback (callback-name &optional (window *window*)) + (%glfw:set-char-mods-callback window (cffi:get-callback callback-name))) + (defun set-mouse-button-callback (callback-name &optional (window *window*)) (%glfw:set-mouse-button-callback window (cffi:get-callback callback-name))) @@ -434,7 +767,16 @@ SHARED: The window whose context to share resources with." (defun set-scroll-callback (callback-name &optional (window *window*)) (%glfw:set-scroll-callback window (cffi:get-callback callback-name))) -(import-export %glfw:joystick-present-p %glfw:get-joystick-axes %glfw:get-joystick-buttons %glfw:get-joystick-name) +(defun set-drop-callback (callback-name &optional (window *window*)) + (%glfw:set-drop-callback window (cffi:get-callback callback-name))) + +(import-export %glfw:raw-mouse-motion-supported-p %glfw:get-key-name %glfw:get-key-scancode %glfw:destroy-cursor + %glfw:create-standard-cursor + %glfw:joystick-present-p %glfw:get-joystick-axes %glfw:get-joystick-buttons %glfw:get-joystick-hats + %glfw:get-joystick-name %glfw:get-joystick-guid %glfw:joystick-is-gamepad-p %glfw:update-gamepad-mappings + %glfw:get-gamepad-name %glfw:get-gamepad-state %glfw:get-timer-value %glfw:get-timer-frequency) + +(deftype joystick-id () '(integer 0 15)) ;;;; ## Clipboard diff --git a/examples/basic-window.lisp b/examples/basic-window.lisp index db35717..0aeee60 100644 --- a/examples/basic-window.lisp +++ b/examples/basic-window.lisp @@ -4,18 +4,18 @@ (export '(basic-window-example)) -(def-key-callback quit-on-escape (window key scancode action mod-keys) +(def-key-callback basic-quit-on-escape (window key scancode action mod-keys) (declare (ignore window scancode mod-keys)) (when (and (eq key :escape) (eq action :press)) (set-window-should-close))) -(defun render () +(defun basic-render () (gl:clear :color-buffer) (gl:with-pushed-matrix (gl:color 1 1 1) (gl:rect -25 -25 25 25))) -(defun set-viewport (width height) +(defun basic-set-viewport (width height) (gl:viewport 0 0 width height) (gl:matrix-mode :projection) (gl:load-identity) @@ -23,20 +23,20 @@ (gl:matrix-mode :modelview) (gl:load-identity)) -(def-window-size-callback update-viewport (window w h) +(def-window-size-callback basic-update-viewport (window w h) (declare (ignore window)) - (set-viewport w h)) + (basic-set-viewport w h)) (defun basic-window-example () ;; Graphics calls on OS X must occur in the main thread (with-body-in-main-thread () (with-init-window (:title "Window test" :width 600 :height 400) (setf %gl:*gl-get-proc-address* #'get-proc-address) - (set-key-callback 'quit-on-escape) - (set-window-size-callback 'update-viewport) + (set-key-callback 'basic-quit-on-escape) + (set-window-size-callback 'basic-update-viewport) (gl:clear-color 0 0 0 0) (set-viewport 600 400) (loop until (window-should-close-p) - do (render) + do (basic-render) do (swap-buffers) do (poll-events))))) diff --git a/examples/events.lisp b/examples/events.lisp index a48e995..dd4532c 100644 --- a/examples/events.lisp +++ b/examples/events.lisp @@ -35,6 +35,37 @@ (setf *window-size* (list w h)) (update-window-title window)) +(def-window-iconify-callback iconify-callback (window minp) + (declare (ignore window)) + (format t "~a~%" (if minp + 'min + 'not-min))) + +(def-window-maximize-callback maximize-callback (window maxp) + (declare (ignore window)) + (format t "~a~%" (if maxp + 'max + 'not-max))) + +#| +(def-drop-callback drop-print-callback+ (window num pathes) + (declare (ignore window)) + (format t "drop~%num:~a, pathes: ~a~%" num pathes) + (let ((p-list (loop for i from 0 below num collect + (pathname (cffi:mem-aref pathes :string i))))) + (print p-list))) +|# + +(def-drop-callback drop-print-callback (window num pathes) + (declare (ignore window)) + (print num) + (print pathes)) +#| + (dotimes (i num) + (print i) + (print (cffi:mem-aref pathes :string i)))) +|# + (defun events-example () ;; Graphics calls on OS X must occur in the main thread (with-body-in-main-thread () @@ -42,6 +73,9 @@ (set-key-callback 'key-callback) (set-mouse-button-callback 'mouse-callback) (set-window-size-callback 'window-size-callback) + (set-window-iconify-callback 'iconify-callback) + (set-window-maximize-callback 'maximize-callback) + (set-drop-callback 'drop-print-callback) (setf *window-size* (get-window-size)) (update-window-title *window*) (loop until (window-should-close-p) do (wait-events))))) diff --git a/examples/fragment-shader.lisp b/examples/fragment-shader.lisp index f7aa788..f5fea13 100644 --- a/examples/fragment-shader.lisp +++ b/examples/fragment-shader.lisp @@ -44,7 +44,7 @@ void main() (defvar *shader-time* 0) -(defun render () +(defun shader-render () (gl:clear :color-buffer) ;; Update our time variable in the shader @@ -114,12 +114,12 @@ void main() ;; Standard window setup below this line ;; ------------------------------------- -(def-key-callback quit-on-escape (window key scancode action mod-keys) +(def-key-callback shader-quit-on-escape (window key scancode action mod-keys) (declare (ignore window scancode mod-keys)) (when (and (eq key :escape) (eq action :press)) (set-window-should-close))) -(defun set-viewport (width height) +(defun shader-set-viewport (width height) ;; Black background (gl:clear-color 0.2 0.2 0.2 0.2) @@ -137,25 +137,25 @@ void main() (gl:matrix-mode :modelview) (gl:load-identity)) -(def-window-size-callback update-viewport (window w h) +(def-window-size-callback shader-update-viewport (window w h) (declare (ignore window)) - (set-viewport w h)) + (shader-set-viewport w h)) (defun fragment-shader-example () ;; Graphics calls on OS X must occur in the main thread (with-body-in-main-thread () (with-init-window (:title "OpenGL test" :width 600 :height 400) - (set-key-callback 'quit-on-escape) + (set-key-callback 'shader-quit-on-escape) ;; Callback for window resize events - (set-window-size-callback 'update-viewport) - (set-viewport 800 400) + (set-window-size-callback 'shader-update-viewport) + (shader-set-viewport 800 400) ;; Compile our shaders and use the program (setup-shader) ;; Our render-loop (loop until (window-should-close-p) - do (render) + do (shader-render) do (swap-buffers) do (poll-events))))) diff --git a/examples/icons.lisp b/examples/icons.lisp new file mode 100644 index 0000000..6d39ffa --- /dev/null +++ b/examples/icons.lisp @@ -0,0 +1,94 @@ +;;;; icons.lisp +;;;; This example shows changed icon. +(in-package #:cl-glfw3-examples) + +(export '(icons-example)) + +(defparameter *cl* #2a((0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0) + (0 0 0 1 1 0 0 0 0 0 2 0 0 0 0 0) + (0 0 1 0 0 1 0 0 0 0 2 0 0 0 0 0) + (0 1 0 0 0 0 0 0 0 0 2 0 0 0 0 0) + (0 1 0 0 0 0 0 0 0 0 2 0 0 0 0 0) + (0 0 1 0 0 1 0 0 0 0 2 0 0 0 0 0) + (0 0 0 1 1 0 0 0 0 0 2 2 2 2 0 0) + (0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0) + (0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0) + (0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0) + (0 0 0 0 0 0 0 0 0 1 0 2 0 3 0 0) + (0 0 0 0 0 0 0 0 0 0 0 2 0 3 0 0) + (0 0 0 0 0 0 0 0 0 0 2 0 0 0 3 0) + (0 0 0 0 0 0 0 0 0 0 2 0 0 0 3 0) + (0 0 0 0 0 0 0 0 0 0 0 2 0 3 0 0) + (0 0 0 0 0 0 0 0 0 0 0 2 0 3 0 0))) + +(defun dot-image (dot-array) + (let* ((width (array-dimension dot-array 0)) + (height (array-dimension dot-array 1)) + (image (make-array `(,height ,width 4) :element-type '(unsigned-byte 8)))) + (loop for j from 0 below height do + (loop for i from 0 below width do + (destructuring-bind (r g b a) + (ecase (aref dot-array i j) + (0 '(0 0 0 0));transparent + (1 '(#xff 0 0 #xff));red + (2 '(0 #xff 0 #xff));green + (3 '(0 0 #xff #xff));blue + (4 '(#xff #xff 0 #xff));yellow + (5 '(#xff 0 #xff #xff));magenta + (6 '(0 #xff #xff #xff));cyan + (7 '(#xff #xff #xff #xff));white + (8 '(0 0 0 #xff)));black + (setf (aref image i j 0) r) + (setf (aref image i j 1) g) + (setf (aref image i j 2) b) + (setf (aref image i j 3) a)))) + image)) + +(defparameter *cl-image* (dot-image *cl*)) +(defparameter *red-image* (dot-image (make-array '(48 48) :initial-element 1))) +(defparameter *green-image* (dot-image (make-array '(48 48) :initial-element 2))) +(defparameter *blue-image* (dot-image (make-array '(48 48) :initial-element 3))) +(defparameter *yellow-image* (dot-image (make-array '(48 48) :initial-element 4))) +(defparameter *magenta-image* (dot-image (make-array '(48 48) :initial-element 5))) +(defparameter *cyan-image* (dot-image (make-array '(48 48) :initial-element 6))) +(defparameter *white-image* (dot-image (make-array '(48 48) :initial-element 7))) +(defparameter *black-image* (dot-image (make-array '(48 48) :initial-element 8))) +(defparameter *color-check* (dot-image (let ((img (make-array '(45 45)))) + (loop for i from 1 below 45 do + (loop for j from 0 below 45 do + (setf (aref img i j) + (floor (/ i 5))))) + img))) + + +(defun icons-example () + ;; Graphics calls on OS X must occur in the main thread + (with-body-in-main-thread () + (with-init-window (:title "Icon test" :width 600 :height 400) + (set-window-icon *cl-image*) + (let ((cursors (make-array 10 :initial-contents (list (create-cursor *color-check* 0 0) + (create-cursor *yellow-image* 48 0) + (create-cursor *red-image* 0 48) + (create-cursor *blue-image* 24 24) + (create-standard-cursor :arrow) + (create-standard-cursor :ibeam) + (create-standard-cursor :crosshair) + (create-standard-cursor :hand) + (create-standard-cursor :hresize) + (create-standard-cursor :vresize)))) + (cursor-num 0)) + (def-mouse-button-callback mouse-cursor-change-callback (window button action mod-keys) + (declare (ignore window mod-keys)) + (if (eq action :press) + (setf cursor-num (mod (+ cursor-num + (cond ((eq button :left) 1) + ((eq button :right) -1) + (t 0))) + 10)) + (set-cursor (aref cursors cursor-num)))) + (set-mouse-button-callback 'mouse-cursor-change-callback) + (set-cursor (aref cursors cursor-num)) + (loop until (window-should-close-p) + do (poll-events)) + (loop for i from 0 below 10 do + (destroy-cursor (aref cursors i))))))) diff --git a/glfw-bindings.lisp b/glfw-bindings.lisp index dfa2d96..b772aaa 100644 --- a/glfw-bindings.lisp +++ b/glfw-bindings.lisp @@ -6,18 +6,23 @@ (export '(+dont-care+ + ;;initialize init terminate - get-version +init-hint +get-version get-version-string set-error-callback + ;;monitor get-monitors get-primary-monitor get-monitor-position - get-monitor-work-area + get-monitor-workarea get-monitor-physical-size get-monitor-content-scale get-monitor-name + set-monitor-user-pointer + get-monitor-user-pointer set-monitor-callback get-video-modes get-video-mode @@ -27,29 +32,38 @@ set-gamma get-gamma-ramp set-gamma-ramp + ;;window default-window-hints window-hint + window-hint-string create-window destroy-window window-should-close-p set-window-should-close set-window-title - get-window-opacity - set-window-opacity + set-window-icon get-window-position set-window-position get-window-size - set-window-size set-window-size-limits set-window-aspect-ratio - get-window-content-scale + set-window-size get-framebuffer-size + get-window-frame-size + get-window-content-scale + get-window-opacity + set-window-opacity iconify-window restore-window + maximize-window show-window hide-window + focus-window + request-window-attention get-window-monitor + set-window-monitor get-window-attribute + set-window-attribute set-window-user-pointer get-window-user-pointer set-window-position-callback @@ -58,42 +72,68 @@ set-window-refresh-callback set-window-focus-callback set-window-iconify-callback + set-window-maximize-callback set-framebuffer-size-callback - set-window-monitor + set-window-content-scale-callback poll-events wait-events + wait-events-timeout post-empty-event + ;;input get-input-mode set-input-mode + raw-mouse-motion-supported-p + get-key-name + get-key-scancode get-key get-mouse-button get-cursor-position set-cursor-position + create-cursor + create-standard-cursor + destroy-cursor + set-cursor set-key-callback set-char-callback + set-char-mods-callback set-mouse-button-callback set-cursor-position-callback set-cursor-enter-callback set-scroll-callback + set-drop-callback joystick-present-p get-joystick-axes get-joystick-buttons + get-joystick-hats get-joystick-name + get-joystick-guid + set-joystick-user-pointer + get-joystick-user-pointer + joystick-is-gamepad-p + set-joystick-callback + update-gamepad-mappings + get-gamepad-name + get-gamepad-state set-clipboard-string get-clipboard-string get-time set-time + get-timer-value + get-timer-frequency + ;;context make-context-current get-current-context swap-buffers swap-interval extension-supported-p get-proc-address + ;;vulkan vulkan-supported-p get-required-instance-extensions get-instance-proc-address physical-device-presentation-support-p - create-window-surface)) + create-window-surface + )) ;; internal stuff (export @@ -102,11 +142,17 @@ (define-foreign-library (glfw) (:darwin (:or ; homebrew naming - "libglfw3.1.dylib" "libglfw3.dylib" + "libglfw3.3.dylib" "libglfw3.2.dylib" "libglfw3.1.dylib" "libglfw3.dylib" ; cmake build naming - "libglfw.3.1.dylib" "libglfw.3.dylib")) - (:unix (:or "libglfw.so.3.1" "libglfw.so.3")) - (:windows "glfw3.dll") + "libglfw.3.3.dylib" "libglfw.3.2.dylib" "libglfw.3.1.dylib" "libglfw.3.dylib" + ;;glfw-blob + "libglfw.dylib.bodged")) + (:unix (:or "libglfw.so.3.3" "libglfw.wo.3.2" "libglfw.so.3.1" "libglfw.so.3" "libglfw.so" + ;;glfw-blob + "libglfw.so.bodged")) + (:windows (:or "glfw3.dll" + ;;glfw-blob + "libglfw.dll.bodged")) (t (:or (:default "libglfw3") (:default "libglfw")))) (use-foreign-library glfw) @@ -181,17 +227,105 @@ CFFI's defcallback that takes care of GLFW specifics." (with-float-traps-restored ,@actual-body)))) +(defmacro define-glfw-drop-callback (&whole whole name args &body body) + "Define a DROP callback. +This macro trunslate pointer passed from glfw to list of pathname +then call callback-function as lambda function." + (multiple-value-bind (actual-body decls doc) + (parse-body body :documentation t :whole whole) + `(defcallback ,name :void ,args + ,@(or doc) + (funcall (lambda ,(mapcar #'first args) + ,@decls + (with-float-traps-restored + ,@actual-body)) + ,(first (first args)) ;;window + ,(first (second args)) ;;counter + (mapcar #'pathname + (c-array->list ,(first (third args)) ,(first (second args)) :string)))))) + (defun c-array->list (array count &optional (type :pointer)) (loop for i below count collect (mem-aref array type i))) (alexandria:define-constant +dont-care+ -1) ;;;; ## GLFW Types +(defcenum (initialize-hint) + (:joystick-hat-buttons #x00050001) + (:cocoa-chdid-resources #x00051001) + (:cocoa-menubar #x00051002)) + (defcenum (key-action) :release :press :repeat) +;;; # Gamepad axes +(defcenum (gamepad-axes) + (:left-x 0) + (:left-y 1) + (:right-x 2) + (:right-y 3) + (:left-trigger 4) + (:right-trigger 5) + (:last 5)) + +;;; # Gamepad buttons +(defcenum (gamepad-buttons) + (:a 0) + (:b 1) + (:x 2) + (:y 3) + (:left-bumper 4) + (:right-bumper 5) + (:back 6) + (:start 7) + (:guide 8) + (:left-thumb 9) + (:right-thumb 10) + (:dpad-up 11) + (:dpad-right 12) + (:dpad-down 13) + (:dpad-left) + (:last 14) + (:cross 0) + (:circle 1) + (:square 2) + (:triangle 3)) + +;;; # joystick hat states +(defbitfield (hat) + (:centered #x0000) + (:up #x0001) + (:right #x0002) + (:down #x0004) + (:left #x0008) + (:right-up #x0003) + (:right-down #x0006) + (:left-up #x0009) + (:left-down #x000c)) + +;;; # Joysticks +(defcenum (joystick) + :1 + :2 + :3 + :4 + :5 + :6 + :7 + :8 + :9 + :10 + :11 + :12 + :13 + :14 + :15 + :16 + (:last 15)) + +;;; # KeyBoard Keys (defcenum (key) (:unknown -1) (:space 32) @@ -315,12 +449,16 @@ CFFI's defcallback that takes care of GLFW specifics." (:right-super 347) (:menu 348)) +;;; # Modifier key flags (defbitfield (mod-keys) :shift :control :alt - :super) + :super + :caps-lock + :num-lock) +;;; # Mouse buttons (defcenum (mouse) (:1 0) (:2 1) @@ -334,25 +472,16 @@ CFFI's defcallback that takes care of GLFW specifics." (:left 0) (:right 1)) -(defcenum (joystick) - :1 - :2 - :3 - :4 - :5 - :6 - :7 - :8 - :9 - :10 - :11 - :12 - :13 - :14 - :15 - :16 - (:last 15)) +;;Standard cursor shapes +(defcenum (cursor-shape) + (:arrow #x00036001) + (:ibeam #x00036002) + (:crosshair #x00036003) + (:hand #x00036004) + (:hresize #x00036005) + (:vresize #x00036006)) +;;; # Error codes (defcenum (errors) (:not-initialized #x00010001) (:no-current-context #x00010002) @@ -364,12 +493,20 @@ CFFI's defcallback that takes care of GLFW specifics." (:platform-error #X00010008) (:format-unavailable #x00010009)) +;;; # window-hint (defcenum (window-hint) (:focused #X00020001) (:iconified #X00020002) (:resizable #X00020003) (:visible #X00020004) (:decorated #X00020005) + (:auto-iconify #x00020006) + (:floating #x00020007) + (:maximized #x00020008) + (:center-cursor #x00020009) + (:transparent-framebuffer #x0002000a) + (:hovered #x0002000b) + (:focus-on-show #x0002000c) (:red-bits #X00021001) (:green-bits #X00021002) (:blue-bits #X00021003) @@ -385,6 +522,7 @@ CFFI's defcallback that takes care of GLFW specifics." (:samples #X0002100d) (:srgb-capable #X0002100E) (:refresh-rate #X0002100F) + (:doublebuffer #x00021010) (:client-api #X00022001) (:context-version-major #x00022002) (:context-version-minor #x00022003) @@ -392,37 +530,76 @@ CFFI's defcallback that takes care of GLFW specifics." (:context-robustness #x00022005) (:opengl-forward-compat #x00022006) (:opengl-debug-context #x00022007) - (:opengl-profile #X00022008)) - + (:opengl-profile #X00022008) + (:context-release-behavior #x00022009) + (:context-no-error #x0002200a) + (:context-creation-api #x0002200b) + (:scale-to-monitor #x0002200c) + (:cocoa-retina-framebuffer #x00023001) + (:cocoa-frame-name #x00023002) + (:cocoa-graphics-switching #x00023003) + (:x11-class-name #x00024001) + (:x11-instance-name #x00024002) + ) + +;;window attributes for set-window-attributes +(defcenum (window-attribute) + (:decorated #x00020005) + (:resizeable #x00020003) + (:floating #x00020007) + (:auto-iconify #x00020005) + (focus-on-show #x0002000c)) + +;; # for client-api hit (defcenum (opengl-api) (:no-api 0) (:opengl-api #X00030001) (:opengl-es-api #X00030002)) +;; # for context-creation-api hint +(defcenum (context-creation) + (:native-context-api #x00036001) + (:egl-context-api #x00036002) + (osmesa-context #x00036003)) + +;; # for context-robustness hint (defcenum (robustness) (:no-robustness 0) (:no-reset-notification #x00031001) (:lose-context-on-reset #x00031002)) +;; # for context-release-behavior hint +(defcenum (release-behavior) + (:any-release-behavior 0) + (:release-behavior-flush #x00035001) + (:release-behavior-none #x00035002)) + +;; # for opengl-profile hint (defcenum (opengl-profile) (:opengl-any-profile 0) (:opengl-core-profile #x00032001) (:opengl-compat-profile #x00032002)) -(defcenum (monitor-event) +;; # for monitor callbacks +(defcenum (connection-event) (:connected #X00040001) (:disconnected #X00040002)) +;; # for get-input-mode and set-input-mode (defcenum (input-mode) (:cursor #X00033001) (:sticky-keys #X00033002) - (:sticky-mouse-buttons #x00033003)) + (:sticky-mouse-buttons #x00033003) + (:lock-key-mods #x00033004) + (:raw-mouse-motion #x00033005)) +;; # for set-input-mode function (defcenum (cursor-mode) (:normal #X00034001) (:hidden #X00034002) (:disabled #X00034003)) +;; # for create-window-surface (defcenum (vk-result :int) (:error-native-window-in-use-khr -1000000001) ;; returned by glfwCreateWindowSurface if the window has not been created with GLFW_NO_API (:error-extension-not-present -7) ;; returned by glfwCreateWindowSurface if the required extensions have not been enabled on the VkInstance @@ -443,9 +620,20 @@ CFFI's defcallback that takes care of GLFW specifics." (blue :pointer) (size :unsigned-int)) +(defcstruct image + (width :int) + (height :int) + (pixels (:pointer :uchar))) + +(defcstruct gamepad-state + (buttons (:pointer :char)) + (axes (:pointer :float))) + (defctype window :pointer) (defctype monitor :pointer) +(defctype cursor :pointer) + ;; vulkan handles (defctype vk-instance :pointer) ;; VkSurfaceKHR is a non-dispatchable handle - type depends on the system @@ -460,6 +648,9 @@ CFFI's defcallback that takes care of GLFW specifics." (defcfun ("glfwInit" init) :boolean) (defcfun ("glfwTerminate" terminate) :void) +(defcfun ("glfwInitHint" init-hint) :void + (hint initialize-hint) (value :boolean)) + (defun get-version () "Returns major, minor, and revison numbers of GLFW library. May be called before INIT." (with-foreign-objects ((major :int) (minor :int) (rev :int)) @@ -474,6 +665,7 @@ Returns the previous error callback." (error-fun :pointer)) ;;;; ### Window and monitor functions +;;;; ### Monitor function (defun get-monitors () "Returns list of pointers to opaque monitor objects." (with-foreign-object (count :int) @@ -491,7 +683,7 @@ Returns the previous error callback." monitor monitor :pointer x :pointer y :void) (list (mem-ref x :int) (mem-ref y :int)))) -(defun get-monitor-work-area (monitor) +(defun get-monitor-workarea (monitor) "Returned work area is (x y w h) in screen coordinates." (with-foreign-objects ((x :int) (y :int) (w :int) (h :int)) (foreign-funcall "glfwGetMonitorWorkarea" @@ -515,8 +707,15 @@ Returns the previous error callback." (defcfun ("glfwGetMonitorName" get-monitor-name) :string (monitor monitor)) +(defcfun ("glfwSetMonitorUserPointer" set-monitor-user-pointer) :void + (monitor monitor) (pointer :pointer)) + +(defcfun ("glfwGetMonitorUserPointer" get-monitor-user-pointer) :pointer + (monitor monitor)) + (defcfun ("glfwSetMonitorCallback" set-monitor-callback) :pointer - "MONITOR-FUN is a callback of type 'void (* GLFWmonitorfun)(GLFWmonitor*,int)'. + "MONITOR-FUN is a callback of type 'void (* GLFWmonitorfun)(GLFWmonitor* monitor,int event)'. + event is one of the connection-event Returns previously set callback." (monitor-fun :pointer)) @@ -543,14 +742,18 @@ Returns previously set callback." '(:struct gamma-ramp))) (defcfun ("glfwSetGammaRamp" set-gamma-ramp) :void - (monitor monitor) (ramp gamma-ramp)) + (monitor monitor) (ramp (:pointer (:struct gamma-ramp)))) +;;;; ### Monitor function (defcfun ("glfwDefaultWindowHints" default-window-hints) :void "Reset all window hints to defaults.") (defcfun ("glfwWindowHint" window-hint) :void (target window-hint) (hint :int)) +(defcfun ("glfwWindowHintString" window-hint-string) :void + (target window-hint) (window-hint-string :string)) + (defcfun ("glfwCreateWindow" create-window) (float-traps-masked window) "Returns a window pointer that shares resources with the window SHARED or NULL." (width :int) (height :int) (title :string) (monitor monitor) (shared window)) @@ -567,10 +770,9 @@ Returns previously set callback." (defcfun ("glfwSetWindowTitle" set-window-title) :void (window window) (title :string)) -(defcfun ("glfwSetWindowMonitor" set-window-monitor) :void - (window window) (monitor monitor) - (x-position :int) (y-position :int) - (width :int) (height :int) (refresh-rate :int)) + +(defcfun ("glfwSetWindowIcon" set-window-icon) :void + (window window) (image-count :int) (images (:pointer (:struct image)))) (defun get-window-position (window) "Returns position of upper left corner of window (x y) in screen coordinates." @@ -582,16 +784,6 @@ Returns previously set callback." (defcfun ("glfwSetWindowPos" set-window-position) :void (window window) (x :int) (y :int)) -(defun get-window-opacity (window) - "Returns opacity of window." - (with-foreign-objects ((x :float)) - (foreign-funcall "glfwGetWindowOpacity" - window window :pointer x :void) - (mem-ref x :float))) - -(defcfun ("glfwSetWindowOpacity" set-window-opacity) :void - (window window) (x :float)) - (defun get-window-size (window) "Returns size (w h) in screen coordinates." (with-foreign-objects ((w :int) (h :int)) @@ -608,6 +800,15 @@ Returns previously set callback." (defcfun ("glfwSetWindowAspectRatio" set-window-aspect-ratio) :void (window window) (width :int) (height :int)) + +(defun get-window-frame-size (window) + "returns size (left top right bottom) of frame size." + (with-foreign-objects ((left :int) (top :int) (right :int) (bottom :int)) + (foreign-funcall "glfwGetWindowFrameSize" + window window + :pointer left :pointer top :pointer right :pointer bottom :void) + (list (mem-ref left :int) (mem-ref top :int) (mem-ref right :int) (mem-ref bottom :int)))) + (defun get-window-content-scale (window) "Returned scale is (x-scale y-scale)." (with-foreign-objects ((x-scale :float) (y-scale :float)) @@ -615,12 +816,15 @@ Returns previously set callback." window window :pointer x-scale :pointer y-scale :void) (list (mem-ref x-scale :float) (mem-ref y-scale :float)))) -(defun get-framebuffer-size (window) - "Returns size (w h) of framebuffer in pixels." - (with-foreign-objects ((w :int) (h :int)) - (foreign-funcall "glfwGetFramebufferSize" - window window :pointer w :pointer h :void) - (list (mem-ref w :int) (mem-ref h :int)))) +(defun get-window-opacity (window) + "Returns opacity of window." + (with-foreign-objects ((x :float)) + (foreign-funcall "glfwGetWindowOpacity" + window window :pointer x :void) + (mem-ref x :float))) + +(defcfun ("glfwSetWindowOpacity" set-window-opacity) :void + (window window) (x :float)) (defcfun ("glfwIconifyWindow" iconify-window) :void (window window)) @@ -628,18 +832,43 @@ Returns previously set callback." (defcfun ("glfwRestoreWindow" restore-window) :void (window window)) +(defcfun ("glfwMaximizeWindow" maximize-window) :void + (window window)) + (defcfun ("glfwShowWindow" show-window) :void (window window)) (defcfun ("glfwHideWindow" hide-window) :void (window window)) + +(defcfun ("glfwFocusWindow" focus-window) :void + (window window)) + +(defcfun ("glfwRequestWindowAttention" request-window-attention) :void + (window window)) + (defcfun ("glfwGetWindowMonitor" get-window-monitor) monitor (window window)) +(defcfun ("glfwSetWindowMonitor" set-window-monitor) :void + (window window) (monitor monitor) + (x-position :int) (y-position :int) + (width :int) (height :int) (refresh-rate :int)) + +(defun get-framebuffer-size (window) + "Returns size (w h) of framebuffer in pixels." + (with-foreign-objects ((w :int) (h :int)) + (foreign-funcall "glfwGetFramebufferSize" + window window :pointer w :pointer h :void) + (list (mem-ref w :int) (mem-ref h :int)))) + (defcfun ("glfwGetWindowAttrib" get-window-attribute) :int (window window) (attribute window-hint)) +(defcfun ("glfwSetWindowAttrib" set-window-attribute) :void + (window window) (attrib window-attribute) (value :boolean)) + (defcfun ("glfwSetWindowUserPointer" set-window-user-pointer) :void (window window) (pointer :pointer)) @@ -676,24 +905,52 @@ Returns previously set callback." Returns previously set callback." (window window) (iconify-fun :pointer)) +(defcfun ("glfwSetWindowMaximizeCallback" set-window-maximize-callback) :pointer + "MAXIMIZE-FUN is a callback of type 'void (* GLFWwindowmaximizefun)(GLFWwindow*,int)'. + Returns previously set callback." + (window window) (maximize-fun :pointer)) + (defcfun ("glfwSetFramebufferSizeCallback" set-framebuffer-size-callback) :pointer "FRAMEBUFFER-SIZE-FUN is a callback of type 'void (* GLFWframebuffersizefun)(GLFWwindow*,int,int)'. Returns previously set callback." (window window) (framebuffer-size-fun :pointer)) +(defcfun ("glfwSetWindowContentScaleCallback" set-window-content-scale-callback) :pointer + "CONTENTS-SCALE-FUN is a callback of type 'void (* GLFWwindowContentsScalefun)(GLFWwindow*,float,float)'. + Returns previously set callback." + (window window) (contents-scale-fun :pointer)) + ;;;; ### Events and input (defcfun ("glfwPollEvents" poll-events) (float-traps-masked :void)) (defcfun ("glfwWaitEvents" wait-events) (float-traps-masked :void)) +;; trapps-masked? +(defcfun ("glfwWaitEventsTimeout" wait-events-timeout) :void + (timeout :double)) + (defcfun ("glfwPostEmptyEvent" post-empty-event) :void) +(defcfun ("glfwSwapBuffers" swap-buffers) :void + (window window)) + +;;;; ### Input function (defcfun ("glfwGetInputMode" get-input-mode) :int (window window) (mode input-mode)) (defcfun ("glfwSetInputMode" set-input-mode) :void + "if mode is :cursor value is cursor-mode + else value is true or false" (window window) (mode input-mode) (value :int)) +(defcfun ("glfwRawMouseMotionSupported" raw-mouse-motion-supported-p) :int) + +(defcfun ("glfwGetKeyName" get-key-name) :string + (key key) (scancode :int)) + +(defcfun ("glfwGetKeyScancode" get-key-scancode) :int + (key key)) + (defcfun ("glfwGetKey" get-key) key-action (window window) (key key)) @@ -710,6 +967,18 @@ Returns previously set callback." (defcfun ("glfwSetCursorPos" set-cursor-position) :void (window window) (x :double) (y :double)) +(defcfun ("glfwCreateCursor" create-cursor) cursor + (image (:pointer (:struct image))) (xhot :int) (yhot :int)) + +(defcfun ("glfwCreateStandardCursor" create-standard-cursor) cursor + (shape cursor-shape)) + +(defcfun ("glfwDestroyCursor" destroy-cursor) :void + (cursor cursor)) + +(defcfun ("glfwSetCursor" set-cursor) :void + (window window) (cursor cursor)) + (defcfun ("glfwSetKeyCallback" set-key-callback) :pointer "KEY-FUN is a callback of type 'void (* GLFWkeyfun)(GLFWwindow*,int,int,int,int)'. Returns previously set callback." @@ -720,6 +989,11 @@ Returns previously set callback." Returns previously set callback." (window window) (char-fun :pointer)) +(defcfun ("glfwSetCharModsCallback" set-char-mods-callback) :pointer + "CHAR-MODS-FUN is a callback of type 'void (* GLFWCharModsfun)(GLFWwindow*,pointer)'. +Returns previously set callback." + (window window) (char-mods-fun :pointer)) + (defcfun ("glfwSetMouseButtonCallback" set-mouse-button-callback) :pointer "MOUSE-BUTTON-FUN is a callback of type 'void (* GLFWmousebuttonfun)(GLFWwindow*,int,int,int)'. Returns previously set callback." @@ -740,6 +1014,13 @@ Returns previously set callback." Returns previously set callback." (window window) (SCROLL-FUN :pointer)) +;;;; ### files +(defcfun ("glfwSetDropCallback" set-drop-callback) :pointer + "DROP-FUN is a callback of type 'void (* GLFWdropfun)(GLFWwindow*,int path_count,struct char** path_names)'. +Returns previously set callback." + (window window) (DROP-FUN :pointer)) + +;;;; ### joystick (defcfun ("glfwJoystickPresent" joystick-present-p) :boolean (joystick :int)) @@ -761,9 +1042,44 @@ Returns previously set callback." (mem-ref count :int) 'key-action))) +(defun get-joystick-hats (joystick) + "Returns list of values for direction of the joystick." + (with-foreign-object (count :int) + (c-array->list (foreign-funcall "glfwGetJoystickHats" + :int joystick :pointer count + :pointer) + (mem-ref count :int) + 'hats))) + (defcfun ("glfwGetJoystickName" get-joystick-name) :string + (joystick :int));jid + +(defcfun ("glfwGetJoystickGUID" get-joystick-guid) :string + (joystick :int)) + +(defcfun ("glfwSetJoystickUserPointer" set-joystick-user-pointer) :void + (joystick :int) (pointer :pointer)) + +(defcfun ("glfwGetJoystickUserPointer" get-joystick-user-pointer) :pointer + (joystick :int)) + +(defcfun ("glfwJoystickIsGamepad" joystick-is-gamepad-p) :boolean (joystick :int)) +(defcfun ("glfwSetJoystickCallback" set-joystick-callback) :pointer + "JOYSTICK-FUN is a callback of type 'void (* GLFWjoystickfun)(int joystick,int event)'. +Returns previously set callback." + (JOYSTICK-FUN :pointer)) + +(defcfun ("glfwUpdateGamepadMappings" update-gamepad-mappings) :boolean + (string :string)) + +(defcfun ("glfwGetGamepadName" get-gamepad-name) :string + (joystick :int)) + +(defcfun ("glfwGetGamepadState" get-gamepad-state) :boolean + (joystick :int) (gamepad-state (:pointer (:struct gamepad-state)))) + ;;;; ### Clipboard (defcfun ("glfwSetClipboardString" set-clipboard-string) :void (window window) (string :string)) @@ -777,15 +1093,16 @@ Returns previously set callback." (defcfun ("glfwSetTime" set-time) :void (time :double)) +(defcfun ("glfwGetTimerValue" get-timer-value) :uint64) + +(defcfun ("glfwGetTimerFrequency" get-timer-frequency) :uint64) + ;;;; ### Context (defcfun ("glfwMakeContextCurrent" make-context-current) :void (window window)) (defcfun ("glfwGetCurrentContext" get-current-context) window) -(defcfun ("glfwSwapBuffers" swap-buffers) :void - (window window)) - (defcfun ("glfwSwapInterval" swap-interval) :void (interval :int)) @@ -795,6 +1112,7 @@ Returns previously set callback." (defcfun ("glfwGetProcAddress" get-proc-address) :pointer (proc-name :string)) +;;;; ### Vulkan function (defcfun ("glfwVulkanSupported" vulkan-supported-p) :boolean) (defun get-required-instance-extensions ()